-
Notifications
You must be signed in to change notification settings - Fork 5
Fix concurrent role creation race condition #325
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
base: main
Are you sure you want to change the base?
Conversation
- Add advisory locks (pg_advisory_xact_lock) to serialize role creation - Catch both duplicate_object and unique_violation exceptions - Fixes error: duplicate key value violates unique constraint pg_authid_rolname_index - Applied to all role creation code paths: - bootstrap-roles.sql (anonymous, authenticated, administrator) - bootstrap-test-roles.sql (app_user, app_admin) - LaunchQLInit.bootstrapDbRoles() - DbAdmin.createUserRole() Under concurrent execution, CREATE ROLE can hit the pg_authid_rolname_index unique constraint before the duplicate_object check, resulting in unique_violation (23505) instead of duplicate_object (42710). Advisory locks prevent the race entirely, and catching both exceptions provides defense in depth. Co-Authored-By: Dan Lynch <[email protected]>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
- Add IF NOT EXISTS checks before every CREATE ROLE statement - Add membership pre-checks before every GRANT statement - Keep advisory locks for serialization (with-locks variant) - Keep both exception handlers (duplicate_object OR unique_violation) - Defense-in-depth: pre-check + lock + exceptions This pedantic approach ensures maximum safety against concurrent role creation and membership grant races. Co-Authored-By: Dan Lynch <[email protected]>
This test demonstrates the race condition that occurs when multiple processes attempt to create the same PostgreSQL role simultaneously. On the main branch, this test FAILS with unique_violation error when multiple concurrent CREATE ROLE statements hit the pg_authid_rolname_index. The test includes: - Concurrent role creation test (reproduces the bug) - Performance benchmarks at concurrency levels 2, 4, 8 - Concurrent GRANT operations test - High concurrency stress test with retries This PR intentionally fails on main to demonstrate the problem. Compare against PR #325 (with locks) and PR #326 (no locks) to see fixes. Co-Authored-By: Dan Lynch <[email protected]>
Latest UpdatesAdded comprehensive pre-existence checks to all CREATE ROLE and GRANT statements for defense-in-depth:
Related PRs
TestingThe concurrent test in PR #327 should PASS with this fix applied. Link to Devin run: https://app.devin.ai/sessions/2c33cab4511f4a7897e29001895487df |
Fix concurrent role creation race condition with advisory locks
Summary
Fixes the intermittent CI error:
ERROR: duplicate key value violates unique constraint "pg_authid_rolname_index"that occurs when multiple processes try to create the same PostgreSQL role concurrently.Root Cause: Under concurrent execution,
CREATE ROLEcan hit thepg_authid_rolname_indexunique constraint before PostgreSQL's duplicate object detection runs, resulting inunique_violation(error code 23505) instead ofduplicate_object(error code 42710).Solution:
pg_advisory_xact_lock(42, hashtext(rolname))to serialize role creation per role nameduplicate_objectORunique_violationbootstrap-roles.sql(anonymous, authenticated, administrator)bootstrap-test-roles.sql(app_user, app_admin)LaunchQLInit.bootstrapDbRoles()(custom users)DbAdmin.createUserRole()(pgsql-test users)The advisory lock prevents the race entirely, while catching both exceptions provides defense in depth.
Review & Testing Checklist for Human
CREATE ROLEstatements that might need the same fix42doesn't collide with other advisory locks used elsewhere in the systemRecommended Test Plan
lql admin-users add --test --yesin multiple parallel shellsNotes
pg_advisory_xact_lock) and will be automatically released at transaction endhashtext()function provides good distribution of lock keys based on role namesLink to Devin run: https://app.devin.ai/sessions/2c33cab4511f4a7897e29001895487df
Requested by: Dan Lynch (@pyramation)