-
Notifications
You must be signed in to change notification settings - Fork 6
Description
Problem
The gridappsd-python library currently requires clients to subscribe to topics using exact string matches. This means applications that need to observe a family of related topics —
for example, all simulation outputs (goss.gridappsd.simulation.output.*) or all platform events under a namespace (goss.gridappsd.simulation.>) — must either:
- Subscribe to each specific topic individually, which requires knowing every topic in advance (often impossible when topic segments like simulation IDs are dynamic), or
- Subscribe at a higher level and manually filter in application code.
Neither approach is practical. The underlying ActiveMQ broker already supports wildcard subscriptions via STOMP, but the Python client's CallbackRouter ignores wildcard semantics and
only performs exact dict lookups on the destination, so wildcard-registered callbacks never fire for matching concrete topics.
Proposed Solution
Add client-side wildcard matching to CallbackRouter that follows https://activemq.apache.org/wildcards:
Token: *
Meaning: Matches exactly one dot-separated segment
Example: goss.gridappsd.field.* matches goss.gridappsd.field.sub1 but not goss.gridappsd.field.sub1.sub2
────────────────────────────────────────
Token: >
Meaning: Matches one or more trailing segments (must be last token)
Example: goss.gridappsd.simulation.> matches goss.gridappsd.simulation.output.12345 and goss.gridappsd.simulation.log.99999
Routing behavior:
- Exact match takes priority. If a destination has a direct entry in the callback map, only those callbacks fire — wildcard patterns are not consulted. This preserves backward
compatibility and avoids duplicate invocations. - Wildcard fallback. When no exact match exists, all registered wildcard patterns are checked and all matching callbacks are dispatched.
- Multiple wildcards can match. If two wildcard patterns both match a destination, callbacks from both are invoked.
Use Cases
- Monitor all simulation channels: Subscribe to goss.gridappsd.simulation.> to receive output, input, and log messages for all simulations without knowing simulation IDs ahead of
time. - Field bus wildcard: Subscribe to goss.gridappsd.field.* to receive data from any single field device topic.
- Request routing: Subscribe to goss.gridappsd.process.request.* to observe all incoming request types (simulation, data, config, etc.).
Implementation Notes
- Wildcard patterns are compiled to regex at registration time, so the per-message cost is a regex fullmatch only when the fast-path exact lookup misses.
- add_callback / remove_callback are made thread-safe with a lock to protect the shared wildcard pattern list.
- Wildcard pattern entries are deduplicated — multiple callbacks on the same wildcard topic share a single compiled regex.
- Cleanup on remove_callback: when the last callback for a wildcard topic is removed, the compiled pattern is also removed.
Acceptance Criteria
-
- matches exactly one segment; > matches one or more trailing segments
- Exact-match callbacks are unaffected (no behavior change for existing code)
- Exact match takes priority over wildcard match to avoid duplicate dispatch
- Multiple wildcard patterns can match the same destination
- Thread-safe callback registration and removal
- Wildcard patterns are cleaned up when all callbacks for that topic are removed
- Works with /topic/, /queue/, and /temp-queue/ prefixes
- Unit tests covering all of the above