From 52b172ece716f68d868edd8d0389529826db06cf Mon Sep 17 00:00:00 2001 From: lunar-mining Date: Sun, 29 Oct 2023 21:43:32 +0100 Subject: [PATCH] dnet: cleanup and add TODOs. also don't crash if a node goes offline. --- bin/dnet/main.py | 18 ++-- bin/dnet/model.py | 5 ++ bin/dnet/view.py | 222 +++++++++++++++++++++++----------------------- 3 files changed, 130 insertions(+), 115 deletions(-) diff --git a/bin/dnet/main.py b/bin/dnet/main.py index e9201b109..9b601329a 100644 --- a/bin/dnet/main.py +++ b/bin/dnet/main.py @@ -53,9 +53,13 @@ class Dnetview: while True: await asyncio.sleep(0.01) data = await rpc.reader.readline() - data = json.loads(data) - info[name] = data - await self.queue.put(info) + try: + data = json.loads(data) + info[name] = data + await self.queue.put(info) + except: + info[name] = {} + await self.queue.put(info) await rpc.dnet_switch(False) await rpc.stop() @@ -79,13 +83,16 @@ class Dnetview: while True: info = await self.queue.get() values = list(info.values())[0] - method = values.get("method") + try: + method = values.get("method") + except: + self.model.add_offline(info) + continue if method == "dnet.subscribe_events": self.model.add_event(info) else: self.model.add_node(info) - self.queue.task_done() def main(self): @@ -101,7 +108,6 @@ class Dnetview: self.ev.create_task(self.start_connect_slots(nodes)) self.ev.create_task(self.view.update_view(self.ev, loop)) - self.ev.create_task(self.view.render_info(self.ev, loop)) loop.run() diff --git a/bin/dnet/model.py b/bin/dnet/model.py index c8dbf4550..06b488ac8 100644 --- a/bin/dnet/model.py +++ b/bin/dnet/model.py @@ -72,6 +72,11 @@ class Model: id = channel["id"] url = channel["url"] self.nodes[name]['manual'][f"{id}"] = url + + def add_offline(self, node): + name = list(node.keys())[0] + values = list(node.values())[0] + self.nodes[name] = values def add_event(self, event): name = list(event.keys())[0] diff --git a/bin/dnet/view.py b/bin/dnet/view.py index e37f2c86e..e09a148f6 100644 --- a/bin/dnet/view.py +++ b/bin/dnet/view.py @@ -40,6 +40,9 @@ class DnetWidget(urwid.WidgetWrap): self._w = urwid.AttrWrap(self._w, None) self._w.focus_attr = 'line' + def is_empty(self): + self.is_empty == True + class Node(DnetWidget): def set_txt(self): @@ -83,11 +86,102 @@ class View(): columns = urwid.Columns([leftbox, rightbox], focus_column=0) self.ui = urwid.Frame(urwid.AttrWrap( columns, 'body' )) + #----------------------------------------------------------------- + # Render get_info() + #----------------------------------------------------------------- + def draw_info(self, node_name, info): + node = Node(node_name, "node") + node.set_txt() + self.listwalker.contents.append(node) + + if info['outbound']: + session = Session(node_name, "outbound") + session.set_txt() + self.listwalker.contents.append(session) + for i, addr in info['outbound'].items(): + slot = Slot(node_name, "outbound-slot") + slot.set_txt(i, addr) + self.listwalker.contents.append(slot) + + if info['inbound']: + session = Session(node_name, "inbound") + session.set_txt() + self.listwalker.contents.append(session) + for i, addr in info['inbound'].items(): + slot = Slot(node_name, "inbound-slot") + slot.set_txt(i, addr) + self.listwalker.contents.append(slot) + + if info['manual']: + session = Session(node_name, "manual") + session.set_txt() + self.listwalker.contents.append(session) + for i, addr in info['manual'].items(): + slot = Slot(node_name, "manual-slot") + slot.set_txt(i, addr) + self.listwalker.contents.append(slot) + + if info['seed']: + session = Session(node_name, "seed") + session.set_txt() + self.listwalker.contents.append(session) + for i, info in info['seed'].items(): + slot = Slot(node_name, "seed-slot") + slot.set_txt(i, addr) + self.listwalker.contents.append(slot) + + #----------------------------------------------------------------- + # Render subscribe_events() (left menu) + #----------------------------------------------------------------- + def fill_left_box(self): + known_inbound = [] + new_inbound= {} + for index, item in enumerate(self.listwalker.contents): + # Update outbound slot info + if item.session == "outbound-slot": + key = (f"{item.node_name}", f"{item.i}") + if key in self.model.nodes[item.node_name]['event']: + info = self.model.nodes[item.node_name]['event'].get(key) + slot = Slot(item.node_name, item.session) + slot.set_txt(item.i, info) + self.listwalker.contents[index] = slot + + #----------------------------------------------------------------- + # Render subscribe_events() (right menu) + #----------------------------------------------------------------- + def fill_right_box(self): + self.pile.contents.clear() + focus_w = self.list.get_focus() + session = focus_w[0].session + + if session == "outbound": + key = (focus_w[0].node_name, "outbound") + info = self.model.nodes.get(focus_w[0].node_name) + if key in info['event']: + ev = info['event'].get(key) + self.pile.contents.append(( + urwid.Text(f" {ev}"), + self.pile.options())) + + if (session == "outbound-slot" or session == "inbound-slot" + or session == "manual-slot" or session == "seed-slot"): + addr = focus_w[0].addr + node_name = focus_w[0].node_name + info = self.model.nodes.get(node_name) + if addr in info['msgs']: + msg = info['msgs'].get(addr) + for m in msg: + time = m[0] + event = m[1] + msg = m[2] + self.pile.contents.append((urwid.Text( + f"{time}: {event}: {msg}"), + self.pile.options())) async def update_view(self, evloop: asyncio.AbstractEventLoop, loop: urwid.MainLoop): known_nodes = [] - known_inbound = [] + off_nodes = [] while True: await asyncio.sleep(0.1) # Redraw the screen @@ -96,115 +190,25 @@ class View(): for index, item in enumerate(self.listwalker.contents): known_nodes.append(item.node_name) - #----------------------------------------------------------------- - # Render get_info() - #----------------------------------------------------------------- + for node_name, info in self.model.nodes.items(): + if not info: + off_nodes.append(node_name) + + # TODO: + # Right now we ignore info if it's in the set of known nodes. + # However, there are a few events that should trigger a redraw: + # * a new inbound connection comes online + # * a new node comes online (FIXME) + # * a known node has gone offline + # * a inbound connection has gone offline + # * when RPC can't connect, display the node as offline. for node_name, info in self.model.nodes.items(): if node_name in known_nodes: continue - else: - node = Node(node_name, "node") - node.set_txt() - self.listwalker.contents.append(node) - - if info['outbound']: - session = Session(node_name, "outbound") - session.set_txt() - self.listwalker.contents.append(session) - for i, addr in info['outbound'].items(): - slot = Slot(node_name, "outbound-slot") - slot.set_txt(i, addr) - self.listwalker.contents.append(slot) - - if info['inbound']: - session = Session(node_name, "inbound") - session.set_txt() - self.listwalker.contents.append(session) - for i, addr in info['inbound'].items(): - slot = Slot(node_name, "inbound-slot") - slot.set_txt(i, addr) - self.listwalker.contents.append(slot) - - if info['manual']: - session = Session(node_name, "manual") - session.set_txt() - self.listwalker.contents.append(session) - for i, addr in info['manual'].items(): - slot = Slot(node_name, "manual-slot") - slot.set_txt(i, addr) - self.listwalker.contents.append(slot) - - if info['seed']: - session = Session(node_name, "seed") - session.set_txt() - self.listwalker.contents.append(session) - for i, info in info['seed'].items(): - slot = Slot(node_name, "seed-slot") - slot.set_txt(i, addr) - self.listwalker.contents.append(slot) - - #----------------------------------------------------------------- - # Render subscribe_events() (left menu) - #----------------------------------------------------------------- - new_inbound = {} - for index, item in enumerate(self.listwalker.contents): - # Update outbound slot info - if item.session == "outbound-slot": - key = (f"{item.node_name}", f"{item.i}") - if key in self.model.nodes[item.node_name]['event']: - info = self.model.nodes[item.node_name]['event'].get(key) - slot = Slot(item.node_name, item.session) - slot.set_txt(item.i, info) - self.listwalker.contents[index] = slot - # Get known inbounds - if item.session == "inbound-slot": - if item.i not in known_inbound: - known_inbound.append(item.i) - # Get unknown inbounds - inbound = self.model.nodes[item.node_name]['inbound'] - for i, addr in inbound.items(): - if i in known_inbound: - continue - else: - new_inbound[i] = (addr, item.node_name) - # TODO: update new inbounds - - - # Render subscribe_events() (right menu) - async def render_info(self, evloop: asyncio.AbstractEventLoop, - loop: urwid.MainLoop): - while True: - await asyncio.sleep(0.01) - # Redraw the screen - evloop.call_soon(loop.draw_screen) - - self.pile.contents.clear() - focus_w = self.list.get_focus() - if focus_w[0] is None: - continue - else: - session = focus_w[0].session - if session == "node": + if node_name in off_nodes: continue - if session == "outbound": - key = (focus_w[0].node_name, "outbound") - info = self.model.nodes.get(focus_w[0].node_name) - if key in info['event']: - ev = info['event'].get(key) - self.pile.contents.append(( - urwid.Text(f" {ev}"), - self.pile.options())) - if (session == "outbound-slot" or session == "inbound-slot" - or session == "manual-slot" or session == "seed-slot"): - addr = focus_w[0].addr - node_name = focus_w[0].node_name - info = self.model.nodes.get(node_name) - if addr in info['msgs']: - msg = info['msgs'].get(addr) - for m in msg: - time = m[0] - event = m[1] - msg = m[2] - self.pile.contents.append((urwid.Text( - f"{time}: {event}: {msg}"), - self.pile.options())) + else: + self.draw_info(node_name, info) + + self.fill_left_box() + self.fill_right_box()