import sys from hashlib import sha256 from typing import List, Tuple from service.async_task_manager import io_task from service.tasks.precondition.consequences.basic import Consequence from service.tasks.precondition.exceptions import DoublePathException from service.tasks.precondition.utils import make_iso_date_now from service.utils.aws_connectors import run_query def add_check(engine, checks, check): try: checks.append(check.check(engine)) except DoublePathException: pass class Check: def __init__(self, root=False, **kwargs): self._task = None self.kwargs = kwargs self.root = root def __repr__(self): return f"{self.__class__.__name__}()" def __hash__(self): return int.from_bytes( sha256( f"{self.__class__.__name__}{str(self.__dict__)}{str(self.kwargs)}".encode() ).digest(), sys.byteorder, ) def set_root(self, root=True): self.root = root def run(self, engine): """Override to implement the check""" return [], [] @io_task def _async_run(self, engine, task_handle=None): checks, consequences = self.run(engine) if self.root: for con in consequences: con.visible = False return checks, consequences def check(self, engine): if self._task is None: if engine.is_unique(self): self._task = self._async_run(engine) else: raise DoublePathException() return self def wait_for_result(self, timeout=None): if self._task is not None: return self._task.wait_for_result(timeout) else: raise RuntimeError("Check not started") @staticmethod def random_id(): return sha256(f"wUf492hg8{make_iso_date_now()}".encode()).hexdigest()[:7] class CheckFor(Check): def __init__(self, query, **kwargs): super().__init__(**kwargs) self.query = query def launch_check(self, engine, *args) -> Tuple[List[Check], List[Consequence]]: """Implement to handle one line of the query. All columns from one line of query are exploded into regular positional arguments, whose names don't have to match datbase column names, because that's what we have in data processor. Transported into aws lambdas they will likely have to match actual column names the query produces""" return [], [] def run_query(self): return run_query(self.query, self.kwargs) def run(self, engine): checks, consequences = super().run(engine) for line in self.run_query(): more_checks, more_consequences = self.launch_check(engine, *line) checks.extend(more_checks) consequences.extend(more_consequences) return checks, consequences