state_machine.py file-level

at sha256:2 · View file ↗ · Intel ↗

History
1 files
1 commits
0 hotspots
0 🧊 dead
0 💥 blast risk
sha256:c Add T4 job cancellation retry and validation · · Jun 11, 2026
1 """Deterministic T2 training job state machine."""
2
3 from __future__ import annotations
4
5 from types import MappingProxyType
6
7 from scooling_lab.contracts import TrainingJobStatus
8 from scooling_lab.errors import ApiError, ErrorCode
9
10
11 TRANSITION_TABLE: MappingProxyType[TrainingJobStatus, frozenset[TrainingJobStatus]] = (
12 MappingProxyType(
13 {
14 TrainingJobStatus.QUEUED: frozenset(
15 {
16 TrainingJobStatus.RUNNING,
17 TrainingJobStatus.FAILED,
18 TrainingJobStatus.CANCELLED,
19 }
20 ),
21 TrainingJobStatus.RUNNING: frozenset(
22 {
23 TrainingJobStatus.SUCCEEDED,
24 TrainingJobStatus.FAILED,
25 TrainingJobStatus.CANCELLED,
26 }
27 ),
28 TrainingJobStatus.SUCCEEDED: frozenset({TrainingJobStatus.DELETED}),
29 TrainingJobStatus.DELETED: frozenset(),
30 TrainingJobStatus.FAILED: frozenset(),
31 TrainingJobStatus.CANCELLED: frozenset(),
32 }
33 )
34 )
35
36
37 def transition(
38 current: TrainingJobStatus, target: TrainingJobStatus
39 ) -> TrainingJobStatus:
40 """Return the next state or raise for invalid non-idempotent transitions."""
41
42 if current == target:
43 return current
44 if target in TRANSITION_TABLE[current]:
45 return target
46 raise ApiError(ErrorCode.INVALID_TRANSITION, 409)
47
48
49 def cancel(current: TrainingJobStatus) -> TrainingJobStatus:
50 """Cancel a queued or running job; terminal replay is idempotent."""
51
52 if current in {
53 TrainingJobStatus.SUCCEEDED,
54 TrainingJobStatus.FAILED,
55 TrainingJobStatus.CANCELLED,
56 TrainingJobStatus.DELETED,
57 }:
58 return current
59 return transition(current, TrainingJobStatus.CANCELLED)