Interface McpSubscriptionBroker
- All Superinterfaces:
McpSubscriptions
- All Known Implementing Classes:
BasicMcpSubscriptionBroker
subscriptions/listen.
Extends McpSubscriptions (the publish half) and adds registration/lifecycle: a v2 dispatch branch
calls registerIfUnder(int, String, McpSubscriptionFilter) once per accepted
subscriptions/listen request. Close (graceful or abrupt) does not flow back through this
interface: the returned McpSubscription.close() instead runs a close-callback wired at
registration time, which removes the entry directly from the registry the returned handle's key was
minted under. unregister(String) is a registry-completeness API for that same by-id removal —
it has no current production caller, since the close-callback path never has to look the id back up.
Application handlers reach this same instance only through the narrower McpSubscriptions view.
Plain register(String, McpSubscriptionFilter) is uncapped — it never rejects, so a caller wanting
an enforced maxConcurrentSubscriptions ceiling must use registerIfUnder(int, String, McpSubscriptionFilter) instead, which admission-checks and mutates the registry as one atomic step. A
separate "check activeCount(), then call register" pair is exactly the TOCTOU race this
capped variant exists to close: two concurrent callers can both observe a count under the cap and both
register before either mutation is visible to the other.
-
Method Summary
Modifier and TypeMethodDescriptionintThe number of currently registered (not yet closed) subscriptions.default voidcloseAll()Closes every currently registered subscription.register(String subscriptionId, McpSubscriptionFilter honoredFilter) Registers a new subscription and returns its queue handle.registerIfUnder(int max, String subscriptionId, McpSubscriptionFilter honoredFilter) Atomically admission-checks againstmaxand registers, closing the TOCTOU window a separateactiveCount()check plusregister(java.lang.String, org.apache.juneau.rest.server.mcp.McpSubscriptionFilter)call would leave open under concurrent callers (in particular against a JVM-wide shared broker instance, where unrelated callers race each other).voidunregister(String subscriptionId) Deregisters and closes the subscription with the given id, if present.Methods inherited from interface org.apache.juneau.rest.server.mcp.McpSubscriptions
promptsListChanged, resourcesListChanged, resourceUpdated, toolsListChanged
-
Method Details
-
register
Registers a new subscription and returns its queue handle. Uncapped: never rejects.- Parameters:
subscriptionId- The subscription identifier (the listen request's JSON-RPC id). Must not benullor empty.honoredFilter- The capability-gated filter this subscription honors. Must not benull.- Returns:
- The new subscription handle. Never
null.
-
registerIfUnder
Optional<McpSubscription> registerIfUnder(int max, String subscriptionId, McpSubscriptionFilter honoredFilter) Atomically admission-checks againstmaxand registers, closing the TOCTOU window a separateactiveCount()check plusregister(java.lang.String, org.apache.juneau.rest.server.mcp.McpSubscriptionFilter)call would leave open under concurrent callers (in particular against a JVM-wide shared broker instance, where unrelated callers race each other).Re-registering an id that is already present is always allowed and never counted against
max, matchingregister(java.lang.String, org.apache.juneau.rest.server.mcp.McpSubscriptionFilter)'s replace-on-same-id semantics (the previous subscription with that id is closed) — a replacement does not growactiveCount(), so it cannot be what pushes the registry over the cap.- Parameters:
max- The maximum number of concurrently active subscriptions to admit under (exclusive: a request is admitted only whileactiveCount()is strictly less than this, except for the same-id replacement case above).subscriptionId- The subscription identifier (the listen request's JSON-RPC id). Must not benullor empty.honoredFilter- The capability-gated filter this subscription honors. Must not benull.- Returns:
- The new subscription handle, or
Optional.empty()if the cap was reached and this was not a same-id replacement.
-
unregister
Deregisters and closes the subscription with the given id, if present.- Parameters:
subscriptionId- The subscription identifier. A missing id is a no-op.
-
activeCount
int activeCount()The number of currently registered (not yet closed) subscriptions.- Returns:
- The active count.
-
closeAll
Closes every currently registered subscription.Called when the server begins shutting down, so open
subscriptions/listenstreams complete promptly instead of holding the graceful drain open until its stop timeout. The default implementation does nothing, so custom brokers that predate this method keep working (their streams then end on the normal heartbeat/idle-timeout paths).
-