refactor(schedule): move orchestrator to application/ + review fixes (stage 8)

Follow-up to the layered refactor (review-driven):

- Move scheduling/orchestrator.py -> application/orchestrator.py
  (orchestrator is application-level coordination, not a cron-trigger
  primitive; matches the intended target tree)
- Migrate orchestrator re-exports from scheduling/__init__.py to
  application/__init__.py; scheduling/ now exposes only CronScheduler
- Rewrite imports + 5 mock.patch string targets in test_janitor.py and
  the orchestrator import in test_layering.py
- Update docstring refs in application/service.py + execution/worker.py
- Add 4 runner smoke tests (test_layering.py): _limited_log under-limit /
  empty-sentinel / above-MAX_LOG_BYTES truncation; execute_artifact
  rejects unsupported script_type with ValueError
- infrastructure/__init__.py re-exports SchedulerStorageClient so
  ``from schedule.infrastructure import SchedulerStorageClient`` is a
  stable top-level surface
- CLAUDE.md engineering note: extend the commit trail to 7476c27 and
  note the stage-8 orchestrator placement

Zero behavior change; schedule/pyproject.toml untouched. 29 tests green.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
tao.chen
2026-09-02 10:10:41 +08:00
committed by tao.chen
co-authored by Claude
parent ff03a79938
commit d196b237a7
9 changed files with 83 additions and 30 deletions
+1 -1
View File
@@ -78,7 +78,7 @@ Hard-won lessons. Read the relevant bullet before touching the named area.
### Schedule service layering (domain / scheduling / application / execution / infrastructure)
Lessons from the zero-behavior-change refactor that split the flat 11-file `schedule/src/schedule/` into five subpackages (commits 3118694 → c89132a). Public class names (`SchedulerService`, `CronScheduler`, `DispatchOrchestrator`, `NodeExecutor`, `SchedulerStorageClient`) and `schedule/pyproject.toml` are unchanged.
Lessons from the zero-behavior-change refactor that split the flat 11-file `schedule/src/schedule/` into five subpackages (commits 3118694 → 7476c27, with a follow-up `git mv` in stage 8 placing the orchestrator under `application/`). Public class names (`SchedulerService`, `CronScheduler`, `DispatchOrchestrator`, `NodeExecutor`, `SchedulerStorageClient`) and `schedule/pyproject.toml` are unchanged.
- **`python -m schedule.notebook_runner` is a stable external contract.** The worker launches the notebook subprocess with `sys.executable, "-m", "schedule.notebook_runner"`. That `-m` string must never change — so `schedule/notebook_runner.py` survives as a 6-line shim re-exporting `main` from `schedule.execution.runners.notebook`. Don't "clean up" the shim.
- **Mock `patch()` string targets and in-function lazy imports are invisible to import-line greps.** `test_janitor.py` patched `"schedule.orchestrator.session_scope"` and `test_worker.py` patched `"schedule.service.build_object_store"`; `worker.py` also had a `from schedule.service import ...` *inside a function body*. When files move, these silently no-op against the old path — and hard-crash once the old file is deleted. After any move, grep the whole tree for the old module path (including tests) and rewrite every hit, not just top-level imports.