mirror of
https://github.com/aljazceru/plugins.git
synced 2025-12-23 16:14:20 +01:00
summary: fix persistent peerstate zero leading window
This commit is contained in:
committed by
Christian Decker
parent
f4e3383ed6
commit
158a15110f
@@ -46,7 +46,7 @@ class PeerThread(threading.Thread):
|
|||||||
try:
|
try:
|
||||||
rpcpeers = plugin.rpc.listpeers()
|
rpcpeers = plugin.rpc.listpeers()
|
||||||
trace_availability(plugin, rpcpeers)
|
trace_availability(plugin, rpcpeers)
|
||||||
plugin.avail_peerstate.sync()
|
plugin.persist.sync()
|
||||||
time.sleep(plugin.avail_interval)
|
time.sleep(plugin.avail_interval)
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
plugin.log("[PeerThread] " + str(ex), 'warn')
|
plugin.log("[PeerThread] " + str(ex), 'warn')
|
||||||
@@ -143,7 +143,7 @@ def summary(plugin, exclude=''):
|
|||||||
c['private'],
|
c['private'],
|
||||||
p['connected'],
|
p['connected'],
|
||||||
c['short_channel_id'],
|
c['short_channel_id'],
|
||||||
plugin.avail_peerstate[pid]['avail']
|
plugin.persist['peerstate'][pid]['avail']
|
||||||
))
|
))
|
||||||
|
|
||||||
if not active_channel and p['connected']:
|
if not active_channel and p['connected']:
|
||||||
@@ -224,10 +224,12 @@ def init(options, configuration, plugin):
|
|||||||
plugin.currency_prefix = options['summary-currency-prefix']
|
plugin.currency_prefix = options['summary-currency-prefix']
|
||||||
plugin.fiat_per_btc = 0
|
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_interval = float(options['summary-availability-interval'])
|
||||||
plugin.avail_window = 60 * 60 * int(options['summary-availability-window'])
|
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()
|
info = plugin.rpc.getinfo()
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ from datetime import datetime
|
|||||||
# ensure an rpc peer is added
|
# ensure an rpc peer is added
|
||||||
def addpeer(p, rpcpeer):
|
def addpeer(p, rpcpeer):
|
||||||
pid = rpcpeer['id']
|
pid = rpcpeer['id']
|
||||||
if not pid in p.avail_peerstate:
|
if not pid in p.persist['peerstate']:
|
||||||
p.avail_peerstate[pid] = {
|
p.persist['peerstate'][pid] = {
|
||||||
'connected' : rpcpeer['connected'],
|
'connected' : rpcpeer['connected'],
|
||||||
'last_seen' : datetime.now() if rpcpeer['connected'] else None,
|
'last_seen' : datetime.now() if rpcpeer['connected'] else None,
|
||||||
'avail' : 1.0 if rpcpeer['connected'] else 0.0
|
'avail' : 1.0 if rpcpeer['connected'] else 0.0
|
||||||
@@ -13,8 +13,8 @@ def addpeer(p, rpcpeer):
|
|||||||
|
|
||||||
# exponetially smooth online/offline states of peers
|
# exponetially smooth online/offline states of peers
|
||||||
def trace_availability(p, rpcpeers):
|
def trace_availability(p, rpcpeers):
|
||||||
p.avail_count += 1
|
p.persist['availcount'] += 1
|
||||||
leadwin = max(min(p.avail_window, p.avail_count * p.avail_interval), p.avail_interval)
|
leadwin = max(min(p.avail_window, p.persist['availcount'] * p.avail_interval), p.avail_interval)
|
||||||
samples = leadwin / p.avail_interval
|
samples = leadwin / p.avail_interval
|
||||||
alpha = 1.0 / samples
|
alpha = 1.0 / samples
|
||||||
beta = 1.0 - alpha
|
beta = 1.0 - alpha
|
||||||
@@ -24,9 +24,9 @@ def trace_availability(p, rpcpeers):
|
|||||||
addpeer(p, rpcpeer)
|
addpeer(p, rpcpeer)
|
||||||
|
|
||||||
if rpcpeer['connected']:
|
if rpcpeer['connected']:
|
||||||
p.avail_peerstate[pid]['last_seen'] = datetime.now()
|
p.persist['peerstate'][pid]['last_seen'] = datetime.now()
|
||||||
p.avail_peerstate[pid]['connected'] = True
|
p.persist['peerstate'][pid]['connected'] = True
|
||||||
p.avail_peerstate[pid]['avail'] = 1.0 * alpha + p.avail_peerstate[pid]['avail'] * beta
|
p.persist['peerstate'][pid]['avail'] = 1.0 * alpha + p.persist['peerstate'][pid]['avail'] * beta
|
||||||
else:
|
else:
|
||||||
p.avail_peerstate[pid]['connected'] = False
|
p.persist['peerstate'][pid]['connected'] = False
|
||||||
p.avail_peerstate[pid]['avail'] = 0.0 * alpha + p.avail_peerstate[pid]['avail'] * beta
|
p.persist['peerstate'][pid]['avail'] = 0.0 * alpha + p.persist['peerstate'][pid]['avail'] * beta
|
||||||
|
|||||||
@@ -15,10 +15,11 @@ pluginopt = {'plugin': os.path.join(os.path.dirname(__file__), "summary.py")}
|
|||||||
# returns a test plugin stub
|
# returns a test plugin stub
|
||||||
def get_stub():
|
def get_stub():
|
||||||
plugin = Plugin()
|
plugin = Plugin()
|
||||||
plugin.avail_peerstate = {}
|
|
||||||
plugin.avail_count = 0
|
|
||||||
plugin.avail_interval = 60
|
plugin.avail_interval = 60
|
||||||
plugin.avail_window = 3600
|
plugin.avail_window = 3600
|
||||||
|
plugin.persist = {}
|
||||||
|
plugin.persist['peerstate'] = {}
|
||||||
|
plugin.persist['availcount'] = 0
|
||||||
return plugin
|
return plugin
|
||||||
|
|
||||||
|
|
||||||
@@ -60,12 +61,12 @@ def test_summary_avail_101():
|
|||||||
trace_availability(plugin, rpcpeers)
|
trace_availability(plugin, rpcpeers)
|
||||||
|
|
||||||
# then
|
# then
|
||||||
assert(plugin.avail_peerstate['1']['avail'] == 1.0)
|
assert(plugin.persist['peerstate']['1']['avail'] == 1.0)
|
||||||
assert(plugin.avail_peerstate['2']['avail'] == 0.0)
|
assert(plugin.persist['peerstate']['2']['avail'] == 0.0)
|
||||||
assert(plugin.avail_peerstate['3']['avail'] == 1.0)
|
assert(plugin.persist['peerstate']['3']['avail'] == 1.0)
|
||||||
assert(plugin.avail_peerstate['1']['connected'] == True)
|
assert(plugin.persist['peerstate']['1']['connected'] == True)
|
||||||
assert(plugin.avail_peerstate['2']['connected'] == False)
|
assert(plugin.persist['peerstate']['2']['connected'] == False)
|
||||||
assert(plugin.avail_peerstate['3']['connected'] == True)
|
assert(plugin.persist['peerstate']['3']['connected'] == True)
|
||||||
|
|
||||||
|
|
||||||
# tests for 50% downtime
|
# tests for 50% downtime
|
||||||
@@ -90,7 +91,7 @@ def test_summary_avail_50():
|
|||||||
trace_availability(plugin, rpcpeers_off)
|
trace_availability(plugin, rpcpeers_off)
|
||||||
|
|
||||||
# then
|
# 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
|
# tests for 2/3 downtime
|
||||||
@@ -115,7 +116,7 @@ def test_summary_avail_33():
|
|||||||
trace_availability(plugin, rpcpeers_off)
|
trace_availability(plugin, rpcpeers_off)
|
||||||
|
|
||||||
# then
|
# 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
|
# tests for 1/3 downtime
|
||||||
@@ -140,7 +141,7 @@ def test_summary_avail_66():
|
|||||||
trace_availability(plugin, rpcpeers_off)
|
trace_availability(plugin, rpcpeers_off)
|
||||||
|
|
||||||
# then
|
# 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
|
# 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)
|
trace_availability(plugin, rpcpeers_off)
|
||||||
|
|
||||||
# then
|
# 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):
|
def test_summary_start(node_factory):
|
||||||
|
|||||||
Reference in New Issue
Block a user