wy471x commented on PR #6906:
URL: https://github.com/apache/shenyu/pull/6906#issuecomment-5295559755

   > ## Review: #6906 — feat: implement MQTT wildcard subscription matching
   > **Verdict: ✅ Approve (with two follow-up suggestions, one a real 
correctness edge case)**
   > 
   > This fills a genuinely broken feature — wildcard subscriptions silently 
never matched because `Publish.send` did an exact `Map.get`. The fix is 
well-structured.
   > 
   > ### What's correct
   > * **`TopicMatcher` is spec-accurate.** I traced the algorithm across the 
test matrix and beyond:
   >   
   >   * `+` matches exactly one level (`sport/+/player1` ❌ 
`sport/tennis/stadium/player1`, ✓ `sport/football/player1`);
   >   * `#` matches any number of levels incl. the parent (`sport/#` ✓ 
`sport`);
   >   * `#` only matches when it's its own level (`sport#` / `sport/tennis#` 
correctly rejected);
   >   * `$`-prefixed topics are not matched by a _leading_ wildcard (`#`/`+` → 
false) but are matched by explicit `$SYS/#` / `$SYS/+` — exactly MQTT-4.7.2-1;
   >   * null inputs return false (no NPE).
   > * **The `get()` exact-lookup method is retained and still used** by 
`add()`/`remove()` internally, so this isn't introducing dead code — good call 
keeping it.
   > * **`getChannelsByTopic`** is a clean O(N) scan that delegates entirely to 
`TopicMatcher`; no logic duplicated.
   > * **`TopicMatcherTest` is thorough** — exact, single-level, multi-level, 
mixed, `$`-topic, and null cases all covered.
   > 
   > ### Suggestions (non-blocking)
   > 1. **Duplicate delivery on overlapping subscriptions (real, please track 
as a follow-up).** `getChannelsByTopic` does `result.addAll(entry.getValue())` 
over every matching filter. If one client holds two overlapping subscriptions 
(e.g. `sport/#` _and_ `#`), it appears under both keys, so a publish to 
`sport/x` adds the same `Channel` twice → the client receives the message 
twice. MQTT requires at most one delivery per publish per client. Collect into 
a `Set<Channel>` (or `LinkedHashSet` if you care about order/stability) before 
returning to avoid this.
   > 2. **Performance fast-path.** Every publish now scans _all_ subscriptions. 
For the very common case where the topic has an exact (non-wildcard) 
subscriber, you could `result.addAll(get(topic))` first (O(1) exact hit) and 
then only scan filters containing `+`/`#`. Not necessary for correctness, just 
a scale consideration.
   > 3. **Minor:** invalid filters (e.g. `#` not as its own level, or trailing 
text after `#`) silently return `false` here. Optionally reject malformed 
filters at subscription time in `Subscribe.add` so bad subscriptions fail fast 
instead of silently never matching.
   > 
   > ### Verdict
   > Approving. The core matching logic is correct and well-tested, and `get()` 
is correctly preserved. Suggestion #1 (dedupe) is worth a quick follow-up PR 
before wildcard support sees production traffic with multi-subscription clients.
   
   Thank you for the code review on this PR.
   
   Fixes for the three review comments:                                         
                                                  
                                                                                
                                                                                
                        
     1. Duplicate delivery on overlapping subscriptions — 
SubscribeRepository.getChannelsByTopic now collects channels into a 
LinkedHashSet before returning, so a client holding       
     overlapping filters (e.g. sport/# and #) receives at most one delivery per 
publish, per MQTT spec.
     2. Performance fast-path — exact topic subscribers are added via an O(1) 
map lookup first; the wildcard scan then skips filters without +/#.             
                          
     3. Malformed filters fail fast — added TopicMatcher.isValidFilter 
(MQTT-4.7.1 rules); Subscribe registers only valid filters and sends SUBACK 
return code 0x80 (FAILURE) for       
     invalid ones.                                                              
                                                                                
                        
                                                                                
                                                                                
                        
   Tests added: TopicMatcherTest validation cases, new SubscribeRepositoryTest 
(dedup/fast-path), new SubscribeTest (rejection + SUBACK codes). 


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to