Overview global 24h rollup + BRIN tuning runbook (#333) #814
No reviewers
Labels
No labels
agent:fix_bugfix
agent:fix_conflicts
agent:fix_security
agent:gap_analysis
agent:implement
agent:implement
agent:implement
agent:open_issues
agent:ready
agent:research
agent:security_audit
agent:verify
architecture
backend
blocker:hybrid
blocker:launch
blocker:limit-orders
blocker:v2
block:log_only
block:security
bug
ci
contracts
correctness
deploy
dev
devops
docs
documentation
duplicate
e2e
enhancement
epic
feature
frontend
functional-completion
gas
good first issue
governance
help wanted
high-risk
hooks
hybrid
indexer
infra
infrastructure
integrators
invalid
launch-blocker
limit-orders
localnet
localterra
low priority
missing-implementation
needs-design
ops
performance
priority
high
priority
medium
product
qa
QA
question
ready
ready
research
scripts
security
security-hardening
smartcontracts
tech-debt
testing
ux
UX
v2
verification
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
code/cl8y-dex-terraclassic!814
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "cursor/gitlab-issue-workflow-2834"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Implements GitLab #333 — follow-up to #281 for bounded
/api/v1/overviewcache-miss latency.Changes
global_stats_24hrollup table (migration20260605120000_global_stats_24h_rollup.sql) — single-row materialized global 24h stats (SUM(offer_amount),SUM(volume_usd),COUNT(*)).refresh_global_stats— refreshed every ~5 min byvolume_aggregatorand once at indexer startup (poller.rs), same cadence aspair_volume_24h.get_global_stats— reads rollup on cache miss; optional liveswap_eventsaggregate viaOVERVIEW_GLOBAL_STATS_LIVE=1for debug/parity.overview.rs.docs/runbooks/overview-global-stats-brin.mdwith production tuning guidance (pages_per_range,autosummarize,brin_summarize_new_values) and before/after EXPLAIN workflow.docs/indexer-invariants.md,skills/AGENTS_INDEXER_VOLUME_PAGINATION.mdupdated for V5 rollup path.Acceptance checklist
/overviewreads rollup — noswap_eventsscancargo test --test indexer_overview_global_stats overview_cache_miss_reads_rollup_not_swap_eventscargo test --test indexer_overview_global_stats global_stats_rollup_matches_live_querydocs/runbooks/overview-global-stats-brin.mdindexer_overview_global_statstests extendeddocs/indexer-invariants.mdupdated — overview uses rollupVerification checklist (third parties)
Optional parity check with live aggregate:
Notes
pair_countstill computed live frompairson each cache miss (unchanged semantics).changed the description
added 1 commit
8fd57cba- test(indexer): fix BigDecimal zero comparison in overview rollup testCompare with previous version
mentioned in issue #333
changed the description
changed the description
Security review
Commit reviewed:
8fd57cbaf68d98ce2453e0cb953cad3c1ea1859d(includes6899d0ffeat +8fd57cbtest fix)Scope:
global_stats_24hmaterialized rollup forGET /api/v1/overviewcache-miss path — migration,refresh_global_stats/get_global_stats(rollup + optionalOVERVIEW_GLOBAL_STATS_LIVElive fallback), volume-aggregator + poller startup refresh, docs/runbook, integration tests.Method: Traced
/api/v1/overview→volume::get_global_stats; reviewed new SQL (parameterized only), migration constraints, background refresh wiring, and whether any attacker-controlled input reaches a new sink.Outcome:
FINDINGS: 0medium+No inline threads — nothing met the bar for a reportable issue on this diff.
Notes (non-findings)
global_stats_24hvs liveswap_eventsaggregate). Existing 60s whole-response cache unchanged.$1); no user/query-string input in SQL.OVERVIEW_GLOBAL_STATS_LIVE: Operator env only (not HTTP/config surface); re-enables live scan for debug — misconfiguration risk is ops-side, not a remote exploit path introduced here.pair_countremains a liveCOUNT(*)onpairs(unchanged pattern)./overviewstays a public read-only stats endpoint; errors still routed viainternal_err.Security review
Commit reviewed:
8fd57cbaf68d98ce2453e0cb953cad3c1ea1859d(test(indexer): fix BigDecimal zero comparison in overview rollup test)Diff scope:
e41f61b..8fd57cb(10 files) —global_stats_24hmaterialized rollup,refresh_global_stats/get_global_statsread path, volume-aggregator + poller refresh, optionalOVERVIEW_GLOBAL_STATS_LIVE=1live aggregate, runbook/docs/tests.Outcome: FINDINGS: 0 (no medium, high, or critical issues on this diff)
Summary
Security review: no medium+ findings on this diff.
Reviewed attacker-controlled inputs on the changed paths:
GET /api/v1/overviewstill has no query/body parameters; the handler only callsvolume::get_global_statsand existing asset/oracle reads. New SQL (refresh_global_stats, rollupSELECT) uses bound parameters only ($1cutoff); no string concatenation from HTTP.OVERVIEW_GLOBAL_STATS_LIVEis process environment only (not client-settable). Mis-setting it in production could restore the pre-#333swap_eventsaggregate (DoS/perf regression), but that requires operator config access and is documented as debug/parity-only in the runbook.The change reduces unauthenticated DoS surface on
/overviewcache miss (O(1)global_stats_24hPK read vs scanningswap_events). Rollup staleness (~5 min) affects public market-stat accuracy, not authn/authz or fund safety.Inline threads: none (no findings to anchor on diff lines).
Automated security review (MR webhook).
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is ON. A cloud agent has been kicked off to fix the reported issue.
Reviewed by Cursor Bugbot for commit
8fd57cbaf6. Configure here.Overview zeros before first refresh
Medium Severity
After the new migration,
get_global_statsserves the seededglobal_stats_24hrow (zeros) on/overviewcache misses untilrefresh_global_statsfinishes. The API task starts in parallel with the indexer, so early requests—and the 60s overview cache—can show zero volume and trades whileswap_eventsalready has data.Additional Locations (1)
indexer/migrations/20260605120000_global_stats_24h_rollup.sql#L4-L13Reviewed by Cursor Bugbot for commit
8fd57cbaf6. Configure here.added 1 commit
91c041a7- fix(indexer): fall back to live global stats when rollup is uninitializedCompare with previous version
Security review
Commit reviewed:
91c041a74063dddbc9ab70153eef9f9450623bc7(fix(indexer): fall back to live global stats when rollup is uninitialized)Diff scope:
e41f61b..91c041a—global_stats_24hmaterialized rollup forGET /api/v1/overviewcache-miss path;refresh_global_stats/get_global_stats(rollup + uninitialized fallback + optionalOVERVIEW_GLOBAL_STATS_LIVE=1live path); volume-aggregator + poller startup refresh; runbook/docs/tests.Method: Re-read prior security-review notes on this MR (reviews at
8fd57cb). Traced/api/v1/overview→volume::get_global_stats; reviewed new SQL (parameterized only), migration constraints (CHECK (id = 1)), background refresh wiring, and the newtotal_trades == 0+EXISTSfallback added in91c041a. Verified no HTTP/query/body input reaches SQL or env toggles.Outcome:
FINDINGS: 0medium+Security review: no medium+ findings on this diff.
Inline threads: none (no findings to anchor on diff lines).
Notes (non-findings)
/overviewis unchanged public read-only with 60s whole-response cache and global per-IP rate limiting.91c041afallback: When the seeded rollup row still showstotal_trades = 0butswap_eventshas rows in the 24h window, the handler runs a cheapEXISTSthen falls back toget_global_stats_live. This restores pre-rollup accuracy during startup/degraded refresh — not an attacker-controllable sink (global_stats_24his indexer-written only; swap rows come from chain ingestion, not HTTP).refresh_global_statspersistently fails — ops/DB issue). That is not worse than the pre-MR cache-miss path and is bounded by existing rate limits.OVERVIEW_GLOBAL_STATS_LIVE: Process environment only; misconfiguration is operator-side, not a remote exploit path.Automated security review (MR webhook).
mentioned in commit
e817be2ae4added 1 commit
e817be2a- test(indexer): regression for uninitialized global_stats_24h rollupCompare with previous version
resolved all threads
changed the description
Security review
Commit reviewed:
e817be2ae48b4df4cc38c8aa5e0c9b9fbb103959(test(indexer): regression for uninitialized global_stats_24h rollup)Diff scope:
e41f61b..e817be2—global_stats_24hmaterialized rollup forGET /api/v1/overviewcache-miss path;refresh_global_stats/get_global_stats(rollup read + uninitialized fallback + optionalOVERVIEW_GLOBAL_STATS_LIVE=1live path); migration backfill on upgrade; volume-aggregator + poller startup refresh; runbook/docs/tests.Method: Re-read prior security-review notes on this MR (reviews at
8fd57cb,91c041a; inline thread on uninitialized rollup zeros — resolved). Traced/api/v1/overview→volume::get_global_stats; reviewed new SQL (parameterized only), migration constraints (CHECK (id = 1)), background refresh wiring,total_trades == 0+EXISTSfallback (91c041a), and migration backfill (e817be2). Verified no HTTP/query/body input reaches SQL or env toggles.Outcome:
FINDINGS: 0medium+Security review: no medium+ findings on this diff.
Inline threads: none (no findings to anchor on diff lines).
Notes (non-findings)
e817be2) and runtime fallback toget_global_stats_livewhen rolluptotal_trades = 0but recent swaps exist (91c041a). Not re-reported./overviewremains public read-only with 60s whole-response cache and global per-IP rate limiting.global_stats_24his indexer-written;swap_eventsrows come from chain ingestion).OVERVIEW_GLOBAL_STATS_LIVE: Process environment only; misconfiguration is operator-side, not a remote exploit path.Automated security review (MR webhook).
mentioned in commit
eb48e91095mentioned in commit
c6fa879c2cmentioned in commit
8d74197226mentioned in commit
76f09228c0mentioned in commit
f178056f36