def stop_services(self, service_id: Optional[str] = None): assert self.is_endpoint_set, 'Service endpoints are not set, please load config first' print('Stopping services...') cleaned = 0 if service_id: all_sid = [service_id] if service_id in self.sid else [] else: all_sid = self.sid for i in all_sid: if i == '3': r = rpc_client.call_aiohttp(self.sid[i]['endpoint'], call_id='ping') if r['status']: rpc_client.call_aiohttp(self.sid[i]['endpoint'], call_id='exit') else: r = rpc_client.call(self.sid[i]['endpoint'], call_id='exit') if r['status']: cleaned = 1 print( f'----Stopped {self.sid[i]["name"]} service endpoint: {self.sid[i]["endpoint"]}' ) print('Stopped all Chainalytic services' if cleaned else 'Nothing to stop')
def init_services( self, zone_id: str, service_id: Optional[str] = None, force_restart: Optional[bool] = 0, always_ping: bool = True, ): assert self.is_endpoint_set, 'Service endpoints are not set, please load config first' if force_restart: self.stop_services() print('Initializing Chainalytic services...') print('') python_exe = sys.executable if service_id: all_sid = [service_id] if service_id in self.sid else [] if not all_sid: raise Exception('Invalid service ID') else: all_sid = self.sid sudo = ['sudo', '-S'] if 'SUDO_PWD' in os.environ else [] echo_pwd = ['echo', os.environ['SUDO_PWD']] if 'SUDO_PWD' in os.environ else [] for i in all_sid: if i == '3' and always_ping: pong = rpc_client.call_aiohttp(self.sid[i]['endpoint'], call_id='ping')['status'] elif always_ping: pong = rpc_client.call(self.sid[i]['endpoint'], call_id='ping')['status'] else: pong = 0 if not pong: echo = subprocess.Popen(echo_pwd, stdout=PIPE) if echo_pwd else None cmd = sudo + [ python_exe, '-m', self.sid[i]['py_pkg'], '--endpoint', self.sid[i]['endpoint'], '--zone_id', zone_id, '--working_dir', os.getcwd(), ] subprocess.Popen( cmd, stdin=echo.stdout if echo else None, stdout=DEVNULL, stderr=STDOUT, start_new_session=True, ) print(f'----Started {self.sid[i]["name"]} service: {" ".join(cmd)}') print('') if not all_sid: print('No service initialized') print('')
def monitor(self, transform_id: Optional[str], refresh_time: float = 1.0): assert self.is_endpoint_set, 'Service endpoints are not set, please load config first' print('Starting aggregation monitor, waiting for Provider and Aggregator service...') r1 = rpc_client.call_aiohttp(self.provider_endpoint, call_id='ping')['status'] r2 = rpc_client.call(self.aggregator_endpoint, call_id='ping')['status'] while not (r1 and r2): time.sleep(0.1) r1 = rpc_client.call_aiohttp(self.provider_endpoint, call_id='ping')['status'] r2 = rpc_client.call(self.aggregator_endpoint, call_id='ping')['status'] provider_client = HTTPClient(f'http://{self.provider_endpoint}') zone_id = rpc_client.call_aiohttp(self.provider_endpoint, call_id='get_zone_id')['data'] stdscr = curses.initscr() curses.noecho() curses.cbreak() r = rpc_client.call(self.aggregator_endpoint, call_id='ls_all_transform_id') if r['status']: all_transforms = r['data'] else: curses.echo() curses.nocbreak() curses.endwin() print('Cannot query official transform IDs, exited console') return if not transform_id: self.monitor_all(zone_id, all_transforms, provider_client, stdscr, refresh_time) elif transform_id == 'stake_history' and transform_id in all_transforms: self.monitor_stake_history(zone_id, transform_id, provider_client, stdscr, refresh_time) elif transform_id in all_transforms: self.monitor_basic(zone_id, transform_id, provider_client, stdscr, refresh_time) else: curses.echo() curses.nocbreak() curses.endwin() print(f'Transform "{transform_id}" not found, exited console')
def monitor_all( self, zone_id: str, all_transform_ids: list, provider_client: HTTPClient, stdscr: '_curses.window', refresh_time: float, ): all_transforms_last_block = {tid: 0 for tid in all_transform_ids} all_transforms_prev_last_block = {tid: 0 for tid in all_transform_ids} all_transforms_prev_time = {tid: 0 for tid in all_transform_ids} all_transforms_speed = {tid: 0 for tid in all_transform_ids} latest_block_height = 0 while 1: upstream_connected = rpc_client.call(self.upstream_endpoint, call_id='ping')['status'] aggregator_connected = rpc_client.call(self.aggregator_endpoint, call_id='ping')[ 'status' ] warehouse_connected = rpc_client.call(self.warehouse_endpoint, call_id='ping')['status'] provider_connected = provider_client.request("_call", call_id='ping').data.result if upstream_connected: upstream_response = rpc_client.call( self.upstream_endpoint, call_id='last_block_height' ) if upstream_response['status']: latest_block_height = upstream_response['data'] if ( upstream_connected and aggregator_connected and warehouse_connected and provider_connected ): for tid in all_transform_ids: last_block = provider_client.request( "_call", call_id='api_call', api_id='last_block_height', api_params={'transform_id': tid}, ).data.result['result'] if last_block: all_transforms_prev_last_block[tid] = all_transforms_last_block[tid] all_transforms_last_block[tid] = last_block all_transforms_speed[tid] = int( (last_block - all_transforms_prev_last_block[tid]) / (time.time() - all_transforms_prev_time[tid]) ) all_transforms_prev_time[tid] = time.time() c1 = C if upstream_connected else D c2 = C if aggregator_connected else D c3 = C if warehouse_connected else D c4 = C if provider_connected else D stdscr.erase() stdscr.addstr( 0, 0, f'== Data Aggregation Monitor | Zone ID: {zone_id} | All Transforms ==', ) stdscr.addstr(1, 0, f'Upstream service: {self.upstream_endpoint} {c1}') stdscr.addstr(2, 0, f'Aggregator service: {self.aggregator_endpoint} {c2}') stdscr.addstr(3, 0, f'Warehouse service: {self.warehouse_endpoint} {c3}') stdscr.addstr(4, 0, f'Provider service: {self.provider_endpoint} {c4}') stdscr.addstr(5, 0, f'Working dir: {self.working_dir}') stdscr.addstr(6, 0, f'----') stdscr.addstr(7, 0, f'Latest upstream block: {latest_block_height:,}') stdscr.addstr(8, 0, f'Latest aggregated block of all transforms') for i, tid in enumerate(all_transforms_last_block): stdscr.addstr( 9 + i, 0, f'----{tid}: {all_transforms_last_block[tid]:,} | {all_transforms_speed[tid]} blocks/s', ) stdscr.refresh() time.sleep(refresh_time)
def monitor_basic( self, zone_id: str, transform_id: str, provider_client: HTTPClient, stdscr: '_curses.window', refresh_time: float, ): latest_block_height = 0 prev_last_block = 0 prev_time = time.time() last_block = 0 while 1: upstream_connected = rpc_client.call(self.upstream_endpoint, call_id='ping')['status'] aggregator_connected = rpc_client.call(self.aggregator_endpoint, call_id='ping')[ 'status' ] warehouse_connected = rpc_client.call(self.warehouse_endpoint, call_id='ping')['status'] provider_connected = provider_client.request("_call", call_id='ping').data.result if upstream_connected: upstream_response = rpc_client.call( self.upstream_endpoint, call_id='last_block_height' ) if upstream_response['status']: latest_block_height = upstream_response['data'] if ( upstream_connected and aggregator_connected and warehouse_connected and provider_connected ): r = provider_client.request( "_call", call_id='api_call', api_id='last_block_height', api_params={'transform_id': transform_id}, ).data.result['result'] if r: last_block = r speed = int((last_block - prev_last_block) / (time.time() - prev_time)) prev_last_block = last_block prev_time = time.time() if latest_block_height > last_block > 0 and speed > 0: remaining_time = seconds_to_datetime((latest_block_height - last_block) / speed) elif latest_block_height == last_block and last_block > 0: remaining_time = 'Fully synced' elif latest_block_height < last_block: remaining_time = ( 'Upstream block height is lower than latest aggregated block (out-of-date)' ) else: remaining_time = 'N/A' remaining_blocks = abs(latest_block_height - last_block) c1 = C if upstream_connected else D c2 = C if aggregator_connected else D c3 = C if warehouse_connected else D c4 = C if provider_connected else D stdscr.erase() stdscr.addstr( 0, 0, f'== Data Aggregation Monitor | Zone ID: {zone_id} | Transform ID: {transform_id} ==', ) stdscr.addstr(1, 0, f'Upstream service: {self.upstream_endpoint} {c1}') stdscr.addstr(2, 0, f'Aggregator service: {self.aggregator_endpoint} {c2}') stdscr.addstr(3, 0, f'Warehouse service: {self.warehouse_endpoint} {c3}') stdscr.addstr(4, 0, f'Provider service: {self.provider_endpoint} {c4}') stdscr.addstr(5, 0, f'Working dir: {self.working_dir}') stdscr.addstr(6, 0, f'----') stdscr.addstr(7, 0, f'Latest upstream block: {latest_block_height:,}') stdscr.addstr(8, 0, f'Latest aggregated block: {last_block:,}') stdscr.addstr(9, 0, f'Data aggregation speed: {speed} blocks/s') stdscr.addstr(10, 0, f'Remaining blocks: {remaining_blocks:,}') stdscr.addstr(11, 0, f'Estimated time remaining: {remaining_time}') stdscr.refresh() time.sleep(refresh_time)