Browse Source

Implement reconnections correctly in IRC

Uses protocol.ReconnectingClientFactory as superclass,
which uses exponential backoff in retrying.
Also change on_welcome_trigger callback to reset the
status of message channels which have reconnected,
so that they become operable once reconnected.
master
Adam Gibson 9 years ago
parent
commit
a9ca13f7d3
No known key found for this signature in database
GPG Key ID: B3AE09F1E9A3197A
  1. 11
      jmdaemon/jmdaemon/irc.py
  2. 6
      jmdaemon/jmdaemon/message_channel.py
  3. 9
      jmdaemon/test/test_message_channel.py

11
jmdaemon/jmdaemon/irc.py

@ -44,7 +44,7 @@ def get_config_irc_channel(chan_name, btcnet):
channel += "-test" channel += "-test"
return channel return channel
class TxIRCFactory(protocol.ClientFactory): class TxIRCFactory(protocol.ReconnectingClientFactory):
def __init__(self, wrapper): def __init__(self, wrapper):
self.wrapper = wrapper self.wrapper = wrapper
self.channel = self.wrapper.channel self.channel = self.wrapper.channel
@ -60,11 +60,16 @@ class TxIRCFactory(protocol.ClientFactory):
if not self.wrapper.give_up: if not self.wrapper.give_up:
if reactor.running: if reactor.running:
log.info('Attempting to reconnect...') log.info('Attempting to reconnect...')
reactor.callLater(self.wrapper.reconnect_interval, protocol.ReconnectingClientFactory.clientConnectionLost(self,
connector.connect()) connector, reason)
def clientConnectionFailed(self, connector, reason): def clientConnectionFailed(self, connector, reason):
log.info('IRC connection failed') log.info('IRC connection failed')
if not self.wrapper.give_up:
if reactor.running:
log.info('Attempting to reconnect...')
protocol.ReconnectingClientFactory.clientConnectionFailed(self,
connector, reason)
class IRCMessageChannel(MessageChannel): class IRCMessageChannel(MessageChannel):

6
jmdaemon/jmdaemon/message_channel.py

@ -403,11 +403,11 @@ class MessageChannelCollection(object):
message channel child threads. message channel child threads.
""" """
with self.mc_lock: with self.mc_lock:
if self.welcomed:
return
#This trigger indicates successful login #This trigger indicates successful login
#so we update status. #so we update status; this also triggers on reconnection.
self.mc_status[mc] = 1 self.mc_status[mc] = 1
if self.welcomed:
return
#This way broadcasts orders or requests ONCE to ALL mchans #This way broadcasts orders or requests ONCE to ALL mchans
#which are actually available. #which are actually available.
if not any([x == 0 for x in self.mc_status.values()]): if not any([x == 0 for x in self.mc_status.values()]):

9
jmdaemon/test/test_message_channel.py

@ -224,13 +224,14 @@ def test_setup_mc():
#try to send the transaction to a wrong cp: #try to send the transaction to a wrong cp:
mcc.send_tx(["notrealcp"], "deadbeef") mcc.send_tx(["notrealcp"], "deadbeef")
#At this stage, dmcs0,2 should be "up" and 1 should be "down" #At this stage, dmcs0,2 should be "up" and 1 should have been reset to 1
assert mcc.mc_status[dmcs[0]] == 1 assert mcc.mc_status[dmcs[0]] == 1
assert mcc.mc_status[dmcs[1]] == 2 assert mcc.mc_status[dmcs[1]] == 1
assert mcc.mc_status[dmcs[2]] == 1 assert mcc.mc_status[dmcs[2]] == 1
#Not currently used:
#simulate re-connection of dmcs[1] ; note that this code isn't used atm #simulate re-connection of dmcs[1] ; note that this code isn't used atm
mcc.on_connect_trigger(dmcs[1]) #mcc.on_connect_trigger(dmcs[1])
assert mcc.mc_status[dmcs[1]] == 1 #assert mcc.mc_status[dmcs[1]] == 1
#Now trigger disconnection code; each mc one by one; the last should trigger #Now trigger disconnection code; each mc one by one; the last should trigger
#on_disconnect callback #on_disconnect callback
for m in dmcs: for m in dmcs:

Loading…
Cancel
Save