migration improvements: (#1228)
* migration improvements + rerunning migrations: (fixes #1227) - avoid starting some workers while migration is still running - ensure workers that aren't performing migration await for migration to complete - backend will not be valid until migration is run * allow rerunning migration from specified version via --set rerun_from_migration=<VERSION> (replaces rerun_last_migration)
This commit is contained in:
parent
1f74f03447
commit
86a424af93
@ -52,15 +52,14 @@ def init_db():
|
|||||||
|
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
async def ping_db(mdb, db_inited):
|
async def ping_db(mdb):
|
||||||
"""run in loop until db is up, set db_inited['inited'] property to true"""
|
"""run in loop until db is up, set db_inited['inited'] property to true"""
|
||||||
print("Waiting DB", flush=True)
|
print("Waiting DB", flush=True)
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
result = await mdb.command("ping")
|
result = await mdb.command("ping")
|
||||||
assert result.get("ok")
|
assert result.get("ok")
|
||||||
db_inited["inited"] = True
|
print("DB reached")
|
||||||
print("DB Ready!")
|
|
||||||
break
|
break
|
||||||
# pylint: disable=broad-exception-caught
|
# pylint: disable=broad-exception-caught
|
||||||
except Exception:
|
except Exception:
|
||||||
@ -88,13 +87,14 @@ async def update_and_prepare_db(
|
|||||||
- Create/update default org
|
- Create/update default org
|
||||||
|
|
||||||
"""
|
"""
|
||||||
await ping_db(mdb, db_inited)
|
await ping_db(mdb)
|
||||||
print("Database setup started", flush=True)
|
print("Database setup started", flush=True)
|
||||||
if await run_db_migrations(mdb, user_manager):
|
if await run_db_migrations(mdb, user_manager):
|
||||||
await drop_indexes(mdb)
|
await drop_indexes(mdb)
|
||||||
await create_indexes(org_ops, crawl_ops, crawl_config_ops, coll_ops, invite_ops)
|
await create_indexes(org_ops, crawl_ops, crawl_config_ops, coll_ops, invite_ops)
|
||||||
await user_manager.create_super_user()
|
await user_manager.create_super_user()
|
||||||
await org_ops.create_default_org()
|
await org_ops.create_default_org()
|
||||||
|
db_inited["inited"] = True
|
||||||
print("Database updated and ready", flush=True)
|
print("Database updated and ready", flush=True)
|
||||||
|
|
||||||
|
|
||||||
@ -141,6 +141,26 @@ async def run_db_migrations(mdb, user_manager):
|
|||||||
return migrations_run
|
return migrations_run
|
||||||
|
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
async def await_db_and_migrations(mdb, db_inited):
|
||||||
|
"""await that db is available and any migrations in progress finish"""
|
||||||
|
await ping_db(mdb)
|
||||||
|
print("Database setup started", flush=True)
|
||||||
|
|
||||||
|
base_migration = BaseMigration(mdb, CURR_DB_VERSION)
|
||||||
|
while await base_migration.migrate_up_needed(ignore_rerun=True):
|
||||||
|
version = await base_migration.get_db_version()
|
||||||
|
print(
|
||||||
|
f"Waiting for migrations to finish, DB at {version}, latest {CURR_DB_VERSION}",
|
||||||
|
flush=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
await asyncio.sleep(5)
|
||||||
|
|
||||||
|
db_inited["inited"] = True
|
||||||
|
print("Database updated and ready", flush=True)
|
||||||
|
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
async def drop_indexes(mdb):
|
async def drop_indexes(mdb):
|
||||||
"""Drop all database indexes."""
|
"""Drop all database indexes."""
|
||||||
|
|||||||
@ -10,7 +10,7 @@ from fastapi import FastAPI, HTTPException
|
|||||||
from fastapi.responses import JSONResponse
|
from fastapi.responses import JSONResponse
|
||||||
from fastapi.routing import APIRouter
|
from fastapi.routing import APIRouter
|
||||||
|
|
||||||
from .db import init_db, ping_db, update_and_prepare_db
|
from .db import init_db, await_db_and_migrations, update_and_prepare_db
|
||||||
|
|
||||||
from .emailsender import EmailSender
|
from .emailsender import EmailSender
|
||||||
from .invites import init_invites
|
from .invites import init_invites
|
||||||
@ -157,7 +157,7 @@ def main():
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
asyncio.create_task(ping_db(mdb, db_inited))
|
asyncio.create_task(await_db_and_migrations(mdb, db_inited))
|
||||||
|
|
||||||
app.include_router(org_ops.router)
|
app.include_router(org_ops.router)
|
||||||
|
|
||||||
|
|||||||
@ -15,7 +15,7 @@ class BaseMigration:
|
|||||||
def __init__(self, mdb, migration_version="0001"):
|
def __init__(self, mdb, migration_version="0001"):
|
||||||
self.mdb = mdb
|
self.mdb = mdb
|
||||||
self.migration_version = migration_version
|
self.migration_version = migration_version
|
||||||
self.rerun_migration = os.environ.get("RERUN_LAST_MIGRATION") == "1"
|
self.rerun_from_migration = os.environ.get("RERUN_FROM_MIGRATION")
|
||||||
|
|
||||||
async def get_db_version(self):
|
async def get_db_version(self):
|
||||||
"""Get current db version from database."""
|
"""Get current db version from database."""
|
||||||
@ -37,7 +37,7 @@ class BaseMigration:
|
|||||||
{}, {"$set": {"version": self.migration_version}}, upsert=True
|
{}, {"$set": {"version": self.migration_version}}, upsert=True
|
||||||
)
|
)
|
||||||
|
|
||||||
async def migrate_up_needed(self):
|
async def migrate_up_needed(self, ignore_rerun=False):
|
||||||
"""Verify migration up is needed and return boolean indicator."""
|
"""Verify migration up is needed and return boolean indicator."""
|
||||||
db_version = await self.get_db_version()
|
db_version = await self.get_db_version()
|
||||||
print(f"Current database version before migration: {db_version}")
|
print(f"Current database version before migration: {db_version}")
|
||||||
@ -48,8 +48,12 @@ class BaseMigration:
|
|||||||
if db_version < self.migration_version:
|
if db_version < self.migration_version:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if self.rerun_migration and db_version == self.migration_version:
|
if (
|
||||||
print("Rerunning last migration")
|
not ignore_rerun
|
||||||
|
and self.rerun_from_migration
|
||||||
|
and self.rerun_from_migration <= self.migration_version
|
||||||
|
):
|
||||||
|
print(f"Rerunning migrations from: {self.migration_version}")
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|||||||
@ -34,7 +34,7 @@ data:
|
|||||||
|
|
||||||
IDLE_TIMEOUT: "{{ .Values.profile_browser_idle_seconds | default 60 }}"
|
IDLE_TIMEOUT: "{{ .Values.profile_browser_idle_seconds | default 60 }}"
|
||||||
|
|
||||||
RERUN_LAST_MIGRATION: "{{ .Values.rerun_last_migration }}"
|
RERUN_FROM_MIGRATION: "{{ .Values.rerun_from_migration }}"
|
||||||
|
|
||||||
PRESIGN_DURATION_MINUTES: "{{ .Values.storage_presign_duration_minutes | default 60 }}"
|
PRESIGN_DURATION_MINUTES: "{{ .Values.storage_presign_duration_minutes | default 60 }}"
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user