Conversation
Baishan
reviewed
Sep 8, 2026
| def rules_tree_by_source_id(id) do | ||
| rules = list_by_source_id(id) | ||
| RulesTree.build(rules) | ||
| {RulesTree.build(rules), Map.new(rules, &{&1.id, &1})} |
Contributor
There was a problem hiding this comment.
Is this not still problematic if there are a lot of rules on the source?
7 of 8 tasks
djwhitt
marked this pull request as ready for review
September 8, 2026 21:21
This branch has not been deployed
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.
Review scope
130bdeb6(#3942)a943dc6a6820c6ee4754419c(#3946)What changes
{rule_id, backend_id, sink}targets from one database query.[:logflare, :rules, :routing_snapshot_store]source/byte gauges on lifecycle changes.Architecture
flowchart LR Q["One rules query"] --> B["Routing tree + compact targets"] B --> C["Cachex header<br/>tree + generation + fallback"] B --> E["ETS generation<br/>target tuple"] P["Prepare once per batch"] --> C C --> M["Match rule IDs"] M --> H{"ETS generation available?"} H -->|Yes| R["Read matched targets"] H -->|No| F["Decode immutable fallback once"] F --> K{"Header still current?"} K -->|Yes| RH["Rehydrate ETS + Cachex header"] K -->|No| L["Carry decoded fallback through batch"]Consistency guarantees
Performance
These are local microbenchmarks, not production-throughput claims. The corrected fixtures assert the intended 1/8/all match counts before measurement. Environment: Linux, 6 available cores, Elixir 1.19.5, OTP 27.3.4.6, JIT, Benchee 1.5.0, parallel 1, warmup 2s, measurement 5s, memory 2s.
1. Initial snapshot vs then-current main
Two alternating runs per revision with fully warmed caches:
130bdeb6a943dc6a2. Hardening commit vs initial snapshot
One adjacent run after adding compact ID-keyed targets, batch state, recovery, and byte-aware lifecycle handling:
The 1,000-rule/one-match regression is explicit. A matching-only probe found ID and positional keys within 1%, so this shape needs production-informed profiling rather than another speculative tree change.
3. Batch allocation and retained representation
For 1,000 rules / 8 matches, preparing the ID-keyed snapshot once per batch was:
Replacing full
%Rule{}values with compact targets reduced the modeled tree/tuple/index/fallback representation by 94.5-95.7%. The 1,000-rule fixtures fell from 1.20-1.42 MB to 58-71 KB. This component model excludes Cachex/ETS table overhead and allocator fragmentation; it is not process RSS.Full hardening details:
source_routing_cache_hardening_results.md.The cumulative final stack vs current main retained-memory and batch-allocation comparison is in #3946. Those positional-head results are not attributed to this ID-keyed boundary.
Earlier #3937 comparison, fixture correction, and commands
Before the rebase, two runs against
1bff0f28showed 6.1-11.0x faster sparse routing and 1.13-1.37x faster dense routing. Those gains are not claimed against current main. Stage isolation for 1,000 rules / 8 matches reduced cache fetch from 433.34 us to 30.40 us while resident-tree matching stayed around 6 us, identifying full-map retrieval as the dominant #3937 regression cost.The previous unquoted
metadata.rule_id:rule-100parsed as equality to"rule"plus a negated message term, so the case labeled “one matching” actually matched zero rules. The fixture is now quoted and every case asserts its intended count. Earlier mislabeled v1.50.9/main numbers are not comparable.Initial snapshot details:
source_routing_snapshot_results.md.A six-reader Benchee attempt was killed with exit -9 before results; no concurrent-throughput claim is made.
Validation
MIX_ENV=test mix compilethrough project wrappers.MIX_ENV=test mix lint.all; only 32 existing design suggestions.MIX_ENV=test mix test.typings; 158 configured errors skipped, 10 existing unnecessary skips, task passed.6820c6ee.Remaining review points
Related: #3935, #3937, #3942. Positional follow-up: #3946.