From 4572617756d0520be82cea220934f21f7a69e68c Mon Sep 17 00:00:00 2001 From: willcl-ark Date: Fri, 9 Feb 2024 10:17:36 +0000 Subject: [PATCH] server: optimistic warnet cache on server --- src/warnet/server.py | 50 ++++++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/src/warnet/server.py b/src/warnet/server.py index 6cd32d1ed..ed054cd07 100644 --- a/src/warnet/server.py +++ b/src/warnet/server.py @@ -64,6 +64,7 @@ def __init__(self, backend): self.setup_global_exception_handler() self.setup_logging() self.setup_rpc() + self.warnets: dict = dict() self.logger.info("Started server") # register a well known /-/healthy endpoint for liveness tests @@ -179,13 +180,21 @@ def setup_rpc(self): # Logs self.jsonrpc.register(self.logs_grep) + def get_warnet(self, network: str) -> Warnet: + if network in self.warnets: + return self.warnets[network] + wn = Warnet.from_network(network, self.backend) + if isinstance(wn, Warnet): + return wn + raise ServerError(f"Could not find warnet {network}") + def tank_bcli( self, node: int, method: str, params: list[str] | None = None, network: str = "warnet" ) -> str: """ Call bitcoin-cli on in [network] """ - wn = Warnet.from_network(network, self.backend) + wn = self.get_warnet(network) try: return wn.container_interface.get_bitcoin_cli(wn.tanks[node], method, params) except Exception as e: @@ -197,7 +206,7 @@ def tank_lncli(self, node: int, command: list[str], network: str = "warnet") -> """ Call lightning cli on in [network] """ - wn = Warnet.from_network(network, self.backend) + wn = self.get_warnet(network) try: return wn.container_interface.ln_cli(wn.tanks[node], command) except Exception as e: @@ -221,7 +230,7 @@ def tank_messages(self, network: str, node_a: int, node_b: int) -> str: """ Fetch messages sent between and . """ - wn = Warnet.from_network(network, self.backend) + wn = self.get_warnet(network) try: messages = [ msg @@ -269,7 +278,8 @@ def network_export(self, network: str) -> str: Export all data for sim-ln to subdirectory """ try: - wn = Warnet.from_network(network) + wn = self.get_warnet(network) + self.warnets[network] = wn subdir = os.path.join(wn.config_dir, "simln") os.makedirs(subdir, exist_ok=True) wn.export(subdir) @@ -424,7 +434,7 @@ def scenarios_list_running(self) -> list[dict]: return running def network_up(self, network: str = "warnet") -> str: - def thread_start(wn): + def thread_start(server: Server, network): try: # wn.container_interface.up() # Update warnet from docker here to get ip addresses @@ -440,7 +450,8 @@ def thread_start(wn): try: wn = Warnet.from_network(network, self.backend) - t = threading.Thread(target=lambda: thread_start(wn)) + self.warnets[network] = wn + t = threading.Thread(target=lambda: thread_start(self, network)) t.daemon = True t.start() return "Resuming warnet..." @@ -456,11 +467,12 @@ def network_from_file( Run a warnet with topology loaded from a """ - def thread_start(wn, lock: threading.Lock): - with lock: + def thread_start(server: Server, network): + with server.image_build_lock: try: + wn = server.get_warnet(network) wn.generate_deployment() - # wn.write_fork_observer_config() + wn.write_fork_observer_config() wn.warnet_build() wn.warnet_up() wn.wait_for_health() @@ -480,11 +492,13 @@ def thread_start(wn, lock: threading.Lock): raise ServerError(message=message, code=CONFIG_DIR_ALREADY_EXISTS) try: - wn = Warnet.from_graph_file(graph_file, config_dir, network, self.backend) - t = threading.Thread(target=lambda: thread_start(wn, self.image_build_lock)) + self.warnets[network] = Warnet.from_graph_file( + graph_file, config_dir, network, self.backend + ) + t = threading.Thread(target=lambda: thread_start(self, network)) t.daemon = True t.start() - return wn._warnet_dict_representation() + return self.warnets[network]._warnet_dict_representation() except Exception as e: msg = f"Error bring up warnet: {e}" self.logger.error(msg) @@ -528,7 +542,7 @@ def network_down(self, network: str = "warnet") -> str: """ Stop all containers in . """ - wn = Warnet.from_network(network, self.backend) + wn = self.get_warnet(network) try: wn.warnet_down() return "Stopping warnet" @@ -541,7 +555,7 @@ def network_info(self, network: str = "warnet") -> dict: """ Get info about a warnet network named """ - wn = Warnet.from_network(network, self.backend) + wn = self.get_warnet(network) return wn._warnet_dict_representation() def network_status(self, network: str = "warnet") -> list[dict]: @@ -549,7 +563,7 @@ def network_status(self, network: str = "warnet") -> list[dict]: Get running status of a warnet network named """ try: - wn = Warnet.from_network(network, self.backend) + wn = self.get_warnet(network) stats = [] for tank in wn.tanks: status = {"tank_index": tank.index, "bitcoin_status": tank.status.name.lower()} @@ -569,7 +583,7 @@ def network_connected(self, network: str = "warnet") -> bool: Indicate whether all of the graph edges are connected in """ try: - wn = Warnet.from_network(network, self.backend) + wn = self.get_warnet(network) return wn.network_connected() except Exception as e: self.logger.error(f"{e}") @@ -585,7 +599,7 @@ def generate_deployment(self, graph_file: str, network: str = "warnet") -> str: message = f"Config dir {config_dir} already exists, not overwriting existing warnet without --force" self.logger.error(message) raise ServerError(message=message, code=CONFIG_DIR_ALREADY_EXISTS) - wn = Warnet.from_graph_file(graph_file, config_dir, network, self.backend) + wn = self.get_warnet(network) wn.generate_deployment() if not wn.deployment_file or not wn.deployment_file.is_file(): raise ServerError(f"No deployment file found at {wn.deployment_file}") @@ -610,7 +624,7 @@ def logs_grep(self, pattern: str, network: str = "warnet") -> str: Grep the logs from the fluentd container for a regex pattern """ try: - wn = Warnet.from_network(network, self.backend) + wn = self.get_warnet(network) return wn.container_interface.logs_grep(pattern, network) except Exception as e: msg = f"Error grepping logs using pattern {pattern}: {e}"