Skip to content

Commit 4194b5b

Browse files
committed
fix(db): alter the live OAuth tables after 0448's commit so token inserts cannot deadlock it
Holding oauth_client's ACCESS EXCLUSIVE lock across the other ALTERs formed a cycle with token inserts, which lock their own table before their foreign-key check reaches oauth_client: the migration or the insert died with 40P01, and the runner retries only lock timeouts, so the deploy failed. Each table is now altered in its own autocommitted statement.
1 parent 6e554b9 commit 4194b5b

1 file changed

Lines changed: 30 additions & 24 deletions

File tree

‎packages/db/migrations/0448_oauth_provider_better_auth_1_7.sql‎

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77
-- per-organization and per-workflow MCP resources itself and never registers private_key_jwt
88
-- clients, but the provider reads these tables, so they must exist.
99
--
10-
-- Tables are altered in the order token issuance locks them (client, consent, refresh token, access
11-
-- token), so a concurrent grant waits for this migration instead of deadlocking with it.
10+
-- The live OAuth tables are altered after the COMMIT, one autocommitted statement each, so this
11+
-- migration never holds one table's lock while waiting for another's. A token insert locks its own
12+
-- table before its foreign-key check reaches oauth_client; holding oauth_client across the other
13+
-- ALTERs would deadlock with it.
1214
--
1315
-- Replay-safety: this file ends in CONCURRENTLY index builds on the live token tables below an
1416
-- embedded COMMIT, so a failure there replays the whole file from the top — every statement here
@@ -49,28 +51,6 @@ CREATE TABLE IF NOT EXISTS "oauth_client_resource" (
4951
);
5052
--> statement-breakpoint
5153
CREATE INDEX IF NOT EXISTS "oauth_client_resource_resource_id_idx" ON "oauth_client_resource" USING btree ("resource_id");--> statement-breakpoint
52-
ALTER TABLE "oauth_client" ADD COLUMN IF NOT EXISTS "client_discovery_id" text;--> statement-breakpoint
53-
ALTER TABLE "oauth_client" ADD COLUMN IF NOT EXISTS "client_credentials_scopes" text[] DEFAULT '{}'::text[];--> statement-breakpoint
54-
ALTER TABLE "oauth_client" ADD COLUMN IF NOT EXISTS "backchannel_logout_uri" text;--> statement-breakpoint
55-
ALTER TABLE "oauth_client" ADD COLUMN IF NOT EXISTS "backchannel_logout_session_required" boolean;--> statement-breakpoint
56-
ALTER TABLE "oauth_client" ADD COLUMN IF NOT EXISTS "application_type" text;--> statement-breakpoint
57-
ALTER TABLE "oauth_client" ADD COLUMN IF NOT EXISTS "jwks" text;--> statement-breakpoint
58-
ALTER TABLE "oauth_client" ADD COLUMN IF NOT EXISTS "jwks_uri" text;--> statement-breakpoint
59-
ALTER TABLE "oauth_client" ADD COLUMN IF NOT EXISTS "dpop_bound_access_tokens" boolean DEFAULT false;--> statement-breakpoint
60-
ALTER TABLE "oauth_consent" ADD COLUMN IF NOT EXISTS "resources" text[];--> statement-breakpoint
61-
ALTER TABLE "oauth_consent" ADD COLUMN IF NOT EXISTS "requested_user_info_claims" text[];--> statement-breakpoint
62-
ALTER TABLE "oauth_refresh_token" ADD COLUMN IF NOT EXISTS "authorization_code_id" text;--> statement-breakpoint
63-
ALTER TABLE "oauth_refresh_token" ADD COLUMN IF NOT EXISTS "resources" text[];--> statement-breakpoint
64-
ALTER TABLE "oauth_refresh_token" ADD COLUMN IF NOT EXISTS "requested_user_info_claims" text[];--> statement-breakpoint
65-
ALTER TABLE "oauth_refresh_token" ADD COLUMN IF NOT EXISTS "rotated_at" timestamp;--> statement-breakpoint
66-
ALTER TABLE "oauth_refresh_token" ADD COLUMN IF NOT EXISTS "rotation_replay_response" text;--> statement-breakpoint
67-
ALTER TABLE "oauth_refresh_token" ADD COLUMN IF NOT EXISTS "rotation_replay_expires_at" timestamp;--> statement-breakpoint
68-
ALTER TABLE "oauth_refresh_token" ADD COLUMN IF NOT EXISTS "confirmation" jsonb;--> statement-breakpoint
69-
ALTER TABLE "oauth_access_token" ADD COLUMN IF NOT EXISTS "revoked" timestamp;--> statement-breakpoint
70-
ALTER TABLE "oauth_access_token" ADD COLUMN IF NOT EXISTS "authorization_code_id" text;--> statement-breakpoint
71-
ALTER TABLE "oauth_access_token" ADD COLUMN IF NOT EXISTS "resources" text[];--> statement-breakpoint
72-
ALTER TABLE "oauth_access_token" ADD COLUMN IF NOT EXISTS "requested_user_info_claims" text[];--> statement-breakpoint
73-
ALTER TABLE "oauth_access_token" ADD COLUMN IF NOT EXISTS "confirmation" jsonb;--> statement-breakpoint
7454
-- A failed concurrent build leaves an invalid index that IF NOT EXISTS would keep: each replay
7555
-- moves one aside to be dropped, never a valid index or one on another table.
7656
DO $$
@@ -96,6 +76,32 @@ BEGIN
9676
END LOOP;
9777
END $$;--> statement-breakpoint
9878
COMMIT;--> statement-breakpoint
79+
ALTER TABLE "oauth_client"
80+
ADD COLUMN IF NOT EXISTS "client_discovery_id" text,
81+
ADD COLUMN IF NOT EXISTS "client_credentials_scopes" text[] DEFAULT '{}'::text[],
82+
ADD COLUMN IF NOT EXISTS "backchannel_logout_uri" text,
83+
ADD COLUMN IF NOT EXISTS "backchannel_logout_session_required" boolean,
84+
ADD COLUMN IF NOT EXISTS "application_type" text,
85+
ADD COLUMN IF NOT EXISTS "jwks" text,
86+
ADD COLUMN IF NOT EXISTS "jwks_uri" text,
87+
ADD COLUMN IF NOT EXISTS "dpop_bound_access_tokens" boolean DEFAULT false;--> statement-breakpoint
88+
ALTER TABLE "oauth_consent"
89+
ADD COLUMN IF NOT EXISTS "resources" text[],
90+
ADD COLUMN IF NOT EXISTS "requested_user_info_claims" text[];--> statement-breakpoint
91+
ALTER TABLE "oauth_refresh_token"
92+
ADD COLUMN IF NOT EXISTS "authorization_code_id" text,
93+
ADD COLUMN IF NOT EXISTS "resources" text[],
94+
ADD COLUMN IF NOT EXISTS "requested_user_info_claims" text[],
95+
ADD COLUMN IF NOT EXISTS "rotated_at" timestamp,
96+
ADD COLUMN IF NOT EXISTS "rotation_replay_response" text,
97+
ADD COLUMN IF NOT EXISTS "rotation_replay_expires_at" timestamp,
98+
ADD COLUMN IF NOT EXISTS "confirmation" jsonb;--> statement-breakpoint
99+
ALTER TABLE "oauth_access_token"
100+
ADD COLUMN IF NOT EXISTS "revoked" timestamp,
101+
ADD COLUMN IF NOT EXISTS "authorization_code_id" text,
102+
ADD COLUMN IF NOT EXISTS "resources" text[],
103+
ADD COLUMN IF NOT EXISTS "requested_user_info_claims" text[],
104+
ADD COLUMN IF NOT EXISTS "confirmation" jsonb;--> statement-breakpoint
99105
SET lock_timeout = 0;--> statement-breakpoint
100106
DROP INDEX CONCURRENTLY IF EXISTS "oauth_access_token_authorization_code_id_idx_failed";--> statement-breakpoint
101107
CREATE INDEX CONCURRENTLY IF NOT EXISTS "oauth_access_token_authorization_code_id_idx" ON "oauth_access_token" USING btree ("authorization_code_id");--> statement-breakpoint

0 commit comments

Comments
 (0)