implement alternative match-making approach with Lua scripts in Redis

This commit is contained in:
2026-10-25 15:57:24 +03:00
parent 582ecb7c74
commit acdaebd491
19 changed files with 796 additions and 139 deletions
@@ -0,0 +1,4 @@
module ApplicationCable
class Channel < ActionCable::Channel::Base
end
end
@@ -0,0 +1,21 @@
module ApplicationCable
class Connection < ActionCable::Connection::Base
identified_by :current_user
def connect
self.current_user = find_user
reject_unauthorized_connection unless current_user
end
private
def find_user
token = request.params[:token].presence ||
request.headers["Authorization"]&.split(" ")&.last
return unless token
decoded = JwtService.decode(token)
User.find_by(id: decoded[:user_id]) if decoded
end
end
end
@@ -0,0 +1,31 @@
# Real-time matchmaking channel.
#
# Client flow:
# 1. Connect: ws(s)://host/cable?token=<JWT>
# 2. Subscribe to "MatchmakingChannel"
# 3. Send { action: "start", rating: <optional int> } to enter the queue
# 4. Receive { type: "matched", ... } or { type: "timeout" }
# 5. Disconnecting (or sending { action: "stop" }) cancels the search.
class MatchmakingChannel < ApplicationCable::Channel
def subscribed
stream_for current_user
# If a match was found while this user had no subscription
# (e.g. brief reconnect), deliver it now — exactly once.
if match = MatchmakingService.claim(current_user.id)
transmit(match)
end
end
def start(data)
MatchmakingService.enqueue(current_user.id, rating: data["rating"])
end
def stop
MatchmakingService.cancel(current_user.id)
end
def unsubscribed
MatchmakingService.cancel(current_user.id)
end
end