Split out of #149 (items 2 & 5) — deferred optimizations
Two performance refinements to the subscription primitive, neither blocking.
1. Trait-level filtering (item 2)
Subscribe to specific event types or stream categories (prefix) at the trait level, instead of the consumer skipping unwanted events in its handler.
Note: this is largely subsumed by futures::StreamExt::filter on the existing stream — per CLAUDE.md Rule 6, combinators come from StreamExt, not bespoke trait methods. Trait-level filtering is only worth it as a read-path optimization (skip decode/IO for unwanted events), not as a combinator convenience. Keep low-priority until a real workload shows the consumer-side filter is a bottleneck.
2. Ring-buffer / disruptor-style notification (item 5)
Pre-allocated lock-free ring buffer for sub-microsecond wakeups. The current tokio::sync::watch notification (~1-5μs, now per-stream via StreamNotifiers, #176) is sufficient; revisit only if profiling shows notification latency dominates.
Depends on #125.
Split out of #149 (items 2 & 5) — deferred optimizations
Two performance refinements to the subscription primitive, neither blocking.
1. Trait-level filtering (item 2)
Subscribe to specific event types or stream categories (prefix) at the trait level, instead of the consumer skipping unwanted events in its handler.
Note: this is largely subsumed by
futures::StreamExt::filteron the existing stream — per CLAUDE.md Rule 6, combinators come fromStreamExt, not bespoke trait methods. Trait-level filtering is only worth it as a read-path optimization (skip decode/IO for unwanted events), not as a combinator convenience. Keep low-priority until a real workload shows the consumer-side filter is a bottleneck.2. Ring-buffer / disruptor-style notification (item 5)
Pre-allocated lock-free ring buffer for sub-microsecond wakeups. The current
tokio::sync::watchnotification (~1-5μs, now per-stream via StreamNotifiers, #176) is sufficient; revisit only if profiling shows notification latency dominates.Depends on #125.