mirror of
https://github.com/aljazceru/nutshell.git
synced 2025-12-20 18:44:20 +01:00
* fast-api-cache setup * testing the cache * fix * still not working * asynccontextmanager * move test * use redis & custom caching setup (like CDK) * make format * poetry lock * fix format string + log when a cached response is found * log when a cahced response is found * fix tests * poetry lock * try tests on github * use docker compose * maybe we dont need docker * fix types * create_task instead of run * how about we start postgres * mint features * format * remove deprecated setex call * use global expiry for all cached routes * refactor feature map and set default to 1 week * refactor feature construction * Cache NUT-19 --------- Co-authored-by: callebtc <93376500+callebtc@users.noreply.github.com>
113 lines
3.4 KiB
Python
113 lines
3.4 KiB
Python
import asyncio
|
|
import sys
|
|
from collections.abc import AsyncIterator
|
|
from contextlib import asynccontextmanager
|
|
from traceback import print_exception
|
|
|
|
from fastapi import FastAPI, status
|
|
from fastapi.exceptions import RequestValidationError
|
|
from fastapi.responses import JSONResponse
|
|
from loguru import logger
|
|
from starlette.requests import Request
|
|
|
|
from ..core.errors import CashuError
|
|
from ..core.logging import configure_logger
|
|
from ..core.settings import settings
|
|
from .router import redis, router
|
|
from .router_deprecated import router_deprecated
|
|
from .startup import shutdown_mint as shutdown_mint_init
|
|
from .startup import start_mint_init
|
|
|
|
if settings.debug_profiling:
|
|
pass
|
|
|
|
if settings.mint_rate_limit:
|
|
pass
|
|
|
|
from .middleware import add_middlewares, request_validation_exception_handler
|
|
|
|
|
|
@asynccontextmanager
|
|
async def lifespan(_: FastAPI) -> AsyncIterator[None]:
|
|
await start_mint_init()
|
|
try:
|
|
yield
|
|
except asyncio.CancelledError:
|
|
# Handle the cancellation gracefully
|
|
logger.info("Shutdown process interrupted by CancelledError")
|
|
finally:
|
|
try:
|
|
await redis.disconnect()
|
|
await shutdown_mint_init()
|
|
except asyncio.CancelledError:
|
|
logger.info("CancelledError during shutdown, shutting down forcefully")
|
|
|
|
|
|
def create_app(config_object="core.settings") -> FastAPI:
|
|
configure_logger()
|
|
|
|
app = FastAPI(
|
|
title="Nutshell Mint",
|
|
description="Ecash mint based on the Cashu protocol.",
|
|
version=settings.version,
|
|
license_info={
|
|
"name": "MIT License",
|
|
"url": "https://raw.githubusercontent.com/cashubtc/cashu/main/LICENSE",
|
|
},
|
|
lifespan=lifespan,
|
|
)
|
|
|
|
return app
|
|
|
|
|
|
app = create_app()
|
|
|
|
# Add middlewares
|
|
add_middlewares(app)
|
|
|
|
|
|
@app.middleware("http")
|
|
async def catch_exceptions(request: Request, call_next):
|
|
CORS_HEADERS = {
|
|
"Access-Control-Allow-Origin": "*",
|
|
"Access-Control-Allow-Methods": "*",
|
|
"Access-Control-Allow-Headers": "*",
|
|
"Access-Control-Allow-Credentials": "true",
|
|
}
|
|
try:
|
|
return await call_next(request)
|
|
except Exception as e:
|
|
try:
|
|
err_message = str(e)
|
|
except Exception:
|
|
err_message = e.args[0] if e.args else "Unknown error"
|
|
|
|
if isinstance(e, CashuError) or isinstance(e.args[0], CashuError):
|
|
logger.error(f"CashuError: {err_message}")
|
|
code = e.code if isinstance(e, CashuError) else e.args[0].code
|
|
# return with cors headers
|
|
return JSONResponse(
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
content={"detail": err_message, "code": code},
|
|
headers=CORS_HEADERS,
|
|
)
|
|
logger.error(f"Exception: {err_message}")
|
|
if settings.debug:
|
|
print_exception(*sys.exc_info())
|
|
return JSONResponse(
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
content={"detail": err_message, "code": 0},
|
|
headers=CORS_HEADERS,
|
|
)
|
|
|
|
|
|
# Add exception handlers
|
|
app.add_exception_handler(RequestValidationError, request_validation_exception_handler) # type: ignore
|
|
|
|
# Add routers
|
|
if settings.debug_mint_only_deprecated:
|
|
app.include_router(router=router_deprecated, tags=["Deprecated"], deprecated=True)
|
|
else:
|
|
app.include_router(router=router, tags=["Mint"])
|
|
app.include_router(router=router_deprecated, tags=["Deprecated"], deprecated=True)
|