def __init__(self, config=None): self.queue = Queue() self.spawner = Spawn(self.queue) self.running_config = {} self.cfg_path = config self.plugin = PluginController(config) self.plugin.start()
def __init__(self, config=None): self.terminating = False self.queue = Queue() self.spawner = Spawn(self.queue) self.aggregator = Aggregator(config_file=config) self.running_config = {} self.cfg_path = config self.plugin = PluginController(config) self.plugin.start()
def __init__(self, config=None): self.terminating = False # Shared memory object to track service health across processes self.shared_health_status = Manager().dict() self.queue = Queue() self.spawner = Spawn(self.queue, self.shared_health_status) self.aggregator = Aggregator(config_file=config) self.running_config = {} self.cfg_path = config self.plugin = PluginController(config) self.plugin.start()
class Cryptostore: def __init__(self, config=None): self.queue = Queue() self.spawner = Spawn(self.queue) self.running_config = {} self.cfg_path = config self.plugin = PluginController(config) self.plugin.start() async def _load_config(self, start, stop): LOG.info("start: %s stop: %s", str(start), str(stop)) for exchange in stop: self.queue.put(json.dumps({'op': 'stop', 'exchange': exchange})) for exchange in start: self.queue.put( json.dumps({ 'op': 'start', 'exchange': exchange, 'collector': self.running_config['exchanges'][exchange], 'config': { i: self.running_config[i] for i in self.running_config if i != 'exchanges' } })) async def _reconfigure(self, config): stop = [] start = [] if self.running_config != config: if not config or 'exchanges' not in config or not config[ 'exchanges'] or len(config['exchanges']) == 0: # shut it all down stop = list(self.running_config['exchanges'].keys() ) if 'exchanges' in self.running_config else [] self.running_config = config elif not self.running_config or 'exchanges' not in self.running_config or len( self.running_config['exchanges']) == 0: # nothing running currently, start it all self.running_config = config start = list(self.running_config['exchanges'].keys()) else: for e in config['exchanges']: if e in self.running_config['exchanges'] and config[ 'exchanges'][e] == self.running_config[ 'exchanges'][e]: continue elif e not in self.running_config['exchanges']: start.append(e) else: stop.append(e) start.append(e) for e in self.running_config['exchanges']: if e in config['exchanges'] and config['exchanges'][ e] == self.running_config['exchanges'][e]: continue elif e not in config['exchanges']: stop.append(e) else: stop.append(e) start.append(e) self.running_config = config await self._load_config(list(set(start)), list(set(stop))) def run(self): LOG.info("Starting cryptostore") LOG.info("Cryptostore running on PID %d", os.getpid()) self.spawner.start() LOG.info("Spawner started") self.aggregator = Aggregator(config_file=self.cfg_path) self.aggregator.start() LOG.info("Aggregator started") loop = asyncio.get_event_loop() self.config = DynamicConfig(file_name=self.cfg_path, callback=self._reconfigure) LOG.info("Cryptostore started") loop.run_forever()
def __init__(self, config=None): self.queue = Queue() self.spawner = Spawn(self.queue) self.running_config = {} self.cfg_path = config
class Cryptostore: def __init__(self, config=None): self.terminating = False # Shared memory object to track service health across processes self.shared_health_status = Manager().dict() self.queue = Queue() self.spawner = Spawn(self.queue, self.shared_health_status) self.aggregator = Aggregator(config_file=config) self.running_config = {} self.cfg_path = config self.plugin = PluginController(config) self.plugin.start() def _stop_on_signal(self, sig, loop): if self.terminating: LOG.info("Cryptostore is already being stopped...") return LOG.info("Stopping Cryptostore due to signal %d", sig) self.terminating = True self.queue.close() self.config.set_terminating() to_stop = [p for p in [self.spawner, self.aggregator] if p is not None] for p in to_stop: p.terminate() if hasattr(self, 'health_check'): self.health_check.stop() for p in to_stop: if p.is_alive(): p.join() stop_event_loop(loop) async def _load_config(self, start, stop): LOG.info("start: %s stop: %s", str(start), str(stop)) try: for exchange in stop: self.queue.put(json.dumps({'op': 'stop', 'exchange': exchange})) for exchange in start: self.queue.put(json.dumps({'op': 'start', 'exchange': exchange, 'collector': self.running_config['exchanges'][exchange], 'config': {i: self.running_config[i] for i in self.running_config if i != 'exchanges'}})) except (ValueError, AssertionError) as e: LOG.info('Config queue put interrupt') async def _reconfigure(self, config): if os.getenv('ENV') != 'TESTING': # TODO figure out config logging for testing self._save_config_mysql(config) self._start_health_check(config) stop = [] start = [] if self.running_config != config: if not config or 'exchanges' not in config or not config['exchanges'] or len(config['exchanges']) == 0: # shut it all down stop = list(self.running_config['exchanges'].keys()) if 'exchanges' in self.running_config else [] self.running_config = config elif not self.running_config or 'exchanges' not in self.running_config or len(self.running_config['exchanges']) == 0: # nothing running currently, start it all self.running_config = config start = list(self.running_config['exchanges'].keys()) else: for e in config['exchanges']: if e in self.running_config['exchanges'] and config['exchanges'][e] == self.running_config['exchanges'][e]: continue elif e not in self.running_config['exchanges']: start.append(e) else: stop.append(e) start.append(e) for e in self.running_config['exchanges']: if e in config['exchanges'] and config['exchanges'][e] == self.running_config['exchanges'][e]: continue elif e not in config['exchanges']: stop.append(e) else: stop.append(e) start.append(e) self.running_config = config await self._load_config(list(set(start)), list(set(stop))) def _start_health_check(self, config): if hasattr(self, 'health_check'): return if 'health_check' in config: self.health_check = HealthCheck(self.spawner, self.aggregator, self.shared_health_status, config['health_check']['port'], config['health_check']['path']) self.health_check.run() def _save_config_mysql(self, config): # TODO add retries and timeouts when startup probes are configured so kuber doesn't restart on failure if hasattr(self, 'mysql_client'): # TODO what happens on reconfigure? return try: self.mysql_client = MysqlClient(config) self.mysql_client.create_tables() self.mysql_client.write_config() except Exception as e: LOG.info("Unable to save config to mysql") raise e def run(self): LOG.info("Starting cryptostore") LOG.info("Cryptostore running on PID %d", os.getpid()) # Setup uvloop asyncio.set_event_loop_policy(uvloop.EventLoopPolicy()) loop = asyncio.get_event_loop() def exception_handler(loop, context): # TODO figure our exception handling and interrupts for all the processes # TODO https://quantlane.com/blog/ensure-asyncio-task-exceptions-get-logged/ # TODO make an untility funcrion and move to utils? # first, handle with default handler loop.default_exception_handler(context) signal.raise_signal(signal.SIGTERM) loop.set_exception_handler(exception_handler) setup_event_loop_signal_handlers(loop, self._stop_on_signal) self.config = DynamicConfig(loop=loop, file_name=self.cfg_path, callback=self._reconfigure) start_prometheus(self.config.config) self.spawner.start() LOG.info("Spawner started") self.aggregator.start() LOG.info("Aggregator started") LOG.info("Cryptostore started") try: loop.run_forever() except Exception as e: LOG.info("Loop crashed") LOG.info("Cryptostore main process stopped")
class Cryptostore: def __init__(self, config=None): self.terminating = False self.queue = Queue() self.spawner = Spawn(self.queue) self.aggregator = Aggregator(config_file=config) self.running_config = {} self.cfg_path = config self.plugin = PluginController(config) self.plugin.start() def _stop_on_signal(self, sig, loop): if self.terminating: LOG.info("Cryptostore is already being stopped...") return LOG.info("Stopping Cryptostore due to signal %d", sig) self.terminating = True self.queue.close() self.config.set_terminating() to_stop = [p for p in [self.spawner, self.aggregator] if p is not None] for p in to_stop: p.terminate() for p in to_stop: if p.is_alive(): p.join() stop_event_loop(loop) async def _load_config(self, start, stop): LOG.info("start: %s stop: %s", str(start), str(stop)) try: for exchange in stop: self.queue.put(json.dumps({ 'op': 'stop', 'exchange': exchange })) for exchange in start: self.queue.put( json.dumps({ 'op': 'start', 'exchange': exchange, 'collector': self.running_config['exchanges'][exchange], 'config': { i: self.running_config[i] for i in self.running_config if i != 'exchanges' } })) except (ValueError, AssertionError) as e: LOG.info('Config queue put interrupt') async def _reconfigure(self, config): stop = [] start = [] if self.running_config != config: if not config or 'exchanges' not in config or not config[ 'exchanges'] or len(config['exchanges']) == 0: # shut it all down stop = list(self.running_config['exchanges'].keys() ) if 'exchanges' in self.running_config else [] self.running_config = config elif not self.running_config or 'exchanges' not in self.running_config or len( self.running_config['exchanges']) == 0: # nothing running currently, start it all self.running_config = config start = list(self.running_config['exchanges'].keys()) else: for e in config['exchanges']: if e in self.running_config['exchanges'] and config[ 'exchanges'][e] == self.running_config[ 'exchanges'][e]: continue elif e not in self.running_config['exchanges']: start.append(e) else: stop.append(e) start.append(e) for e in self.running_config['exchanges']: if e in config['exchanges'] and config['exchanges'][ e] == self.running_config['exchanges'][e]: continue elif e not in config['exchanges']: stop.append(e) else: stop.append(e) start.append(e) self.running_config = config await self._load_config(list(set(start)), list(set(stop))) def run(self): LOG.info("Starting cryptostore") LOG.info("Cryptostore running on PID %d", os.getpid()) self.spawner.start() LOG.info("Spawner started") self.aggregator.start() LOG.info("Aggregator started") loop = asyncio.get_event_loop() setup_event_loop_signal_handlers(loop, self._stop_on_signal) self.config = DynamicConfig(loop=loop, file_name=self.cfg_path, callback=self._reconfigure) LOG.info("Cryptostore started") loop.run_forever() LOG.info("Cryptostore main process stopped")