Aggiunge i tornei con hub, pagina pubblica e tabellone per semifinali e finali.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-05 15:05:57 +02:00
co-authored by Cursor
parent d52434fb2e
commit a1f4c24a43
124 changed files with 6979 additions and 91 deletions
@@ -0,0 +1,83 @@
# frozen_string_literal: true
module Streams
# Durante quiet hours chiude CPX cloud idle; se hanno sessioni attive solo alert Ops.
class NightCloudSweeper
Result = Struct.new(:skipped, :actions, :error, keyword_init: true)
class << self
def enabled?
ENV.fetch("STREAM_NIGHT_SWEEP_ENABLED", "1") == "1"
end
def sweep!(provisioner: nil)
new(provisioner: provisioner).sweep!
end
end
def initialize(provisioner: nil)
@provisioner = provisioner || NodeProvisioner.new
end
def sweep!
unless self.class.enabled?
return Result.new(skipped: true, actions: [], error: "disabled")
end
unless QuietHours.active?
return Result.new(skipped: true, actions: [], error: "outside_quiet_hours")
end
actions = []
cloud_nodes.find_each do |node|
if node.occupying_sessions.exists?
alert_active_night_node!(node)
actions << :"alert_active_#{node.slug}"
next
end
close_idle_node!(node)
actions << :"decommission_#{node.slug}"
rescue NodeProvisioner::BusyError, NodeProvisioner::Error => e
Rails.logger.warn("[Streams::NightCloudSweeper] #{node.slug}: #{e.message}")
actions << :"error_#{node.slug}"
end
Rails.logger.info("[Streams::NightCloudSweeper] actions=#{actions.inspect}")
Result.new(skipped: false, actions: actions)
end
private
def cloud_nodes
StreamNode.where(role: "cloud").where(status: %w[ready draining provisioning])
end
def alert_active_night_node!(node)
Ops::IncidentRecorder.record(
{
kind: "stream_overflow",
severity: "warning",
title: "CPX attivo di notte — verificare evento",
message: "Nodo #{node.slug} ha #{node.active_publishers} sessione/i in quiet hours (#{QuietHours.range_config} #{QuietHours.time_zone_name})",
metadata: {
"slug" => node.slug,
"session_ids" => node.occupying_sessions.pluck(:id),
"quiet_hours" => QuietHours.range_config
},
fingerprint: "stream_overflow:night_active:#{node.slug}"
}
)
end
def close_idle_node!(node)
@provisioner.drain!(node) unless node.status == "draining"
node.reload
raise NodeProvisioner::BusyError, "sessioni ancora attive" if node.occupying_sessions.exists?
slug = node.slug
@provisioner.decommission!(node)
Rails.logger.warn("[Streams::NightCloudSweeper] decommissioned idle cloud node #{slug} during quiet hours")
Ops::IncidentRecorder.resolve(fingerprint: "stream_overflow:night_active:#{slug}")
end
end
end