Many thread safe updates.

Updating instances timesout after 10 seconds.
Now waits until checking all instances finishes before starting the timer for next.
More random debugging logs
This commit is contained in:
Kevinf100 2025-06-03 23:37:20 -04:00
parent 4dcd6dd2f4
commit 54ea7f04fd
4 changed files with 52 additions and 14 deletions

View File

@ -5,35 +5,54 @@ module BackendInfo
@@csp : Array(String) = Array.new(CONFIG.invidious_companion.size, "") @@csp : Array(String) = Array.new(CONFIG.invidious_companion.size, "")
@@working_ends : Array(Int32) = Array(Int32).new(0) @@working_ends : Array(Int32) = Array(Int32).new(0)
@@mutex : Mutex = Mutex.new @@mutex : Mutex = Mutex.new
@@working_mutex : Mutex = Mutex.new
def check_backends def check_backends
check_companion() check_companion()
LOGGER.debug("Invidious companion: Updating working_ends") LOGGER.debug("Invidious companion: Updating working_ends")
@@working_ends.clear updated_ends = Array(Int32).new(0)
@@status.each_with_index do |_, index| @@status.each_with_index do |_, index|
if @@status[index] == 2 if @@status[index] == 2
@@working_ends.push(index) updated_ends.push(index)
end end
end end
@@working_mutex.synchronize do
@@working_ends = updated_ends
end
LOGGER.debug("Invidious companion: New working_ends \"#{@@working_ends}\"") LOGGER.debug("Invidious companion: New working_ends \"#{@@working_ends}\"")
end end
private def check_companion private def check_companion
# Create Channels the size of CONFIG.invidious_companion
comp_size = CONFIG.invidious_companion.size
channels = Channel(Nil).new(comp_size)
LOGGER.debug("Invidious companion: comp_size \"#{comp_size}\"")
CONFIG.invidious_companion.each_with_index do |companion, index| CONFIG.invidious_companion.each_with_index do |companion, index|
spawn do spawn do
begin begin
response = HTTP::Client.get "#{companion.private_url}/healthz" client = HTTP::Client.new(companion.private_url)
client.connect_timeout = 10.seconds
response = client.get("/healthz")
if response.status_code == 200 if response.status_code == 200
check_videoplayback_proxy(companion, index) check_videoplayback_proxy(companion, index)
generate_csp([companion.public_url.to_s, companion.i2p_public_url.to_s], @@exvpp_url[index], index) generate_csp([companion.public_url.to_s, companion.i2p_public_url.to_s], @@exvpp_url[index], index)
else else
@@status[index] = 0 @@mutex.synchronize do
@@status[index] = 0
end
end end
rescue rescue
@@status[index] = 0 @@mutex.synchronize do
@@status[index] = 0
end
ensure
LOGGER.debug("Invidious companion: Done Index: \"#{index}\"")
channels.send(nil)
end end
end end
end end
# Wait until we receive a signal from them all
comp_size.times { channels.receive }
end end
private def check_videoplayback_proxy(companion : Config::CompanionConfig, index : Int32) private def check_videoplayback_proxy(companion : Config::CompanionConfig, index : Int32)
@ -41,26 +60,36 @@ module BackendInfo
info = HTTP::Client.get "#{companion.private_url}/info" info = HTTP::Client.get "#{companion.private_url}/info"
exvpp_url = JSON.parse(info.body)["external_videoplayback_proxy"]?.try &.to_s exvpp_url = JSON.parse(info.body)["external_videoplayback_proxy"]?.try &.to_s
rescue JSON::ParseException rescue JSON::ParseException
@@status[index] = 2 @@mutex.synchronize do
@@status[index] = 2
end
return return
end end
exvpp_url = "" if exvpp_url.nil? exvpp_url = "" if exvpp_url.nil?
@@exvpp_url[index] = exvpp_url @@exvpp_url[index] = exvpp_url
if exvpp_url.empty? if exvpp_url.empty?
@@status[index] = 2 @@mutex.synchronize do
@@status[index] = 2
end
return return
else else
begin begin
exvpp_health = HTTP::Client.get "#{exvpp_url}/health" exvpp_health = HTTP::Client.get "#{exvpp_url}/health"
if exvpp_health.status_code == 200 if exvpp_health.status_code == 200
@@status[index] = 2 @@mutex.synchronize do
@@status[index] = 2
end
return exvpp_url return exvpp_url
else else
@@status[index] = 1 @@mutex.synchronize do
@@status[index] = 1
end
end end
rescue rescue
@@status[index] = 1 @@mutex.synchronize do
@@status[index] = 1
end
end end
end end
end end
@ -80,7 +109,11 @@ module BackendInfo
end end
def get_working_ends def get_working_ends
return @@working_ends # We need to stall this if we are updating the array
# Not doing this can cause this to return weird values while being updated
@@working_mutex.synchronize do
@@working_ends.dup
end
end end
def get_exvpp def get_exvpp

View File

@ -4,6 +4,7 @@ class Invidious::Jobs::CheckBackend < Invidious::Jobs::BaseJob
def begin def begin
loop do loop do
LOGGER.info("Backend Checker: Starting")
BackendInfo.check_backends BackendInfo.check_backends
LOGGER.info("Backend Checker: Done, sleeping for #{CONFIG.check_backends_interval} seconds") LOGGER.info("Backend Checker: Done, sleeping for #{CONFIG.check_backends_interval} seconds")
sleep CONFIG.check_backends_interval.seconds sleep CONFIG.check_backends_interval.seconds

View File

@ -46,7 +46,9 @@ module Invidious::Routes::BeforeAll
begin begin
current_companion = env.request.cookies[CONFIG.server_id_cookie_name].value.try &.to_i current_companion = env.request.cookies[CONFIG.server_id_cookie_name].value.try &.to_i
rescue rescue
current_companion = BackendInfo.get_working_ends.sample working_ends = BackendInfo.get_working_ends
LOGGER.debug("Invidious companion youtube_api: get_working_ends: \"#{working_ends}\"")
current_companion = working_ends.sample
end end
if current_companion > CONFIG.invidious_companion.size if current_companion > CONFIG.invidious_companion.size

View File

@ -689,11 +689,13 @@ module YoutubeAPI
begin begin
if env.nil? if env.nil?
current_companion = BackendInfo.get_working_ends.sample working_ends = BackendInfo.get_working_ends
LOGGER.debug("Invidious companion youtube_api: get_working_ends: \"#{working_ends}\"")
current_companion = working_ends.sample
else else
current_companion = env.get("current_companion").as(Int32) current_companion = env.get("current_companion").as(Int32)
end end
LOGGER.trace("Invidious companion: current_companion: #{current_companion}") LOGGER.debug("Invidious companion: current_companion: #{current_companion}")
response = COMPANION_POOL[current_companion].client &.post(endpoint, headers: headers, body: data.to_json) response = COMPANION_POOL[current_companion].client &.post(endpoint, headers: headers, body: data.to_json)
body = response.body body = response.body
if (response.status_code != 200) if (response.status_code != 200)