feat: RoutingIndex -- metric-bucketed Tier-2 structural match - #435
Merged
Merged
Conversation
Implements the Tier-2 half of control_plane/docs/design-backend-plan-wire-format.md (#433) §4's RoutingIndex, sourced from PolicyRegistry (StreamingConfig's content-addressed view -- genuinely "what control_plane planned" today, not reconstructed from ingest side effects) rather than the not-yet-built BackendPlan wire format. Tier 1 (exact PolicyFingerprint lookup) is already PolicyRegistry::get, unchanged. find_matching_policies (control_plane::asap_tier_analysis) used to scan every policy in the registry for every candidate, checking each one's metric name first -- paying for every OTHER metric's policies on every lookup. RoutingIndex buckets by metric once at construction, so a lookup only touches policies for the relevant metric. Same match predicate, same observable behavior (verified: all ~18 existing find_matching_policies tests pass unchanged, only their PolicyRegistry construction is now wrapped in RoutingIndex::build). engine.rs's two candidate-resolution loops (range-query, instant-query) now build a RoutingIndex once per query snapshot instead of a raw PolicyRegistry, matching the design doc's stated caller pattern. Building RoutingIndex once per StreamingConfig hot-reload swap instead of once per query (StreamingConfig::policy_registry's own doc comment already flags this as a further, larger optimization "if it shows up in profiles") is not done here -- would require threading a cached derived value through HotReloadStreamingConfig's swap path, a separate, larger change. Co-Authored-By: Claude Sonnet 5 <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.
Summary
Implements the Tier-2 half of
control_plane/docs/design-backend-plan-wire-format.md(#433) §4'sRoutingIndex-- items #2/#3 from that design (structural index + wiring it into the live serving path), scoped to run in parallel with #434 (theBackendPlanwire types, #1), which it has no code dependency on.Sourced from
PolicyRegistry(StreamingConfig's content-addressed view) rather than the not-yet-builtBackendPlanmessage --PolicyRegistryis already genuinely "whatcontrol_planeplanned" (pushed viaStreamingConfig), not something reconstructed from ingest-time side effects, so this is a faithful (if not yet wire-format-complete) implementation of the design's intent, not a stand-in for it.PolicyFingerprintlookup) is alreadyPolicyRegistry::get-- O(1), untouched.RoutingIndexbuckets policies by metric at construction time.find_matching_policies(control_plane::asap_tier_analysis) used to scan every policy in the registry for every candidate, checking each one's metric name first -- paying for every other metric's policies on every lookup. It now only touches the bucket for the candidate's own metric.engine.rs's two candidate-resolution loops (range-query, instant-query) build aRoutingIndexonce per query snapshot instead of a rawPolicyRegistry, matching the design doc's caller pattern.Not done here (documented in the module doc as explicit follow-up): building
RoutingIndexonce perStreamingConfighot-reload swap instead of once per query --StreamingConfig::policy_registry's own doc comment already flags this as a further optimization "if it shows up in profiles." That requires threading a cached derived value throughHotReloadStreamingConfig's swap path, a separate, larger change than this PR's scope.Behavior is unchanged:
find_matching_policies's match predicate is untouched, and all ~18 of its existing tests pass with no assertion changes (only theirPolicyRegistryconstruction is now wrapped inRoutingIndex::build).Test plan
cargo build --release --workspace-- cleancargo test --release -p asap_types-- 42/42 (5 newRoutingIndextests)cargo test --release --lib -p control_plane-- 712/712 (1 pre-existing, unrelated skip as before)cargo test --release --lib -p data_plane-- 906/906cargo test --release -p data_plane --test e2e_controller_plans_and_backend_serves-- 10/14 (2 pre-existing unrelated failures + 2 known#[ignore]d, unchanged from before this PR)🤖 Generated with Claude Code