# frozen_string_literal: true
# Overseer watches and checks pending requests to servers for timeouts
module ESM
class Websocket
class Request
class Overseer
# Starts a thread that loops over all connections requests and times them out if they are taking too long
def self.watch!
check_every = ESM.config.websocket_request_overseer.check_every
@thread = Thread.new do
loop do
check_connections
sleep(check_every)
end
end
end
# Stops the EM thread
def self.die
return if @thread.nil?
Thread.kill(@thread)
end
# Checks all the connections
# @private
def self.check_connections
ESM::Websocket.connections.each do |server_id, connection|
process_connection(server_id, connection)
end
end
# Checks a connection's requests
# @private
def self.process_connection(_server_id, connection)
@connection = connection
@connection.requests.each do |id, request|
check_request(id, request)
end
end
# Finally, check a single request, and remove it if it's timed out
# @private
def self.check_request(id, request)
return if !request.timed_out?
# Remove the request
@connection.remove_request(id)
# Don't warn on our internal messages
return if request.user.nil?
embed =
ESM::Embed.build do |e|
e.description = I18n.t(
"request_timed_out",
command_message: request.command.usage,
server_id: @connection.server.server_id,
user: request.user.mention
)
e.color = :red
end
# Let the user know
request.command.reply(embed)
rescue => e
ESM.logger.error("#{self.class}##{__method__}") do
ESM::JSON.pretty_generate(
server_id: @connection&.server&.server_id,
command_name: request&.command&.name,
request: request&.to_h,
message: e.message,
backtrace: e.backtrace
)
end
end
end
end
end
end