Skip to content

Commit 13016fd

Browse files
authored
Merge pull request #1473 from haddocking/grid-fallback
fallback to `Scheduler` if the GRID is not available on runtime
2 parents 556e6b6 + f0adb0c commit 13016fd

3 files changed

Lines changed: 70 additions & 12 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
# Changelog
22

3+
- 2026-02-20: Add fallback routine to use `Scheduler` if the GRID is not available
34
- 2025-12-15: Added missing NGA glycan parameters - Issue #1462
45
- 2025-11-25: Simplify the use of multiple ambig archives
56
- 2025-11-19: Corrected CNS verbosity settings - Issue #1446
67
- 2025-11-19: Added zinc-finger docking example, related to Issue #1445
7-
- 2025-11-19: Corrected flexref module for Issue #1445
8+
- 2025-11-19: Corrected flexref module for Issue #1445
89
- 2025-11-17: Added possibility to use alascan with ligands - Issue #1411
910
- 2025-10-22: Allow the definition of chain combinations to be used for scoring - Issue #1414
1011
- 2025-09-11: Added `grid` mode

src/haddock/modules/__init__.py

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
from haddock.gear.parameters import config_mandatory_general_parameters
2929
from haddock.gear.yaml2cfg import read_from_yaml_config, find_incompatible_parameters
3030
from haddock.libs.libhpc import HPCScheduler
31-
from haddock.libs.libgrid import GRIDScheduler
31+
from haddock.libs.libgrid import GRIDScheduler, ping_dirac
3232
from haddock.libs.libio import folder_exists, working_directory
3333
from haddock.libs.libmpi import MPIScheduler
3434
from haddock.libs.libontology import ModuleIO, PDBFile
@@ -65,9 +65,7 @@
6565
# modules will use these parameters. It is the responsibility of the module to
6666
# extract the parameters it needs.
6767
# the config file is in modules/defaults.cfg
68-
non_mandatory_general_parameters_defaults = read_from_yaml_config(
69-
modules_defaults_path
70-
) # noqa : E501
68+
non_mandatory_general_parameters_defaults = read_from_yaml_config(modules_defaults_path) # noqa : E501
7169

7270
incompatible_defaults_params = find_incompatible_parameters(modules_defaults_path)
7371

@@ -187,9 +185,7 @@ def update_params(
187185
>>> m.update_params(...)
188186
"""
189187
if update_from_cfg_file and params:
190-
_msg = (
191-
"You can not provide both `update_from_cfg_file` " "and key arguments."
192-
)
188+
_msg = "You can not provide both `update_from_cfg_file` and key arguments."
193189
raise TypeError(_msg)
194190

195191
if update_from_cfg_file:
@@ -305,7 +301,7 @@ def export_io_models(self, faulty_tolerance: float = 0.0) -> None:
305301
if detected_errors := find_all_cns_errors(self.path):
306302
_msg += linesep
307303
for error in detected_errors.values():
308-
_msg += f'{str(error["error"])}{linesep}'
304+
_msg += f"{str(error['error'])}{linesep}"
309305
# Show final error message
310306
self.finish_with_error(_msg)
311307

@@ -399,7 +395,7 @@ def _fill_emptypaths(self) -> None:
399395
def get_engine(
400396
mode: str,
401397
params: dict[Any, Any],
402-
) -> partial[Union[HPCScheduler, Scheduler, MPIScheduler]]:
398+
) -> partial[Union[HPCScheduler, Scheduler, MPIScheduler, GRIDScheduler]]:
403399
"""
404400
Create an engine to run the jobs.
405401
@@ -433,10 +429,22 @@ def get_engine(
433429
return partial(MPIScheduler, ncores=params["ncores"]) # type: ignore
434430

435431
elif mode == "grid":
436-
return partial(GRIDScheduler, params=params) # type: ignore
432+
# `grid` mode should only be used IF the grid is reachable,
433+
# if not it should fallback to `local`
434+
grid_available = ping_dirac()
435+
436+
if grid_available:
437+
return partial(GRIDScheduler, params=params) # type: ignore
438+
else:
439+
log.warning("GRID is not available, activating fallback using `mode=local`")
440+
return partial( # type: ignore
441+
Scheduler,
442+
ncores=params["ncores"],
443+
max_cpus=params["max_cpus"],
444+
)
437445

438446
else:
439-
available_engines = ("batch", "local", "mpi")
447+
available_engines = ("batch", "local", "mpi", "grid")
440448
raise ValueError(
441449
f"Scheduler `mode` {mode!r} not recognized. "
442450
f"Available options are {', '.join(available_engines)}"

tests/test_modules.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
from functools import partial
2+
from unittest.mock import patch
3+
4+
from haddock.libs.libgrid import GRIDScheduler
5+
from haddock.libs.libhpc import HPCScheduler
6+
from haddock.libs.libmpi import MPIScheduler
7+
from haddock.libs.libparallel import Scheduler
8+
from haddock.modules import get_engine
9+
10+
11+
def test_get_engine_grid_unavailable():
12+
with patch("haddock.modules.ping_dirac", return_value=False):
13+
engine = get_engine(mode="grid", params={"ncores": 1, "max_cpus": 4})
14+
assert isinstance(engine, partial)
15+
assert engine.func is Scheduler
16+
17+
18+
def test_get_engine_grid_available():
19+
with patch("haddock.modules.ping_dirac", return_value=True):
20+
engine = get_engine(mode="grid", params={"ncores": 1, "max_cpus": 4})
21+
assert isinstance(engine, partial)
22+
assert engine.func is GRIDScheduler
23+
24+
25+
def test_get_engine_local():
26+
engine = get_engine(mode="local", params={"ncores": 2, "max_cpus": 8})
27+
assert isinstance(engine, partial)
28+
assert engine.func is Scheduler
29+
assert engine.keywords["ncores"] == 2
30+
assert engine.keywords["max_cpus"] == 8
31+
32+
33+
def test_get_engine_batch():
34+
engine = get_engine(
35+
mode="batch",
36+
params={"queue": "short", "queue_limit": 100, "concat": 5},
37+
)
38+
assert isinstance(engine, partial)
39+
assert engine.func is HPCScheduler
40+
assert engine.keywords["target_queue"] == "short"
41+
assert engine.keywords["queue_limit"] == 100
42+
assert engine.keywords["concat"] == 5
43+
44+
45+
def test_get_engine_mpi():
46+
engine = get_engine(mode="mpi", params={"ncores": 4})
47+
assert isinstance(engine, partial)
48+
assert engine.func is MPIScheduler
49+
assert engine.keywords["ncores"] == 4

0 commit comments

Comments
 (0)