Repository navigation
Add saga management satellite - #7996
Closed
SzymonPobiega wants to merge 3 commits into
Closed
SzymonPobiega wants to merge 3 commits into
SzymonPobiega wants to merge 3 commits into
Conversation
This was referenced Oct 19, 2026
mauroservienti
force-pushed
the
saga-timeout-full-messages
branch
from
October 19, 2026 16:02
5c3bd73 to
46e9722
Compare
mauroservienti
force-pushed
the
saga-timeout-full-messages-satellite
branch
from
October 19, 2026 16:02
e85a4e4 to
7e837ef
Compare
|
|
||
| // Applies timeout changes requested by an operator in ServiceControl. Satellites bypass the message pipeline, | ||
| // so the saga is loaded and saved directly, and the outbox is used the same way TransportReceiveToPhysicalMessageConnector uses it. | ||
| sealed partial class SagaTimeoutManagementSatellite( |
Contributor
There was a problem hiding this comment.
would it be worthwhile having a core concept for "satellites with pipelines"?
Contributor
There was a problem hiding this comment.
I made a spike one day I should be able to find. It is actually not that complicated. The problem is more whether you want to use the normal stages or whether you'd like to introduce specific stages so that user behavior don't automatically get loaded when they are placed into a specific stage but maybe that could also be a "desirable" trait
Updates the callers this branch adds to await FindTimeouts and CancelTimeout.
mauroservienti
added a commit
that referenced
this pull request
Oct 21, 2026
Updates the callers this branch adds to await the timeout management API.
Contributor
|
Closing all intermediate spikes in favor of #8000 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Endpoints can report saga timeout changes to ServiceControl and apply timeout changes that an operator requests in ServicePulse. Reporting is opt-in with
endpointConfiguration.ReportSagaTimeoutsToServiceControl().This builds on
saga-timeout-full-messages. The design across NServiceBus, ServiceControl, and ServicePulse is in docs/saga-timeout-management-design.md in Particular/ServiceControl#6025. The relevant sections are "Endpoint side" and "Rollout and compatibility".Why opt-in
A ServiceControl version without timeout management does not know the report message types. Reports sent to it would fail on the primary instance's input queue and end up in the error queue as failed messages of ServiceControl itself. The feature also needs a persister that implements
ISupportTimeoutManagement; today only the learning persister does.Changes
ReportSagaTimeoutsToServiceControl()enables theReportSagaTimeoutsToPlatformfeature. Without it, the saga pipeline no longer reports timeout changes.Host,HostId, andManagementAddress, the transport address of the management satellite.SagaTimeoutRescheduled,SagaTimeoutCanceled, andSagaTimeoutChangeRejectedcarryOperationIdwhen an operator requested the change.Reasoncan now beTimeoutNotFound,VersionMismatch, orSagaNotFound.SagaCompletedis sent when a saga that had stored timeouts when it was loaded completes. Before, it depended on the timeouts left after the handler ran, so a handler that canceled the last timeout and then completed reported nothing.{endpoint queue}.SagaTimeouts. It appliesRescheduleandCancelrequests carried entirely inNServiceBus.SagaTimeoutManagement.*headers, so the body is never deserialized. A reschedule body, when present, replaces the timeout payload as is. "Trigger now" is a reschedule to the current time.How the satellite applies a request
ExpectedVersionwith the stored timeout.SagaTimeoutChangeRejected.The outbox handling mirrors
TransportReceiveToPhysicalMessageConnector, whose outbox conversion helpers are now internal so the satellite can reuse them. A malformed request moves to the error queue without retries; other failures use the default recoverability policy.Without the outbox, one gap remains. If the saga save commits and the dispatch fails, the retried request is rejected with
VersionMismatch. The change is saved but not reported, and the rescheduled timeout message is lost. ServiceControl then shows the timeout as overdue.Alternatives considered
The first design proposed a
ChangeSagaTimeoutcommand handled in the normal pipeline. A satellite was chosen instead. It does not benefit from the pipeline, and it does not need to: every field of the request travels in headers, and the body is stored as is.Verification
SagaTimeoutManagementSatelliteTestscovers the outbox paths with a fake outbox storage: a new request, a duplicate, and a rejection. No in-repo persister supports both timeout management and the outbox, so there is no end-to-end outbox test.SagaTimeoutManagementRequestTestscovers header parsing.When_operator_changes_saga_timeoutdrives the satellite through the reportedManagementAddress: reschedule with a new payload, a stale cancel rejected withVersionMismatch, and a cancel.When_saga_timeouts_changecovers the opt-in, the new fields, and completion after the last timeout is canceled.🤖 Generated with Claude Code