Skip to content

Commit 399deea

Browse files
authored
Merge pull request #638 from ThalesGroup/codex/remove-orchestrate-legacy-worker-paths
Remove legacy workflow data path compatibility
2 parents b908e14 + 99c9b89 commit 399deea

2 files changed

Lines changed: 75 additions & 73 deletions

File tree

src/agilab/orchestrate/orchestrate_cluster.py

Lines changed: 21 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,6 @@
5353
WORKFLOW_SESSION_POLICY_OPTIONS = ("new", "last", "select")
5454
WORKFLOW_SESSION_DEFAULT_POLICY = "new"
5555
WORKFLOW_DEFAULT_ID = "workflows"
56-
WORKFLOW_SESSION_DIR = "workflows"
57-
WORKFLOW_SESSION_LEGACY_WORKERS_DIR = "workers"
5856
WORKFLOW_PROJECT_SUFFIXES = ("_project", "-project")
5957

6058

@@ -421,11 +419,6 @@ def _workflow_sessions_root(cluster_share: Path, user: Any, workflow_name: Any)
421419
return _workflow_user_root(cluster_share, user) / safe_workflow
422420

423421

424-
def _legacy_workflow_sessions_root(cluster_share: Path, user: Any, workflow_name: Any) -> Path:
425-
safe_workflow = _safe_workflow_component(workflow_name, "default")
426-
return _workflow_user_root(cluster_share, user) / WORKFLOW_SESSION_DIR / safe_workflow
427-
428-
429422
def _list_workflow_sessions(sessions_root: Path) -> list[Path]:
430423
try:
431424
entries = [path for path in sessions_root.iterdir() if path.is_dir()]
@@ -477,39 +470,16 @@ def _resolve_workflow_session_module_path(
477470
return module_path, session_id, resolved_policy
478471

479472

480-
def _resolve_workflow_session_workers_path(
481-
cluster_share: Path,
482-
*,
483-
user: Any,
484-
workflow_name: Any,
485-
project_name: Any = None,
486-
policy: Any,
487-
selected_session: Any = "",
488-
create: bool = True,
489-
session_id_factory: Callable[[], str] = _new_workflow_session_id,
490-
) -> tuple[Path, str, str]:
491-
return _resolve_workflow_session_module_path(
492-
cluster_share,
493-
user=user,
494-
workflow_name=workflow_name,
495-
project_name=project_name,
496-
policy=policy,
497-
selected_session=selected_session,
498-
create=create,
499-
session_id_factory=session_id_factory,
500-
)
501-
502-
503-
def _workflow_workers_data_path_text(cluster_share: Path, workers_path: Path, env: Any) -> str:
473+
def _workflow_data_path_text(cluster_share: Path, module_path: Path, env: Any) -> str:
504474
cluster_share_setting = _env_cluster_share_setting(env)
505475
if cluster_share_setting:
506476
try:
507-
suffix = workers_path.relative_to(cluster_share)
477+
suffix = module_path.relative_to(cluster_share)
508478
except ValueError:
509479
pass
510480
else:
511481
return (Path(cluster_share_setting) / suffix).as_posix()
512-
return _home_relative_share_text(workers_path, env) or str(workers_path)
482+
return _home_relative_share_text(module_path, env) or str(module_path)
513483

514484

515485
def _path_matches_workflow_session_leaf(data_path: Path, sessions_root: Path, leaf_name: str) -> bool:
@@ -520,14 +490,21 @@ def _path_matches_workflow_session_leaf(data_path: Path, sessions_root: Path, le
520490
return len(relative_path.parts) == 2 and relative_path.parts[1] == leaf_name
521491

522492

493+
def _path_is_current_workflow_module_or_child(data_path: Path, sessions_root: Path, module_name: str) -> bool:
494+
try:
495+
relative_path = data_path.relative_to(sessions_root)
496+
except ValueError:
497+
return False
498+
return len(relative_path.parts) >= 2 and relative_path.parts[1] == module_name
499+
500+
523501
def _workers_data_path_should_follow_workflow_session(
524502
value: Any,
525503
env: Any,
526504
*,
527505
user: Any,
528506
workflow_name: Any,
529507
project_name: Any = None,
530-
legacy_workflow_names: tuple[Any, ...] = (),
531508
) -> bool:
532509
text = _clean_path_text(value)
533510
if not text:
@@ -541,25 +518,13 @@ def _workers_data_path_should_follow_workflow_session(
541518
if data_path == cluster_share:
542519
return True
543520
module_name = _workflow_module_component(workflow_name if project_name is None else project_name)
544-
candidate_roots = [
545-
_workflow_sessions_root(cluster_share, user, workflow_name),
546-
_legacy_workflow_sessions_root(cluster_share, user, workflow_name),
547-
]
548-
seen_roots = {root.resolve(strict=False) for root in candidate_roots}
549-
for legacy_workflow_name in legacy_workflow_names:
550-
for candidate_root in (
551-
_workflow_sessions_root(cluster_share, user, legacy_workflow_name),
552-
_legacy_workflow_sessions_root(cluster_share, user, legacy_workflow_name),
553-
):
554-
resolved_candidate_root = candidate_root.resolve(strict=False)
555-
if resolved_candidate_root not in seen_roots:
556-
candidate_roots.append(candidate_root)
557-
seen_roots.add(resolved_candidate_root)
558-
return any(
559-
_path_matches_workflow_session_leaf(data_path, candidate_root, module_name)
560-
or _path_matches_workflow_session_leaf(data_path, candidate_root, WORKFLOW_SESSION_LEGACY_WORKERS_DIR)
561-
for candidate_root in candidate_roots
562-
)
521+
sessions_root = _workflow_sessions_root(cluster_share, user, workflow_name)
522+
if _path_matches_workflow_session_leaf(data_path, sessions_root, module_name):
523+
return True
524+
user_root = _workflow_user_root(cluster_share, user)
525+
if _path_is_within(data_path, user_root):
526+
return not _path_is_current_workflow_module_or_child(data_path, sessions_root, module_name)
527+
return False
563528

564529

565530
def _orchestrate_workflow_id(cluster_params: dict[str, Any], env: Any) -> str:
@@ -760,7 +725,7 @@ def _lan_discovery_cluster_defaults(
760725
*,
761726
home: Path | str | None = None,
762727
) -> dict[str, Any]:
763-
"""Return scheduler/workers defaults from the last LAN discovery cache."""
728+
"""Return scheduler and worker defaults from the last LAN discovery cache."""
764729
cache_file = cache_path or _default_lan_discovery_cache_path(home)
765730
try:
766731
payload = json.loads(cache_file.expanduser().read_text(encoding="utf-8"))
@@ -1527,7 +1492,7 @@ def render_cluster_settings_ui(env: Any, deps: OrchestrateClusterDeps, *, show_r
15271492
workflow_session_error_shown = True
15281493
st.error(f"Could not prepare workflow session under `{cluster_share_candidate}`: {exc}")
15291494
else:
1530-
workflow_workers_data_path = _workflow_workers_data_path_text(
1495+
workflow_workers_data_path = _workflow_data_path_text(
15311496
cluster_share_candidate,
15321497
workflow_workers_path,
15331498
env,
@@ -1604,7 +1569,7 @@ def render_cluster_settings_ui(env: Any, deps: OrchestrateClusterDeps, *, show_r
16041569
except OSError as exc:
16051570
st.error(f"Could not prepare workflow session under `{cluster_share_candidate}`: {exc}")
16061571
else:
1607-
workflow_workers_data_path = _workflow_workers_data_path_text(
1572+
workflow_workers_data_path = _workflow_data_path_text(
16081573
cluster_share_candidate,
16091574
workflow_workers_path,
16101575
env,
@@ -1626,7 +1591,6 @@ def render_cluster_settings_ui(env: Any, deps: OrchestrateClusterDeps, *, show_r
16261591
user=sanitized_user,
16271592
workflow_name=workflow_id,
16281593
project_name=app_state_name,
1629-
legacy_workflow_names=(app_state_name,),
16301594
):
16311595
cluster_params["workers_data_path"] = workflow_workers_data_path
16321596
st.session_state[workers_data_path_widget_key] = workflow_workers_data_path

test/test_orchestrate_cluster.py

Lines changed: 54 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -530,55 +530,93 @@ def test_workflow_session_module_path_policies(tmp_path):
530530
user="agi",
531531
workflow_name="workflows",
532532
project_name="demo_project",
533-
legacy_workflow_names=("demo_project",),
534533
)
535534
assert orchestrate_cluster._workers_data_path_should_follow_workflow_session(
536535
"clustershare/agi/workflows/latest-run/demo",
537536
env,
538537
user="agi",
539538
workflow_name="workflows",
540539
project_name="demo_project",
541-
legacy_workflow_names=("demo_project",),
542540
)
543541
assert orchestrate_cluster._workers_data_path_should_follow_workflow_session(
544-
"clustershare/agi/demo_project/latest-run/workers",
542+
"clustershare/agi/workflows/demo_project/latest-run/stale",
545543
env,
546544
user="agi",
547545
workflow_name="workflows",
548546
project_name="demo_project",
549-
legacy_workflow_names=("demo_project",),
550547
)
551548
assert orchestrate_cluster._workers_data_path_should_follow_workflow_session(
552-
"clustershare/agi/workflows/demo_project/latest-run/workers",
549+
"clustershare/agi/demo_project/latest-run/stale",
553550
env,
554551
user="agi",
555552
workflow_name="workflows",
556553
project_name="demo_project",
557-
legacy_workflow_names=("demo_project",),
558554
)
559-
assert not orchestrate_cluster._workers_data_path_should_follow_workflow_session(
555+
assert orchestrate_cluster._workers_data_path_should_follow_workflow_session(
560556
"clustershare/agi/workflows/latest-run/custom-module",
561557
env,
562558
user="agi",
563559
workflow_name="workflows",
564560
project_name="demo_project",
565-
legacy_workflow_names=("demo_project",),
566561
)
567562
assert not orchestrate_cluster._workers_data_path_should_follow_workflow_session(
568563
"clustershare/agi/workflows/latest-run/demo/custom-data",
569564
env,
570565
user="agi",
571566
workflow_name="workflows",
572567
project_name="demo_project",
573-
legacy_workflow_names=("demo_project",),
574568
)
575569
assert not orchestrate_cluster._workers_data_path_should_follow_workflow_session(
576570
"/external/data",
577571
env,
578572
user="agi",
579573
workflow_name="workflows",
580574
project_name="demo_project",
581-
legacy_workflow_names=("demo_project",),
575+
)
576+
577+
578+
def test_workflow_session_path_regression_uses_workflow_session_module_semantic(tmp_path):
579+
share = tmp_path / "clustershare" / "agi"
580+
session_id = "20260618T093102Z-492de776"
581+
582+
path, session, policy = orchestrate_cluster._resolve_workflow_session_module_path(
583+
share,
584+
user="agi",
585+
workflow_name="workflows",
586+
project_name="flight_telemetry_project",
587+
policy="select",
588+
selected_session=session_id,
589+
create=False,
590+
)
591+
592+
assert policy == "select"
593+
assert session == session_id
594+
assert path == share / "workflows" / session_id / "flight_telemetry"
595+
assert "workers" not in path.parts
596+
assert "flight_telemetry_project" not in path.parts
597+
598+
599+
def test_workers_data_path_regression_rewrites_misplaced_managed_share_values(tmp_path):
600+
share = tmp_path / "clustershare" / "agi"
601+
env = SimpleNamespace(
602+
home_abs=tmp_path,
603+
AGI_CLUSTER_SHARE=str(share),
604+
AGI_LOCAL_SHARE=str(tmp_path / "localshare"),
605+
)
606+
607+
assert orchestrate_cluster._workers_data_path_should_follow_workflow_session(
608+
"clustershare/agi/workflows/flight_telemetry_project/20260618T093102Z-492de776/stale",
609+
env,
610+
user="agi",
611+
workflow_name="workflows",
612+
project_name="flight_telemetry_project",
613+
)
614+
assert not orchestrate_cluster._workers_data_path_should_follow_workflow_session(
615+
"clustershare/agi/workflows/20260618T093102Z-492de776/flight_telemetry/custom-data",
616+
env,
617+
user="agi",
618+
workflow_name="workflows",
619+
project_name="flight_telemetry_project",
582620
)
583621

584622

@@ -1437,12 +1475,12 @@ def test_render_cluster_settings_ui_empty_workflow_session_auto_selects_latest(m
14371475
"cluster_enabled": True,
14381476
"workflow_session_policy": "select",
14391477
"workflow_session": "session-a",
1440-
"workers_data_path": "cluster-share/agi/workflows/demo_project/session-a/workers",
1478+
"workers_data_path": "cluster-share/agi/workflows/demo_project/session-a/stale",
14411479
}
14421480
},
14431481
widget_keys["workflow_session_policy"]: "select",
14441482
widget_keys["workflow_session"]: "session-a",
1445-
widget_keys["workers_data_path"]: "cluster-share/agi/workflows/demo_project/session-a/workers",
1483+
widget_keys["workers_data_path"]: "cluster-share/agi/workflows/demo_project/session-a/stale",
14461484
"benchmark": False,
14471485
},
14481486
)
@@ -2709,20 +2747,20 @@ def iterdir(self):
27092747

27102748
env_with_setting = SimpleNamespace(home_abs=tmp_path, AGI_CLUSTER_SHARE=str(share))
27112749
assert (
2712-
orchestrate_cluster._workflow_workers_data_path_text(
2750+
orchestrate_cluster._workflow_data_path_text(
27132751
share,
2714-
tmp_path / "other" / "workers",
2752+
tmp_path / "other" / "data",
27152753
env_with_setting,
27162754
)
2717-
== "other/workers"
2755+
== "other/data"
27182756
)
27192757

27202758
env_without_setting = SimpleNamespace(
27212759
home_abs=tmp_path,
27222760
share_root_path=lambda: (_ for _ in ()).throw(RuntimeError("missing share")),
27232761
)
27242762
assert (
2725-
orchestrate_cluster._workflow_workers_data_path_text(
2763+
orchestrate_cluster._workflow_data_path_text(
27262764
share,
27272765
share / "agi" / "workflows" / "session-a" / "demo",
27282766
env_without_setting,

0 commit comments

Comments
 (0)