fix: reconcile ambiguous Stripe event ordering
Some checks failed
CI / verify (push) Has been cancelled

This commit is contained in:
237899745
2026-07-26 03:08:23 +08:00
parent 08000cc16e
commit 326a678249
6 changed files with 1081 additions and 262 deletions

View File

@@ -0,0 +1,57 @@
ALTER TABLE provider_object_event_watermarks
ADD COLUMN IF NOT EXISTS requires_reconciliation BOOLEAN NOT NULL DEFAULT false,
ADD COLUMN IF NOT EXISTS reconciliation_reason TEXT,
ADD COLUMN IF NOT EXISTS last_snapshot_at TIMESTAMPTZ;
CREATE TABLE IF NOT EXISTS stripe_subscription_reconciliations (
provider_subscription_id VARCHAR(200) PRIMARY KEY,
reason TEXT NOT NULL,
status VARCHAR(20) NOT NULL DEFAULT 'pending',
attempts INTEGER NOT NULL DEFAULT 0,
next_attempt_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
last_error TEXT,
lease_owner UUID,
lease_until TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
completed_at TIMESTAMPTZ,
CONSTRAINT stripe_subscription_reconciliations_status_check
CHECK (status IN ('pending', 'processing', 'completed', 'failed'))
);
WITH corrected AS (
UPDATE provider_object_event_watermarks
SET last_event_created = 0,
last_event_rank = 0,
last_event_id = 'reconcile:migration',
requires_reconciliation = true,
reconciliation_reason = 'migration_016_non_causal_seed',
updated_at = NOW()
WHERE provider = 'stripe'
AND object_type = 'subscription'
AND is_deleted = false
AND last_event_id LIKE 'migration:%'
RETURNING provider_object_id
)
INSERT INTO stripe_subscription_reconciliations (
provider_subscription_id, reason, status, next_attempt_at
)
SELECT
provider_object_id,
'migration_016_non_causal_seed',
'pending',
NOW()
FROM corrected
ON CONFLICT (provider_subscription_id) DO UPDATE
SET reason = EXCLUDED.reason,
status = 'pending',
next_attempt_at = NOW(),
last_error = NULL,
lease_owner = NULL,
lease_until = NULL,
completed_at = NULL,
updated_at = NOW();
CREATE INDEX IF NOT EXISTS idx_stripe_subscription_reconciliations_ready
ON stripe_subscription_reconciliations(next_attempt_at, updated_at)
WHERE status IN ('pending', 'failed');