mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-09-18 18:46:17 +00:00
A review pass over domain/schedule found three genuinely untested branches, all of which now have cases: - ensure_launchable with a naive `now`. next_after already had this covered; the delay floor did not, so a caller handing over a naive clock reading could have had it shifted by the local offset unnoticed. - update_task changing the prompt. Only the title path was exercised. - _save finding the row gone. get_task saw it and save no longer does, which is a concurrent delete; the caller must get the same not-found it would have got a moment earlier rather than a None leaking out. That takes service.py and every model module to 100%. The one remaining uncovered line is croniter's naive-return guard, carried over verbatim from schedules.py and unreachable with an aware input -- it now says so instead of looking like an untested branch. Also fills in the documentation the migration skipped: TaskStatus, ContextMode and RunStatus arrived from the original draft without docstrings while their newer siblings had them, and ScheduleService plus four of its use cases were undocumented. Each now records the reasoning a reader would otherwise have to reconstruct -- why RUNNING is not "the agent is executing", why SKIPPED never passes through QUEUED, why INTERRUPTED is not FAILED. CRON_FIELD_COUNT stops being exported: it has no consumer outside the module that defines it.
95 lines
2.8 KiB
Python
95 lines
2.8 KiB
Python
from __future__ import annotations
|
|
|
|
from enum import StrEnum
|
|
|
|
|
|
class TaskStatus(StrEnum):
|
|
"""Lifecycle of a standing instruction.
|
|
|
|
RUNNING does not mean "the agent is executing" -- it means this dispatch
|
|
round's scheduling ownership is held. That is why `ensure_mutable` refuses
|
|
edits in that state, and why a crash can strand a task there.
|
|
|
|
The last three are terminal for the *current* schedule, not forever: moving
|
|
the schedule into the future re-arms them (see TERMINAL_TASK_STATUSES).
|
|
"""
|
|
|
|
ENABLED = "enabled"
|
|
PAUSED = "paused"
|
|
RUNNING = "running"
|
|
COMPLETED = "completed"
|
|
FAILED = "failed"
|
|
CANCELLED = "cancelled"
|
|
|
|
|
|
class ContextMode(StrEnum):
|
|
"""Which thread a dispatch executes in.
|
|
|
|
REUSE_THREAD lets consecutive executions see each other's history and
|
|
requires a thread up front; the default gives each one a fresh thread and
|
|
therefore no shared context.
|
|
"""
|
|
|
|
FRESH_THREAD_PER_RUN = "fresh_thread_per_run"
|
|
REUSE_THREAD = "reuse_thread"
|
|
|
|
|
|
class ScheduleType(StrEnum):
|
|
"""How the next fire time is derived.
|
|
|
|
The two branch almost every rule in this context: CRON always has a next
|
|
occurrence, ONCE is consumed by its first one.
|
|
"""
|
|
|
|
ONCE = "once"
|
|
CRON = "cron"
|
|
|
|
|
|
class RunStatus(StrEnum):
|
|
"""Lifecycle of one execution record.
|
|
|
|
QUEUED and RUNNING are the two that occupy a task's single active slot;
|
|
everything else is terminal.
|
|
|
|
SKIPPED is created directly terminal and never passes through QUEUED -- a
|
|
queued tombstone would collide with the very run it is recording the
|
|
overlap with (see ScheduledRun.skipped_tombstone). INTERRUPTED is kept
|
|
distinct from FAILED because a cancel or takeover is not an execution
|
|
failure, and the two lead a `once` task to different terminal states.
|
|
"""
|
|
|
|
QUEUED = "queued"
|
|
RUNNING = "running"
|
|
SUCCESS = "success"
|
|
FAILED = "failed"
|
|
INTERRUPTED = "interrupted"
|
|
SKIPPED = "skipped"
|
|
|
|
|
|
class DispatchOutcome(StrEnum):
|
|
"""What one dispatch attempt produced.
|
|
|
|
A domain vocabulary rather than a set of strings: the caller branches on
|
|
all four, and the distinction between SKIPPED and CONFLICT is itself a
|
|
business rule -- a dropped scheduled occurrence is accounted for, while a
|
|
rejected on-demand trigger is reported and leaves no trace.
|
|
"""
|
|
|
|
LAUNCHED = "launched"
|
|
SKIPPED = "skipped"
|
|
CONFLICT = "conflict"
|
|
FAILED = "failed"
|
|
|
|
|
|
class TriggerKind(StrEnum):
|
|
"""What caused a dispatch.
|
|
|
|
The two kinds diverge in almost every decision the domain makes — how an
|
|
overlap is handled, what status survives a failed launch, whether a paused
|
|
task stays paused — so this is a first-class concept rather than the raw
|
|
string the old service compared in four places.
|
|
"""
|
|
|
|
SCHEDULED = "scheduled"
|
|
MANUAL = "manual"
|