diff --git a/README.md b/README.md index 9f38559..4eedbbf 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,13 @@ Für die Entwicklung mit WebSocket-Unterstützung verwenden wir Daphne: daphne -b 127.0.0.1 -p 8000 core.asgi:application ``` +3. Starte den REDIS Server + ```sh + redis-server + ``` + > **Hinweis:** Der Redis Server muss, wenn er nicht auf dem selben Gerät unter Standardeinstellungen läuft, in der Datei play/consumers/lobby.py und core/settings.py entsprechend umkonfiguriert werden! + + Alternativ kannst du den Django-Entwicklungsserver verwenden, wenn du keine WebSocket-Funktionalität benötigst: ```sh python3 core/manage.py runserver @@ -91,6 +98,12 @@ Für den Produktivbetrieb verwenden wir Daphne als ASGI-Server, der sowohl HTTP ``` - Dann `0 0 * * * /path/to/venv/bin/python /path/to/your_project/manage.py cleanup_games` einfügen, damit um Mitternacht alle Spiele gelöscht werden +5. Starte den REDIS Server + ```sh + redis-server + ``` + > **Hinweis:** Der Redis Server muss, wenn er nicht auf dem selben Gerät unter Standardeinstellungen läuft, in der Datei play/consumers/lobby.py und core/settings.py entsprechend umkonfiguriert werden! + Damit ist das Projekt erfolgreich eingerichtet und der Server kann gestartet werden! ## Superuser erstellen diff --git a/django/core/settings.py b/django/core/settings.py index 10c7c97..31ac5f5 100644 --- a/django/core/settings.py +++ b/django/core/settings.py @@ -79,12 +79,16 @@ WSGI_APPLICATION = 'core.wsgi.application' ASGI_APPLICATION = 'core.asgi.application' CHANNEL_LAYERS = { - 'default': { - 'BACKEND': 'channels.layers.InMemoryChannelLayer' - } + "default": { + "BACKEND": "channels_redis.core.RedisChannelLayer", + "CONFIG": { + "hosts": [("127.0.0.1", 6379)], + }, + }, } + # Database # https://docs.djangoproject.com/en/5.1/ref/settings/#databases diff --git a/django/play/consumers/lobby.py b/django/play/consumers/lobby.py index 8fd72c1..c076abe 100644 --- a/django/play/consumers/lobby.py +++ b/django/play/consumers/lobby.py @@ -3,6 +3,7 @@ import json import asyncio from ..models import QuizGame, QuizGameParticipant from channels.db import database_sync_to_async +import redis # Dictionary to track inactive check tasks and active connections per game game_check_tasks = {} @@ -10,6 +11,8 @@ game_connections = {} class LobbyConsumer(AsyncWebsocketConsumer): + r = redis.Redis(host='localhost', port=6379, db=0, decode_responses=True) + async def connect(self): self.join_code = self.scope['url_route']['kwargs']['join_code'] self.room_group_name = f'lobby_{self.join_code}' @@ -142,12 +145,21 @@ class LobbyConsumer(AsyncWebsocketConsumer): ))() - # Send join notification for new participants + # Zustand laden try: - prev_names = set(p['display_name'] for p in self.last_participants) if hasattr(self, 'last_participants') else set() + r = redis.Redis(host='localhost', port=6379, db=0, decode_responses=True) + + # Alte Teilnehmer aus Redis holen + data = r.get(f"last_participants_{self.room_group_name}") + prev_names = set(json.loads(data)) if data else set() + + # Aktuelle Teilnehmer aus dem Argument extrahieren current_names = set(p['display_name'] for p in participants) + + # Neue Teilnehmer bestimmen new_participants = current_names - prev_names - + + # Benachrichtigung für neue Teilnehmer versenden for name in new_participants: await self.channel_layer.group_send( self.room_group_name, @@ -156,9 +168,12 @@ class LobbyConsumer(AsyncWebsocketConsumer): 'player_name': name } ) + + # Teilnehmerliste in Redis aktualisieren + r.set(f"last_participants_{self.room_group_name}", json.dumps(list(current_names))) + except Exception as e: - print(f'Error sending join notifications: {e}') - + print(f"Error in send_join_notifications: {e}") self.last_participants = participants return participants except QuizGame.DoesNotExist: diff --git a/django/templates/play/lobby.html b/django/templates/play/lobby.html index 890cb39..a7b8030 100644 --- a/django/templates/play/lobby.html +++ b/django/templates/play/lobby.html @@ -33,7 +33,7 @@ Teilnehmer -