️(asgi) use uvicorn to serve backend

This is a naive first switch from sync to async.
This enables the backend to still answer to incomming requests
while streaming LLM results to the user.

For sure there is room for code cleaning and improvements, but
this provides a nice improvement out of the box.
This commit is contained in:
Manuel Raynaud
2026-02-13 11:52:09 +01:00
committed by Anthony LC
parent 5011db9bd7
commit 050b106a8f
6 changed files with 76 additions and 10 deletions

View File

@@ -151,7 +151,7 @@ RUN rm -rf /var/cache/apk/*
ARG IMPRESS_STATIC_ROOT=/data/static ARG IMPRESS_STATIC_ROOT=/data/static
# Gunicorn # Gunicorn - not used by default but configuration file is provided
RUN mkdir -p /usr/local/etc/gunicorn RUN mkdir -p /usr/local/etc/gunicorn
COPY docker/files/usr/local/etc/gunicorn/impress.py /usr/local/etc/gunicorn/impress.py COPY docker/files/usr/local/etc/gunicorn/impress.py /usr/local/etc/gunicorn/impress.py
@@ -165,5 +165,18 @@ COPY --from=link-collector ${IMPRESS_STATIC_ROOT} ${IMPRESS_STATIC_ROOT}
# Copy impress mails # Copy impress mails
COPY --from=mail-builder /mail/backend/core/templates/mail /app/core/templates/mail COPY --from=mail-builder /mail/backend/core/templates/mail /app/core/templates/mail
# The default command runs gunicorn WSGI server in impress's main module # The default command runs uvicorn ASGI server in dics's main module
CMD ["gunicorn", "-c", "/usr/local/etc/gunicorn/impress.py", "impress.wsgi:application"] # WEB_CONCURRENCY: number of workers to run <=> --workers=4
ENV WEB_CONCURRENCY=4
CMD [\
"uvicorn",\
"--app-dir=/app",\
"--host=0.0.0.0",\
"--timeout-graceful-shutdown=300",\
"--limit-max-requests=20000",\
"--lifespan=off",\
"impress.asgi:application"\
]
# To run using gunicorn WSGI server use this instead:
#CMD ["gunicorn", "-c", "/usr/local/etc/gunicorn/conversations.py", "impress.wsgi:application"]

View File

@@ -0,0 +1,18 @@
"""
ASGI config for impress project.
It exposes the ASGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/dev/howto/deployment/asgi/
"""
import os
from configurations.asgi import get_asgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "impress.settings")
os.environ.setdefault("DJANGO_CONFIGURATION", "Development")
os.environ.setdefault("PYTHON_SERVER_MODE", "async")
application = get_asgi_application()

View File

@@ -13,5 +13,6 @@ from configurations.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "impress.settings") os.environ.setdefault("DJANGO_SETTINGS_MODULE", "impress.settings")
os.environ.setdefault("DJANGO_CONFIGURATION", "Development") os.environ.setdefault("DJANGO_CONFIGURATION", "Development")
os.environ.setdefault("PYTHON_SERVER_MODE", "sync")
application = get_wsgi_application() application = get_wsgi_application()

View File

@@ -61,6 +61,7 @@ dependencies = [
"redis<6.0.0", "redis<6.0.0",
"requests==2.32.5", "requests==2.32.5",
"sentry-sdk==2.48.0", "sentry-sdk==2.48.0",
"uvicorn==0.40.0",
"whitenoise==6.11.0", "whitenoise==6.11.0",
] ]

View File

@@ -135,9 +135,15 @@
} }
}, },
"header": { "header": {
"logo": {},
"icon": { "icon": {
"src": "/assets/icon-docs.svg", "src": "/assets/icon-docs.svg",
"width": "32px" "style": {
"width": "32px",
"height": "auto"
},
"alt": "",
"withTitle": true
} }
}, },
"waffle": { "waffle": {
@@ -164,5 +170,26 @@
] ]
}, },
"showMoreLimit": 9 "showMoreLimit": 9
},
"home": {
"with-proconnect": false,
"icon-banner": {
"src": "/assets/icon-docs.svg",
"style": {
"width": "64px",
"height": "auto"
},
"alt": ""
}
},
"favicon": {
"light": {
"href": "/assets/favicon-light.png",
"type": "image/png"
},
"dark": {
"href": "/assets/favicon-dark.png",
"type": "image/png"
}
} }
} }

View File

@@ -91,11 +91,14 @@ backend:
restartPolicy: Never restartPolicy: Never
command: command:
- "gunicorn" - uvicorn
- "-c" - --app-dir=/app
- "/usr/local/etc/gunicorn/impress.py" - --host=0.0.0.0
- "impress.wsgi:application" - --timeout-graceful-shutdown=300
- "--reload" - --limit-max-requests=20000
- --lifespan=off
- --reload
- "impress.asgi:application"
createsuperuser: createsuperuser:
command: command:
@@ -145,6 +148,9 @@ frontend:
pullPolicy: Always pullPolicy: Always
tag: "latest" tag: "latest"
securityContext:
runAsNonRoot: false
yProvider: yProvider:
replicas: 1 replicas: 1