Skip to content

Commit c703032

Browse files
committed
reworked capsul soma-workflow config
- added max_runnung_jobs and max_queued_jobs in config - set them and use them to dynamically drive the workflow controller during execution - added commandline parameters for them - fix: I thing the SWF config was not properly handled in capsul runner and was basically unused. We still don't use it the way it was initially intended I think (config environment key should correspond to the computing resource if I remember, here we always use the "global" env), however at least it is consistent in all parts of the code.
1 parent 8cece4b commit c703032

3 files changed

Lines changed: 95 additions & 12 deletions

File tree

capsul/engine/module/somaworkflow.py

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,26 @@ def init_settings(capsul_engine):
5858
description="Soma-workflow paths translations mapping: "
5959
"{local_path: (identifier, uuid)}",
6060
),
61+
dict(
62+
name="max_running_jobs",
63+
type="int",
64+
description="max running jobs in queue (overrides "
65+
"soma-workflow config file settings)"
66+
),
67+
dict(
68+
name="max_queued_jobs",
69+
type="int",
70+
description="max queued jobs (overrides "
71+
"soma-workflow config file settings)"
72+
),
6173
],
6274
)
6375
initialize_callbacks(capsul_engine)
6476

6577

6678
def activate_configurations():
6779
"""
68-
Activate the SPM module (set env variables) from the global configurations,
80+
Activate the Soma-Workflow module (set env variables) from the global configurations,
6981
in order to use them via :mod:`capsul.in_context.spm` functions
7082
"""
7183
conf = engine.configurations.get("capsul.engine.module.somaworkflow", {})
@@ -84,7 +96,8 @@ def validate_config(widget):
8496
controller = widget.controller_widget.controller
8597
with widget.engine.settings as session:
8698
values = {}
87-
for key in ("computing_resource", "config_file", "queue"):
99+
for key in ("computing_resource", "config_file", "queue",
100+
"max_running_jobs", "max_queued_jobs"):
88101
if getattr(controller, key) in (None, traits.Undefined, ""):
89102
values[key] = None
90103
else:
@@ -112,7 +125,9 @@ def validate_config(widget):
112125
"keep_failed_workflows",
113126
"keep_succeeded_workflows",
114127
"transfer_paths",
115-
#'path_translations'
128+
"max_running_jobs",
129+
"max_queued_jobs",
130+
#'path_translations',
116131
):
117132
setattr(conf, k, values[k])
118133
if id != widget.config_id:
@@ -156,15 +171,19 @@ def validate_config(widget):
156171
desc=''))
157172
controller.add_trait('transfer_paths',
158173
traits.List(traits.Directory,
159-
[], output=False,
160-
desc=''))
174+
[], output=False,
175+
desc=''))
161176
controller.add_trait('path_translations',
162177
traits.Dict(
163178
key_trait=traits.Directory,
164179
value_trait=traits.List(str)(['', ''], minlen=2,
165180
maxlen=2),
166181
value={}, output=False,
167182
desc=''))
183+
controller.add_trait('max_running_jobs', traits.Int(0, output=False,
184+
desc=""))
185+
controller.add_trait('max_queued_jobs', traits.Int(0, output=False,
186+
desc=""))
168187
conf = None
169188
if config_id == "any":
170189
conf = engine.settings.select_configurations(
@@ -205,6 +224,14 @@ def validate_config(widget):
205224
controller.path_translations = conf.get(
206225
"capsul.engine.module.somaworkflow", {}
207226
).get("path_translations", {})
227+
controller.max_running_jobs = conf.get(
228+
"capsul.engine.module.somaworkflow", {}).get(
229+
"max_running_jobs", Undefined
230+
)
231+
controller.max_queued_jobs = conf.get(
232+
"capsul.engine.module.somaworkflow", {}).get(
233+
"max_queued_jobs", Undefined
234+
)
208235

209236
# TODO handle several configs
210237

@@ -244,6 +271,9 @@ def sync_from_sc(engine, param=None, value=None):
244271
"SomaWorkflowConfig" in sc.modules
245272
and "capsul.engine.module.somaworkflow" in engine._loaded_modules
246273
):
274+
resource_id = sc.somaworkflow_computing_resource
275+
if resource_id is None:
276+
resource_id = 'localhost'
247277
with engine.settings as session:
248278
cif = engine.settings.config_id_field
249279
config = session.config("somaworkflow", "global")

