"""Script utilities.""" import functools import time from datetime import date, datetime, timedelta import config from constants.common import DEFAULT_DATE_FORMAT from logger import logger def as_date(f): """Convert string to date.""" def wrapper(*args, **kwargs) -> date: result = f(*args, **kwargs) if not result: return result if isinstance(result, datetime): return result.date() if isinstance(result, date): return result return datetime.strptime(result, DEFAULT_DATE_FORMAT).date() return wrapper def single_column(f): """Return single column query value.""" def wrapper(*args, **kwargs) -> list: result = f(*args, **kwargs) return [r[0] for r in result] return wrapper def handle_errors(custom_handler=None): """Retry on db errors. Args: custom_handler: Custom error handling function. """ def inner(f): def wrapped(*args, **kwargs): for i in range(1, config.RETRY_COUNT + 1): try: return f(*args, **kwargs) except Exception as ex: if i != config.RETRY_COUNT: logger.info(f"Retry on error: {ex}") if custom_handler: custom_handler(*args, **kwargs) time.sleep(i * config.RETRY_WAIT_RATE) else: logger.info(ex) raise ex return wrapped return inner def timing(f): """Log execution time.""" @functools.wraps(f) def wrapper(*args, **kwargs): start_time = time.time() result = f(*args, **kwargs) elapsed_time = time.time() - start_time logger.debug(f"{f.__name__} {timedelta(seconds=elapsed_time)}") return result return wrapper class ThrottleLogger: def __init__(self, throttle_count: int, chunk_size: int, items_count: int): self.throttle_chunk_size = throttle_count * chunk_size self.chunk_size = chunk_size self.items_count = items_count self.changes_count = 0 self.previous_send = 0 def need_send(self, index: int): return (index - self.previous_send) >= self.throttle_chunk_size or (index + self.chunk_size) >= self.items_count def debug(self, message: str, index: int, changes_count: int): self.changes_count += changes_count if self.need_send(index): logger.debug(f"{message} {self.changes_count} changes") self.changes_count = 0 self.previous_send = index