Skip to content

feat: add should_complete to CompletionConfig - #605

Draft
ayushiahjolia wants to merge 1 commit into
mainfrom
feat/custom-completion-predicate
Draft

feat: add should_complete to CompletionConfig#605
ayushiahjolia wants to merge 1 commit into
mainfrom
feat/custom-completion-predicate

Conversation

@ayushiahjolia

@ayushiahjolia ayushiahjolia commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Issue #, if available: #519

Description of changes:
Adds a should_complete predicate to CompletionConfig for map and parallel operations, giving full control over when a batch completes early.

from aws_durable_execution_sdk_python import complete_batch, continue_batch

config = CompletionConfig(
    should_complete=lambda status: (
        complete_batch() if status.success_count >= 2
        else continue_batch()
    )
)

The predicate receives a CompletionStatus snapshot (counts + per-item statuses) and returns a CompletionDecision - either continue_batch() or complete_batch(outcome). The outcome determines whether CUSTOM_COMPLETION_SUCCEEDED or CUSTOM_COMPLETION_FAILED is reported.

Key design decisions -

  • Cannot be combined with threshold fields (raises ValidationError)
  • Predicate must be deterministic and side-effect-free
  • Replay uses the checkpointed decision, never re-invokes the predicate
  • On resumed invocations, deferred until prior checkpoints replay

Testing -

  • Unit tests, integration tests and examples

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

@ayushiahjolia
ayushiahjolia force-pushed the feat/custom-completion-predicate branch from 862e017 to c72785b Compare July 31, 2026 05:22
@ayushiahjolia ayushiahjolia changed the title feat: custom completion predicate feat: add should_complete to CompletionConfig Jul 31, 2026
@ayushiahjolia
ayushiahjolia temporarily deployed to ai-pr-review-runtime July 31, 2026 05:36 — with GitHub Actions Inactive
@ayushiahjolia
ayushiahjolia temporarily deployed to ai-pr-review-runtime July 31, 2026 05:36 — with GitHub Actions Inactive
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@ayushiahjolia
ayushiahjolia force-pushed the feat/custom-completion-predicate branch from c72785b to 306c81c Compare July 31, 2026 19:22
@ayushiahjolia
ayushiahjolia had a problem deploying to ai-pr-review-runtime July 31, 2026 19:39 — with GitHub Actions Failure
@ayushiahjolia
ayushiahjolia had a problem deploying to ai-pr-review-runtime July 31, 2026 19:39 — with GitHub Actions Failure
@ayushiahjolia
ayushiahjolia force-pushed the feat/custom-completion-predicate branch from 306c81c to 5483a62 Compare July 31, 2026 19:44
@ayushiahjolia
ayushiahjolia temporarily deployed to ai-pr-review-runtime July 31, 2026 20:13 — with GitHub Actions Inactive
@ayushiahjolia
ayushiahjolia temporarily deployed to ai-pr-review-runtime July 31, 2026 20:13 — with GitHub Actions Inactive
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@ayushiahjolia
ayushiahjolia force-pushed the feat/custom-completion-predicate branch from 5483a62 to fffee6d Compare July 31, 2026 21:17
@ayushiahjolia
ayushiahjolia temporarily deployed to ai-pr-review-runtime July 31, 2026 21:18 — with GitHub Actions Inactive
@ayushiahjolia
ayushiahjolia temporarily deployed to ai-pr-review-runtime July 31, 2026 21:18 — with GitHub Actions Inactive
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@ayushiahjolia
ayushiahjolia force-pushed the feat/custom-completion-predicate branch from fffee6d to 7ad4242 Compare July 31, 2026 21:55
@ayushiahjolia
ayushiahjolia force-pushed the feat/custom-completion-predicate branch from 7ad4242 to 302330d Compare July 31, 2026 21:56
@ayushiahjolia
ayushiahjolia force-pushed the feat/custom-completion-predicate branch 2 times, most recently from 05ea8fa to 84b7cb7 Compare August 13, 2026 03:46
@ayushiahjolia
ayushiahjolia temporarily deployed to ai-pr-review-runtime August 13, 2026 05:21 — with GitHub Actions Inactive
@github-actions

This comment has been minimized.

@ayushiahjolia
ayushiahjolia force-pushed the feat/custom-completion-predicate branch from 84b7cb7 to de4ef87 Compare August 13, 2026 15:20
@ayushiahjolia
ayushiahjolia temporarily deployed to ai-pr-review-runtime August 13, 2026 15:23 — with GitHub Actions Inactive
@github-actions

This comment has been minimized.

@ayushiahjolia
ayushiahjolia force-pushed the feat/custom-completion-predicate branch from de4ef87 to 28943d5 Compare August 13, 2026 20:48
@ayushiahjolia
ayushiahjolia force-pushed the feat/custom-completion-predicate branch from 28943d5 to 2480b1e Compare August 13, 2026 22:34
@ayushiahjolia
ayushiahjolia temporarily deployed to ai-pr-review-runtime August 13, 2026 22:39 — with GitHub Actions Inactive
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

succeeded,
failed,
items_snapshot,
restored_events_seen >= len(restored_terminal_indexes),

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

[P1] Block new work while restoring terminal events. The restoration gate only suppresses predicate evaluation; scheduling remains enabled. With two restored terminal branches and max_concurrency=2, the first replayed event frees a slot and causes a previously unstarted third branch to execute before the second event opens the gate. This can introduce new durable side effects during replay. Track previously existing branches and admit only those until restoration and predicate evaluation are complete.

Comment on lines +253 to +267
# Defer predicate evaluation until all previously-checkpointed
# terminal branches have reported again, ensuring deterministic
# decisions regardless of replayed event order.
restored_terminal_indexes: set[int] = set()
if self.policy.should_complete is not None:
for exe in self.executables:
op_id: str = self.operation_id_namespace.create_id_for_step(
exe.index
)
cp: CheckpointedResult = execution_state.get_checkpoint_result(
op_id
)
if cp.is_succeeded() or cp.is_failed():
restored_terminal_indexes.add(exe.index)
restored_events_seen: int = 0

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

[P1] Persist the custom completion decision itself. Re-evaluating only after all terminal child checkpoints replay does not reproduce the status that originally triggered the decision. For example, a deterministic predicate that completes when success_count == 1 can fire live while a second branch has already checkpointed; if the invocation dies before the parent checkpoint, resume evaluates at two successes and continues with a different result. Synchronously checkpoint the decision/outcome when it fires, or explicitly restrict and validate predicates to monotonic decisions with stable outcomes.

@github-actions

Copy link
Copy Markdown
Contributor

Codex AI review

Two replay-safety issues can change execution after a crash. Existing resume tests do not cover the decision-to-parent-checkpoint race window.

Reviewed commit 87a2c4a2faef5ca7c2b1e84ec132615a978dcb46. Workflow run

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants