Repository navigation
Dedup retried Nexus signals - #3180
Conversation
Can you expand on this ,, are you saying signal-with-start didn't require a workflow ID before? |
| /** | ||
| * Returns the underlying {@link WorkflowClient} for advanced use cases. | ||
| * | ||
| * <p>Signals sent from the operation handler carry the operation's request ID so a retried Nexus |
There was a problem hiding this comment.
I think it would be better to move this up to the docs on TemporalNexusClient where we talk about sending a signal from a TemporalOperation, also this is quite verbose don't you think?
There was a problem hiding this comment.
Yep, I can move and shorten the comment.
Can you expand on this ,, are you saying signal-with-start didn't require a workflow ID before? |
Before, the workflow ID for Signal-with-Start was derived from sdk-java/temporal-sdk/src/main/java/io/temporal/client/WorkflowStubImpl.java Lines 212 to 218 in de77db8 But since the server only matches request IDs within the same workflow run, we need a consistent workflow ID for deduplication. Python, TypeScript and .NET already require a workflow ID for Signal-with-Start. I added a similar check in Go in temporalio/sdk-go#2781. |
32eb497 to
e5992ee
Compare
e5992ee to
58327e3
Compare
What was changed
TemporalNexusClient.getWorkflowClient()in a@TemporalOperationhandler now reuse the Nexus operation's request ID.BAD_REQUESTerror. Signal-With-Start counts toward the limit; a failed signal doesn't; a retried Nexus task starts with a fresh limit.Nexus.getOperationContext().getWorkflowClient()returns the same client, so signals sent through it from a@TemporalOperationhandler are covered too. Signals from other Nexus handlers (e.g.OperationHandler.sync,WorkflowRunOperation), or from threads other than the handler thread, are unchanged.Why?
When a Nexus task is retried, the handler reruns and sends its signal again with a new random request ID, so the workflow receives it twice. Reusing the operation's request ID lets the server dedupe the retry. However, every signal in one handler run then shares that ID, so a second signal to the same workflow would be silently dropped while reported as delivered. Limiting each run to one signal turns that silent loss into a clear error. Signal-With-Start also requires an explicit workflow ID, since a generated one would differ on each retry and start a second workflow instead of deduping.
Checklist
How was this tested:
Added unit and integration tests.
Any docs updates needed?
No.