Files
MatchLiveTv/backend/app/services/mediamtx/cleanup_orphan_paths.rb
Emiliano Frascaro 827abf80cb Elimina i path MediaMTX orfani dopo ogni diretta.
Corregge il cleanup dei path live/match_{uuid}, rimuove sempre il path a fine sessione e lo esegue ogni ora via cron.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-16 20:42:40 +02:00

95 lines
2.6 KiB
Ruby

# frozen_string_literal: true
module Mediamtx
# Rimuove path MediaMTX live/match_{uuid} lasciati attivi dopo fine diretta.
class CleanupOrphanPaths
Result = Struct.new(:removed, :skipped, keyword_init: true)
SESSION_PATH = %r{\Alive/match_([0-9a-f-]{36})(?:_air)?\z}i
ACTIVE_SESSION_STATUSES = %w[live paused connecting reconnecting].freeze
PROCESSING_GRACE = -> { ENV.fetch("RECORDINGS_LOCAL_PROCESSING_GRACE_HOURS", "6").to_i.hours }
def initialize(client: Client.new, logger: Rails.logger)
@client = client
@logger = logger
@removed = 0
@skipped = 0
@deleted_session_ids = Set.new
end
def call
online = @client.online_path_names
@client.list_paths.each do |item|
name = item["name"].to_s
session_id = session_id_from_path(name)
unless session_id
@skipped += 1
next
end
if online.include?(name) || item["online"]
@skipped += 1
next
end
next unless removable?(session_id)
remove_session_paths(session_id, name)
end
Result.new(removed: @removed, skipped: @skipped)
end
def removable?(session_id)
session = StreamSession.find_by(id: session_id)
return true if session.nil?
return false if ACTIVE_SESSION_STATUSES.include?(session.status)
recording = Recording.find_by(stream_session: session)
return true if recording.nil?
return false if recording.status == "processing" && processing_within_grace?(session)
true
end
private
def session_id_from_path(path_name)
match = path_name.match(SESSION_PATH)
match&.[](1)
end
def processing_within_grace?(session)
ended_at = session.ended_at || session.updated_at
ended_at.nil? || ended_at >= PROCESSING_GRACE.call.ago
end
def remove_session_paths(session_id, path_name)
return if @deleted_session_ids.include?(session_id)
session = StreamSession.find_by(id: session_id)
if session
@client.delete_path(session)
else
delete_orphan_path_names(session_id)
end
@deleted_session_ids.add(session_id)
@removed += 1
@logger.info("[Mediamtx::CleanupOrphanPaths] removed paths for session #{session_id} (from #{path_name})")
rescue Client::Error, Faraday::Error => e
@skipped += 1
@logger.warn("[Mediamtx::CleanupOrphanPaths] skip #{path_name}: #{e.message}")
end
def delete_orphan_path_names(session_id)
@client.delete_path_name("live/match_#{session_id}")
@client.delete_path_name("live/match_#{session_id}_air")
end
end
end