Skip to content
Snippets Groups Projects
Commit 354ce3ba authored by Daniel Göbel's avatar Daniel Göbel
Browse files

Merge branch...

Merge branch 'feature/71-create-http-client-once-during-startup-instead-per-request' into 'development'

Resolve "Create http client once during startup instead per request"

Closes #71

See merge request cmg/clowm/clowm-s3proxy-service!68
parents 6a6356d3 042f028b
No related branches found
No related tags found
No related merge requests found
...@@ -21,7 +21,7 @@ repos: ...@@ -21,7 +21,7 @@ repos:
files: app files: app
args: [--check] args: [--check]
- repo: https://github.com/charliermarsh/ruff-pre-commit - repo: https://github.com/charliermarsh/ruff-pre-commit
rev: 'v0.1.5' rev: 'v0.1.6'
hooks: hooks:
- id: ruff - id: ruff
- repo: https://github.com/PyCQA/isort - repo: https://github.com/PyCQA/isort
...@@ -31,7 +31,7 @@ repos: ...@@ -31,7 +31,7 @@ repos:
files: app files: app
args: [-c] args: [-c]
- repo: https://github.com/pre-commit/mirrors-mypy - repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.7.0 rev: v1.7.1
hooks: hooks:
- id: mypy - id: mypy
files: app files: app
......
...@@ -3,7 +3,7 @@ from typing import TYPE_CHECKING, Annotated, AsyncGenerator, Awaitable, Callable ...@@ -3,7 +3,7 @@ from typing import TYPE_CHECKING, Annotated, AsyncGenerator, Awaitable, Callable
from authlib.jose.errors import BadSignatureError, DecodeError, ExpiredTokenError from authlib.jose.errors import BadSignatureError, DecodeError, ExpiredTokenError
from clowmdb.db.session import get_async_session from clowmdb.db.session import get_async_session
from clowmdb.models import Bucket, User from clowmdb.models import Bucket, User
from fastapi import Depends, HTTPException, Path, status from fastapi import Depends, HTTPException, Path, Request, status
from fastapi.security import HTTPBearer from fastapi.security import HTTPBearer
from fastapi.security.http import HTTPAuthorizationCredentials from fastapi.security.http import HTTPAuthorizationCredentials
from httpx import AsyncClient from httpx import AsyncClient
...@@ -63,17 +63,9 @@ async def get_db() -> AsyncGenerator[AsyncSession, None]: ...@@ -63,17 +63,9 @@ async def get_db() -> AsyncGenerator[AsyncSession, None]:
DBSession = Annotated[AsyncSession, Depends(get_db)] DBSession = Annotated[AsyncSession, Depends(get_db)]
async def get_httpx_client() -> AsyncGenerator[AsyncClient, None]: # pragma: no cover async def get_httpx_client(request: Request) -> AsyncClient: # pragma: no cover
""" # Fetch open http client from the app
Get a async HTTP client, that can be overwritten during testing. return request.app.requests_client
Returns
-------
client : AsyncGenerator[httpx.AsyncClient, None]
Http client with an open connection
"""
async with AsyncClient() as client:
yield client
HTTPXClient = Annotated[AsyncClient, Depends(get_httpx_client)] HTTPXClient = Annotated[AsyncClient, Depends(get_httpx_client)]
......
from contextlib import asynccontextmanager
from hashlib import md5 from hashlib import md5
from typing import AsyncGenerator
from fastapi import FastAPI, Request, Response, status from fastapi import FastAPI, Request, Response, status
from fastapi.exception_handlers import http_exception_handler, request_validation_exception_handler from fastapi.exception_handlers import http_exception_handler, request_validation_exception_handler
...@@ -7,6 +9,7 @@ from fastapi.middleware.gzip import GZipMiddleware ...@@ -7,6 +9,7 @@ from fastapi.middleware.gzip import GZipMiddleware
from fastapi.openapi.docs import get_swagger_ui_html from fastapi.openapi.docs import get_swagger_ui_html
from fastapi.responses import HTMLResponse, JSONResponse from fastapi.responses import HTMLResponse, JSONResponse
from fastapi.routing import APIRoute from fastapi.routing import APIRoute
from httpx import AsyncClient
from opentelemetry import trace from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
...@@ -28,6 +31,14 @@ def custom_generate_unique_id(route: APIRoute) -> str: ...@@ -28,6 +31,14 @@ def custom_generate_unique_id(route: APIRoute) -> str:
return f"{route.tags[-1]}-{route.name}" return f"{route.tags[-1]}-{route.name}"
@asynccontextmanager
async def lifespan(fastapi_app: FastAPI) -> AsyncGenerator[None, None]: # pragma: no cover
# Create a http client once instead for every request and attach it to the app
async with AsyncClient() as client:
fastapi_app.requests_client = client # type: ignore[attr-defined]
yield
app = FastAPI( app = FastAPI(
title="CloWM S3-Proxy Service", title="CloWM S3-Proxy Service",
version="2.0.0", version="2.0.0",
...@@ -41,6 +52,7 @@ app = FastAPI( ...@@ -41,6 +52,7 @@ app = FastAPI(
# license_info={"name": "MIT", "url": "https://mit-license.org/"}, # license_info={"name": "MIT", "url": "https://mit-license.org/"},
root_path=settings.API_PREFIX, root_path=settings.API_PREFIX,
openapi_url=None, # create it manually to enable caching on client side openapi_url=None, # create it manually to enable caching on client side
lifespan=lifespan,
) )
if settings.API_PREFIX: # pragma: no cover if settings.API_PREFIX: # pragma: no cover
app.servers.insert(0, {"url": settings.API_PREFIX}) app.servers.insert(0, {"url": settings.API_PREFIX})
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment