Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 25 additions & 40 deletions scripts/ops/reclaim_supabase_swap.sql
Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
-- Capgo-EU Phase A reclaim (run manually in a maintenance window).
-- REQUIRED: psql for VACUUM (cannot run inside a transaction / SQL-editor tx).
-- Prefer ~/.pgpass / PGPASSFILE instead of putting the password on the CLI.
-- Capgo-EU Phase A reclaim — safe for Supabase SQL Editor.
-- Paste this whole file into SQL Editor and run.
--
-- Schema source of truth: migration 20260722154010_app_versions_manifest_present_idx.
-- Optional non-blocking prebuild before that migration deploys:
-- psql "$DATABASE_URL" -v ON_ERROR_STOP=1 -f scripts/ops/reclaim_supabase_swap_index.sql
-- Prerequisites (deploy first, or this script fails the preflight):
-- - 20260722082019_fix_supabase_swap_memory
-- - 20260722154010_app_versions_manifest_present_idx
--
-- Example:
-- psql "postgresql://postgres@HOST:5432/postgres?sslmode=require" -v ON_ERROR_STOP=1 -f scripts/ops/reclaim_supabase_swap.sql
-- Safe order: truncate -> archives -> null manifests -> audit trim.
-- Re-run the FULL script until cleanup notices report deleted/updated = 0
-- (functions always emit a notice, including zero totals).
-- Re-run until Notices show deleted/updated = 0 (functions always raise a notice).
-- VACUUM is NOT here: SQL Editor wraps work in a transaction and rejects VACUUM.
-- Optional later via psql: scripts/ops/reclaim_supabase_swap_vacuum.sql

SET lock_timeout = '5s';
SET statement_timeout = '180s';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: A successful run can leak the new 180-second timeout into a reused SQL Editor session, causing later unrelated queries to fail after 180 seconds. SET LOCAL statement_timeout = '180s' would constrain the limit to this pasted transaction instead of changing the session.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/ops/reclaim_supabase_swap.sql, line 13:

<comment>A successful run can leak the new 180-second timeout into a reused SQL Editor session, causing later unrelated queries to fail after 180 seconds. `SET LOCAL statement_timeout = '180s'` would constrain the limit to this pasted transaction instead of changing the session.</comment>

<file context>
@@ -1,26 +1,28 @@
+-- Optional later via psql: scripts/ops/reclaim_supabase_swap_vacuum.sql
 
 SET lock_timeout = '5s';
+SET statement_timeout = '180s';
 
 -- ---------------------------------------------------------------------------
</file context>
Suggested change
SET statement_timeout = '180s';
SET LOCAL statement_timeout = '180s';


-- ---------------------------------------------------------------------------
-- 0) Baseline sizes + require a valid candidate index
-- 0) Preflight + baseline sizes
-- ---------------------------------------------------------------------------
SELECT pg_size_pretty(pg_database_size(current_database())::bigint) AS db_size;

DO $$
BEGIN
IF to_regprocedure('public.null_migrated_app_version_manifests()') IS NULL
OR to_regprocedure('public.cleanup_net_http_response()') IS NULL THEN
RAISE EXCEPTION
'Missing reclaim functions. Deploy migration 20260722082019_fix_supabase_swap_memory first.';
END IF;
Comment on lines +20 to +24

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Make the preflight match the functions this script invokes.

The check omits cleanup_queue_messages() and cleanup_old_audit_logs(), which are called at Lines 69 and 79. If either is missing, preflight passes and execution fails only after the TRUNCATE at Line 64. Add the missing checks; retain cleanup_net_http_response() only if the full migration contract requires it.

🔧 Proposed fix
   IF to_regprocedure('public.null_migrated_app_version_manifests()') IS NULL
+     OR to_regprocedure('public.cleanup_queue_messages()') IS NULL
+     OR to_regprocedure('public.cleanup_old_audit_logs()') IS NULL
      OR to_regprocedure('public.cleanup_net_http_response()') IS NULL THEN
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
IF to_regprocedure('public.null_migrated_app_version_manifests()') IS NULL
OR to_regprocedure('public.cleanup_net_http_response()') IS NULL THEN
RAISE EXCEPTION
'Missing reclaim functions. Deploy migration 20260722082019_fix_supabase_swap_memory first.';
END IF;
IF to_regprocedure('public.null_migrated_app_version_manifests()') IS NULL
OR to_regprocedure('public.cleanup_queue_messages()') IS NULL
OR to_regprocedure('public.cleanup_old_audit_logs()') IS NULL
OR to_regprocedure('public.cleanup_net_http_response()') IS NULL THEN
RAISE EXCEPTION
'Missing reclaim functions. Deploy migration 20260722082019_fix_supabase_swap_memory first.';
END IF;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/ops/reclaim_supabase_swap.sql` around lines 20 - 24, Update the
preflight function-existence check in the reclaim script to include
cleanup_queue_messages() and cleanup_old_audit_logs(), matching the functions
invoked later by the script. Keep cleanup_net_http_response() only if it is part
of the migration’s required contract, and preserve the existing exception
behavior when any required function is missing.


IF NOT EXISTS (
SELECT 1
FROM pg_catalog.pg_class AS idx
Expand All @@ -32,9 +34,12 @@ BEGIN
AND i.indisvalid
) THEN
RAISE EXCEPTION
'Missing or invalid app_versions_manifest_present_idx. Deploy migration 20260722154010 (or run scripts/ops/reclaim_supabase_swap_index.sql alone first if the index is invalid/missing).';
'Missing or invalid app_versions_manifest_present_idx. Deploy migration 20260722154010 first.';
END IF;
END $$;
END
$$;

SELECT pg_size_pretty(pg_database_size(current_database())::bigint) AS db_size;

SELECT
relname,
Expand All @@ -54,45 +59,25 @@ WHERE (schemaname, relname) IN (
ORDER BY pg_total_relation_size(format('%I.%I', schemaname, relname)::regclass) DESC;

-- ---------------------------------------------------------------------------
-- 1) Truncate pg_net response bloat
-- 1) Truncate pg_net response bloat (biggest immediate win)
-- ---------------------------------------------------------------------------
TRUNCATE TABLE net._http_response;

-- ---------------------------------------------------------------------------
-- 2) Purge pgmq archives/stuck messages.
-- Re-run the FULL script until archived_deleted=0 and stuck_deleted=0.
-- 2) Purge pgmq archives/stuck messages (batched; re-run until notice = 0)
-- ---------------------------------------------------------------------------
SELECT public.cleanup_queue_messages();

VACUUM (VERBOSE) pgmq.a_on_version_update;
VACUUM (VERBOSE) pgmq.a_on_manifest_create;
VACUUM (VERBOSE) pgmq.a_webhook_dispatcher;
VACUUM (VERBOSE) pgmq.a_on_channel_update;
VACUUM (VERBOSE) pgmq.q_on_version_update;
VACUUM (VERBOSE) pgmq.q_on_manifest_create;
VACUUM (VERBOSE) pgmq.q_webhook_dispatcher;
VACUUM (VERBOSE) pgmq.q_on_channel_update;

-- ---------------------------------------------------------------------------
-- 3) Null fully migrated app_versions.manifest arrays (s3_path + file_hash).
-- Re-run the FULL script until updated=0.
-- 3) Null fully migrated app_versions.manifest arrays (re-run until notice = 0)
-- ---------------------------------------------------------------------------
SELECT public.null_migrated_app_version_manifests();

VACUUM (ANALYZE, VERBOSE) public.app_versions;
-- Optional TOAST compaction after updated=0:
-- VACUUM (FULL, VERBOSE) public.app_versions;

-- ---------------------------------------------------------------------------
-- 4) Trim audit_logs older than 30 days.
-- Re-run the FULL script until deleted=0.
-- 4) Trim audit_logs older than 30 days (re-run until notice = 0)
-- ---------------------------------------------------------------------------
SELECT public.cleanup_old_audit_logs();

VACUUM (ANALYZE, VERBOSE) public.audit_logs;
-- Optional TOAST compaction after deleted=0:
-- VACUUM (FULL, VERBOSE) public.audit_logs;

-- ---------------------------------------------------------------------------
-- 5) Final sizes
-- ---------------------------------------------------------------------------
Expand Down
12 changes: 5 additions & 7 deletions scripts/ops/reclaim_supabase_swap_index.sql
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
-- Optional Capgo-EU pre-deploy: build the candidate index without blocking writes.
-- Run this ALONE (one statement) before applying migration
-- 20260722154010_app_versions_manifest_present_idx so the migration's
-- CREATE INDEX IF NOT EXISTS becomes a no-op.
-- Prefer deploying migration 20260722154010 instead.
-- If you still need this: run the SINGLE statement below alone in SQL Editor
-- (or psql). Do not mix with other statements in one Editor run if the Editor
-- wraps a transaction — CREATE INDEX CONCURRENTLY cannot run in a transaction.
--
-- REQUIRED: psql (CREATE INDEX CONCURRENTLY cannot run inside a transaction).
-- SQL Editor: paste ONLY the CREATE INDEX statement below.
--
-- Example:
-- Example (psql):
-- psql "$DATABASE_URL" -v ON_ERROR_STOP=1 -f scripts/ops/reclaim_supabase_swap_index.sql

CREATE INDEX CONCURRENTLY IF NOT EXISTS app_versions_manifest_present_idx
Expand Down
5 changes: 5 additions & 0 deletions scripts/ops/reclaim_supabase_swap_truncate_http.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-- Capgo-EU immediate reclaim — safe for Supabase SQL Editor.
-- Single statement. Run alone. No migration required.
-- Frees net._http_response bloat (~5GB on Capgo-EU when empty/stale).

TRUNCATE TABLE net._http_response;
Comment on lines +1 to +5

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🔵 Trivial

Bound lock acquisition for the standalone TRUNCATE.

Unlike reclaim_supabase_swap.sql, this one-statement variant has no lock_timeout or statement_timeout. A conflicting long-running transaction can leave SQL Editor waiting indefinitely. Document the required client/session timeout or replace the one-liner with a single DO statement that sets local timeouts before truncating.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/ops/reclaim_supabase_swap_truncate_http.sql` around lines 1 - 5,
Update the standalone reclaim statement around TRUNCATE TABLE net._http_response
to bound lock acquisition before truncating. Use a single DO statement that sets
local lock_timeout and statement_timeout values before executing the truncate,
or document the required client/session timeout directly in this script while
preserving its standalone execution requirement.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: On a busy database, this standalone path can wait indefinitely behind an active query or pg_net worker and leave the SQL Editor run hanging. Adding the same lock and statement time bounds as the full reclaim path, or requiring them in the operator session, would keep this emergency script bounded.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/ops/reclaim_supabase_swap_truncate_http.sql, line 5:

