Skip to content

Commit 546f75f

Browse files
authored
feat: Model to track node states and has_ended flag (#94)
### TL;DR Added an `ExecutionSummary` class to track execution state with comprehensive test coverage. ### What changed? - Created a new `ExecutionSummary` dataclass in `api_server_sql.py` that tracks: - Total number of nodes - Number of ended nodes - Whether the entire execution has ended - Added a `count_node_status` method to update counters based on node status - Created a new test file `test_api_server_sql.py`. ### How to test? Run the new test suite: ``` pytest tests/test_api_server_sql.py ``` ### Why make this change? This will be used in upstream PRs to calculate execution summary for runs and root nodes.
1 parent f7913db commit 546f75f

2 files changed

Lines changed: 73 additions & 0 deletions

File tree

cloud_pipelines_backend/api_server_sql.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,22 @@ class ArtifactNodeIdResponse:
475475
id: bts.IdType
476476

477477

478+
@dataclasses.dataclass(kw_only=True)
479+
class ExecutionStatusSummary:
480+
total_executions: int = 0
481+
ended_executions: int = 0
482+
has_ended: bool = False
483+
484+
def count_execution_status(
485+
self, *, status: bts.ContainerExecutionStatus, count: int
486+
) -> None:
487+
self.total_executions += count
488+
if status in bts.CONTAINER_STATUSES_ENDED:
489+
self.ended_executions += count
490+
491+
self.has_ended = self.ended_executions == self.total_executions
492+
493+
478494
@dataclasses.dataclass
479495
class GetGraphExecutionStateResponse:
480496
child_execution_status_stats: dict[bts.IdType, dict[str, int]]

tests/test_api_server_sql.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
from cloud_pipelines_backend import backend_types_sql as bts
2+
from cloud_pipelines_backend.api_server_sql import ExecutionStatusSummary
3+
4+
5+
class TestExecutionStatusSummary:
6+
def test_initial_state(self):
7+
summary = ExecutionStatusSummary()
8+
assert summary.total_executions == 0
9+
assert summary.ended_executions == 0
10+
assert summary.has_ended is False
11+
12+
def test_accumulate_all_ended_statuses(self):
13+
"""Add each ended status with 2^i count for robust uniqueness."""
14+
summary = ExecutionStatusSummary()
15+
ended_statuses = sorted(bts.CONTAINER_STATUSES_ENDED, key=lambda s: s.value)
16+
expected_total = 0
17+
expected_ended = 0
18+
for i, status in enumerate(ended_statuses):
19+
count = 2**i
20+
summary.count_execution_status(status=status, count=count)
21+
expected_total += count
22+
expected_ended += count
23+
assert summary.total_executions == expected_total
24+
assert summary.ended_executions == expected_ended
25+
assert summary.has_ended is True
26+
27+
def test_accumulate_all_in_progress_statuses(self):
28+
"""Add each in-progress status with 2^i count for robust uniqueness."""
29+
summary = ExecutionStatusSummary()
30+
in_progress_statuses = sorted(
31+
set(bts.ContainerExecutionStatus) - bts.CONTAINER_STATUSES_ENDED,
32+
key=lambda s: s.value,
33+
)
34+
expected_total = 0
35+
for i, status in enumerate(in_progress_statuses):
36+
count = 2**i
37+
summary.count_execution_status(status=status, count=count)
38+
expected_total += count
39+
assert summary.total_executions == expected_total
40+
assert summary.ended_executions == 0
41+
assert summary.has_ended is False
42+
43+
def test_accumulate_all_statuses(self):
44+
"""Add every status with 2^i count. Summary math must be exact."""
45+
summary = ExecutionStatusSummary()
46+
all_statuses = sorted(bts.ContainerExecutionStatus, key=lambda s: s.value)
47+
expected_total = 0
48+
expected_ended = 0
49+
for i, status in enumerate(all_statuses):
50+
count = 2**i
51+
expected_total += count
52+
if status in bts.CONTAINER_STATUSES_ENDED:
53+
expected_ended += count
54+
summary.count_execution_status(status=status, count=count)
55+
assert summary.total_executions == expected_total
56+
assert summary.ended_executions == expected_ended
57+
assert summary.has_ended == (expected_ended == expected_total)

0 commit comments

Comments
 (0)