module IrcLag
IrcLag — server lag probe state and Ibis announcement footers. Public: announcement_footer, format_one_line, lag_meta_parts, record_lag_probe_reply!, pending_replies Depends: IrcFormat Tests: test/lib/irc_lag_test.rb, test/plugins/autoop_test.rb
Constants
- LAG_PROBE_PREFIX
- PING_INTERVAL_SEC
Public Instance Methods
Source
# File lib/irc_lag.rb, line 67 def announcement_ready?(pending) !pending.nil? && !pending[:lag_ms].nil? && !pending[:ping_ms].nil? end
Source
# File lib/irc_lag.rb, line 217 def append(text, lag_ms: current_ms, ping_ms: nil, server: nil) body = text.to_s return body if body.empty? "#{body}\n#{footer(lag_ms: lag_ms, ping_ms: ping_ms, server: server)}" end
Source
# File lib/irc_lag.rb, line 63 def complete_pending?(pending, lag_ms:) !pending.nil? && !lag_ms.nil? end
Source
# File lib/irc_lag.rb, line 152 def due_for_ping?(last_ping_at, now:, interval_sec: PING_INTERVAL_SEC, pending: probe_pending?) return false if pending last_ping_at.nil? || (now - last_ping_at) >= interval_sec end
Source
# File lib/irc_lag.rb, line 144 def elapsed_ms(start_time, clock: -> { Process.clock_gettime(Process::CLOCK_MONOTONIC) }) ((clock.call - start_time) * 1000).round end
Source
# File lib/irc_lag.rb, line 58 def find_pending_by_nick(nick, store: pending_replies) target = nick.to_s store.find { |_token, entry| entry[:nick].to_s.casecmp?(target) }&.last end
Source
# File lib/irc_lag.rb, line 224 def format_one_line(tag:, title:, body:, lag_ms: current_ms, ping_ms: nil, server: nil, banner_style: IrcFormat.color(0, 4)) [ IrcFormat.bracket_label(tag), IrcFormat.menu_heading(title.to_s.strip, style: banner_style), body, inline_footer(lag_ms: lag_ms, ping_ms: ping_ms, server: server) ].join(" ") end
Source
# File lib/irc_lag.rb, line 148 def lag_from_roundtrip(sent_at:, received_at:) elapsed_ms(sent_at, clock: -> { received_at }) end
Source
# File lib/irc_lag.rb, line 201 def lag_meta_parts(lag_ms:, ping_ms: nil, server: nil) parts = ["lag #{lag_ms.to_i}ms"] parts << "ping #{ping_ms.to_i}ms" unless ping_ms.nil? server_text = server.to_s.strip parts << server_text unless server_text.empty? parts end
Source
# File lib/irc_lag.rb, line 126 def lag_probe_error?(params, prefix: LAG_PROBE_PREFIX) unknown_command_from_error(params).start_with?(prefix) end
Source
# File lib/irc_lag.rb, line 110 def lag_probe_token(timestamp) (timestamp.to_f * 1_000_000).round end
Source
# File lib/irc_lag.rb, line 130 def parse_lag_probe_token(command) match = command.to_s.match(/\A#{LAG_PROBE_PREFIX}(\d+)\z/) return nil unless match match[1].to_i end
Source
# File lib/irc_lag.rb, line 137 def parse_pong_token(param) match = param.to_s.sub(/\A:/, "").match(/\A#{LAG_PROBE_PREFIX}(\d+)\z/) return nil unless match match[1].to_i end
Source
# File lib/irc_lag.rb, line 24 def pending_replies @pending_replies ||= {} end
Source
# File lib/irc_lag.rb, line 114 def ping_command(timestamp:) "PING :#{LAG_PROBE_PREFIX}#{lag_probe_token(timestamp)}" end
Source
# File lib/irc_lag.rb, line 98 def ping_interval_sec PING_INTERVAL_SEC end
Source
# File lib/irc_lag.rb, line 106 def probe_pending? !@pending_sent_at.nil? end
Source
# File lib/irc_lag.rb, line 175 def record_lag_probe_reply!(params, received_at:, store: pending_replies) return nil unless lag_probe_error?(params) token = parse_lag_probe_token(unknown_command_from_error(params)) return nil unless token pending = store[token] return nil unless pending ms = lag_from_roundtrip(sent_at: pending[:sent_at], received_at: received_at) set_current_ms!(ms) pending[:lag_ms] = ms { ms: ms, pending: pending, token: token } end
Source
# File lib/irc_lag.rb, line 163 def record_pong!(params, received_at:) token = parse_pong_token(Array(params).first) return nil unless token return nil unless @pending_sent_at ms = lag_from_roundtrip(sent_at: @pending_sent_at, received_at: received_at) @pending_sent_at = nil set_current_ms!(ms) set_current_ping_ms!(ms) ms end
Source
# File lib/irc_lag.rb, line 32 def register_pending_reply(token, sent_at:, nick:, count:, message: nil, channel: nil, server: nil, ping_sent_at: nil, store: pending_replies) store[token] = { sent_at: sent_at, nick: nick, count: count, message: message, channel: channel, server: server, ping_sent_at: ping_sent_at, ping_ms: nil } end
Source
# File lib/irc_lag.rb, line 158 def register_ping!(sent_at) @pending_sent_at = sent_at @last_ping_at = sent_at end
Source
# File lib/irc_lag.rb, line 118 def reply_probe_command(timestamp:) "#{LAG_PROBE_PREFIX}#{lag_probe_token(timestamp)}" end
Source
# File lib/irc_lag.rb, line 16 def reset! @current_ms = 0 @current_ping_ms = nil @pending_sent_at = nil @last_ping_at = nil reset_pending_replies! end
Source
# File lib/irc_lag.rb, line 28 def reset_pending_replies!(store: {}) @pending_replies = store end
Source
# File lib/irc_lag.rb, line 86 def set_current_ms!(ms) @current_ms = ms.to_i end
Source
# File lib/irc_lag.rb, line 94 def set_current_ping_ms!(ms) @current_ping_ms = ms.nil? ? nil : ms.to_i end
Source
# File lib/irc_lag.rb, line 71 def stale_pending_announcements(max_age_sec:, now: Process.clock_gettime(Process::CLOCK_MONOTONIC), store: pending_replies) store.filter_map do |token, pending| next unless pending[:lag_ms] next unless pending[:ping_ms].nil? next if (now - pending[:sent_at]) < max_age_sec [token, pending] end end
Source
# File lib/irc_lag.rb, line 190 def sync_bot_lag!(bot, ms: current_ms, ping_ms: current_ping_ms) return unless bot bot.data[:irc_lag_ms] = ms.to_i bot.data[:irc_ping_ms] = ping_ms.to_i unless ping_ms.nil? end
Source
# File lib/irc_lag.rb, line 46 def take_pending_reply(token, store: pending_replies) store.delete(token) end
Source
# File lib/irc_lag.rb, line 122 def unknown_command_from_error(params) Array(params)[1].to_s end
Source
# File lib/irc_lag.rb, line 50 def update_pending_ping!(token, ping_ms:, store: pending_replies) entry = store[token] return nil unless entry entry[:ping_ms] = ping_ms.to_i entry end