Fix up logic for Omnibot.Core pinging and auto-reconnect
The core module keeps track of the last message received. If the last message received was more than X seconds ago (configurable), it will send a ping. If the last message was received more than Y seconds ago (again, configurable) then reset the connection. Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
38
lib/core.ex
38
lib/core.ex
@@ -3,7 +3,7 @@ defmodule Omnibot.Core do
|
|||||||
use Omnibot.Plugin
|
use Omnibot.Plugin
|
||||||
alias Omnibot.{Config, Irc, Util}
|
alias Omnibot.{Config, Irc, Util}
|
||||||
|
|
||||||
@default_config ping_every: 60, ping_after: 60, channels: :all
|
@default_config quit_after: 180, ping_after: 60, channels: :all
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def children(_cfg) do
|
def children(_cfg) do
|
||||||
@@ -59,16 +59,15 @@ defmodule Omnibot.Core do
|
|||||||
"001" -> sync_channels(irc)
|
"001" -> sync_channels(irc)
|
||||||
"PING" ->
|
"PING" ->
|
||||||
Irc.send_msg(irc, "PONG", msg.params)
|
Irc.send_msg(irc, "PONG", msg.params)
|
||||||
update_last_ping(Util.now_unix())
|
update_last_reply(Util.now_unix())
|
||||||
update_last_pong(Util.now_unix()) # also update pong because we ponged
|
|
||||||
"PONG" -> update_last_pong(Util.now_unix())
|
|
||||||
_ -> route_msg(irc, msg)
|
_ -> route_msg(irc, msg)
|
||||||
end
|
end
|
||||||
|
update_last_reply(Util.now_unix())
|
||||||
end
|
end
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def on_init(_cfg) do
|
def on_init(_cfg) do
|
||||||
%{channels: MapSet.new(), last_pong: Util.now_unix(), last_ping: Util.now_unix()}
|
%{channels: MapSet.new(), last_reply: Util.now_unix()}
|
||||||
end
|
end
|
||||||
|
|
||||||
defp sync_channels(irc) do
|
defp sync_channels(irc) do
|
||||||
@@ -93,35 +92,28 @@ defmodule Omnibot.Core do
|
|||||||
update_state(fn cfg = %{channels: channels} -> %{cfg | channels: MapSet.delete(channels, channel)} end)
|
update_state(fn cfg = %{channels: channels} -> %{cfg | channels: MapSet.delete(channels, channel)} end)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp last_pong() do
|
defp last_reply() do
|
||||||
state().last_pong
|
state().last_reply
|
||||||
end
|
end
|
||||||
|
|
||||||
defp update_last_pong(last_pong) do
|
defp update_last_reply(last_reply) do
|
||||||
update_state(fn cfg -> %{cfg | last_pong: last_pong} end)
|
update_state(fn cfg -> %{cfg | last_reply: last_reply} end)
|
||||||
end
|
|
||||||
|
|
||||||
defp last_ping() do
|
|
||||||
state().last_ping
|
|
||||||
end
|
|
||||||
|
|
||||||
defp update_last_ping(last_ping) do
|
|
||||||
update_state(fn cfg -> %{cfg | last_ping: last_ping} end)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
defp ping_watcher(irc) do
|
defp ping_watcher(irc) do
|
||||||
since_pong = Util.now_unix() - last_pong()
|
since_reply = Util.now_unix() - last_reply()
|
||||||
since_ping = Util.now_unix() - last_ping()
|
|
||||||
ping_every = cfg(:ping_every)
|
|
||||||
ping_after = cfg(:ping_after)
|
ping_after = cfg(:ping_after)
|
||||||
|
quit_after = cfg(:quit_after)
|
||||||
cond do
|
cond do
|
||||||
# Kill IRC instance
|
# Kill IRC instance
|
||||||
since_pong >= (3 * ping_every) ->
|
since_reply >= quit_after ->
|
||||||
Logger.error("IRC has not replied in #{3 * ping_every}")
|
Logger.error("IRC has not replied in #{quit_after}")
|
||||||
Process.exit(irc, :ping_timeout)
|
Process.exit(irc, :ping_timeout)
|
||||||
|
|
||||||
# Send ping message
|
# Send ping message
|
||||||
since_pong >= ping_every and ping_after >= since_ping ->
|
# use == since >= will ping each time until a reply is received
|
||||||
|
since_reply == ping_after ->
|
||||||
|
update_last_reply(Util.now_unix())
|
||||||
Irc.send_msg(irc, "PING", "omnibot")
|
Irc.send_msg(irc, "PING", "omnibot")
|
||||||
|
|
||||||
true -> nil
|
true -> nil
|
||||||
|
|||||||
Reference in New Issue
Block a user