Wait for DB init for healthcheck + settings (#885)
* init check: (backend fix for #794) - wait until db is inited before settings /api/settings to return 200 - also return 503 from healthcheck endpoint, until db is available
This commit is contained in:
parent
965aa7ff90
commit
d7c19c7613
@ -4,6 +4,8 @@ Browsertrix API Mongo DB initialization
|
|||||||
import importlib.util
|
import importlib.util
|
||||||
import os
|
import os
|
||||||
import urllib
|
import urllib
|
||||||
|
import asyncio
|
||||||
|
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
import motor.motor_asyncio
|
import motor.motor_asyncio
|
||||||
@ -49,6 +51,23 @@ def init_db():
|
|||||||
return client, mdb
|
return client, mdb
|
||||||
|
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
async def ping_db(mdb, db_inited):
|
||||||
|
"""run in loop until db is up, set db_inited['inited'] property to true"""
|
||||||
|
print("Waiting DB", flush=True)
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
result = await mdb.command("ping")
|
||||||
|
assert result.get("ok")
|
||||||
|
db_inited["inited"] = True
|
||||||
|
print("DB Ready!")
|
||||||
|
break
|
||||||
|
# pylint: disable=broad-exception-caught
|
||||||
|
except Exception:
|
||||||
|
print("Retrying, waiting for DB to be ready")
|
||||||
|
await asyncio.sleep(3)
|
||||||
|
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
async def update_and_prepare_db(
|
async def update_and_prepare_db(
|
||||||
# pylint: disable=R0913
|
# pylint: disable=R0913
|
||||||
@ -59,6 +78,7 @@ async def update_and_prepare_db(
|
|||||||
crawl_config_ops,
|
crawl_config_ops,
|
||||||
coll_ops,
|
coll_ops,
|
||||||
invite_ops,
|
invite_ops,
|
||||||
|
db_inited,
|
||||||
):
|
):
|
||||||
"""Prepare database for application.
|
"""Prepare database for application.
|
||||||
|
|
||||||
@ -68,6 +88,7 @@ async def update_and_prepare_db(
|
|||||||
- Create/update default org
|
- Create/update default org
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
await ping_db(mdb, db_inited)
|
||||||
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)
|
||||||
|
@ -6,11 +6,11 @@ import os
|
|||||||
import asyncio
|
import asyncio
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from fastapi import FastAPI
|
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, update_and_prepare_db
|
from .db import init_db, ping_db, update_and_prepare_db
|
||||||
|
|
||||||
from .emailsender import EmailSender
|
from .emailsender import EmailSender
|
||||||
from .invites import init_invites
|
from .invites import init_invites
|
||||||
@ -35,6 +35,8 @@ app_root = FastAPI(
|
|||||||
openapi_url=API_PREFIX + "/openapi.json",
|
openapi_url=API_PREFIX + "/openapi.json",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
db_inited = {"inited": False}
|
||||||
|
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# pylint: disable=too-many-locals
|
# pylint: disable=too-many-locals
|
||||||
@ -114,14 +116,25 @@ def main():
|
|||||||
if run_once_lock("btrix-init-db"):
|
if run_once_lock("btrix-init-db"):
|
||||||
asyncio.create_task(
|
asyncio.create_task(
|
||||||
update_and_prepare_db(
|
update_and_prepare_db(
|
||||||
mdb, user_manager, org_ops, crawls, crawl_config_ops, coll_ops, invites
|
mdb,
|
||||||
|
user_manager,
|
||||||
|
org_ops,
|
||||||
|
crawls,
|
||||||
|
crawl_config_ops,
|
||||||
|
coll_ops,
|
||||||
|
invites,
|
||||||
|
db_inited,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
else:
|
||||||
|
asyncio.create_task(ping_db(mdb, db_inited))
|
||||||
|
|
||||||
app.include_router(org_ops.router)
|
app.include_router(org_ops.router)
|
||||||
|
|
||||||
@app.get("/settings")
|
@app.get("/settings")
|
||||||
async def get_settings():
|
async def get_settings():
|
||||||
|
if not db_inited.get("inited"):
|
||||||
|
raise HTTPException(status_code=503, detail="not_ready_yet")
|
||||||
return settings
|
return settings
|
||||||
|
|
||||||
# internal routes
|
# internal routes
|
||||||
@ -132,6 +145,8 @@ def main():
|
|||||||
|
|
||||||
@app_root.get("/healthz", include_in_schema=False)
|
@app_root.get("/healthz", include_in_schema=False)
|
||||||
async def healthz():
|
async def healthz():
|
||||||
|
if not db_inited.get("inited"):
|
||||||
|
raise HTTPException(status_code=503, detail="not_ready_yet")
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
app_root.include_router(app, prefix=API_PREFIX)
|
app_root.include_router(app, prefix=API_PREFIX)
|
||||||
|
Loading…
Reference in New Issue
Block a user