mirror of
https://github.com/umap-project/umap.git
synced 2025-04-28 19:42:36 +02:00
feat(websockets): run the WS server as a django management command.
This allows to handle the loading of the settings in a consistant way, and aditionnaly to provide a way to override the `WEBSOCKET_BACK_HOST` and `WEBSOCKET_BACK_PORT` settings with arg commands `--host` and `--port`. Without this change, because of how we are currently loading our settings, we would require the settings the be exposed by the `umap.settings.__init__` file. Previous implementations were exposing these settings, with the following code: ```python settings_as_dict = {k: v for k, v in globals().items() if k.isupper()} ```
This commit is contained in:
parent
940ae77602
commit
d91c86e7fa
4 changed files with 34 additions and 22 deletions
|
@ -279,12 +279,15 @@ Setting `WEBSOCKET_ENABLED` to `True` will **not** enable real-time
|
||||||
collaboration on all the maps served by the server. Instead, a switch will be
|
collaboration on all the maps served by the server. Instead, a switch will be
|
||||||
available in the "advanced properties" of the map.
|
available in the "advanced properties" of the map.
|
||||||
|
|
||||||
The websocket server can be run with the following command:
|
The websocket server can be started with the following command:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python -m umap.ws
|
umap run_websocket_server
|
||||||
```
|
```
|
||||||
|
|
||||||
|
And can take optional settings `--host` and `--port` (default values are defined in
|
||||||
|
the settings).
|
||||||
|
|
||||||
Configuration example:
|
Configuration example:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
|
|
23
umap/management/commands/run_websocket_server.py
Normal file
23
umap/management/commands/run_websocket_server.py
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
from django.conf import settings
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
|
||||||
|
from umap import ws
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
help = "Run the websocket server"
|
||||||
|
|
||||||
|
def add_arguments(self, parser):
|
||||||
|
parser.add_argument(
|
||||||
|
"--host",
|
||||||
|
help="The server host to bind to.",
|
||||||
|
default=settings.WEBSOCKET_BACK_HOST,
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--port",
|
||||||
|
help="The server port to bind to.",
|
||||||
|
default=settings.WEBSOCKET_BACK_PORT,
|
||||||
|
)
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
ws.run(options["host"], options["port"])
|
|
@ -43,6 +43,3 @@ if path:
|
||||||
globals()["STATICFILES_DIRS"].insert(0, value)
|
globals()["STATICFILES_DIRS"].insert(0, value)
|
||||||
else:
|
else:
|
||||||
globals()[key] = value
|
globals()[key] = value
|
||||||
|
|
||||||
# Expose these settings for consumption by e.g. django.settings.configure.
|
|
||||||
settings_as_dict = {k: v for k, v in globals().items() if k.isupper()}
|
|
||||||
|
|
17
umap/ws.py
17
umap/ws.py
|
@ -4,7 +4,6 @@ import asyncio
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from typing import Literal, Optional
|
from typing import Literal, Optional
|
||||||
|
|
||||||
import django
|
|
||||||
import websockets
|
import websockets
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.signing import TimestampSigner
|
from django.core.signing import TimestampSigner
|
||||||
|
@ -12,13 +11,6 @@ from pydantic import BaseModel, ValidationError
|
||||||
from websockets import WebSocketClientProtocol
|
from websockets import WebSocketClientProtocol
|
||||||
from websockets.server import serve
|
from websockets.server import serve
|
||||||
|
|
||||||
# This needs to run before the django-specific imports
|
|
||||||
# See https://docs.djangoproject.com/en/5.0/topics/settings/#calling-django-setup-is-required-for-standalone-django-usage
|
|
||||||
from umap.settings import settings_as_dict
|
|
||||||
|
|
||||||
settings.configure(**settings_as_dict)
|
|
||||||
django.setup()
|
|
||||||
|
|
||||||
from umap.models import Map, User # NOQA
|
from umap.models import Map, User # NOQA
|
||||||
|
|
||||||
# Contains the list of websocket connections handled by this process.
|
# Contains the list of websocket connections handled by this process.
|
||||||
|
@ -81,7 +73,7 @@ async def handler(websocket):
|
||||||
await join_and_listen(map_id, permissions, user, websocket)
|
await join_and_listen(map_id, permissions, user, websocket)
|
||||||
|
|
||||||
|
|
||||||
async def main():
|
def run(host, port):
|
||||||
if not settings.WEBSOCKET_ENABLED:
|
if not settings.WEBSOCKET_ENABLED:
|
||||||
msg = (
|
msg = (
|
||||||
"WEBSOCKET_ENABLED should be set to True to run the WebSocket Server. "
|
"WEBSOCKET_ENABLED should be set to True to run the WebSocket Server. "
|
||||||
|
@ -92,12 +84,9 @@ async def main():
|
||||||
print(msg)
|
print(msg)
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
host = settings.WEBSOCKET_BACK_HOST
|
async def _serve():
|
||||||
port = settings.WEBSOCKET_BACK_PORT
|
|
||||||
|
|
||||||
async with serve(handler, host, port):
|
async with serve(handler, host, port):
|
||||||
print(f"Waiting for connections on {host}:{port}")
|
print(f"Waiting for connections on {host}:{port}")
|
||||||
await asyncio.Future() # run forever
|
await asyncio.Future() # run forever
|
||||||
|
|
||||||
|
asyncio.run(_serve())
|
||||||
asyncio.run(main())
|
|
||||||
|
|
Loading…
Reference in a new issue