Client: match subscriptions by context, not path only - #273
Open
t0susnik wants to merge 1 commit into
Open
Conversation
t0susnik
marked this pull request as draft
July 28, 2026 22:48
Add SubscriptionMatcher.pathAndContext() to select path-and-context matching without naming Filter classes, and use it in OpenCmwDataSource. Notifications are attributed to a subscription by the context keys whose Filter is registered in FilterRegistry; keys without one are ignored. Selecting context matching previously required passing Filter classes to the constructor, which also registers them globally. A client that registers its filters elsewhere had no way to enable it, so OpenCmwDataSource compared the URI path only and could not tell apart concurrent subscriptions that differ only by their query.
t0susnik
force-pushed
the
fix/client-demultiplex-subscriptions-by-channel-name
branch
from
July 29, 2026 07:41
f187a9d to
7482d69
Compare
t0susnik
marked this pull request as ready for review
July 29, 2026 08:02
Author
|
@RalphSteinhagen - flagging this for whenever you are back, no urgency. Fixes #272: a There is a design question in the description about the varargs constructor conflating mode selection |
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.
Fixes #272
SubscriptionMatchercan compare path and context, but the only way to select that mode was to passFilterclasses to its constructor, which also registers them globally. A client that registers itsfilters elsewhere could not enable it, so
OpenCmwDataSourcecompared the URI path only and couldnot tell apart concurrent subscriptions that differ only by their query.
This adds
SubscriptionMatcher.pathAndContext()and uses it inOpenCmwDataSource. Nothingdomain-specific enters
io.opencmw: the matcher discriminates on whichever context keys have aFilterregistered inFilterRegistry, and whoever owns a key registers it. On its own this changeis a no-op for a client that registers nothing. On our side a filter for
channelNameFilterisregistered one layer up, which is what actually separates the subscriptions; the same approach covers
a second key we need without any further change here.
Behaviour change
Any query key present in the subscriber URI and registered in the global
FilterRegistryis nowenforced when matching notifications; unregistered keys are still ignored. Because the registry is
global, filters registered elsewhere in the same JVM (e.g.
TimingCtxviaDataSourcePublisher.checkClassForNewFilters()) are enforced too. That is the documented behaviourof
testPathAndContext, but it is new for this call site.Note this is permanent for the process: there is no unregister, and nothing in
coreorclientcalls
FilterRegistry.clear(), so once a key is registered every context-mode matcher in the JVMenforces it for the rest of the run. Registration itself is idempotent -
registerNewFilterreturnsearly if all the classes are already known - so repeated calls are harmless. Two different
Filterimplementations claiming the same key would silently collide though: both land in the class map, but
the key map keeps only the last registered, so the winner depends on class-initialisation order.
An observation on the constructor
SubscriptionMatcher(Class<? extends Filter>...)conflates two independent concerns: it selects thematching mode and registers filters, with the mode derived from the argument count. It also does
not retain
filterConfig- the only field isisPathOnly- so two matchers built with differentfilter arguments behave identically, because matching consults the global registry. The argument list
therefore reads as if it scoped the matcher when it does not, and "context matching, with filters
registered elsewhere" is inexpressible, which is what this PR works around.
If you would rather make the mode explicit and deprecate the varargs form, say so and I will redo it
that way. I left it untouched because it is published API with tests against it, and reshaping it
does not belong in a bug fix.
Verification
Two concurrent subscriptions differing only by one context key against a C++ OpenCMW worker now
receive independent, correctly attributed streams for the full run; without the change one stops
receiving the instant the second registers.
SubscriptionMatcherTestcovers the new factory with afilter registered via
FilterRegistryrather than passed to the constructor.