import signal import sqlite3 import sys import time import sql_requests import utils from EDMCLogging import get_main_logger logger = get_main_logger() db = sqlite3.connect('squads.sqlite') with open('sql_schema.sql', 'r', encoding='utf-8') as schema_file: db.executescript(''.join(schema_file.readlines())) shutting_down: bool = False can_be_shutdown: bool = False """ TODO: 1. Hooks for update (done) 2. Tags resolver 3. Proper shutdown (done) 4. capi.demb.design special api 5. FID tracking system 6. Log level as argument =========================DONT RELAY ON news_view========================= Two modes: 1. Discover new squads get last_known_id tries = 0 failed: list while True if tries = 2 break id_to_try = last_known_id + 1 update squad info with id_to_try and suppressing absence if success process triggers tries = 0 for failed_squad in failed delete(failed_squad) failed_squad = list() else (fail) failed.append(id_to_try) tries = tries + 1 sleep(3) 2. Update exists get oldest updated existing squad if DB is empty return update it if squad still exists process triggers """ def shutdown_callback(sig, frame) -> None: logger.info(f'Planning shutdown by {sig} signal') global shutting_down shutting_down = True if can_be_shutdown: logger.info('Can be shutdown') exit(0) def discover(back_count: int = 0): """Discover new squads :param back_count: int how many squads back we should check, it is helpful to recheck newly created squads :return: """ # id_to_try = utils.get_last_known_id(db) # id_to_try = utils.get_next_id_for_discover(db) - 1 id_to_try = utils.get_next_hole_id_for_discover(db) - 1 tries: int = 0 failed: list = list() TRIES_LIMIT_RETROSPECTIVELY: int = 5000 TRIES_LIMIT_ON_THE_TIME: int = 5 def smart_tries_limit(_squad_id: int) -> int: # something smarter but still have to be better if _squad_id < 65000: return TRIES_LIMIT_RETROSPECTIVELY else: return TRIES_LIMIT_ON_THE_TIME """ tries_limit, probably, should be something more smart because on retrospectively scan we can have large spaces of dead squadrons but when we are discovering on real time, large value of tries_limit will just waste our time and, probable, confuses FDEV *Outdated but it still can be more smart* """ if back_count != 0: logger.debug(f'back_count = {back_count}') squad_id: list for squad_id in db.execute(sql_requests.select_new_squads_to_update, (back_count,)).fetchall(): squad_id: int = squad_id[0] logger.debug(f'Back updating {squad_id}') utils.update_squad_info(squad_id, db) while True: if shutting_down: return id_to_try = id_to_try + 1 # logger.debug(f'Starting discover loop iteration, tries: {tries} of {tries_limit}, id to try {id_to_try}, ' # f'failed list: {failed}') if tries == smart_tries_limit(id_to_try): break squad_info = utils.update_squad_info(id_to_try, db, suppress_absence=True) if isinstance(squad_info, dict): # success logger.debug(f'Success discover for {id_to_try} ID') tries = 0 # reset tries counter for failed_squad in failed: # since we found an exists squad, then all previous failed wasn't exists utils.properly_delete_squadron(failed_squad, db) failed = list() else: # fail, should be only False logger.debug(f'Fail on discovery for {id_to_try} ID') failed.append(id_to_try) tries = tries + 1 def update(squad_id: int = None, amount_to_update: int = 1, thursday_target: bool = False): """ :param thursday_target: if we aiming to update all squads before thursday (FDEV scheduled maintenance) and we don't wanna update squads which already updated after previous thursday :param squad_id: update specified squad, updates only that squad :param amount_to_update: update specified amount, ignores when squad_id specified :return: """ if isinstance(squad_id, int): logger.debug(f'Going to update one specified squadron: {squad_id} ID') utils.update_squad_info(squad_id, db, suppress_absence=True) # suppress_absence is required because if we updating squad with some high id it may just don't exists yet return logger.debug(f'Going to update {amount_to_update} squadrons with thursday_target = {thursday_target}') if thursday_target: prev_thursday = utils.get_previous_thursday_severs_reboot_datetime() squads_id_to_update: list = db.execute( sql_requests.select_squads_to_update_thursday_aimed, (prev_thursday, amount_to_update)).fetchall() if len(squads_id_to_update) == 0: logger.info(f'thursday_target and no squads to update') else: squads_id_to_update: list = db.execute(sql_requests.select_squads_to_update, (amount_to_update,)).fetchall() for single_squad_to_update in squads_id_to_update: # if db is empty, then loop will not happen if shutting_down: return id_to_update: int = single_squad_to_update[0] logger.info(f'Updating {id_to_update} ID') utils.update_squad_info(id_to_update, db) if __name__ == '__main__': signal.signal(signal.SIGTERM, shutdown_callback) signal.signal(signal.SIGINT, shutdown_callback) def help_cli() -> str: return """Possible arguments: main.py discover main.py update main.py update amount main.py update id main.py daemon""" logger.debug(f'argv: {sys.argv}') if len(sys.argv) == 1: print(help_cli()) exit(1) elif len(sys.argv) == 2: if sys.argv[1] == 'discover': # main.py discover logger.info(f'Entering discover mode') discover() exit(0) elif sys.argv[1] == 'update': # main.py update logger.info(f'Entering common update mode') update() exit(0) elif sys.argv[1] == 'daemon': # main.py daemon logger.info('Entering daemon mode') while True: can_be_shutdown = False update(amount_to_update=500, thursday_target=True) if shutting_down: exit(0) logger.info('Updated, sleeping') can_be_shutdown = True time.sleep(30 * 60) can_be_shutdown = False logger.info('Discovering') discover(back_count=20) if shutting_down: exit(0) logger.info('Discovered, sleeping') can_be_shutdown = True time.sleep(30 * 60) else: print(help_cli()) exit(1) elif len(sys.argv) == 4: if sys.argv[1] == 'update': if sys.argv[2] == 'amount': # main.py update amount try: amount: int = int(sys.argv[3]) logger.info(f'Entering update amount mode, amount: {amount}') update(amount_to_update=amount) exit(0) except ValueError: print('Amount must be integer') exit(1) elif sys.argv[2] == 'id': # main.py update id try: id_for_update: int = int(sys.argv[3]) logger.info(f'Entering update specified squad: {id_for_update} ID') update(squad_id=id_for_update) exit(0) except ValueError: print('ID must be integer') exit(1) else: logger.info(f'Unknown argument {sys.argv[2]}') else: print(help_cli()) exit(1)