pynenc.orchestrator.atomic_service¶
Atomic service coordination for distributed Pynenc runners.
Pure scheduling logic: no I/O, no orchestrator dependencies. The single entry
point is :func:decide_atomic_service_claim which returns one
- class:
AtomicServiceClaimdescribing what the caller should do next.
Module Contents¶
Classes¶
Identifies one atomic-service run. |
|
Identifies one atomic-service cycle claimed by a runner. |
|
Outcome labels produced by the scheduler claim decision. |
|
Information about an active runner including heartbeat tracking. |
|
Lifecycle status of a recorded atomic-service execution attempt. |
|
A recorded atomic-service execution attempt by one runner. |
|
Final scheduling result. The single object callers consume. |
|
Mutable scratch-pad. The scheduler mutates this object and then calls
one of the named terminal methods, each of which calls |
Functions¶
(start, end) for this position, or None when the margin is too wide. |
|
Decide whether |
Data¶
API¶
- class pynenc.orchestrator.atomic_service.AtomicServiceId[source]¶
Identifies one atomic-service run.
- class pynenc.orchestrator.atomic_service.AtomicServiceRun[source]¶
Identifies one atomic-service cycle claimed by a runner.
Accepts either a composed
atomic_service_idor the flatrunner_id/atomic_service_run_idpair so downstream call sites can construct runs without first building anAtomicServiceId.- atomic_service_id: pynenc.orchestrator.atomic_service.AtomicServiceId¶
None
- cycle_start: datetime.datetime | None¶
None
- slot_start: datetime.datetime | None¶
None
- slot_end: datetime.datetime | None¶
None
- started_at: datetime.datetime | None¶
None
- class pynenc.orchestrator.atomic_service.AtomicServiceDecisionReason[source]¶
Bases:
enum.StrEnumOutcome labels produced by the scheduler claim decision.
Initialization
Initialize self. See help(type(self)) for accurate signature.
- ASSIGNED¶
‘auto(…)’
- NOT_ASSIGNED_SLOT¶
‘auto(…)’
- NO_STABLE_RUNNERS¶
‘auto(…)’
- SCHEDULED_RUNNER_IN_GRACE¶
‘auto(…)’
- SLOT_WINDOW_INVALID¶
‘auto(…)’
- LATE_START¶
‘auto(…)’
- pynenc.orchestrator.atomic_service._PERSISTED_REASONS¶
‘frozenset(…)’
- class pynenc.orchestrator.atomic_service.ActiveRunnerInfo[source]¶
Bases:
typing.NamedTupleInformation about an active runner including heartbeat tracking.
- creation_time: datetime.datetime¶
None
- last_heartbeat: datetime.datetime¶
None
- class pynenc.orchestrator.atomic_service.AtomicServiceExecutionStatus[source]¶
Bases:
enum.StrEnumLifecycle status of a recorded atomic-service execution attempt.
Initialization
Initialize self. See help(type(self)) for accurate signature.
- RUNNING¶
‘running’
- COMPLETED¶
‘completed’
- ABANDONED¶
‘abandoned’
- BLOCKED¶
‘blocked’
- class pynenc.orchestrator.atomic_service.AtomicServiceExecution[source]¶
Bases:
typing.NamedTupleA recorded atomic-service execution attempt by one runner.
- atomic_service_id: pynenc.orchestrator.atomic_service.AtomicServiceId¶
None
- start_time: datetime.datetime¶
None
- end_time: datetime.datetime | None¶
None
- classmethod from_raw(runner_id: str, atomic_service_run_id: str, start_time: datetime.datetime, end_time: datetime.datetime | None, status: pynenc.orchestrator.atomic_service.AtomicServiceExecutionStatus = AtomicServiceExecutionStatus.RUNNING, reason: str = '') pynenc.orchestrator.atomic_service.AtomicServiceExecution[source]¶
- property atomic_service_run: pynenc.orchestrator.atomic_service.AtomicServiceRun¶
- class pynenc.orchestrator.atomic_service.AtomicServiceClaim[source]¶
Final scheduling result. The single object callers consume.
Carries everything an orchestrator or UI needs: the reason, the slot layout, the assigned runner, the optional
AtomicServiceRunwhen the runner is cleared to start, and the optionalskip_message/late_start_fractionwhen the slot is held reserved.- cycle_start: datetime.datetime¶
None
- slot_start: datetime.datetime | None¶
None
- slot_end: datetime.datetime | None¶
None
- atomic_service_run: pynenc.orchestrator.atomic_service.AtomicServiceRun | None¶
None
- property skip_reason: pynenc.orchestrator.atomic_service.AtomicServiceDecisionReason | None¶
- property decision: pynenc.orchestrator.atomic_service.AtomicServiceClaim¶
- class pynenc.orchestrator.atomic_service._ClaimBuilder[source]¶
Mutable scratch-pad. The scheduler mutates this object and then calls one of the named terminal methods, each of which calls
_build()exactly once with the right reason.Defaults represent the “skip, nothing to report” outcome — every branch only sets the fields that differ.
- started_at: datetime.datetime¶
None
- cycle_start: datetime.datetime¶
‘field(…)’
- slot_start: datetime.datetime | None¶
None
- slot_end: datetime.datetime | None¶
None
- set_slot(window: tuple[datetime.datetime, datetime.datetime], *, is_owner: bool) None[source]¶
- not_in_stable_set() pynenc.orchestrator.atomic_service.AtomicServiceClaim[source]¶
- invalid_window() pynenc.orchestrator.atomic_service.AtomicServiceClaim[source]¶
- late_start(fraction: float, max_fraction: float) pynenc.orchestrator.atomic_service.AtomicServiceClaim[source]¶
- cleared_to_start() pynenc.orchestrator.atomic_service.AtomicServiceClaim[source]¶
- _build(reason: pynenc.orchestrator.atomic_service.AtomicServiceDecisionReason, *, atomic_service_run: pynenc.orchestrator.atomic_service.AtomicServiceRun | None = None, skip_message: str = '', late_start_fraction: float | None = None) pynenc.orchestrator.atomic_service.AtomicServiceClaim[source]¶
- pynenc.orchestrator.atomic_service._slot_window(cycle_start_ts: float, position: int, slot_size: float, spread_seconds: float, *, single_runner: bool) tuple[datetime.datetime, datetime.datetime] | None[source]¶
(start, end) for this position, or None when the margin is too wide.
- pynenc.orchestrator.atomic_service._is_in_grace(runner: pynenc.orchestrator.atomic_service.ActiveRunnerInfo, now: float, stabilization_seconds: float) bool[source]¶
- pynenc.orchestrator.atomic_service._late_start_fraction(started_at: datetime.datetime, slot_start: datetime.datetime | None, slot_end: datetime.datetime | None, max_fraction: float) float | None[source]¶
- pynenc.orchestrator.atomic_service.decide_atomic_service_claim(*, runner_id: str, active_runners: list[pynenc.orchestrator.atomic_service.ActiveRunnerInfo], current_time: float, service_interval_minutes: float, spread_margin_minutes: float, membership_stabilization_seconds: float, max_start_slot_fraction: float) pynenc.orchestrator.atomic_service.AtomicServiceClaim[source]¶
Decide whether
runner_idshould start the atomic service now.Returns a single :class:
AtomicServiceClaimdescribing the outcome. Callers inspectclaim.atomic_service_run(non-None means start),claim.skip_reason(non-None means persist as BLOCKED), andclaim.reasonfor diagnostics.