class MainController: def __init__(self, bitshares_instance, config): self.bitshares_instance = bitshares_instance set_shared_bitshares_instance(bitshares_instance) self.config = config self.worker_manager = None # Configure logging formatter = logging.Formatter( '%(asctime)s - %(worker_name)s using account %(account)s on %(market)s - %(levelname)s - %(message)s') logger = logging.getLogger("dexbot.per_worker") fh = logging.FileHandler('dexbot.log') fh.setFormatter(formatter) logger.addHandler(fh) logger.setLevel(logging.INFO) self.pyqt_handler = PyQtHandler() self.pyqt_handler.setLevel(logging.INFO) logger.addHandler(self.pyqt_handler) logger.info("DEXBot {} on python {} {}".format(VERSION, sys.version[:6], sys.platform), extra={ 'worker_name': 'NONE', 'account': 'NONE', 'market': 'NONE'}) # Configure orders logging initialize_orders_log() def set_info_handler(self, handler): self.pyqt_handler.set_info_handler(handler) def start_worker(self, worker_name, config, view): # Todo: Add some threading here so that the GUI doesn't freeze if self.worker_manager and self.worker_manager.is_alive(): self.worker_manager.add_worker(worker_name, config) else: self.worker_manager = WorkerInfrastructure(config, self.bitshares_instance, view) self.worker_manager.daemon = True self.worker_manager.start() def pause_worker(self, worker_name): self.worker_manager.stop(worker_name, pause=True) def remove_worker(self, worker_name): # Todo: Add some threading here so that the GUI doesn't freeze if self.worker_manager and self.worker_manager.is_alive(): # Worker manager currently running if worker_name in self.worker_manager.workers: self.worker_manager.remove_worker(worker_name) self.worker_manager.stop(worker_name) else: # Worker not running config = self.config.get_worker_config(worker_name) WorkerInfrastructure.remove_offline_worker(config, worker_name) else: # Worker manager not running config = self.config.get_worker_config(worker_name) WorkerInfrastructure.remove_offline_worker(config, worker_name) @staticmethod def create_worker(worker_name): # Deletes old worker's data WorkerInfrastructure.remove_offline_worker_data(worker_name)
def run(ctx): """ Continuously run the worker """ if ctx.obj['pidfile']: with open(ctx.obj['pidfile'], 'w') as fd: fd.write(str(os.getpid())) try: try: worker = WorkerInfrastructure(ctx.config) # Set up signalling. do it here as of no relevance to GUI kill_workers = worker_job(worker, lambda: worker.stop(pause=True)) # These first two UNIX & Windows signal.signal(signal.SIGTERM, kill_workers) signal.signal(signal.SIGINT, kill_workers) try: # These signals are UNIX-only territory, will ValueError here on Windows signal.signal(signal.SIGHUP, kill_workers) # TODO: reload config on SIGUSR1 # signal.signal(signal.SIGUSR1, lambda x, y: worker.do_next_tick(worker.reread_config)) except AttributeError: log.debug( "Cannot set all signals -- not available on this platform") worker.run() finally: if ctx.obj['pidfile']: os.unlink(ctx.obj['pidfile']) except errors.NoWorkersAvailable: sys.exit(70) # 70= "Software error" in /usr/include/sysexts.h
class MainController: def __init__(self, bitshares_instance): self.bitshares_instance = bitshares_instance set_shared_bitshares_instance(bitshares_instance) self.worker_manager = None # Configure logging formatter = logging.Formatter( '%(asctime)s - %(worker_name)s using account %(account)s on %(market)s - %(levelname)s - %(message)s') logger = logging.getLogger("dexbot.per_worker") fh = logging.FileHandler('dexbot.log') fh.setFormatter(formatter) logger.addHandler(fh) logger.setLevel(logging.INFO) def create_worker(self, worker_name, config, view): # Todo: Add some threading here so that the GUI doesn't freeze if self.worker_manager and self.worker_manager.is_alive(): self.worker_manager.add_worker(worker_name, config) else: self.worker_manager = WorkerInfrastructure(config, self.bitshares_instance, view) self.worker_manager.daemon = True self.worker_manager.start() def stop_worker(self, worker_name): self.worker_manager.stop(worker_name) def remove_worker(self, worker_name): # Todo: Add some threading here so that the GUI doesn't freeze if self.worker_manager and self.worker_manager.is_alive(): # Worker manager currently running if worker_name in self.worker_manager.workers: self.worker_manager.remove_worker(worker_name) self.worker_manager.stop(worker_name) else: # Worker not running config = self.get_worker_config(worker_name) WorkerInfrastructure.remove_offline_worker(config, worker_name) else: # Worker manager not running config = self.get_worker_config(worker_name) WorkerInfrastructure.remove_offline_worker(config, worker_name) @staticmethod def load_config(): yaml = YAML() with open('config.yml', 'r') as f: return yaml.load(f) @staticmethod def get_workers_data(): """ Returns dict of all the workers data """ with open('config.yml', 'r') as f: yaml = YAML() return yaml.load(f)['workers'] @staticmethod def get_worker_config(worker_name): """ Returns config file data with only the data from a specific worker """ with open('config.yml', 'r') as f: yaml = YAML() config = yaml.load(f) config['workers'] = {worker_name: config['workers'][worker_name]} return config @staticmethod def remove_worker_config(worker_name): yaml = YAML() with open('config.yml', 'r') as f: config = yaml.load(f) config['workers'].pop(worker_name, None) with open("config.yml", "w") as f: yaml.dump(config, f) @staticmethod def add_worker_config(worker_name, worker_data): yaml = YAML() with open('config.yml', 'r') as f: config = yaml.load(f) config['workers'][worker_name] = worker_data with open("config.yml", "w") as f: yaml.dump(config, f) @staticmethod def replace_worker_config(worker_name, new_worker_name, worker_data): yaml = YAML() with open('config.yml', 'r') as f: config = yaml.load(f) workers = config['workers'] # Rotate the dict keys to keep order for _ in range(len(workers)): key, value = workers.popitem(False) if worker_name == key: workers[new_worker_name] = worker_data else: workers[key] = value with open("config.yml", "w") as f: yaml.dump(config, f)
class MainController: def __init__(self, config): self.bitshares_instance = None self.config = config self.worker_manager = None # Configure logging data_dir = user_data_dir(APP_NAME, AUTHOR) filename = os.path.join(data_dir, 'dexbot.log') formatter = logging.Formatter( '%(asctime)s - %(worker_name)s using account %(account)s on %(market)s - %(levelname)s - %(message)s' ) logger = logging.getLogger("dexbot.per_worker") fh = logging.FileHandler(filename) fh.setFormatter(formatter) logger.addHandler(fh) logger.setLevel(logging.INFO) self.pyqt_handler = PyQtHandler() self.pyqt_handler.setLevel(logging.INFO) logger.addHandler(self.pyqt_handler) logger.info("DEXBot {} on python {} {}".format(VERSION, sys.version[:6], sys.platform), extra={ 'worker_name': 'NONE', 'account': 'NONE', 'market': 'NONE' }) # Configure orders logging initialize_orders_log() # Initialize folders initialize_data_folders() def set_bitshares_instance(self, bitshares_instance): """ Set bitshares instance :param bitshares_instance: A bitshares instance """ self.bitshares_instance = bitshares_instance set_shared_bitshares_instance(bitshares_instance) def new_bitshares_instance(self, node, retries=-1, expiration=60): """ Create bitshares instance :param retries: Number of retries to connect, -1 default to infinity :param expiration: Delay in seconds until transactions are supposed to expire :param list node: Node or a list of nodes """ self.bitshares_instance = BitShares(node, num_retries=retries, expiration=expiration) set_shared_bitshares_instance(self.bitshares_instance) def set_info_handler(self, handler): self.pyqt_handler.set_info_handler(handler) def start_worker(self, worker_name, config, view): # Todo: Add some threading here so that the GUI doesn't freeze if self.worker_manager and self.worker_manager.is_alive(): self.worker_manager.add_worker(worker_name, config) else: self.worker_manager = WorkerInfrastructure(config, self.bitshares_instance, view) self.worker_manager.daemon = True self.worker_manager.start() def pause_worker(self, worker_name, config=None): if self.worker_manager and self.worker_manager.is_alive(): self.worker_manager.stop(worker_name, pause=True) else: self.worker_manager = WorkerInfrastructure(config, self.bitshares_instance) def remove_worker(self, worker_name): # Todo: Add some threading here so that the GUI doesn't freeze if self.worker_manager and self.worker_manager.is_alive(): # Worker manager currently running if worker_name in self.worker_manager.workers: self.worker_manager.remove_worker(worker_name) self.worker_manager.stop(worker_name) else: # Worker not running config = self.config.get_worker_config(worker_name) WorkerInfrastructure.remove_offline_worker( config, worker_name, self.bitshares_instance) else: # Worker manager not running config = self.config.get_worker_config(worker_name) WorkerInfrastructure.remove_offline_worker(config, worker_name, self.bitshares_instance) @staticmethod def measure_latency(nodes): """ Measures latency of first alive node from given nodes in milliseconds :param str,list nodes: Bitshares node address(-es) :return: int: latency in milliseconds :raises grapheneapi.exceptions.NumRetriesReached: if failed to find a working node """ if isinstance(nodes, str): nodes = [nodes] # Check nodes one-by-one until first working found for node in nodes: try: start = time.time() BitSharesNodeRPC(node, num_retries=1) latency = (time.time() - start) * 1000 return latency except (NumRetriesReached, OSError): # [Errno 111] Connection refused -> OSError continue raise NumRetriesReached @staticmethod def create_worker(worker_name): # Deletes old worker's data WorkerInfrastructure.remove_offline_worker_data(worker_name)