예제 #1
0
 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()
예제 #2
0
 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()
예제 #3
0
    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()
예제 #4
0
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()
예제 #5
0
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")
예제 #6
0
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")