lifecycle: only lock database when system migrations need to be applied, and during django migrations, and don't double unlock
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
parent
62c0f69541
commit
e22a286a6f
|
@ -13,6 +13,7 @@ from authentik.lib.config import CONFIG
|
||||||
|
|
||||||
LOGGER = get_logger()
|
LOGGER = get_logger()
|
||||||
ADV_LOCK_UID = 1000
|
ADV_LOCK_UID = 1000
|
||||||
|
LOCKED = False
|
||||||
|
|
||||||
|
|
||||||
class BaseMigration:
|
class BaseMigration:
|
||||||
|
@ -33,6 +34,22 @@ class BaseMigration:
|
||||||
"""Run the actual migration"""
|
"""Run the actual migration"""
|
||||||
|
|
||||||
|
|
||||||
|
def wait_for_lock():
|
||||||
|
"""lock an advisory lock to prevent multiple instances from migrating at once"""
|
||||||
|
LOGGER.info("waiting to acquire database lock")
|
||||||
|
curr.execute("SELECT pg_advisory_lock(%s)", (ADV_LOCK_UID,))
|
||||||
|
# pylint: disable=global-statement
|
||||||
|
global LOCKED
|
||||||
|
LOCKED = True
|
||||||
|
|
||||||
|
|
||||||
|
def release_lock():
|
||||||
|
"""Release database lock"""
|
||||||
|
if not LOCKED:
|
||||||
|
return
|
||||||
|
curr.execute("SELECT pg_advisory_unlock(%s)", (ADV_LOCK_UID,))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
||||||
conn = connect(
|
conn = connect(
|
||||||
|
@ -43,9 +60,6 @@ if __name__ == "__main__":
|
||||||
port=int(CONFIG.y("postgresql.port")),
|
port=int(CONFIG.y("postgresql.port")),
|
||||||
)
|
)
|
||||||
curr = conn.cursor()
|
curr = conn.cursor()
|
||||||
# lock an advisory lock to prevent multiple instances from migrating at once
|
|
||||||
LOGGER.info("waiting to acquire database lock")
|
|
||||||
curr.execute("SELECT pg_advisory_lock(%s)", (ADV_LOCK_UID,))
|
|
||||||
try:
|
try:
|
||||||
for migration in Path(__file__).parent.absolute().glob("system_migrations/*.py"):
|
for migration in Path(__file__).parent.absolute().glob("system_migrations/*.py"):
|
||||||
spec = spec_from_file_location("lifecycle.system_migrations", migration)
|
spec = spec_from_file_location("lifecycle.system_migrations", migration)
|
||||||
|
@ -58,11 +72,14 @@ if __name__ == "__main__":
|
||||||
continue
|
continue
|
||||||
migration = sub(curr, conn)
|
migration = sub(curr, conn)
|
||||||
if migration.needs_migration():
|
if migration.needs_migration():
|
||||||
|
wait_for_lock()
|
||||||
LOGGER.info("Migration needs to be applied", migration=sub)
|
LOGGER.info("Migration needs to be applied", migration=sub)
|
||||||
migration.run()
|
migration.run()
|
||||||
LOGGER.info("Migration finished applying", migration=sub)
|
LOGGER.info("Migration finished applying", migration=sub)
|
||||||
|
release_lock()
|
||||||
LOGGER.info("applying django migrations")
|
LOGGER.info("applying django migrations")
|
||||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "authentik.root.settings")
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "authentik.root.settings")
|
||||||
|
wait_for_lock()
|
||||||
try:
|
try:
|
||||||
from django.core.management import execute_from_command_line
|
from django.core.management import execute_from_command_line
|
||||||
except ImportError as exc:
|
except ImportError as exc:
|
||||||
|
@ -73,4 +90,4 @@ if __name__ == "__main__":
|
||||||
) from exc
|
) from exc
|
||||||
execute_from_command_line(["", "migrate"])
|
execute_from_command_line(["", "migrate"])
|
||||||
finally:
|
finally:
|
||||||
curr.execute("SELECT pg_advisory_unlock(%s)", (ADV_LOCK_UID,))
|
release_lock()
|
||||||
|
|
Reference in New Issue