Merge pull request 'future/AURORA-1008' (#8) from future/AURORA-1008 into test
Reviewed-on: #8 Reviewed-by: tsygankoviva <tsygankov.itis@gmail.com>
This commit is contained in:
commit
47fac8acbc
25
api/src/api/v1/admin.py
Normal file
25
api/src/api/v1/admin.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
from fastapi import APIRouter, Depends, HTTPException, status
|
||||||
|
from sqlalchemy import text
|
||||||
|
from sqlalchemy.exc import SQLAlchemyError
|
||||||
|
|
||||||
|
from src.api.v1.deps import require_admin
|
||||||
|
from src.db.base import engine
|
||||||
|
from src.db.models.app_user import AppUser
|
||||||
|
|
||||||
|
router = APIRouter(prefix="/admin", tags=["admin"])
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/refresh-tree")
|
||||||
|
async def refresh_tree(current_user: AppUser = Depends(require_admin)):
|
||||||
|
"""Обновляет MV дерева статей расходов."""
|
||||||
|
try:
|
||||||
|
async with engine.connect() as conn:
|
||||||
|
# CONCURRENTLY требует autocommit-режим.
|
||||||
|
conn = await conn.execution_options(isolation_level="AUTOCOMMIT")
|
||||||
|
await conn.execute(text("REFRESH MATERIALIZED VIEW CONCURRENTLY v3.mv_expense_item_tree"))
|
||||||
|
except SQLAlchemyError as exc:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
||||||
|
detail=f"Не удалось обновить mv_expense_item_tree: {exc}",
|
||||||
|
) from exc
|
||||||
|
return {"status": "ok", "message": "mv_expense_item_tree refreshed"}
|
||||||
@ -1,11 +1,10 @@
|
|||||||
from fastapi import APIRouter
|
from fastapi import APIRouter
|
||||||
|
|
||||||
from src.api.v1 import projects
|
from src.api.v1 import auth, users, admin, forms, projects
|
||||||
from src.api.v1 import forms
|
|
||||||
from src.api.v1 import auth, users
|
|
||||||
|
|
||||||
api_router = APIRouter()
|
api_router = APIRouter()
|
||||||
api_router.include_router(auth.router)
|
api_router.include_router(auth.router)
|
||||||
api_router.include_router(users.router)
|
api_router.include_router(users.router)
|
||||||
|
api_router.include_router(admin.router)
|
||||||
api_router.include_router(forms.router)
|
api_router.include_router(forms.router)
|
||||||
api_router.include_router(projects.router)
|
api_router.include_router(projects.router)
|
||||||
|
|||||||
@ -2,8 +2,10 @@ import os
|
|||||||
from contextlib import asynccontextmanager
|
from contextlib import asynccontextmanager
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
|
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI, Response
|
||||||
from fastapi.middleware.cors import CORSMiddleware
|
from fastapi.middleware.cors import CORSMiddleware
|
||||||
|
from sqlalchemy import text
|
||||||
|
from sqlalchemy.exc import SQLAlchemyError
|
||||||
from fastapi.staticfiles import StaticFiles
|
from fastapi.staticfiles import StaticFiles
|
||||||
from starlette.middleware.gzip import GZipMiddleware
|
from starlette.middleware.gzip import GZipMiddleware
|
||||||
from uvicorn.middleware.proxy_headers import ProxyHeadersMiddleware
|
from uvicorn.middleware.proxy_headers import ProxyHeadersMiddleware
|
||||||
@ -69,6 +71,41 @@ async def healthcheck2():
|
|||||||
"port": settings.PORT,
|
"port": settings.PORT,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@app.get("/healthz", status_code=200)
|
||||||
|
async def healthz():
|
||||||
|
return {"status": "ok", "uptime": UP_TIME, "version": VERSION}
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/readyz")
|
||||||
|
async def readyz(response: Response):
|
||||||
|
result = {"status": "ok", "db_status": "ok", "mv_expense_item_tree": "ok"}
|
||||||
|
try:
|
||||||
|
async with engine.connect() as conn:
|
||||||
|
await conn.execute(text("SELECT 1"))
|
||||||
|
if "postgresql" in settings.DATABASE_URL:
|
||||||
|
my_exists = (
|
||||||
|
await conn.execute(
|
||||||
|
text(
|
||||||
|
"""
|
||||||
|
SELECT 1
|
||||||
|
FROM pg_matviews
|
||||||
|
WHERE schemaname = 'v3'
|
||||||
|
AND matviewname = 'mv_expense_item_tree'
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
)
|
||||||
|
).scalar_one_or_none()
|
||||||
|
if my_exists is None:
|
||||||
|
result["status"] = "fail"
|
||||||
|
result["mv_expense_item_tree"] = "missing"
|
||||||
|
response.status_code = 503
|
||||||
|
except SQLAlchemyError as exc:
|
||||||
|
result["status"] = "fail"
|
||||||
|
result["db"] = f"error: {exc.__class__.__name__}"
|
||||||
|
response.status_code = 503
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if not settings.DEBUG:
|
if not settings.DEBUG:
|
||||||
app.add_middleware(
|
app.add_middleware(
|
||||||
@ -83,6 +120,16 @@ if not settings.DEBUG:
|
|||||||
path=settings.ROOT_PATH + "/healthcheck",
|
path=settings.ROOT_PATH + "/healthcheck",
|
||||||
type_search=SearchType.ABSOLUTE,
|
type_search=SearchType.ABSOLUTE,
|
||||||
),
|
),
|
||||||
|
OpenEndpoint(path="/healthz", type_search=SearchType.ABSOLUTE),
|
||||||
|
OpenEndpoint(
|
||||||
|
path=settings.ROOT_PATH + "/healthz",
|
||||||
|
type_search=SearchType.ABSOLUTE,
|
||||||
|
),
|
||||||
|
OpenEndpoint(path="/readyz", type_search=SearchType.ABSOLUTE),
|
||||||
|
OpenEndpoint(
|
||||||
|
path=settings.ROOT_PATH + "/readyz",
|
||||||
|
type_search=SearchType.ABSOLUTE,
|
||||||
|
),
|
||||||
OpenEndpoint(path="/openapi.json", type_search=SearchType.START),
|
OpenEndpoint(path="/openapi.json", type_search=SearchType.START),
|
||||||
OpenEndpoint(
|
OpenEndpoint(
|
||||||
path=settings.ROOT_PATH + "/openapi.json",
|
path=settings.ROOT_PATH + "/openapi.json",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user