wip invalidate cache when room is finished

This commit is contained in:
lebaudantoine
2025-01-06 19:37:46 +01:00
parent 5428aec43e
commit 8d9ac96d2b
3 changed files with 52 additions and 10 deletions
+31 -1
View File
@@ -47,6 +47,8 @@ from core.recording.worker.mediator import (
from . import permissions, serializers
from livekit import api as livekit_api
# pylint: disable=too-many-ancestors
logger = getLogger(__name__)
@@ -347,7 +349,35 @@ class RoomViewSet(
{"message": f"Recording stopped for room {room.slug}."}
)
# todo - support a callback endpoint when a room is finished, to invalidate cached key
@decorators.action(
detail=False,
methods=["post"],
url_path="livekit-webhook",
permission_classes=[],
authentication_classes=[],
)
def handle_livekit_webhook(self, request, pk=None): # pylint: disable=unused-argument
"""Handle LiveKit webhook events."""
auth_token = request.headers.get("Authorization")
if not auth_token:
return drf_response.Response(
{"error": "Missing LiveKit authentication token"},
status=drf_status.HTTP_401_UNAUTHORIZED
)
token_verifier = livekit_api.TokenVerifier()
webhook_receiver = livekit_api.WebhookReceiver(token_verifier)
webhook_data = webhook_receiver.receive(request.body.decode("utf-8"), auth_token)
# Todo - livekit triggers a webhook for all events, see if we can restrict webhook to a limited number of events.
# Todo - handle Egress stopped / aborted events.
if webhook_data.event == "room_finished":
room_id = webhook_data.room.name
utils.clear_cache_passphrase(room_id)
return drf_response.Response({"message": f"Event processed"})
class ResourceAccessListModelMixin:
+17 -9
View File
@@ -28,25 +28,33 @@ def generate_random_passphrase(length=26):
alphabet = string.ascii_letters + string.digits
return ''.join(secrets.choice(alphabet) for _ in range(length))
def get_cached_passphrase(room_id):
"""Get or generate a cached passphrase for a room slug"""
def build_room_passphrase_key(room_id: str) -> str:
"""Build cache key for room passphrase."""
return f"room_passphrase:{room_id}"
def get_cached_passphrase(room_id: str) -> str:
"""Get or generate encrypted passphrase for a room.
Retrieves existing passphrase from cache or generates,
encrypts and caches a new one if not found.
"""
cypher = Fernet(settings.PASSPHRASE_ENCRYPTION_KEY.encode())
# todo - discuss this hardcoded key prefix
encrypted_passphrase = cache.get(f"room_passphrase:{room_id}")
cache_key = build_room_passphrase_key(room_id)
encrypted_passphrase = cache.get(cache_key)
if encrypted_passphrase is None:
passphrase = generate_random_passphrase()
encrypted_passphrase = cypher.encrypt(passphrase.encode()).decode()
# Store in cache with a timeout (e.g., 24 hours = 86400 seconds)
cache.set(f"room_passphrase:{room_id}", encrypted_passphrase, timeout=86400)
cache.set(cache_key, encrypted_passphrase, timeout=86400) # 24 hours
return passphrase
return cypher.decrypt(encrypted_passphrase.encode()).decode()
def clear_room_passphrase(room_id: str) -> None:
"""Remove room passphrase from cache."""
cache.delete(build_room_passphrase_key(room_id))
def generate_color(identity: str) -> str:
"""Generates a consistent HSL color based on a given identity string.
@@ -17,6 +17,10 @@ livekit:
udp_port: 443
domain: livekit.127.0.0.1.nip.io
loadBalancerAnnotations: {}
webhook:
api_key: devkey
urls:
- https://meet.127.0.0.1.nip.io/api/v1.0/rooms/livekit-webhook/
loadBalancer: