From 158a15110fa1edfffb4f88030c6b7499df3ac25f Mon Sep 17 00:00:00 2001 From: Michael Schmoock Date: Sun, 2 Aug 2020 22:58:15 +0200 Subject: [PATCH] summary: fix persistent peerstate zero leading window --- summary/summary.py | 10 +++++---- summary/summary_avail.py | 18 ++++++++-------- summary/test_summary.py | 46 +++++++++++++++++++++++++++++----------- 3 files changed, 49 insertions(+), 25 deletions(-) diff --git a/summary/summary.py b/summary/summary.py index 0cd43ac2e..b6cd1b20a 100755 --- a/summary/summary.py +++ b/summary/summary.py @@ -46,7 +46,7 @@ def run(self): try: rpcpeers = plugin.rpc.listpeers() trace_availability(plugin, rpcpeers) - plugin.avail_peerstate.sync() + plugin.persist.sync() time.sleep(plugin.avail_interval) except Exception as ex: plugin.log("[PeerThread] " + str(ex), 'warn') @@ -143,7 +143,7 @@ def summary(plugin, exclude=''): c['private'], p['connected'], c['short_channel_id'], - plugin.avail_peerstate[pid]['avail'] + plugin.persist['peerstate'][pid]['avail'] )) if not active_channel and p['connected']: @@ -224,10 +224,12 @@ def init(options, configuration, plugin): plugin.currency_prefix = options['summary-currency-prefix'] plugin.fiat_per_btc = 0 - plugin.avail_peerstate = shelve.open('summary.dat', writeback=True) - plugin.avail_count = 0 plugin.avail_interval = float(options['summary-availability-interval']) plugin.avail_window = 60 * 60 * int(options['summary-availability-window']) + plugin.persist = shelve.open('summary.dat', writeback=True) + if not 'peerstate' in plugin.persist: + plugin.persist['peerstate'] = {} + plugin.persist['availcount'] = 0 info = plugin.rpc.getinfo() diff --git a/summary/summary_avail.py b/summary/summary_avail.py index 4d8d219fb..84533b958 100644 --- a/summary/summary_avail.py +++ b/summary/summary_avail.py @@ -3,8 +3,8 @@ # ensure an rpc peer is added def addpeer(p, rpcpeer): pid = rpcpeer['id'] - if not pid in p.avail_peerstate: - p.avail_peerstate[pid] = { + if not pid in p.persist['peerstate']: + p.persist['peerstate'][pid] = { 'connected' : rpcpeer['connected'], 'last_seen' : datetime.now() if rpcpeer['connected'] else None, 'avail' : 1.0 if rpcpeer['connected'] else 0.0 @@ -13,8 +13,8 @@ def addpeer(p, rpcpeer): # exponetially smooth online/offline states of peers def trace_availability(p, rpcpeers): - p.avail_count += 1 - leadwin = max(min(p.avail_window, p.avail_count * p.avail_interval), p.avail_interval) + p.persist['availcount'] += 1 + leadwin = max(min(p.avail_window, p.persist['availcount'] * p.avail_interval), p.avail_interval) samples = leadwin / p.avail_interval alpha = 1.0 / samples beta = 1.0 - alpha @@ -24,9 +24,9 @@ def trace_availability(p, rpcpeers): addpeer(p, rpcpeer) if rpcpeer['connected']: - p.avail_peerstate[pid]['last_seen'] = datetime.now() - p.avail_peerstate[pid]['connected'] = True - p.avail_peerstate[pid]['avail'] = 1.0 * alpha + p.avail_peerstate[pid]['avail'] * beta + p.persist['peerstate'][pid]['last_seen'] = datetime.now() + p.persist['peerstate'][pid]['connected'] = True + p.persist['peerstate'][pid]['avail'] = 1.0 * alpha + p.persist['peerstate'][pid]['avail'] * beta else: - p.avail_peerstate[pid]['connected'] = False - p.avail_peerstate[pid]['avail'] = 0.0 * alpha + p.avail_peerstate[pid]['avail'] * beta + p.persist['peerstate'][pid]['connected'] = False + p.persist['peerstate'][pid]['avail'] = 0.0 * alpha + p.persist['peerstate'][pid]['avail'] * beta diff --git a/summary/test_summary.py b/summary/test_summary.py index 19dc2946c..87fbaab10 100644 --- a/summary/test_summary.py +++ b/summary/test_summary.py @@ -15,10 +15,11 @@ # returns a test plugin stub def get_stub(): plugin = Plugin() - plugin.avail_peerstate = {} - plugin.avail_count = 0 plugin.avail_interval = 60 plugin.avail_window = 3600 + plugin.persist = {} + plugin.persist['peerstate'] = {} + plugin.persist['availcount'] = 0 return plugin @@ -60,12 +61,12 @@ def test_summary_avail_101(): trace_availability(plugin, rpcpeers) # then - assert(plugin.avail_peerstate['1']['avail'] == 1.0) - assert(plugin.avail_peerstate['2']['avail'] == 0.0) - assert(plugin.avail_peerstate['3']['avail'] == 1.0) - assert(plugin.avail_peerstate['1']['connected'] == True) - assert(plugin.avail_peerstate['2']['connected'] == False) - assert(plugin.avail_peerstate['3']['connected'] == True) + assert(plugin.persist['peerstate']['1']['avail'] == 1.0) + assert(plugin.persist['peerstate']['2']['avail'] == 0.0) + assert(plugin.persist['peerstate']['3']['avail'] == 1.0) + assert(plugin.persist['peerstate']['1']['connected'] == True) + assert(plugin.persist['peerstate']['2']['connected'] == False) + assert(plugin.persist['peerstate']['3']['connected'] == True) # tests for 50% downtime @@ -90,7 +91,7 @@ def test_summary_avail_50(): trace_availability(plugin, rpcpeers_off) # then - assert(round(plugin.avail_peerstate['1']['avail'], 3) == 0.5) + assert(round(plugin.persist['peerstate']['1']['avail'], 3) == 0.5) # tests for 2/3 downtime @@ -115,7 +116,7 @@ def test_summary_avail_33(): trace_availability(plugin, rpcpeers_off) # then - assert(round(plugin.avail_peerstate['1']['avail'], 3) == 0.333) + assert(round(plugin.persist['peerstate']['1']['avail'], 3) == 0.333) # tests for 1/3 downtime @@ -140,7 +141,7 @@ def test_summary_avail_66(): trace_availability(plugin, rpcpeers_off) # then - assert(round(plugin.avail_peerstate['1']['avail'], 3) == 0.667) + assert(round(plugin.persist['peerstate']['1']['avail'], 3) == 0.667) # checks the leading window is smaller if interval count is low @@ -165,7 +166,28 @@ def test_summary_avail_leadwin(): trace_availability(plugin, rpcpeers_off) # then - assert(round(plugin.avail_peerstate['1']['avail'], 3) == 0.667) + assert(round(plugin.persist['peerstate']['1']['avail'], 3) == 0.667) + + +# checks whether the peerstate is persistent +def test_summary_persist(node_factory): + # in order to give the PeerThread a chance in a unit test + # we need to give it a low interval + opts = {'summary-availability-interval' : 0.1} + opts.update(pluginopt) + l1, l2 = node_factory.line_graph(2, opts=opts) + + # when + time.sleep(0.5) # wait a bit for the PeerThread to capture data + s1 = l1.rpc.summary() + l1.restart() + s2 = l1.rpc.summary() + + # then + avail1 = int(re.search(' ([0-9]*)% ', s1['channels'][2]).group(1)) + avail2 = int(re.search(' ([0-9]*)% ', s2['channels'][2]).group(1)) + assert(avail1 == 100) + assert(avail2 > 0) def test_summary_start(node_factory):