Fix concurrent advisory message evaluation (#2519) - #2540
Conversation
Give each advisory send a copied broker connection context with independent message evaluation state. Preserve existing copy semantics and broker permissions, and cover concurrent consumer removal with a deterministic regression test.
cshannon
left a comment
There was a problem hiding this comment.
Thanks for the fix!
This was broken by #2071, which made the change to always use the broker context to send advisories which allowed getting rid of the requirement for all users to have permissions on advisory topics to publish. I had cached the ConnectionContext to avoid having to create a new one for each send but I forgot that the evaluation context is mutable.
It still makes sense to cache the advisory the advisory context because we can configure it how we want (such as flow control false) but now it's just treated as a template and copied each time which makes sense. The context is small (mostly null fields) and we already have to create a new ProducerBrokerExchange for every send, so the impact here will be very minimal and should fix the issue.
I'll merge and backport, assuming the tests are all good.
Concurrent advisory sends share the broker admin context's mutable message evaluation state. When one topic dispatch clears that state while another evaluates a conditional network bridge filter, consumer removal can fail with a null destination and leave cleanup incomplete.
Give each advisory producer exchange a copied connection context with its own
NonCachedMessageEvaluationContext. Add aConnectionContext.copy(MessageEvaluationContext)overload to preserve the existing connection settings and broker permissions; the no-argumentcopy()retains its existing behavior.The regression test pauses one consumer-removal advisory while another completes, then verifies that both removals succeed, both removal advisories arrive, and the destinations have no remaining consumers. It exercises the real conditional network bridge filter and also checks that broker identity and disabled advisory flow control are preserved.
Validation:
mvn -o -B -pl activemq-broker -Dsurefire.enableProcessChecker=ping test: 88 tests passed on JDK 21.AdvisoryBrokerwith the version from upstream commit5d3c979reproduces the reported NPE.NetworkRemovesSubscriptionsTest: all 5 tests passed on JDK 17, compiled from source and run directly with JUnitCore against the broker test classpath.mvn -o -B -pl activemq-broker apache-rat:check: passed.The
pingoption follows the repository's Windows 11 guidance for systems withoutwmic. The full reactor suite and the reporter's three-broker Docker workload were not run.Fixes #2519.