capsul/engine/run.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -170,15 +170,16 @@ def start(engine, process, workflow=None, history=True, get_pipeline=False, **kw
170170
from capsul.pipeline.pipeline_workflow import workflow_from_pipeline
171171
import soma_workflow.client as swclient
172172

173-
swf_config = engine.settings.select_configurations(
174-
'global', {'somaworkflow': 'config_id=="somaworkflow"'})
175173
swm = engine.study_config.modules['SomaWorkflowConfig']
176174
swm.connect_resource(engine.connected_to())
177175
controller = swm.get_workflow_controller()
178176
resource_id = swm.get_resource_id()
179177

178+
query = 'config_id=="somaworkflow"'
179+
if resource_id is not None:
180+
query = f'computing_resource == "{resource_id}"'
180181
resource_config_d = engine.settings.select_configurations(
181-
resource_id, {'somaworkflow': 'config_id=="somaworkflow"'})
182+
'global', {'somaworkflow': query})
182183
resource_config = resource_config_d.get(
183184
'capsul.engine.module.somaworkflow', {})
184185
has_resource_config = ('capsul.engine.module.somaworkflow'
@@ -192,7 +193,9 @@ def start(engine, process, workflow=None, history=True, get_pipeline=False, **kw
192193
if workflow is None:
193194
workflow = workflow_from_pipeline(process, environment=environment)
194195

195-
queue = getattr(resource_config, 'queue', None)
196+
queue = resource_config.get('queue', None)
197+
max_running_jobs = resource_config.get('max_running_jobs', None)
198+
max_queued_jobs = resource_config.get('max_queued_jobs', None)
196199
#if hasattr(engine.study_config.somaworkflow_computing_resources_config,
197200
#resource_id):
198201
#res_conf = getattr(
@@ -201,6 +204,21 @@ def start(engine, process, workflow=None, history=True, get_pipeline=False, **kw
201204
#queue = res_conf.queue
202205
#if queue is Undefined:
203206
#queue = None
207+
if max_running_jobs is not None:
208+
controller.config.change_running_jobs_limits(queue, max_running_jobs)
209+
if controller.config.is_local_resource(
210+
controller.config._config_parser, resource_id) \
211+
and controller.config.get_scheduler_type() \
212+
== 'local_basic':
213+
controller.scheduler_config.set_max_proc_nb(max_running_jobs)
214+
controller.scheduler_config.set_proc_nb(max_running_jobs)
215+
if max_queued_jobs is not None:
216+
controller.config.change_queue_limits(queue, max_queued_jobs)
217+
if controller.config.is_local_resource(
218+
controller.config._config_parser, resource_id) \
219+
and controller.config.get_scheduler_type() \
220+
== 'local_basic':
221+
controller.scheduler_config.set_proc_nb(max_queued_jobs)
204222
workflow_name = process.name
205223
wf_id = controller.submit_workflow(workflow=workflow, name=workflow_name,
206224
queue=queue)

capsul/process/runprocess.py

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ def run_process_with_distribution(
256256
resource_id=None, password=None, config=None, rsa_key_pass=None,
257257
queue=None, input_file_processing=None, output_file_processing=None,
258258
keep_workflow=False, keep_failed_workflow=False,
259-
write_workflow_only=None):
259+
write_workflow_only=None, max_running_jobs=None, max_queued_jobs=None):
260260
''' Run the given process, either sequentially or distributed through
261261
Soma-Workflow.
262262
@@ -299,6 +299,10 @@ def run_process_with_distribution(
299299
if specified, this is an output filename where the workflow file will
300300
be written. The workflow will not be actually run, because int his
301301
situation the user probably wants to use the workflow on his own.
302+
max_running_jobs: int
303+
override the queue settings for OCFG_MAX_JOB_RUNNING in soma-workflow
304+
max_queued_jobs: int
305+
override the queue settings for OCFG_MAX_JOB_IN_QUEUE in soma-workflow
302306
'''
303307
if write_workflow_only:
304308
use_soma_workflow = True
@@ -332,6 +336,28 @@ def run_process_with_distribution(
332336
resource_id, {})
333337
getattr(study_config.somaworkflow_computing_resources_config,
334338
resource_id).queue = queue
339+
if max_running_jobs is not None or max_queued_jobs is not None:
340+
values = {}
341+
values['computing_resource'] = resource_id
342+
if queue is not None:
343+
values['queue'] = queue
344+
if max_running_jobs is not None:
345+
values['max_running_jobs'] = max_running_jobs
346+
if max_queued_jobs is not None:
347+
values['max_queued_jobs'] = max_queued_jobs
348+
engine = study_config.engine
349+
engine.load_module('somaworkflow')
350+
with engine.settings as session:
351+
query = 'config_id == "somaworkflow"'
352+
if resource_id is not None:
353+
query += f' AND computing_resource == "{resource_id}"'
354+
conf = session.config('somaworkflow', 'global',
355+
selection=query)
356+
if conf is None:
357+
session.new_config('somaworkflow', 'global', values)
358+
else:
359+
for k, v in values.items():
360+
setattr(conf, k, v)
335361

336362
res = study_config.run(process)
337363
return res
@@ -508,6 +534,12 @@ def main():
508534
group2.add_option('--queue', dest='queue', default=None,
509535
help='Queue to use on the computing resource. If not '
510536
'specified, use the default queue.')
537+
group2.add_option('--max_running', type=int, default=None,
538+
help='set maximum running jobs (override the queue '
539+
'settings in config file)')
540+
group2.add_option('--max_queued', type=int, default=None,
541+
help='set maximum queued jobs (override the queue '
542+
'settings in config file)')
511543
#group2.add_option('--input-processing', dest='input_file_processing',
512544
#default=None, help='Input files processing: local_path, '
513545
#'transfer, translate, or translate_shared. The default is '
@@ -585,7 +617,7 @@ def main():
585617
args += new_args
586618

587619
engine = capsul_engine()
588-
engine.load_modules(['fom', 'axon'])
620+
engine.load_modules(['fom', 'axon', 'somaworkflow'])
589621
study_config = engine.study_config
590622

591623
if options.config:
@@ -755,6 +787,8 @@ def main():
755787
rsa_key_pass = options.rsa_key_pass
756788
queue = options.queue
757789
file_processing = []
790+
max_running_jobs = options.max_running
791+
max_queued_jobs = options.max_queued
758792

759793
study_config.use_soma_workflow = options.soma_workflow
760794

@@ -772,7 +806,8 @@ def main():
772806
password=password, rsa_key_pass=rsa_key_pass,
773807
queue=queue, input_file_processing=file_processing[0],
774808
output_file_processing=file_processing[1],
775-
write_workflow_only=options.write_workflow)
809+
write_workflow_only=options.write_workflow,
810+
max_running_jobs=max_running_jobs, max_queued_jobs=max_queued_jobs)
776811

777812
# if there was no exception, we assume the process has succeeded.
778813
# sys.exit(0)

0 commit comments

Comments
 (0)