Skip to content

fix(testing): filter EXECUTION ops by type, not index - #637

Merged
yaythomas merged 1 commit into
aws:mainfrom
SravyaPeri:fix/456-assertable-operations-execution-type
Aug 13, 2026
Merged

fix(testing): filter EXECUTION ops by type, not index#637
yaythomas merged 1 commit into
aws:mainfrom
SravyaPeri:fix/456-assertable-operations-execution-type

Conversation

@SravyaPeri

Copy link
Copy Markdown
Contributor

Issue #, if available: #456

Description of changes:

While looking into this I found get_assertable_operations() had a TODO on it questioning its own logic, it excludes the EXECUTION operation by just slicing off operations[1:], assuming that operation is always first. That's true today, but it leaves a couple of things unhandled:

  • If a second EXECUTION-type entry ever shows up at the end of the list (which is literally what the TODO was asking about, something like a future large-payload checkpoint), it would slip through and end up in the "assertable" results by mistake.
  • This method is also the only place in the class that reads self.operations without grabbing _state_lock first. Every other method that touches operations (get_navigable_operations, start, _end_execution, the callback completions, etc.) does take the lock, so this one stood out. Since checkpoints can land on a worker thread while this is being read, it felt worth fixing rather than leaving as a latent race.

What I changed:

  • Filter operations by operation_type != OperationType.EXECUTION instead of slicing by index, so it excludes any EXECUTION-type entry no matter where it shows up.
  • Added the _state_lock around the read, matching how get_navigable_operations() already does it.
  • Added a couple of tests: one for a trailing EXECUTION operation getting excluded correctly, and one checking the returned list doesn't alias self.operations (so mutating the execution afterward doesn't change a result you already got back).

Ran the full suite plus lint/type checks locally, all green:
hatch run dev-testing:test # 1379 passed
hatch fmt --check # clean
hatch run dev-testing:typecheck # clean

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@SravyaPeri
SravyaPeri deployed to ai-pr-review August 13, 2026 13:16 — with GitHub Actions Active
@SravyaPeri
SravyaPeri temporarily deployed to ai-pr-review-runtime August 13, 2026 17:15 — with GitHub Actions Inactive
@SravyaPeri
SravyaPeri temporarily deployed to ai-pr-review-runtime August 13, 2026 17:15 — with GitHub Actions Inactive
Comment on lines +356 to +360
with self._state_lock:
return [
operation
for operation in self.operations
if operation.operation_type != OperationType.EXECUTION

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codex AI review

P2: This lock does not synchronize with checkpoint writes. CheckpointRequestDispatcher.apply_updates() replaces and appends to execution.operations without acquiring _state_lock, so this read can still observe a partially applied checkpoint batch. Guard the entire checkpoint mutation with the same lock, or route this read through the execution worker lane, and add a concurrent checkpoint/read test.

@github-actions

Copy link
Copy Markdown
Contributor

Codex AI review

Found one concurrency gap. Filtering is covered, but checkpoint/read synchronization is not.

Reviewed commit ea6d2c40901cb4893baf209c1d239ae743dafc5a. Workflow run

@github-actions

Copy link
Copy Markdown
Contributor

Claude AI review

This PR reworks Execution.get_assertable_operations() in the testing package to filter operations by operation_type != OperationType.EXECUTION (instead of slicing operations[1:]) and to read self.operations under _state_lock, returning a fresh list.

Assessment: no actionable findings.

  • Filter change is correct. start() always appends the EXECUTION operation first and get_operation_execution_started() reads operations[0], so index 0 is invariably EXECUTION. The type-based filter is equivalent for the normal case, strictly more robust for a trailing EXECUTION entry, and preserves order; empty-list behavior is unchanged.
  • Lock addition is safe. _state_lock is a non-reentrant Lock; I confirmed there are no src/ callers of get_assertable_operations that already hold the lock (only tests/external consumers call it), so no deadlock is introduced. It now matches get_navigable_operations().
  • Snapshot is genuinely independent — the list comprehension always allocates a new list, so the result never aliases self.operations.

Residual test risk (minor, not filed inline): test_get_assertable_operations_returns_independent_snapshot appends an EXECUTION-type op after snapshotting and asserts result == []. Since EXECUTION ops are filtered out regardless, this would also pass under an aliasing implementation; appending a STEP op would make the independence guarantee it claims to verify actually load-bearing.

Reviewed commit ea6d2c40901cb4893baf209c1d239ae743dafc5a. Workflow run

@yaythomas yaythomas added needs-triage Issue needs triage needs-review and removed needs-triage Issue needs triage labels Aug 13, 2026
@yaythomas
yaythomas force-pushed the fix/456-assertable-operations-execution-type branch from ea6d2c4 to b4a4de5 Compare August 13, 2026 22:24
@yaythomas

Copy link
Copy Markdown
Contributor

the extra _state_lock is actually not necessary, and if anything we could/should probably remove it from get_navigable and friends, reason being the recent lane-based re-architecture isolated an execution into its own lane that serializes Checkpoint writes that run as CheckpointTask on that same lane, so the read and write cannot overlap.

however, that's wider refactor beyond the scope fo this PR, and since the lock is harmless and for the sake of symmetry might as well let it stand as introduced here and then revisit clean-up opportunities for redundant locks throughout later.

@yaythomas
yaythomas merged commit fa76e76 into aws:main Aug 13, 2026
5 of 10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants