Periodically ping server to detect disconnection

In some cases, disconnection from the server can be unclean and won't be
noticed until the bot tries to send a message, which may never happen if
it did not disconnect during the game. To solve this problem, it will
now ping the server every 2 minutes by default, which will result in
a broken pipe error if the connection is dead. This won't be able to
detect netsplits where the server the bot is on stays online, because
those are impossible to correctly detect in every case.

This commit also adds a !latency command so that users can verify if the
bot is lagging.
This commit is contained in:
nyuszika7h 2017-01-06 15:52:26 +01:00
parent d78f0e5179
commit a6e3c0a720
4 changed files with 26 additions and 2 deletions

View File

@ -33,6 +33,7 @@
"Give me a ping, Vasily. One ping only, please.",
"Would you people please leave me alone? Seriously."
],
"latency": "{0:.3f} second{1}.",
"lynch_reveal": [
"The villagers, after much debate, finally decide on lynching \u0002{0}\u0002, who turned out to be... a{1} \u0002{2}\u0002.",
"After a prolonged struggle, \u0002{0}\u0002 is forced to the gallows, and is discovered after death to be a{1} \u0002{2}\u0002.",

View File

@ -3,6 +3,8 @@
import base64
import socket
import sys
import threading
import time
import traceback
import botconfig
@ -44,6 +46,13 @@ def unhandled(cli, prefix, cmd, *args):
for fn in decorators.HOOKS.get(cmd, []):
fn.caller(cli, prefix, *args)
def ping_server(cli):
if var.SERVER_PING_INTERVAL > 0:
ts = time.time()
var.LAST_SERVER_PING = ts
cli.send("PING :{0}".format(ts))
threading.Timer(var.SERVER_PING_INTERVAL, ping_server, args=(cli,)).start()
def connect_callback(cli):
regaincount = 0
releasecount = 0
@ -81,6 +90,8 @@ def connect_callback(cli):
users.Bot.change_nick(botconfig.NICK)
ping_server(cli)
def mustregain(cli, server, bot_nick, nick, msg):
nonlocal regaincount

View File

@ -204,6 +204,9 @@ DEV_CHANNEL = ""
DEV_PREFIX = ""
PASTEBIN_ERRORS = False
# How often to ping the server (in seconds) to detect unclean disconnection
SERVER_PING_INTERVAL = 120
LAST_SERVER_PING = None
# TODO: move this to a game mode called "fixed" once we implement a way to randomize roles (and have that game mode be called "random")
DEFAULT_ROLE = "villager"

View File

@ -46,7 +46,7 @@ import botconfig
import src
import src.settings as var
from src.utilities import *
from src import db, events, channels, users, hooks, logger, proxy, debuglog, errlog, plog
from src import db, events, channels, users, handler, hooks, logger, proxy, debuglog, errlog, plog
from src.decorators import command, cmd, hook, handle_error, event_listener, COMMANDS
from src.messages import messages
from src.warnings import *
@ -481,7 +481,6 @@ def restart_program(cli, nick, chan, rest): # XXX: sighandler (top of file) also
# handler now, but I'm keeping it for now just in case.
var.RESTARTING = True
@cmd("ping", pm=True)
def pinger(cli, nick, chan, rest):
"""Check if you or the bot is still connected."""
@ -491,6 +490,16 @@ def pinger(cli, nick, chan, rest):
cmd_char=botconfig.CMD_CHAR,
goat_action=random.choice(messages["goat_actions"])))
@cmd("latency", pm=True)
def latency(cli, nick, chan, rest):
handler.ping_server(cli)
@hook("pong", hookid=300)
def latency_pong(cli, server, target, ts):
lat = round(time.time() - var.LAST_SERVER_PING, 3)
reply(cli, nick, chan, messages["latency"].format(lat, "" if lat == 1 else "s"))
hook.unhook(300)
@cmd("simple", raw_nick=True, pm=True)
def mark_simple_notify(cli, nick, chan, rest):
"""Makes the bot give you simple role instructions, in case you are familiar with the roles."""