<comment>On a busy database, this standalone path can wait indefinitely behind an active query or pg_net worker and leave the SQL Editor run hanging. Adding the same lock and statement time bounds as the full reclaim path, or requiring them in the operator session, would keep this emergency script bounded.</comment>

<file context>
@@ -0,0 +1,5 @@
+-- Single statement. Run alone. No migration required.
+-- Frees net._http_response bloat (~5GB on Capgo-EU when empty/stale).
+
+TRUNCATE TABLE net._http_response;
</file context>

22 changes: 22 additions & 0 deletions scripts/ops/reclaim_supabase_swap_vacuum.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
-- Optional Capgo-EU reclaim VACUUM — psql only (NOT SQL Editor).
-- Run after scripts/ops/reclaim_supabase_swap.sql when deleted/updated notices are 0.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Cleanup functions are capped per invocation, so a non-zero SQL Editor pass commits dead tuples before the next pass; waiting for notices to reach 0 lets bloat accumulate during a reclaim. The runbook should run this psql file after every reclaim pass, then rerun the full reclaim script until the notices are 0.

(Based on your team's feedback about rerunning the full reclaim script after cleanup batches.)

View Feedback

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/ops/reclaim_supabase_swap_vacuum.sql, line 2:

<comment>Cleanup functions are capped per invocation, so a non-zero SQL Editor pass commits dead tuples before the next pass; waiting for notices to reach 0 lets bloat accumulate during a reclaim. The runbook should run this psql file after every reclaim pass, then rerun the full reclaim script until the notices are 0.

(Based on your team's feedback about rerunning the full reclaim script after cleanup batches.) </comment>

<file context>
@@ -0,0 +1,22 @@
+-- Optional Capgo-EU reclaim VACUUM — psql only (NOT SQL Editor).
+-- Run after scripts/ops/reclaim_supabase_swap.sql when deleted/updated notices are 0.
+--
+-- Example:
</file context>
Suggested change
-- Run after scripts/ops/reclaim_supabase_swap.sql when deleted/updated notices are 0.
-- Run after every scripts/ops/reclaim_supabase_swap.sql pass; rerun the reclaim script until deleted/updated notices are 0.

--
-- Example:
-- psql "$DATABASE_URL" -v ON_ERROR_STOP=1 -f scripts/ops/reclaim_supabase_swap_vacuum.sql

VACUUM (VERBOSE) pgmq.a_on_version_update;
VACUUM (VERBOSE) pgmq.a_on_manifest_create;
VACUUM (VERBOSE) pgmq.a_webhook_dispatcher;
VACUUM (VERBOSE) pgmq.a_on_channel_update;
VACUUM (VERBOSE) pgmq.q_on_version_update;
VACUUM (VERBOSE) pgmq.q_on_manifest_create;
VACUUM (VERBOSE) pgmq.q_webhook_dispatcher;
VACUUM (VERBOSE) pgmq.q_on_channel_update;
Comment on lines +7 to +14

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The reclaim step cleans every pgmq.list_queues() queue, but this file vacuums only the four named queue pairs, leaving other queues' deleted rows unreclaimed. Generating the VACUUM statements from pgmq.list_queues() would keep this psql-only script aligned with cleanup_queue_messages().

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/ops/reclaim_supabase_swap_vacuum.sql, line 7:

<comment>The reclaim step cleans every `pgmq.list_queues()` queue, but this file vacuums only the four named queue pairs, leaving other queues' deleted rows unreclaimed. Generating the VACUUM statements from `pgmq.list_queues()` would keep this psql-only script aligned with `cleanup_queue_messages()`.</comment>

<file context>
@@ -0,0 +1,22 @@
+-- Example:
+--   psql "$DATABASE_URL" -v ON_ERROR_STOP=1 -f scripts/ops/reclaim_supabase_swap_vacuum.sql
+
+VACUUM (VERBOSE) pgmq.a_on_version_update;
+VACUUM (VERBOSE) pgmq.a_on_manifest_create;
+VACUUM (VERBOSE) pgmq.a_webhook_dispatcher;
</file context>
Suggested change
VACUUM (VERBOSE) pgmq.a_on_version_update;
VACUUM (VERBOSE) pgmq.a_on_manifest_create;
VACUUM (VERBOSE) pgmq.a_webhook_dispatcher;
VACUUM (VERBOSE) pgmq.a_on_channel_update;
VACUUM (VERBOSE) pgmq.q_on_version_update;
VACUUM (VERBOSE) pgmq.q_on_manifest_create;
VACUUM (VERBOSE) pgmq.q_webhook_dispatcher;
VACUUM (VERBOSE) pgmq.q_on_channel_update;
SELECT pg_catalog.format('VACUUM (VERBOSE) pgmq.%I', 'a_' || q.queue_name)
FROM pgmq.list_queues() AS q
\gexec
SELECT pg_catalog.format('VACUUM (VERBOSE) pgmq.%I', 'q_' || q.queue_name)
FROM pgmq.list_queues() AS q
\gexec


VACUUM (ANALYZE, VERBOSE) public.app_versions;
-- Optional TOAST compaction after dual-storage nulling is done:
-- VACUUM (FULL, VERBOSE) public.app_versions;

VACUUM (ANALYZE, VERBOSE) public.audit_logs;
-- Optional TOAST compaction after audit trim is done:
-- VACUUM (FULL, VERBOSE) public.audit_logs;
82 changes: 52 additions & 30 deletions scripts/ops/verify_supabase_swap.sql
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
-- Post-deploy / post-reclaim verification for Capgo-EU swap pressure.
-- REQUIRED: psql (uses \gexec). Example:
-- psql "$DATABASE_URL" -v ON_ERROR_STOP=1 -f scripts/ops/verify_supabase_swap.sql
-- Capgo-EU post-reclaim verification — safe for Supabase SQL Editor.
-- Paste into SQL Editor and run (no psql meta-commands).

SELECT pg_size_pretty(pg_database_size(current_database())::bigint) AS db_size;

Expand Down Expand Up @@ -52,6 +51,10 @@ FROM (
)
) AS eligible;

SELECT count(*)::bigint AS non_null_manifest_versions
FROM public.app_versions
WHERE manifest IS NOT NULL;

Comment on lines +54 to +57

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Running this verification now scans every non-null manifest to produce an exact count, which can add substantial load or time out in SQL Editor on the production-sized app_versions table. Keeping this metric bounded like the existing sample, or making the global count a separate opt-in check, would keep the pasteable verification path lightweight.

(Based on your team's feedback about bounded verification queries.) .

View Feedback

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/ops/verify_supabase_swap.sql, line 54:

<comment>Running this verification now scans every non-null manifest to produce an exact count, which can add substantial load or time out in SQL Editor on the production-sized `app_versions` table. Keeping this metric bounded like the existing sample, or making the global count a separate opt-in check, would keep the pasteable verification path lightweight.

(Based on your team's feedback about bounded verification queries.) .</comment>

<file context>
@@ -52,6 +51,10 @@ FROM (
     )
 ) AS eligible;
 
+SELECT count(*)::bigint AS non_null_manifest_versions
+FROM public.app_versions
+WHERE manifest IS NOT NULL;
</file context>
Suggested change
SELECT count(*)::bigint AS non_null_manifest_versions
FROM public.app_versions
WHERE manifest IS NOT NULL;
SELECT count(*)::bigint AS non_null_manifest_versions_sample
FROM (
SELECT 1
FROM public.app_versions
WHERE manifest IS NOT NULL
ORDER BY id
LIMIT 1000
) AS sample;

SELECT
name,
enabled,
Expand All @@ -70,7 +73,15 @@ WHERE name IN (
)
ORDER BY name;

SELECT indexname
SELECT indexname,
(
SELECT i.indisvalid
FROM pg_catalog.pg_class AS idx
JOIN pg_catalog.pg_namespace AS ns ON ns.oid = idx.relnamespace
JOIN pg_catalog.pg_index AS i ON i.indexrelid = idx.oid
WHERE ns.nspname = 'public'
AND idx.relname = 'app_versions_manifest_present_idx'
) AS indisvalid
FROM pg_indexes
WHERE schemaname = 'public'
AND indexname = 'app_versions_manifest_present_idx';
Expand All @@ -82,33 +93,44 @@ SELECT EXISTS (
LIMIT 1
) AS has_audit_logs_older_than_30d;

SELECT format(
$fmt$SELECT %L AS queue_name,
EXISTS (
SELECT 1
FROM pgmq.%I
WHERE archived_at < now() - interval '2 days'
LIMIT 1
) AS has_rows_older_than_2d;$fmt$,
queue_name,
'a_' || pg_catalog.lower(queue_name)
)
FROM pgmq.list_queues()
\gexec
-- Fixed Capgo-EU queue set (no psql \gexec).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Queue verification now reports only four queues, so the SQL Editor run can show a clean result while other deployed pgmq queues still contain rows that cleanup_queue_messages() is expected to reclaim. Preserving the all-queue coverage through SQL-Editor-compatible dynamic SQL, or explicitly covering every deployed queue, would avoid this false negative.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/ops/verify_supabase_swap.sql, line 96:

<comment>Queue verification now reports only four queues, so the SQL Editor run can show a clean result while other deployed pgmq queues still contain rows that `cleanup_queue_messages()` is expected to reclaim. Preserving the all-queue coverage through SQL-Editor-compatible dynamic SQL, or explicitly covering every deployed queue, would avoid this false negative.</comment>

<file context>
@@ -82,33 +93,44 @@ SELECT EXISTS (
-)
-FROM pgmq.list_queues()
-\gexec
+-- Fixed Capgo-EU queue set (no psql \gexec).
+SELECT 'a_on_manifest_create' AS queue_name,
+       EXISTS (
</file context>

SELECT 'a_on_manifest_create' AS queue_name,
EXISTS (
SELECT 1 FROM pgmq.a_on_manifest_create
WHERE archived_at < now() - interval '2 days' LIMIT 1
) AS has_rows_older_than_2d
UNION ALL SELECT 'a_on_version_update',
EXISTS (
SELECT 1 FROM pgmq.a_on_version_update
WHERE archived_at < now() - interval '2 days' LIMIT 1
)
UNION ALL SELECT 'a_webhook_dispatcher',
EXISTS (
SELECT 1 FROM pgmq.a_webhook_dispatcher
WHERE archived_at < now() - interval '2 days' LIMIT 1
)
UNION ALL SELECT 'a_on_channel_update',
EXISTS (
SELECT 1 FROM pgmq.a_on_channel_update
WHERE archived_at < now() - interval '2 days' LIMIT 1
);

SELECT format(
$fmt$SELECT %L AS queue_name,
EXISTS (
SELECT 1
FROM pgmq.%I
WHERE read_ct > 5
LIMIT 1
) AS has_stuck_read_ct_gt_5;$fmt$,
queue_name,
'q_' || pg_catalog.lower(queue_name)
)
FROM pgmq.list_queues()
\gexec
SELECT 'q_on_manifest_create' AS queue_name,
EXISTS (
SELECT 1 FROM pgmq.q_on_manifest_create WHERE read_ct > 5 LIMIT 1
) AS has_stuck_read_ct_gt_5
UNION ALL SELECT 'q_on_version_update',
EXISTS (
SELECT 1 FROM pgmq.q_on_version_update WHERE read_ct > 5 LIMIT 1
)
UNION ALL SELECT 'q_webhook_dispatcher',
EXISTS (
SELECT 1 FROM pgmq.q_webhook_dispatcher WHERE read_ct > 5 LIMIT 1
)
UNION ALL SELECT 'q_on_channel_update',
EXISTS (
SELECT 1 FROM pgmq.q_on_channel_update WHERE read_ct > 5 LIMIT 1
);

SELECT
'index hit rate' AS name,
Expand Down
Loading