File size: 2,589 Bytes
62516b8
 
08b192a
62516b8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
08b192a
62516b8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
08b192a
62516b8
 
 
 
 
08b192a
62516b8
 
 
08b192a
62516b8
 
 
 
 
08b192a
62516b8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
from __future__ import annotations

import logging
from collections.abc import Awaitable, Callable
from contextlib import asynccontextmanager
from typing import AsyncIterator

from fastapi import FastAPI, Request
from starlette.responses import Response

from src.agent.callback import WebhookCallbackClient
from src.agent.jobs import MaterialJobStore
from src.agent.lkpd_storage import LkpdFileStorage
from src.agent.runtime import AgentRuntime
from src.agent.worker import MaterialJobWorker
from src.api import build_lkpd_router, build_material_router, build_oauth_router
from src.auth.revocation import shutdown_token_denylist
from src.core.api_response import (
    attach_meta_to_json_response,
    build_request_id,
)
from src.core.constants import APP_NAME, APP_VERSION
from src.core.exceptions import register_exception_handlers
from src.core.logging import configure_logging


configure_logging()
logger = logging.getLogger(__name__)

agent_runtime = AgentRuntime()
job_store = MaterialJobStore()
callback_client = WebhookCallbackClient()
lkpd_storage = LkpdFileStorage()
job_worker = MaterialJobWorker(
    runtime=agent_runtime,
    job_store=job_store,
    callback_client=callback_client,
    lkpd_storage=lkpd_storage,
)


@asynccontextmanager
async def app_lifespan(_: FastAPI) -> AsyncIterator[None]:
    logger.info("app_startup_begin")
    await agent_runtime.initialize()
    await job_store.initialize()
    await callback_client.initialize()
    await lkpd_storage.initialize()
    job_worker.start()
    logger.info("app_startup_complete")
    try:
        yield
    finally:
        logger.info("app_shutdown_begin")
        await job_worker.stop()
        await callback_client.shutdown()
        await shutdown_token_denylist()
        await job_store.shutdown()
        await agent_runtime.shutdown()
        logger.info("app_shutdown_complete")


app = FastAPI(title=APP_NAME, version=APP_VERSION, lifespan=app_lifespan)


app.include_router(build_material_router(job_store))
app.include_router(build_lkpd_router(job_store, lkpd_storage))
app.include_router(build_oauth_router())


@app.middleware("http")
async def request_id_middleware(
    request: Request, call_next: Callable[[Request], Awaitable[Response]]
) -> Response:
    request_id = build_request_id()
    request.state.request_id = request_id

    response = await call_next(request)
    response.headers["X-Request-ID"] = request_id
    if request.url.path.startswith("/api"):
        return attach_meta_to_json_response(response, request_id)
    return response


register_exception_handlers(app)