Repository navigation
Conversation
The XML docs on IAmProducersConfiguration said the interval is ignored when the limit is 0, the ones on ProducersConfiguration said it is ignored for -1 or 0, and both described it as measured since the last insertion into the outbox. A limit of 0 is a real limit, so the interval still applies to it: once a check has counted an outstanding message at least that old, the next add to the outbox throws OutboxLimitReachedException. The interval is the minimum time between background checks, measured from the previous check, and a check starts after messages are cleared from the outbox, which Post does straight after the deposit. It is also the minimum age for a message to count as outstanding, as it is passed to the outbox as dispatchedSince. Correct the docs on both, and on the maxOutStandingCheckInterval parameter of OutboxProducerMediator. What happens with -1 is left to the fix later in this series, which stops the count for it.
Add CountingOutbox, an InMemoryOutbox that counts, thread-safely, how often the mediator asks it for the outstanding message count, and a builder that wires a CommandProcessor around it with an explicit limit and check interval. The two tests are positive controls for skipping the count when there is no limit: with a limit of 100, and with a limit of 0 (a real limit, not "no limit"), posting must still make the mediator count outstanding messages. They pass on the current code. Each was seen to fail under a temporary mutation of CheckOutstandingMessages, never committed: - returning at the top: both tests fail - returning at the top when the limit is <= 0: the limit-0 test fails, the limit-100 test passes
With the default AddProducers settings (MaxOutStandingMessages = -1 and MaxOutStandingCheckInterval = TimeSpan.Zero) CheckOutstandingMessages queued a background count after every Post and Clear, although with no limit the count is never compared with a limit. Each count took the process-wide semaphore and queried the outbox: a sort of every retained entry for the in-memory outbox, a SELECT per Post for a relational one. Return at the top of CheckOutstandingMessages when the limit is -1. Only -1 returns early: 0 is a real limit and still counts, and values below -1 keep their current behaviour. The XML docs for the interval now say that it is ignored for -1, as the outbox is not consulted. The new tests post 20 times through Post and PostAsync with a limit of -1 and an interval of zero and assert that the outbox is never asked for the count. They failed before the fix (20 counts each). A control mediator with a limit gives the background work time to run before the assertion. Part of issue BrighterCommand#4554
Add a note under Master for the change to the outstanding message check when MaxOutStandingMessages is -1, including the span and the debug log lines that change. Part of issue BrighterCommand#4554
guilhermeappel
requested review from
DevJonny,
holytshirt,
iancooper and
preardon
as code owners
October 8, 2026 23:51
iancooper
approved these changes
Oct 9, 2026
Member
|
Thanks @guilhermeappel I'm really excited about this, as across this set of changes, we should be able to address some problems we note at scale |
Member
|
Thanks @guilhermeappel |
7 of 9 tasks
iancooper
pushed a commit
that referenced
this pull request
Oct 10, 2026
The note that PR #4564 added for issue #4554 only covers the case with no limit. Extend it with what changes when a limit is set: each mediator keeps at most one check queued or running, and the time of the last check is recorded when the check is queued. Retitle the entry to match. Also correct the semaphore the checks wait on: the note called it process-wide, but it is a static field of the generic mediator, so it is shared by every mediator with the same message and transaction types. Part of issue #4554
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.
Description
With the default
AddProducerssettings,MaxOutStandingMessagesis -1 (no limit) andMaxOutStandingCheckIntervalis zero, soCheckOutstandingMessagesqueued a background count after every Post and clear even though the count is never compared with a limit. Each count takes the process-wide semaphore and asks the outbox for the count, which for the in-memory outbox sorts every retained entry.CheckOutstandingMessagesnow returns straight away when the limit is -1. Only -1 is skipped, the same valueCheckOutboxOutstandingLimittreats as no limit: 0 is a real limit and still counts, and other negative values behave as before.The XML docs for
MaxOutStandingCheckIntervalsaid it is ignored when the limit is 0, which is a real limit, and described the interval as measured since the last insertion. I corrected them onIAmProducersConfiguration,ProducersConfigurationand themaxOutStandingCheckIntervalparameter ofOutboxProducerMediator.This is the first of the three PRs I described on issue #4554. The next one records the time before queuing the check and keeps at most one check in flight per mediator, and the last one drops the sort and the copy from the in-memory count. Once this is in, I'll bring PR #4552 up to date on top of it.
Related Issues
Part of issue #4554.
Type of Change
Checklist
Additional Notes
CheckOutstandingMessagesthat I didn't commit: returning at the top fails both, and returning when the limit is <= 0 fails the limit-0 one.count.outstanding_messagesspan under the clear operation. With the defaults it no longer appears after this change. I can update the Docs repo once this ships.