-
Notifications
You must be signed in to change notification settings - Fork 92
feat(RHINENG-21958): Implement database migration locking #3157
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: master
Are you sure you want to change the base?
Conversation
Reviewer's GuideThis PR adds a PostgreSQL advisory lock mechanism around Alembic migrations to prevent concurrent migrations, featuring a computed lock ID, configurable timeout and retry interval, retry logic with detailed logging, graceful exit on failure, and guaranteed lock release in a finally block. Sequence diagram for migration lock acquisition and release during Alembic migrationssequenceDiagram
participant Pod
participant DB["PostgreSQL"]
participant Alembic
Pod->DB: Try to acquire advisory lock (pg_try_advisory_lock)
alt Lock acquired
Pod->Alembic: Run migrations
Alembic->DB: Execute migration SQL
Pod->DB: Release advisory lock (pg_advisory_unlock)
else Lock not acquired (timeout)
Pod->DB: Retry until timeout
Pod->Pod: Log and exit gracefully
end
Class diagram for migration lock logic in env.pyclassDiagram
class env {
+acquire_migration_lock(conn: Connection, timeout: int) bool
+release_migration_lock(conn: Connection)
MIGRATION_LOCK_ID: int
MIGRATION_LOCK_TIMEOUT: int
MIGRATION_LOCK_RETRY_INTERVAL: int
}
class AlembicMigration {
+migrate_alembic_version_table(conn: Connection)
}
env <|-- AlembicMigration
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
Adds PostgreSQL advisory lock mechanism to prevent race conditions when multiple pods attempt to run migrations simultaneously during deployments. - Lock acquired before any migration work (including version table checks) - Configurable timeout (MIGRATION_LOCK_TIMEOUT, default 30 min) - Retry logic with configurable interval (MIGRATION_LOCK_RETRY_INTERVAL, default 15s) - Enhanced logging for lock acquisition, wait times, and release - Graceful pod exit if lock cannot be acquired - Lock always released in finally block to prevent deadlocks 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
abeb55f to
aca402e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New security issues found
| elapsed = time.time() - start_time | ||
|
|
||
| # Try to acquire the lock (non-blocking) | ||
| result = conn.execute(f"SELECT pg_try_advisory_lock({MIGRATION_LOCK_ID})").scalar() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
security (python.sqlalchemy.security.sqlalchemy-execute-raw-query): Avoiding SQL string concatenation: untrusted input concatenated with raw SQL query can result in SQL Injection. In order to execute raw query safely, prepared statement should be used. SQLAlchemy provides TextualSQL to easily used prepared statement with named parameters. For complex SQL composition, use SQL Expression Language or Schema Definition Language. In most cases, SQLAlchemy ORM will be a better option.
Source: opengrep
| conn: SQLAlchemy connection object | ||
| """ | ||
| try: | ||
| result = conn.execute(f"SELECT pg_advisory_unlock({MIGRATION_LOCK_ID})").scalar() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
security (python.sqlalchemy.security.sqlalchemy-execute-raw-query): Avoiding SQL string concatenation: untrusted input concatenated with raw SQL query can result in SQL Injection. In order to execute raw query safely, prepared statement should be used. SQLAlchemy provides TextualSQL to easily used prepared statement with named parameters. For complex SQL composition, use SQL Expression Language or Schema Definition Language. In most cases, SQLAlchemy ORM will be a better option.
Source: opengrep
|
Ah, we already do have a lock! Interesting :) |
Adds PostgreSQL advisory lock mechanism to prevent race conditions when multiple pods attempt to run migrations simultaneously during deployments.
🤖 Generated with Claude Code
This PR is being created to address RHINENG-21958.
Summary by Sourcery
Serialize database migrations across multiple pods using PostgreSQL advisory locks, with configurable timeout and retry behavior and improved logging to ensure safe and observable deployments
New Features:
Enhancements: