mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-09-18 18:46:17 +00:00
First step of the scheduled-task context's hexagonal migration: the inner-ring model, with zero infrastructure dependencies. - ScheduleSpec / SchedulePolicy value objects - ScheduledTask aggregate root - ScheduledRun aggregate - 9 domain errors, 5 enums Rules are migrated verbatim from their current homes, each method's docstring citing the source line: timezone/cron/next-run calculation from deerflow/scheduler/schedules.py, context-mode and re-arm rules from routers/scheduled_tasks.py, and the four status-derivation rules from app/scheduler/service.py. Two things previously held by convention are now enforced by construction. Validation and normalization live in __post_init__, so building a ScheduleSpec field-by-field cannot bypass them. The skipped tombstone is a separate factory, so it can never be written as the transient queued row that would collide with uq_scheduled_task_run_active. The domain does not serialize itself: mapping the stored schedule_spec JSON in and out stays with the adapter layer, keeping Mapping[str, Any] out of every domain signature. Production code still runs through app/scheduler/service.py -- this commit adds no call sites and changes no behavior.
49 lines
1.4 KiB
Python
49 lines
1.4 KiB
Python
from __future__ import annotations
|
|
|
|
|
|
class ScheduleError(Exception):
|
|
"""Base error for the schedule domain."""
|
|
|
|
|
|
class InvalidScheduleError(ScheduleError):
|
|
"""Timezone, cron expression, or run_at is not usable."""
|
|
|
|
|
|
class InvalidContextModeError(ScheduleError):
|
|
"""context_mode is unknown, or reuse_thread is missing its thread_id."""
|
|
|
|
|
|
class TaskNotFoundError(ScheduleError):
|
|
"""The task does not exist or does not belong to the user."""
|
|
|
|
|
|
class TaskNotMutableError(ScheduleError):
|
|
"""The task is currently running and cannot be edited."""
|
|
|
|
|
|
class ThreadNotFoundError(ScheduleError):
|
|
"""reuse_thread points at a thread the user cannot access."""
|
|
|
|
|
|
class ActiveRunConflictError(ScheduleError):
|
|
"""The task already holds its single active run slot.
|
|
|
|
Raised by the run repository when the partial unique index
|
|
``uq_scheduled_task_run_active`` rejects a second active row. Moved here
|
|
from ``persistence/scheduled_task_runs/sql.py`` (was
|
|
``ActiveScheduledRunConflict``) so the domain owns its own vocabulary.
|
|
"""
|
|
|
|
|
|
class ThreadBusyError(ScheduleError):
|
|
"""The execution thread already has an in-flight run.
|
|
|
|
Translated by the RunLauncher adapter from ConflictError / HTTP 409.
|
|
This is what removes `from fastapi import HTTPException` from the
|
|
orchestration layer.
|
|
"""
|
|
|
|
|
|
class LaunchFailedError(ScheduleError):
|
|
"""The run could not be launched for any non-conflict reason."""
|