Evita che ensure_home_from_env! annulli il drain a ogni allocate, e prepara /slates/offline.mp4 sul nodo Cloud per create_path MediaMTX. Co-authored-by: Cursor <cursoragent@cursor.com>
60 lines
1.9 KiB
Ruby
60 lines
1.9 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module Streams
|
|
# Assegna un StreamNode a una nuova sessione (least-loaded tra i ready).
|
|
# Garantisce il nodo "home" derivato dagli ENV MediaMTX attuali.
|
|
class NodeRegistry
|
|
class NoCapacityError < StandardError; end
|
|
|
|
HOME_SLUG = "home"
|
|
|
|
class << self
|
|
def ensure_home_from_env!
|
|
StreamNode.find_or_initialize_by(slug: HOME_SLUG).tap do |node|
|
|
attrs = {
|
|
hostname: home_hostname,
|
|
role: "home",
|
|
provider: "local",
|
|
rtmp_base_url: MatchLiveTv.mediamtx_rtmp_url,
|
|
hls_base_url: MatchLiveTv.hls_public_url,
|
|
api_base_url: MatchLiveTv.mediamtx_api_url,
|
|
internal_rtmp_url: ENV.fetch("MEDIAMTX_INTERNAL_RTMP_URL", "rtmp://mediamtx:1935"),
|
|
internal_hls_url: ENV.fetch("MEDIAMTX_HLS_URL", "http://mediamtx:8888"),
|
|
max_publishers: ENV.fetch("STREAM_NODE_HOME_MAX_PUBLISHERS", "6").to_i,
|
|
max_relays: ENV.fetch("STREAM_NODE_HOME_MAX_RELAYS", "6").to_i
|
|
}
|
|
# Non sovrascrivere drain/offline/error (ops) a ogni allocate!
|
|
attrs[:status] = "ready" if node.new_record? || !%w[draining offline error].include?(node.status)
|
|
node.assign_attributes(attrs)
|
|
node.save!
|
|
end
|
|
end
|
|
|
|
def allocate!
|
|
ensure_home_from_env!
|
|
|
|
node = StreamNode.ready
|
|
.to_a
|
|
.select(&:allocatable?)
|
|
.min_by { |n| [n.active_publishers, n.role == "home" ? 1 : 0, n.slug] }
|
|
|
|
raise NoCapacityError, "Nessun nodo streaming con slot liberi" if node.nil?
|
|
|
|
node
|
|
end
|
|
|
|
private
|
|
|
|
def home_hostname
|
|
ENV["STREAM_NODE_HOME_HOSTNAME"].presence ||
|
|
begin
|
|
uri = URI.parse(MatchLiveTv.mediamtx_rtmp_url.sub(/\Artmps?:\/\//, "http://"))
|
|
uri.host.presence
|
|
rescue URI::InvalidURIError
|
|
nil
|
|
end || "home"
|
|
end
|
|
end
|
|
end
|
|
end
|