Repository navigation
fix(db): reclaim Capgo-EU swap pressure without upgrading #2721
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 3 commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
31fe40b
fix(db): reclaim Capgo-EU swap pressure without upgrading
riderx c63d4db
test(db): align audit cleanup cron test with 30-day retention
riderx ad18df6
fix(db): make queue cleanup SQL plpgsql_check-safe
riderx 0347360
fix(db): skip encryption checks when nulling dual-storage columns
riderx d731d6d
fix(db): harden swap reclaim batching and dual-storage null gate
riderx 169b939
fix(db): avoid pg_catalog.GREATEST in dual-storage null gate
riderx 8b41f3f
fix(db): bound queue cleanup globally and skip reclaim queue fan-out
riderx 0e2bbe1
fix(db): count only productive batches in queue cleanup budget
riderx 03ed950
chore(db): sync read-replica schema for manifest present index
riderx 1ef934d
docs(db): clarify reclaim verify coverage and native_packages lock
riderx dd9b96a
fix(db): tighten dual-storage reclaim safety and cleanup fairness
riderx 140138f
fix(db): block incomplete manifest nulling on in-progress bundles
riderx f537d99
chore(ops): drop unused manifest_count from verify sample
riderx a3b7649
fix(db): add manifest candidate index and harden cleanup budget exits
riderx 6a6fd8a
fix(db): match dual-storage reclaim by s3_path and file_hash
riderx 4757e8a
fix(db): align trigger reclaim guards with s3_path/hash identity
riderx File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,167 @@ | ||
| -- Capgo-EU Phase A reclaim (run manually in a maintenance window). | ||
|
riderx marked this conversation as resolved.
riderx marked this conversation as resolved.
riderx marked this conversation as resolved.
riderx marked this conversation as resolved.
riderx marked this conversation as resolved.
riderx marked this conversation as resolved.
|
||
| -- Safe order: truncate empty bloat -> batched archive deletes -> null dual manifests -> trim audit. | ||
| -- Do NOT wrap the whole file in one transaction. VACUUM cannot run inside a transaction block. | ||
| -- Prefer Supabase SQL editor / psql as postgres. Re-run sections until counts hit zero. | ||
|
|
||
| \timing on | ||
|
riderx marked this conversation as resolved.
Outdated
|
||
| \set ON_ERROR_STOP on | ||
|
|
||
| -- --------------------------------------------------------------------------- | ||
| -- 0) Baseline sizes | ||
| -- --------------------------------------------------------------------------- | ||
| SELECT pg_size_pretty(pg_database_size(current_database())::bigint) AS db_size; | ||
|
|
||
| SELECT | ||
| relname, | ||
| n_live_tup, | ||
| pg_size_pretty(pg_total_relation_size(format('%I.%I', schemaname, relname)::regclass)::bigint) AS total | ||
| FROM pg_stat_user_tables | ||
| WHERE (schemaname, relname) IN ( | ||
| ('net', '_http_response'), | ||
| ('public', 'audit_logs'), | ||
| ('public', 'app_versions'), | ||
| ('public', 'manifest'), | ||
| ('pgmq', 'a_on_version_update'), | ||
| ('pgmq', 'a_on_manifest_create'), | ||
| ('pgmq', 'a_webhook_dispatcher'), | ||
| ('pgmq', 'a_on_channel_update') | ||
| ) | ||
| ORDER BY pg_total_relation_size(format('%I.%I', schemaname, relname)::regclass) DESC; | ||
|
|
||
| -- --------------------------------------------------------------------------- | ||
| -- 1) Truncate pg_net response bloat (~5GB empty table in prod) | ||
| -- --------------------------------------------------------------------------- | ||
| TRUNCATE TABLE net._http_response; | ||
|
riderx marked this conversation as resolved.
|
||
|
|
||
| -- --------------------------------------------------------------------------- | ||
| -- 2) Purge pgmq archives older than 2 days (batched). Repeat until deleted=0. | ||
| -- --------------------------------------------------------------------------- | ||
| DO $$ | ||
| DECLARE | ||
| queue_name text; | ||
| cutoff timestamptz := now() - interval '2 days'; | ||
| batch_size integer := 10000; | ||
| deleted_batch integer; | ||
| deleted_total bigint; | ||
| BEGIN | ||
| FOREACH queue_name IN ARRAY ARRAY[ | ||
| 'on_version_update', | ||
| 'on_manifest_create', | ||
| 'webhook_dispatcher', | ||
| 'on_channel_update' | ||
| ] | ||
| LOOP | ||
| deleted_total := 0; | ||
| LOOP | ||
| EXECUTE format( | ||
| 'WITH doomed AS ( | ||
| SELECT ctid FROM pgmq.a_%I WHERE archived_at < $1 LIMIT $2 | ||
| ) | ||
| DELETE FROM pgmq.a_%I AS archive | ||
| USING doomed | ||
| WHERE archive.ctid = doomed.ctid', | ||
| queue_name, queue_name | ||
| ) USING cutoff, batch_size; | ||
| GET DIAGNOSTICS deleted_batch = ROW_COUNT; | ||
| deleted_total := deleted_total + deleted_batch; | ||
| EXIT WHEN deleted_batch = 0; | ||
| END LOOP; | ||
| RAISE NOTICE 'purged % rows from pgmq.a_%', deleted_total, queue_name; | ||
| END LOOP; | ||
| END $$; | ||
|
|
||
| VACUUM (VERBOSE) pgmq.a_on_version_update; | ||
|
riderx marked this conversation as resolved.
|
||
| VACUUM (VERBOSE) pgmq.a_on_manifest_create; | ||
| VACUUM (VERBOSE) pgmq.a_webhook_dispatcher; | ||
| VACUUM (VERBOSE) pgmq.a_on_channel_update; | ||
|
|
||
| -- Optional hard reclaim if VACUUM leaves a lot of empty pages (takes stronger locks): | ||
| -- VACUUM (FULL, VERBOSE) pgmq.a_on_version_update; | ||
| -- VACUUM (FULL, VERBOSE) pgmq.a_on_manifest_create; | ||
| -- VACUUM (FULL, VERBOSE) pgmq.a_webhook_dispatcher; | ||
| -- VACUUM (FULL, VERBOSE) pgmq.a_on_channel_update; | ||
|
|
||
| -- --------------------------------------------------------------------------- | ||
| -- 3) Null migrated app_versions.manifest arrays (dual storage leftovers) | ||
| -- --------------------------------------------------------------------------- | ||
| DO $$ | ||
| DECLARE | ||
| batch_size integer := 200; | ||
| updated_batch integer; | ||
| updated_total bigint := 0; | ||
| BEGIN | ||
| LOOP | ||
| WITH doomed AS ( | ||
| SELECT av.id | ||
| FROM public.app_versions AS av | ||
| WHERE av.manifest IS NOT NULL | ||
| AND cardinality(av.manifest) > 0 | ||
| AND EXISTS ( | ||
|
riderx marked this conversation as resolved.
Outdated
|
||
| SELECT 1 FROM public.manifest AS m WHERE m.app_version_id = av.id | ||
| ) | ||
| ORDER BY av.id | ||
| LIMIT batch_size | ||
| ) | ||
| UPDATE public.app_versions AS av | ||
| SET manifest = NULL | ||
| FROM doomed | ||
| WHERE av.id = doomed.id; | ||
| GET DIAGNOSTICS updated_batch = ROW_COUNT; | ||
| updated_total := updated_total + updated_batch; | ||
| EXIT WHEN updated_batch = 0; | ||
| END LOOP; | ||
| RAISE NOTICE 'nulled manifest arrays on % versions', updated_total; | ||
| END $$; | ||
|
|
||
| VACUUM (VERBOSE) public.app_versions; | ||
|
|
||
| -- --------------------------------------------------------------------------- | ||
| -- 4) Trim audit_logs older than 30 days (batched) | ||
| -- --------------------------------------------------------------------------- | ||
| DO $$ | ||
| DECLARE | ||
| cutoff timestamptz := now() - interval '30 days'; | ||
| batch_size integer := 5000; | ||
| deleted_batch integer; | ||
| deleted_total bigint := 0; | ||
| BEGIN | ||
| LOOP | ||
| WITH doomed AS ( | ||
| SELECT ctid | ||
| FROM public.audit_logs | ||
| WHERE created_at < cutoff | ||
| LIMIT batch_size | ||
| ) | ||
| DELETE FROM public.audit_logs AS audit_logs | ||
| USING doomed | ||
| WHERE audit_logs.ctid = doomed.ctid; | ||
| GET DIAGNOSTICS deleted_batch = ROW_COUNT; | ||
| deleted_total := deleted_total + deleted_batch; | ||
| EXIT WHEN deleted_batch = 0; | ||
| END LOOP; | ||
| RAISE NOTICE 'deleted % audit_logs rows older than 30 days', deleted_total; | ||
| END $$; | ||
|
|
||
| VACUUM (VERBOSE) public.audit_logs; | ||
|
|
||
| -- --------------------------------------------------------------------------- | ||
| -- 5) Final sizes | ||
| -- --------------------------------------------------------------------------- | ||
| SELECT pg_size_pretty(pg_database_size(current_database())::bigint) AS db_size_after; | ||
|
|
||
| SELECT | ||
| relname, | ||
| n_live_tup, | ||
| pg_size_pretty(pg_total_relation_size(format('%I.%I', schemaname, relname)::regclass)::bigint) AS total | ||
| FROM pg_stat_user_tables | ||
| WHERE (schemaname, relname) IN ( | ||
| ('net', '_http_response'), | ||
| ('public', 'audit_logs'), | ||
| ('public', 'app_versions'), | ||
| ('public', 'manifest'), | ||
| ('pgmq', 'a_on_version_update'), | ||
| ('pgmq', 'a_on_manifest_create'), | ||
| ('pgmq', 'a_webhook_dispatcher'), | ||
| ('pgmq', 'a_on_channel_update') | ||
| ) | ||
| ORDER BY pg_total_relation_size(format('%I.%I', schemaname, relname)::regclass) DESC; | ||
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| -- Post-deploy / post-reclaim verification for Capgo-EU swap pressure. | ||
|
riderx marked this conversation as resolved.
|
||
|
|
||
| SELECT pg_size_pretty(pg_database_size(current_database())::bigint) AS db_size; | ||
|
|
||
| SELECT | ||
| name, | ||
| setting | ||
| FROM pg_settings | ||
| WHERE name IN ('shared_buffers', 'work_mem', 'max_connections'); | ||
|
|
||
| SELECT | ||
| relname, | ||
| n_live_tup, | ||
| pg_size_pretty(pg_total_relation_size(format('%I.%I', schemaname, relname)::regclass)::bigint) AS total | ||
| FROM pg_stat_user_tables | ||
| WHERE (schemaname, relname) IN ( | ||
| ('net', '_http_response'), | ||
| ('public', 'audit_logs'), | ||
| ('public', 'app_versions'), | ||
| ('public', 'manifest'), | ||
| ('pgmq', 'a_on_version_update'), | ||
| ('pgmq', 'a_on_manifest_create'), | ||
| ('pgmq', 'a_webhook_dispatcher'), | ||
| ('pgmq', 'a_on_channel_update') | ||
| ) | ||
| ORDER BY pg_total_relation_size(format('%I.%I', schemaname, relname)::regclass) DESC; | ||
|
|
||
| SELECT count(*) AS versions_with_array_manifest | ||
| FROM public.app_versions | ||
| WHERE manifest IS NOT NULL AND cardinality(manifest) > 0; | ||
|
riderx marked this conversation as resolved.
Outdated
|
||
|
|
||
| SELECT name, enabled, hour_interval, run_at_hour, run_at_minute, target | ||
| FROM public.cron_tasks | ||
| WHERE name IN ( | ||
| 'cleanup_queue_messages', | ||
| 'cleanup_net_http_response', | ||
| 'cleanup_old_audit_logs', | ||
| 'null_migrated_app_version_manifests' | ||
| ) | ||
| ORDER BY name; | ||
|
|
||
| SELECT status, return_message, count(*) AS n | ||
|
riderx marked this conversation as resolved.
Outdated
|
||
| FROM cron.job_run_details | ||
| WHERE start_time > now() - interval '24 hours' | ||
| OR (start_time IS NULL AND status IN ('failed', 'connecting')) | ||
| GROUP BY status, return_message | ||
| ORDER BY n DESC | ||
| LIMIT 20; | ||
|
|
||
| SELECT | ||
| count(*) FILTER (WHERE archived_at < now() - interval '2 days') AS archives_older_than_2d, | ||
| count(*) AS archives_total | ||
| FROM pgmq.a_on_manifest_create; | ||
|
riderx marked this conversation as resolved.
Outdated
|
||
|
|
||
| SELECT | ||
| 'index hit rate' AS name, | ||
| ROUND((sum(idx_blks_hit) / nullif(sum(idx_blks_hit + idx_blks_read), 0) * 100)::numeric, 2) AS ratio | ||
|
riderx marked this conversation as resolved.
Outdated
|
||
| FROM pg_statio_user_indexes | ||
| UNION ALL | ||
| SELECT | ||
| 'table hit rate', | ||
| ROUND((sum(heap_blks_hit) / nullif(sum(heap_blks_hit) + sum(heap_blks_read), 0) * 100)::numeric, 2) | ||
| FROM pg_statio_user_tables; | ||
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
Oops, something went wrong.
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.