Initial commit: monorepo Match Live TV.

Rails API, app Flutter, infrastruttura Docker/MediaMTX, sito marketing e documentazione di deploy.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-05-26 17:45:37 +02:00
commit bba6df52c0
381 changed files with 20599 additions and 0 deletions

View File

@@ -0,0 +1,94 @@
module Webhooks
class MediamtxHandler
def initialize(event:, session_id:, metadata: {})
@event = event
@session_id = session_id
@metadata = metadata
end
def call
session = StreamSession.find_by(id: @session_id)
return unless session
case @event
when "connect"
handle_connect(session)
when "disconnect"
handle_disconnect(session)
when "ready"
handle_ready(session)
end
end
private
def handle_connect(session)
return if session.live? && session.stream_events.where(event_type: "connected").exists?
if session.reconnecting?
session.reconnect! if session.may_reconnect?
cancel_timeout(session)
log(session, "reconnected")
broadcast(session, "reconnected")
elsif session.connecting? || session.idle?
session.go_live! if session.may_go_live?
log(session, "connected")
broadcast(session, "connected")
end
end
def handle_disconnect(session)
return unless session.live? || session.connecting?
if session.connecting?
session.update!(status: "reconnecting")
elsif session.may_lose_connection?
session.lose_connection!
end
log(session, "disconnected", @metadata)
broadcast(session, "disconnected")
schedule_timeout(session)
end
def handle_ready(session)
log(session, "connected", { ready: true })
end
def schedule_timeout(session)
job = DisconnectionTimeoutJob.perform_in(
MatchLiveTv.reconnect_timeout_seconds.seconds,
session.id
)
session.update!(timeout_job_id: job)
end
def cancel_timeout(session)
return if session.timeout_job_id.blank?
Sidekiq::ScheduledSet.new.find_job(session.timeout_job_id)&.delete
session.update!(timeout_job_id: nil)
end
def log(session, type, meta = {})
return if duplicate_event?(session, type, meta)
session.stream_events.create!(
event_type: type,
metadata: meta.merge(source: "mediamtx"),
occurred_at: Time.current
)
end
def duplicate_event?(session, type, meta)
session.stream_events
.where(event_type: type)
.where("occurred_at > ?", 2.seconds.ago)
.where(metadata: meta.merge(source: "mediamtx"))
.exists?
end
def broadcast(session, event)
SessionChannel.broadcast_message(session, { type: "stream_event", event: event })
end
end
end