Skip to content

particula.execution.scheduler

scheduler

Resolve direct-import-only, declaration-only scheduling metadata.

This concrete module validates immutable P1 graph declarations before applying enabled-node selection, direction policy, and freshness closure. Resolution is prelaunch-only: it neither loads backends nor enters lifecycle state, allocates resources, executes refreshes, or mutates caller-owned data. Its names are not package exports and must be imported from this module directly.

EnabledNodeSelection dataclass

EnabledNodeSelection(enabled_node_ids: frozenset[str])

Declare the complete immutable set of enabled P1 node identifiers.

Graph membership is deliberately deferred to schedule resolution, after complete P1 plan validation.

Parameters:

  • enabled_node_ids (frozenset[str]) –

    Exact frozenset of syntactically valid node IDs.

__post_init__

__post_init__() -> None

Validate selection container and identifier syntax.

Source code in particula/execution/scheduler.py
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
def __post_init__(self) -> None:
    """Validate selection container and identifier syntax."""
    if type(self.enabled_node_ids) is not frozenset:
        raise TypeError(
            "EnabledNodeSelection.enabled_node_ids must be a frozenset."
        )
    for node_id in self.enabled_node_ids:
        if type(node_id) is not str:
            raise TypeError(
                "EnabledNodeSelection.enabled_node_ids must contain only "
                "str instances."
            )
        if not _NAME_PATTERN.fullmatch(node_id):
            raise ValueError(
                "EnabledNodeSelection.enabled_node_ids must contain valid "
                "node IDs."
            )

NucleationCondensationDirection

Bases: str, Enum

Declare the reviewed nucleation/condensation ordering.

ResolvedTimestepSchedule dataclass

ResolvedTimestepSchedule(nodes: tuple[ProcessNode, ...], dependencies: tuple[DependencyEdge, ...], ordered_node_ids: tuple[str, ...], source_graph: ResolvedProcessGraph | None = None, _provenance: object | None = None)

Store canonical, immutable declaration-only scheduling metadata.

Nodes and dependencies are canonically sorted. The order is a permutation of node IDs created before any lifecycle entry, resource action, or process launch.

Parameters:

  • nodes (tuple[ProcessNode, ...]) –

    Sorted exact tuple of enabled process nodes.

  • dependencies (tuple[DependencyEdge, ...]) –

    Sorted exact tuple of effective dependency edges.

  • ordered_node_ids (tuple[str, ...]) –

    Canonical dependency order for exactly these nodes.

__post_init__

__post_init__() -> None

Validate canonical immutable schedule fields.

Source code in particula/execution/scheduler.py
134
135
136
137
def __post_init__(self) -> None:
    """Validate canonical immutable schedule fields."""
    _validate_schedule_types(self)
    _validate_schedule_content(self)

SchedulerProfile dataclass

SchedulerProfile(nucleation_condensation_direction: NucleationCondensationDirection)

Declare immutable scheduler direction policy without selecting execution.

The enum represents exactly one reviewed nucleation/condensation direction; it cannot encode both directions or no direction.

Parameters:

__post_init__

__post_init__() -> None

Validate the single direction declaration.

Source code in particula/execution/scheduler.py
100
101
102
103
104
105
106
107
108
109
def __post_init__(self) -> None:
    """Validate the single direction declaration."""
    if not isinstance(
        self.nucleation_condensation_direction,
        NucleationCondensationDirection,
    ):
        raise TypeError(
            "SchedulerProfile.nucleation_condensation_direction must be a "
            "NucleationCondensationDirection."
        )

is_resolver_produced_schedule

is_resolver_produced_schedule(schedule: ResolvedTimestepSchedule, graph: ResolvedProcessGraph) -> bool

Return whether a schedule retains its exact resolver-produced graph.

This internal provenance check prevents a structurally similar hand-built schedule from entering the resident execution boundary.

Source code in particula/execution/scheduler.py
267
268
269
270
271
272
273
274
275
276
277
def is_resolver_produced_schedule(
    schedule: ResolvedTimestepSchedule, graph: ResolvedProcessGraph
) -> bool:
    """Return whether a schedule retains its exact resolver-produced graph.

    This internal provenance check prevents a structurally similar hand-built
    schedule from entering the resident execution boundary.
    """
    return schedule.source_graph is graph and any(
        schedule is registered for registered in _RESOLVER_SCHEDULES
    )

resolve_timestep_schedule

resolve_timestep_schedule(plan: TimestepPlan, selection: EnabledNodeSelection, profile: SchedulerProfile) -> ResolvedTimestepSchedule

Resolve an immutable effective schedule without running any process.

After exact carrier-type checks, complete P1 graph validation happens before selection or profile inspection. This function then applies selected IDs, direction policy, required freshness closure, and canonical topology ordering. It returns metadata only and performs no lifecycle, resource, or GPU work.

Parameters:

Returns:

Raises:

  • TypeError

    If a carrier is not its exact declared type.

  • ValueError

    If selection, direction, closure, or effective topology is invalid. No input is mutated when resolution fails; no rollback is required because resolution has no side effects.

Source code in particula/execution/scheduler.py
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
def resolve_timestep_schedule(
    plan: TimestepPlan,
    selection: EnabledNodeSelection,
    profile: SchedulerProfile,
) -> ResolvedTimestepSchedule:
    """Resolve an immutable effective schedule without running any process.

    After exact carrier-type checks, complete P1 graph validation happens before
    selection or profile inspection. This function then applies selected IDs,
    direction policy, required freshness closure, and canonical topology
    ordering. It returns metadata only and performs no lifecycle, resource, or
    GPU work.

    Args:
        plan: Exact P1 plan declaration.
        selection: Exact enabled-node selection.
        profile: Exact immutable direction policy.

    Returns:
        A new canonical schedule with no disabled dependency endpoints.

    Raises:
        TypeError: If a carrier is not its exact declared type.
        ValueError: If selection, direction, closure, or effective topology is
            invalid. No input is mutated when resolution fails; no rollback is
            required because resolution has no side effects.
    """
    _validate_resolution_inputs(plan, selection, profile)
    resolved = resolve_timestep_plan(plan)
    _validate_selected_ids(selection, resolved)
    direction = _direction_edge(profile)
    _validate_profile_direction(resolved, direction)
    pairs = _resolve_effective_pairs(resolved, selection, profile, direction)
    nodes = tuple(
        node
        for node in resolved.nodes
        if node.node_id in selection.enabled_node_ids
    )
    dependencies = tuple(DependencyEdge(*pair) for pair in sorted(pairs))
    order = resolve_canonical_topological_order(nodes, dependencies)
    schedule = ResolvedTimestepSchedule(
        nodes,
        dependencies,
        order,
        source_graph=resolved,
        _provenance=_SCHEDULE_PROVENANCE,
    )
    _RESOLVER_SCHEDULES.append(schedule)
    return schedule