diff --git a/classes.py b/classes.py index 2126c92..256e861 100644 --- a/classes.py +++ b/classes.py @@ -65,6 +65,9 @@ class Irc(utils.DeprecatedAttributesObject): self.pingTimer = None + # Sets the multiplier for autoconnect delay (grows with time). + self.autoconnect_active_multiplier = 1 + self.initVars() if world.testing: @@ -310,6 +313,7 @@ class Irc(utils.DeprecatedAttributesObject): log.info('(%s) Starting ping schedulers....', self.name) self.schedulePing() log.info('(%s) Server ready; listening for data.', self.name) + self.autoconnect_active_multiplier = 1 # Reset any extra autoconnect delays self.run() else: # Configuration error :( log.error('(%s) A configuration error was encountered ' @@ -327,8 +331,22 @@ class Irc(utils.DeprecatedAttributesObject): # If autoconnect is enabled, loop back to the start. Otherwise, # return and stop. autoconnect = self.serverdata.get('autoconnect') + + # Sets the autoconnect growth multiplier (e.g. a value of 2 multiplies the autoconnect + # time by 2 on every failure, etc.) + autoconnect_multiplier = self.serverdata.get('autoconnect_multiplier', 2) + autoconnect_max = self.serverdata.get('autoconnect_max', 1800) + # These values must at least be 1. + autoconnect_multiplier = max(autoconnect_multiplier, 1) + autoconnect_max = max(autoconnect_max, 1) + log.debug('(%s) Autoconnect delay set to %s seconds.', self.name, autoconnect) if autoconnect is not None and autoconnect >= 1: + log.debug('(%s) Multiplying autoconnect delay %s by %s.', self.name, autoconnect, self.autoconnect_active_multiplier) + autoconnect *= self.autoconnect_active_multiplier + # Add a cap on the max. autoconnect delay, so that we don't go on forever... + autoconnect = min(autoconnect, autoconnect_max) + log.info('(%s) Going to auto-reconnect in %s seconds.', self.name, autoconnect) # Continue when either self.aborted is set or the autoconnect time passes. # Compared to time.sleep(), this allows us to stop connections quicker if we @@ -336,6 +354,9 @@ class Irc(utils.DeprecatedAttributesObject): self.aborted.clear() self.aborted.wait(autoconnect) + # Store in the local state what the autoconnect multiplier currently is. + self.autoconnect_active_multiplier *= autoconnect_multiplier + if self not in world.networkobjects.values(): log.debug('Stopping stale connect loop for old connection %r', self.name) return diff --git a/coremods/control.py b/coremods/control.py index 2d3ba7b..8511b87 100644 --- a/coremods/control.py +++ b/coremods/control.py @@ -93,9 +93,11 @@ def _rehash(): log.debug('rehash: removing connection to %r (removed from config).', network) remove_network(ircobj) else: + # XXX: we should really just add abstraction to Irc to update config settings... ircobj.conf = new_conf ircobj.serverdata = new_conf['servers'][network] ircobj.botdata = new_conf['bot'] + ircobj.autoconnect_cache = 1 # Clear the IRC object's channel loggers and replace them with # new ones by re-running logSetup(). diff --git a/example-conf.yml b/example-conf.yml index f28f451..dca98a5 100644 --- a/example-conf.yml +++ b/example-conf.yml @@ -151,6 +151,13 @@ servers: # disable autoconnect entirely. autoconnect: 5 + # Optional autoconnect settings: + # Defines whether we should multiply the autoconnect delay by a certain value every time + # a connection fails. This defaults to 2 if not set (30 secs becomes 60 secs, 120 secs, etc.) + #autoconnect_multiplier: 2 + # Defines what the maximum autoconnect time will be (defaults to 1800 secs). + #autoconnect_max: 1800 + # Sets the ping frequency in seconds (i.e. how long we should wait between # sending pings to our uplink). When more than two consecutive pings are missed, # PyLink will disconnect with a ping timeout. This defaults to 90 if not set.