Skip to content

Commit 2abb96c

Browse files
committed
feat: implement MatchingService with Redis queue, peer matching and timeout handling
1 parent 5f04c94 commit 2abb96c

File tree

1 file changed

+62
-0
lines changed

1 file changed

+62
-0
lines changed
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
from app.models.match import MatchRequest, MatchResponse
2+
import uuid
3+
from app.services import queue
4+
import time
5+
import asyncio
6+
from app.services.websocket_manager import manager
7+
8+
TIMEOUT_SECONDS = 60
9+
10+
class MatchingService:
11+
12+
@staticmethod
13+
async def join_queue(request: MatchRequest) -> MatchResponse:
14+
difficulty = request.difficulty
15+
topic = request.topic
16+
language = request.language
17+
user_id = request.user_id
18+
19+
peer_id = queue.dequeue_user(difficulty, topic, language)
20+
21+
# suitable match
22+
if peer_id:
23+
await manager.send_event(user_id, "match.found", {"peer_id": peer_id})
24+
await manager.send_event(peer_id, "match.found", {"peer_id": user_id})
25+
26+
# TODO: Initialise collaboration session and assign question
27+
28+
return MatchResponse(success=True, peer_id=peer_id, message="Peer found")
29+
else:
30+
# no suitable match
31+
queue.enqueue_user(difficulty, topic, language, user_id)
32+
position = queue.get_queue_position(difficulty, topic, language, user_id)
33+
34+
return MatchResponse(
35+
success=True,
36+
message="Added to queue",
37+
# queue_position=position
38+
)
39+
40+
@staticmethod
41+
def cancel_queue(request: MatchRequest) -> MatchResponse:
42+
removed = queue.remove_user(request.difficulty, request.topic, request.language, request.user_id)
43+
if removed:
44+
return MatchResponse(success=True, message="Removed from queue")
45+
else:
46+
return MatchResponse(success=False, message="User not in queue")
47+
48+
@staticmethod
49+
async def check_timeouts(request: MatchRequest):
50+
await asyncio.sleep(TIMEOUT_SECONDS)
51+
position = queue.get_queue_position(request.difficulty, request.topic, request.language, request.user_id)
52+
53+
if position is not None:
54+
queue.remove_user(request.difficulty, request.topic, request.language, request.user_id)
55+
print(f"Timeout: Removed user {request.user_id} from queue after {TIMEOUT_SECONDS}")
56+
57+
# send WebSocket event timeout
58+
await manager.send_event(
59+
request.user_id,
60+
"match.timeout",
61+
{"message": f"Timeout after {TIMEOUT_SECONDS} seconds, removed from queue"}
62+
)

0 commit comments

Comments
 (0)