Files
lda-wf/src/wf_core/runtime/limits.py
T

40 lines
1.6 KiB
Python

"""Run-wide step budget policy and admission.
One finite, persisted counter (``RunState.steps_executed``) covers every frame
and subgraph scope in a run. Admission happens immediately before step dispatch:
an admitted attempt increments the counter and stamps the selected frame with
its one-based step number; a denied attempt raises without incrementing and
without invoking any handler. This slice deliberately adds no per-step durable
checkpoints; the counter is persisted inside the existing stopped-run envelope.
"""
from __future__ import annotations
from typing import TYPE_CHECKING
from wf_core.errors import WorkflowStepLimitExceeded
if TYPE_CHECKING:
from wf_core.run_state import ExecutionFrame, RunState
def admit_step_attempt(run: RunState, frame: ExecutionFrame, node_id: str) -> int:
"""Admit one step attempt for ``frame`` about to dispatch ``node_id``.
On success the run-wide counter is incremented, the frame remembers the
assigned step number, and that number is returned. When the budget is
already exhausted the counter is left untouched, the frame keeps its
previous number, and ``WorkflowStepLimitExceeded`` is raised before any
handler runs.
"""
if run.steps_executed >= run.limits.max_steps:
raise WorkflowStepLimitExceeded.from_run(run, frame, node_id)
run.steps_executed += 1
frame.step_number = run.steps_executed
return frame.step_number
def remaining_step_attempts(run: RunState) -> int:
"""Return the unspent budget, floored at zero (never negative)."""
return run.steps_remaining