Skip to content

fix(insight): schedule on-change exports - #699

Closed
wangyb-A wants to merge 1 commit into
mainfrom
workflow-insight-on-change-scheduler
Closed

fix(insight): schedule on-change exports#699
wangyb-A wants to merge 1 commit into
mainfrom
workflow-insight-on-change-scheduler

Conversation

@wangyb-A

@wangyb-A wangyb-A commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

Issue Link, if available

Related to #679.

Addresses #661 (comment).

Description

ON_CHANGE previously performed exporter I/O and flush() synchronously from checkpoint callbacks. Slow S3 or CloudWatch calls could delay checkpoint coordination, and a delayed RUNNING write could finish after the terminal S3 write.

This PR moves ON_CHANGE delivery to an invocation-scoped bounded FIFO. The queue preserves normal bursts, drops the oldest waiting RUNNING snapshot only after reaching its depth of 16, reserves the invocation-final record, and rejects late updates after sealing. onInvocationEnd() drains the ordered queue and flushes each exporter once before Lambda can freeze.

The implementation deliberately avoids the unconditional latest-slot coalescing pattern identified in aws/aws-durable-execution-sdk-python#702 (comment). A deterministic no-delay test verifies that eleven RUNNING snapshots plus one final snapshot all arrive.

Demo/Screenshots

Not applicable. This is backend scheduling and lifecycle behavior with no UI changes.

Checklist

  • I have filled out every section of the PR template
  • I have thoroughly tested this change

Testing

  • git diff --check
  • mvn -B -q spotless:check --file pom.xml
  • mvn -q -pl insight-plugin -am clean verify
  • mvn -q clean verify
  • Repeated ExportSchedulerTest and WorkflowInsightHookTest runs to check deterministic ordering

Unit Tests

Yes. ExportSchedulerTest covers no-delay burst preservation, bounded oldest-drop behavior, final-record retention, late-update rejection, idle-worker restart, exporter failure isolation, flush ordering, and transient executor rejection recovery.

Integration Tests

Yes. WorkflowInsightHookTest drives the real plugin hooks and verifies that blocked exporter I/O does not block onOperationChange(), invocation end waits for ordered draining, normal bursts are preserved, the terminal record is last, and exporters flush once.

The complete insight-plugin reactor and full Maven reactor pass.

Examples

No example change is needed. The public Workflow Insight configuration API is unchanged.

Move exporter I/O off checkpoint callbacks through a bounded per-invocation FIFO. Preserve normal bursts, drop oldest waiting snapshots only under backpressure, and drain the final record plus one flush barrier at invocation end.
@wangyb-A

wangyb-A commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

/ai review

if (queue.size() == capacity) {
queue.removeFirst();
}
queue.addLast(record);

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 · Finding arf_v1_zd7gncmrres5u3dmq4nazbmvno

[P2] Freeze each record before placing it on the asynchronous queue. Records can contain live mutable values, notably executionResult or objects returned by content/result transforms, while deepCopy() currently occurs only when the worker eventually exports them. Under backpressure, later mutation can therefore change an earlier snapshot and make Workflow Insight disagree with the already-serialized durable result. Deep-copy or otherwise detach mutable record content during enqueue, and add a test that mutates content before a delayed worker runs.

Comment on lines +97 to +98
queue.clear();
drained.complete(null);

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 · Finding arf_v1_yk6awyvhew5xhws3cqn4dgeagn

[P2] Do not report a sealed queue as drained when worker submission fails. If the worker went idle and sealAndDrain() encounters a rejection or thread-creation failure, this branch discards the reserved final record and every queued update, skips exporter flushing, and lets onInvocationEnd() return successfully. Preserve the queue and synchronously drain it at the invocation boundary, or retry submission while leaving drained incomplete; cover rejection specifically on the final submission.

@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Codex AI review

Found two correctness issues in the new ON_CHANGE scheduler. Review was read-only; tests were not executed.

Reviewed commit fce38360ca359997d6a91cb11116c4008ee0e1ad. 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.

1 participant