Stage 2 of the layered refactor. Move the storage HTTP client one package deeper so that infrastructure code lives under a dedicated namespace. - Add schedule/src/schedule/infrastructure/__init__.py - Add schedule/src/schedule/infrastructure/storage/__init__.py - Add schedule/src/schedule/infrastructure/storage/client.py (verbatim copy of old schedule/src/schedule/storage_client.py, byte-identical via diff — 2682 bytes) - main.py line 17: import path rewrite to the new module (only consumer — service.py and worker.py take storage_client as an `Any` constructor param and never imported the class) - old schedule/src/schedule/storage_client.py left on disk; stage 6 deletes it once all layers are extracted. Validation: - uv run --package schedule pytest schedule/tests -q: 18 passed - uv run python -m compileall schedule/src: zero errors - grep 'from schedule.storage_client' (old path): 0 matches - service.py and worker.py byte-identical to HEAD - main.py / pyproject.toml / tests/ unchanged apart from the 1 import line Co-Authored-By: Claude <noreply@anthropic.com>
Schedule Executor
独立调度执行服务,内置 APScheduler。
- Cron 任务持久化到 MySQL 的
apscheduler_jobs表; - FastAPI Backend 创建运行记录和 Outbox 事件后,通过 HTTP 尝试立即推送;
- HTTP 推送失败时,Executor 继续轮询 MySQL
outbox_events,保证任务不会丢失; - Executor 负责 DAG 节点派发、稳定版本执行、重试、状态推进和结果回写;
- 不依赖 Redis,MySQL 是调度状态与幂等状态的唯一权威。