Overview global 24h rollup + production BRIN tuning (GitLab #281 follow-up) #333
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#333
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
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?
Parent
Follow-ups to GitLab #281 (
/overviewglobal 24h stats — open). Phase 1 (BRIN + 60s cache) merged infd11a22; issue discussion calls for rollup + production BRIN tuning.Current codebase
Shipped mitigations (#281)
idx_swaps_block_timestamp_brinonswap_events(block_timestamp)— migrationindexer/migrations/20260604120100_swap_events_block_timestamp_brin.sql.indexer/src/api/overview.rs.get_global_stats(indexer/src/db/queries/volume.rs) still runs live:pair_volume_24htable refreshed ~5 min byvolume_aggregator.rs— used forGET /pairs?sort=volume_24h, not for global overview (rollup lacksoffer_amount/volume_usd/ trade count semantics perdocs/indexer-invariants.md).Gaps
global_volume_24hrollup would bound latency to O(1) read.pages_per_rangeandautosummarizeshould be tuned fromEXPLAIN (ANALYZE, BUFFERS)on production-sized data.Why this is needed
/api/v1/overviewis unauthenticated — cache miss + full aggregate is a DoS surface (docs/indexer-invariants.md§ DoS).swap_eventsis append-only and unbounded — cross-pair 24h aggregate must not scale linearly with table size on every cache expiry.Constraints / guardrails
SUM(offer_amount),COALESCE(SUM(volume_usd),0),COUNT(*), 24h window onblock_timestamp, pluspair_countfrompairstable.volume_aggregatorloop (~5 min) unless stricter freshness documented.ALTER INDEX ... SET (pages_per_range = …),brin_summarize_new_valuesschedule; document in ops runbook.Relevant files
indexer/src/api/overview.rsindexer/src/db/queries/volume.rs—get_global_statsindexer/src/indexer/volume_aggregator.rsindexer/migrations/20260531143000_pair_volume_24h_rollup.sql,pair_volume_24hqueriesindexer/migrations/20260604120100_swap_events_block_timestamp_brin.sqlindexer/tests/indexer_overview_global_stats.rs,indexer/tests/indexer_pair_volume_pagination.rsdocs/indexer-invariants.md,skills/AGENTS_INDEXER_VOLUME_PAGINATION.mdRecommended direction
A. Dedicated
global_volume_24hrollupglobal_stats_24h (total_volume, total_volume_usd, total_trades, updated_at)or single-row materialized view refreshed by aggregator.INSERT … ON CONFLICT UPDATEfromswap_events WHERE block_timestamp >= now()-24hon same schedule as pair rollup (or incremental delta if feasible).get_global_statsreads rollup on cache miss; optional fallback to live query behind env flag for debug.B. Production BRIN tuning
EXPLAIN (ANALYZE, BUFFERS)on production clone with realisticswap_eventsrow count.pages_per_range(common starting points 32–128 depending on page density).autosummarizeif not default; documentbrin_summarize_new_values('idx_swaps_block_timestamp_brin')in reindex/replay runbook.Acceptance criteria
/overviewreads rollup table — no fullswap_eventsscan in steady state.EXPLAINevidence on production-scale fixture.indexer_overview_global_statstests extended.docs/indexer-invariants.mdupdated — overview uses rollup.Test plan — all paths
get_global_statsupdated_atadvancespairsCOUNTTest plan — attack / abuse / hack vectors
/overviewVerification criteria
cargo test --test indexer_overview_global_statsgreen.EXPLAINon cache-miss path shows rollup index scan or single-row fetch, not seq scan onswap_events.marked as related to #281
mentioned in commit
6899d0f69fmentioned in merge request !814
Implementation complete — MR !814
Opened !814 on branch
cursor/gitlab-issue-workflow-2834.Summary
global_stats_24hsingle-row rollup table;/overviewcache miss now reads O(1) rollup instead of scanningswap_events.refresh_global_statsruns on indexer startup and every ~5 min with the volume aggregator (same cadence aspair_volume_24h).OVERVIEW_GLOBAL_STATS_LIVE=1env flag restores live aggregate for debug/parity.docs/runbooks/overview-global-stats-brin.md.Acceptance criteria
swap_eventsscanoverview_cache_miss_reads_rollup_not_swap_eventsglobal_stats_rollup_matches_live_querydocs/runbooks/overview-global-stats-brin.mdindexer_overview_global_statsextendeddocs/indexer-invariants.mdupdatedIssue left open pending deploy verification (#281 closable after production confirms rollup freshness).
mentioned in commit
eb48e91095#333 verified on current main (merged !814,
eb48e91). All five acceptance items hold; I also captured the before/after EXPLAIN evidence the MR left as a documented workflow.Tests + wiring:
Before/after EXPLAIN (ANALYZE, BUFFERS) on a 1M-row swap_events fixture, 24h window ~= 33k rows (3.3%):
So the architecture holds end to end: the rollup bounds cache-miss latency to a single-row O(1) read (~0.1 ms) regardless of table growth, and the BRIN is the safety net for the optional live fallback, turning a full seq scan into a bounded recent-range bitmap scan. Honest caveat: the fixture is 1M rows (212 MB), not true production millions — the buffer/timing ratios are the point, and the rollup read is O(1) by construction at any scale.
Verification criteria: cargo test green; EXPLAIN on the cache-miss path shows the single-row rollup Index Scan, not a swap_events seq scan; runbook BRIN section present (now with captured numbers). #281 is closable once you're satisfied with the deployed rollup behavior. @PlasticDigits
Verification complete — #333
Independent QA pass on
main(includes merged !814,eb48e91). No repo changes required.Acceptance criteria
/overviewreads rollup table — no fullswap_eventsscanoverview_cache_miss_reads_rollup_not_swap_events— EXPLAIN showsglobal_stats_24honly, noswap_eventsglobal_stats_rollup_matches_live_query,global_stats_rollup_excludes_swaps_older_than_24h,global_stats_uninitialized_rollup_falls_back_to_livedocs/runbooks/overview-global-stats-brin.md— tuning steps,pages_per_range,brin_summarize_new_values, before/after EXPLAIN workflowindexer_overview_global_statstests extendeddocs/indexer-invariants.mdupdated — overview uses rollupglobal_stats_24hrollup + runbookVerification criteria
cargo test --test indexer_overview_global_statsgreenswap_eventsseq scanoverview_cache_miss_reads_rollup_not_swap_eventsdocs/runbooks/overview-global-stats-brin.mdget_global_stats,refresh_global_statson startup (poller.rs) + ~5 min (volume_aggregator.rs); optionalOVERVIEW_GLOBAL_STATS_LIVE=1for parityTest plan paths
global_stats_empty_db_returns_zeros)overview_response_cached_within_ttl)updated_atglobal_stats_refresh_advances_updated_at)pairsCOUNTapi_overview::overview_returns_stats)Attack / abuse vectors
Commands run
Follow-up
Parent #281 can be closed once production deploy confirms rollup freshness in your environment.
mentioned in commit
3577d93b8fmentioned in commit
8d74197226mentioned in commit
f178056f36mentioned in issue #548
marked as related to #548
mentioned in issue #550
marked as related to #550
mentioned in issue #569
mentioned in issue #576
mentioned in issue #577
mentioned in merge request !1099
mentioned in issue #586