Skip to content

Commit 9188878

Browse files
committed
[lichess] switch to async Views
As Lichess-related Views will mainly be proxies to the Lichess HTTP API, we would likely benefit from being able to not block workers' threads while the I/O between our server and Lichess are taking place.
1 parent fdf4f60 commit 9188878

File tree

7 files changed

+199
-9
lines changed

7 files changed

+199
-9
lines changed

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ EXPOSE 8080
179179

180180
ENV DJANGO_SETTINGS_MODULE=project.settings.production
181181

182-
ENV GUNICORN_CMD_ARGS="--bind 0.0.0.0:8080 --workers 2 --max-requests 120 --max-requests-jitter 20 --timeout 8"
182+
ENV GUNICORN_CMD_ARGS="--bind 0.0.0.0:8080 --workers 4 -k uvicorn_worker.UvicornWorker --max-requests 120 --max-requests-jitter 20 --timeout 8"
183183

184184
RUN chmod +x scripts/start_server.sh
185185
# See <https://hynek.me/articles/docker-signals/>.

Makefile

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,17 @@ backend/install: bin/uv .venv ## Install the Python dependencies (via uv) and in
3838
@${SUB_MAKE} .venv/bin/black
3939

4040
.PHONY: backend/watch
41+
backend/watch: env_vars ?=
4142
backend/watch: address ?= localhost
4243
backend/watch: port ?= 8000
4344
backend/watch: dotenv_file ?= .env.local
44-
backend/watch: ## Start the Django development server
45-
@${SUB_MAKE} django/manage cmd='runserver ${address}:${port}'
45+
backend/watch: ## Start Django via Uvicorn, in "watch" mode
46+
@@DJANGO_SETTINGS_MODULE=${DJANGO_SETTINGS_MODULE} ${env_vars} \
47+
${UV} run uvicorn \
48+
--reload --reload-dir src/ \
49+
--host ${address} --port ${port} \
50+
--env-file ${dotenv_file} \
51+
project.asgi:application
4652

4753
.PHONY: backend/resetdb
4854
backend/resetdb: dotenv_file ?= .env.local

pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ dependencies= [
1414
# Django doesn't follow SemVer, so we need to specify the minor version:
1515
"Django==5.1.*",
1616
"gunicorn==22.*",
17+
"uvicorn[standard]==0.30.*",
18+
"uvicorn-worker==0.2.*",
1719
"django-alive==1.*",
1820
"chess==1.*",
1921
"django-htmx==1.*",

src/apps/lichess_bridge/components/pages/lichess.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from apps.webui.components.forms_common import csrf_hidden_input
88
from apps.webui.components.layout import page
99

10-
from ...lichess_api import get_lichess_api_client
10+
from ... import lichess_api
1111
from ..misc_ui import detach_lichess_account_form
1212
from ..svg_icons import ICON_SVG_LOG_IN
1313

@@ -43,12 +43,12 @@ def lichess_no_account_linked_page(
4343
)
4444

4545

46-
def lichess_account_linked_homepage(
46+
async def lichess_account_linked_homepage(
4747
*,
4848
request: "HttpRequest",
4949
access_token: "LichessAccessToken",
5050
) -> str:
51-
me = get_lichess_api_client(access_token).account.get()
51+
me = await lichess_api.get_lichess_my_account(access_token)
5252

5353
return page(
5454
div(

src/apps/lichess_bridge/lichess_api.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from typing import TYPE_CHECKING
22

33
import berserk
4+
from asgiref.sync import sync_to_async
45

56
from .models import LICHESS_ACCESS_TOKEN_PREFIX
67

@@ -12,7 +13,14 @@ def is_lichess_api_access_token_valid(token: str) -> bool:
1213
return token.startswith(LICHESS_ACCESS_TOKEN_PREFIX) and len(token) > 10
1314

1415

15-
def get_lichess_api_client(access_token: "LichessAccessToken") -> berserk.Client:
16+
@sync_to_async(thread_sensitive=False)
17+
def get_lichess_my_account(
18+
access_token: "LichessAccessToken",
19+
) -> berserk.types.AccountInformation:
20+
return _get_lichess_api_client(access_token).account.get()
21+
22+
23+
def _get_lichess_api_client(access_token: "LichessAccessToken") -> berserk.Client:
1624
return _create_lichess_api_client(access_token)
1725

1826

src/apps/lichess_bridge/views.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222

2323
@require_GET
24-
def lichess_home(request: "HttpRequest") -> HttpResponse:
24+
async def lichess_home(request: "HttpRequest") -> HttpResponse:
2525
# Do we have a Lichess API token for this user?
2626
lichess_access_token = cookie_helpers.get_lichess_api_access_token_from_request(
2727
request
@@ -30,7 +30,7 @@ def lichess_home(request: "HttpRequest") -> HttpResponse:
3030
if not lichess_access_token:
3131
page_content = lichess_no_account_linked_page(request=request)
3232
else:
33-
page_content = lichess_account_linked_homepage(
33+
page_content = await lichess_account_linked_homepage(
3434
request=request,
3535
access_token=lichess_access_token,
3636
)

0 commit comments

Comments
 (0)