fix(flow): follow kafka topics + rename --max-hops to --depth#396
Merged
Conversation
_resolve_route_candidates matched only on path/path_template, so kafka_topic Routes (name in `topic`, `path=''`) were unresolvable by name. `jrag flow <topic>` / `callers <topic>` / `overview <topic>` returned 'none' even though the route + EXPOSES edge existed, while trace_request_flow already supported kafka end-to-end (async inbound via ASYNC_CALLS/topic + outbound via EXPOSES). Add r.topic exact + prefix queries mirroring _resolve_producer_candidates (new route_topic / route_topic_prefix reasons). _drop_route_mirrors already collapses the no-EXPOSES producer phantom onto the @KafkaListener server route (kafka fqn='' groups them), so a producer+consumer topic resolves to the single server route. Co-Authored-By: Claude <noreply@anthropic.com>
Rename flow's hop-count flag to --depth so it matches callers/callees/ impact/decompose. --max-hops is kept as a hidden back-compat alias (argparse.SUPPRESS, same dest=depth). The query positional now also accepts a Kafka topic name, made reachable by the resolver fix. Co-Authored-By: Claude <noreply@anthropic.com>
…iguation Address code-review feedback (test-coverage gaps; no behavior change): - test_flow_follows_kafka_topic_on_fixture now uses banking.chat.incoming (producer + listener) and asserts a non-empty follow graph WITH an ASYNC_CALLS edge — the previous compliance.review target has an empty listener body, so it only proved resolution, not that flow follows kafka. - test_flow_depth_flag_and_max_hops_alias now also asserts --depth 1 yields strictly fewer edges than --depth 5 (proves the flag affects traversal, not just parses). - New test_callers_topic_disambiguates_with_kind: documents that a dual-sided topic (producer + route) resolves ambiguously without --kind, and that --kind route is the working disambiguation for callers (callers rejects a producer root; use the `producers` command for that view). Co-Authored-By: Claude <noreply@anthropic.com>
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.
Problem
Consumer report:
jrag flow(1) does not follow kafka even when the route exists, and (2) has no--depthflag.Root cause
Kafka:
_resolve_route_candidatesmatched only onpath/path_template, butkafka_topicRoutes carry their name intopic(withpath=""). Sojrag flow <topic>died at the resolve step (status=none) before reachingtrace_request_flow— even though the backend already supported kafka (async inbound viaASYNC_CALLS/topic + outbound viaEXPOSES). Asymmetric with_resolve_producer_candidates, which already matchesp.topic.--depth:flowexposed--max-hopswhile every sibling traversal (callers/callees/impact/decompose) uses--depth, sojrag flow '/x' --depth 3errored with "unrecognized arguments".Changes
Commit 1 —
fix(resolve)route_topic+route_topic_prefixtoResolveReason/VALID_RESOLVE_REASONS(java_ontology.py).r.topicexact + prefix queries to_resolve_route_candidates, mirroring the producer resolver (resolve_service.py)._drop_route_mirrorsalready collapses the no-EXPOSES producer phantom onto the@KafkaListenerserver route (kafkafqn=''groups them).Commit 2 —
feat(flow)--max-hops→--depth(dest=depth, default 5); keep--max-hopsas a hidden back-compat alias. Thequerypositional now also accepts a Kafka topic name.Commit 3 —
test(flow)(review follow-up)The Python API param
trace_request_flow(..., max_hops=...)is intentionally left as-is — internal kwarg, not a user-facing flag.Scope of the resolver fix
The resolver is shared, so the fix reaches beyond
flow:flow <topic>— fully works (inbound producers + outbound CALLS). ✅callers <topic>— works via--kind route. Behavior change: a topic with both a Producer and a server Route is now genuinely ambiguous without--kind(previously only the Producer matched, which then errored becausecallersonly accepts Symbol/Route roots).--kind routeis the disambiguation that runsfind_route_callers.overview <topic>— onlyoverview --as route <topic>benefits; the bare form auto-detects the subject as a topic and routes to the topic view, not the route resolver.Tests (6 total)
test_resolve_service_route_kafka_topic— consumer-only topic resolves to one Route (wasnonebefore the fix).test_resolve_service_route_kafka_topic_drops_producer_mirror— producer+consumer topic collapses to the single server Route.test_resolve_every_reason_in_closed_set_appears— extended with a kafka row +r.topicmock branches.test_flow_follows_kafka_topic_on_fixture—jrag flow <topic>end-to-end; asserts a non-empty follow graph with a kafka-specificASYNC_CALLSedge (proves following, not just resolution).test_flow_depth_flag_and_max_hops_alias—--depthworks,--max-hopsalias preserved, and--depthactually changes traversal size (depth 1 ≪ depth 5).test_callers_topic_disambiguates_with_kind— documents the dual-sided-topic ambiguity +--kind routerecovery.Verification
ruff: changed files clean (one pre-existingF821atjrag.py:1644is unrelated and present onmaster).Known limitations / follow-ups (out of scope here)
_drop_route_mirrorsgroups routes byfqn, which is""for every kafka topic. Verified correct for all realizable cases (phantoms are dead-end artifacts that should be dropped; exposed server routes for distinct topics both survive since both carry EXPOSES; Producers are untouched). A future non-kafka route kind with empty method+path could mis-group — hardening the grouping key is a cheap follow-up if such a kind is ever added.producer_topic_prefix=1 butproducer_topic=3 — exact ranks below prefix) is a separate latent bug on the producer side; not introduced or touched here. Worth its own ticket.🤖 Generated with Claude Code