Skip to content

Propagate backlinks on Signal and Signal-with-Start responses#9897

Open
long-nt-tran wants to merge 1 commit intotemporalio:mainfrom
long-nt-tran:signals-updates-backlink
Open

Propagate backlinks on Signal and Signal-with-Start responses#9897
long-nt-tran wants to merge 1 commit intotemporalio:mainfrom
long-nt-tran:signals-updates-backlink

Conversation

@long-nt-tran
Copy link
Copy Markdown
Contributor

@long-nt-tran long-nt-tran commented Apr 9, 2026

What changed?

With these PRs to add the linking on the Signal and Signal-with-Start responses, This PR adds logic from the server that:

  • Attaches requestID from Signal and Signal-with-Start requests to the mutable state + event store so these requestIDs stay in buffer
  • Return a backlink in the response that references the requestID
  • On buffer flush to the DB transaction, attach these requestID to a concrete eventID, which would allow users to later know which event correlated w/ this request

In functional tests, I augmented existing tests for Signal and Signal-with-Start to:

  • Ensure that backlink is returned via the responses
  • Later use DescribeWorkflow to ensure that we get a concrete EventID (mapped when buffer flushed)
  • Multiple signals with the same requestID gets de-dupped

Note

Doing it this way from discussion w/ @Quinn-With-Two-Ns since signals are buffered and we will not have a concrete event ID.

Why?

This will enable the caller of the signal to have a backlink to the cross-namespace signal invoked, which will become more relevant for Nexus SDK ergonomics.

How did you test it?

  • built
  • run locally and tested manually
  • covered by existing tests
  • added new unit test(s)
  • added new functional test(s)

Functional tests

$ go test ./tests/ -run TestLinksTestSuite
ok      go.temporal.io/server/tests     1.486s
$ go test ./tests/ -run 'TestNexusWorkflowTestSuite' -count=1
ok      go.temporal.io/server/tests     4.714s

Potential risks

Need to test end-to-end to see that the link shows up correctly in the Web UI.

@long-nt-tran long-nt-tran force-pushed the signals-updates-backlink branch 3 times, most recently from 589224e to 4c69cc2 Compare April 10, 2026 16:22
go.mod Outdated
Comment on lines +219 to +220

replace go.temporal.io/api => github.com/long-nt-tran/api-go v0.0.0-20260410154440-a741268f8bab
Copy link
Copy Markdown
Contributor Author

@long-nt-tran long-nt-tran Apr 10, 2026

Choose a reason for hiding this comment

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

only pointing to my fork for CI tests, will wait for temporalio/api#761 and subsequent api-go codegen to be merged and then remove these before I merge this PR

@long-nt-tran long-nt-tran marked this pull request as ready for review April 10, 2026 16:48
@long-nt-tran long-nt-tran requested review from a team as code owners April 10, 2026 16:48
Copy link
Copy Markdown
Member

@bergundy bergundy left a comment

Choose a reason for hiding this comment

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

Here's what's missing:

  • Adding to the map that tracks request ID to event ID
  • A functional test that verifies that request IDs for all of these requests are added to the map
  • Ensure that the workflow start link is only populated if an execution was started

@long-nt-tran long-nt-tran force-pushed the signals-updates-backlink branch 4 times, most recently from 984be28 to 51b9594 Compare April 13, 2026 19:10
@long-nt-tran long-nt-tran force-pushed the signals-updates-backlink branch from 51b9594 to 52c0da3 Compare April 13, 2026 20:21
modernc.org/memory v1.11.0 // indirect
)

replace go.temporal.io/api => github.com/long-nt-tran/api-go v0.0.0-20260413175257-fd07f9923cd0
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

temp, will delete once api PR temporalio/api#761 merges

@long-nt-tran
Copy link
Copy Markdown
Contributor Author

Addressed feedback, I think the cleanest way to have the requestID be in the mutable state is to have it on the event is to have it be a new field in WorkflowExecutionSignaledEventAttributes, so I did need to add this field to the api PR. Let me know if there are other preferable alternatives -- I saw some other events also do the same thing of having requestID be part of the attributes so followed that pattern.

Also put all testing at functional test level so we can end-to-end assert on request ID presence + concrete event ID resolution -- edited summary to reflect this.

cc @bergundy @Quinn-With-Two-Ns

@long-nt-tran long-nt-tran requested a review from bergundy April 13, 2026 20:48
@bergundy
Copy link
Copy Markdown
Member

Addressed feedback, I think the cleanest way to have the requestID be in the mutable state is to have it on the event is to have it be a new field in WorkflowExecutionSignaledEventAttributes, so I did need to add this field to the api PR. Let me know if there are other preferable alternatives -- I saw some other events also do the same thing of having requestID be part of the attributes so followed that pattern.

Also put all testing at functional test level so we can end-to-end assert on request ID presence + concrete event ID resolution -- edited summary to reflect this.

cc @bergundy @Quinn-With-Two-Ns

That makes sense to me because the signal could be cherry picked into a new history branch on conflict resolution and reset and you'll want to carry over the same request ID when that happens.

},
},
},
Link: api.GenerateStartedEventRefLink("", wfKey.WorkflowID, wfKey.RunID),
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Namespace is empty here. Looks like the bug was pre-existing.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

yeah i noticed that too but wasn't sure if it was expected, was planning to look into it later to not change too much, but probably ok to opportunistically fix here

Comment on lines +5674 to +5676
if requestID != "" {
ms.AttachRequestID(requestID, enumspb.EVENT_TYPE_WORKFLOW_EXECUTION_SIGNALED, common.BufferedEventID)
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not quite seeing the value of attaching the buffered event ID here. It's supposed to be a temporary ID.
Also not quite sure how the request ID mapping works with signal-with-start where the same request ID maps to two history events. We shouldn't override the request ID of the WorkflowExecutionStarted event.

I think we may need to extend the proto to allow a single request ID to reference two separate events.

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