from queue import Queue import threading import logging logger = logging.getLogger(__name__) # ========================================= # CONFIG # ========================================= MAX_CONCURRENT_EXCEL = 10 # ========================================= # STATE # ========================================= EXCEL_QUEUE = Queue() EXCEL_LOCK = threading.Lock() ACTIVE_JOBS = set() # jobs em execução # ========================================= # Helpers # ========================================= def get_queue_position(job_id: str) -> int: """ Retorna: 0 = já está executando 1..N = posição na fila -1 = não encontrado """ with EXCEL_LOCK: if job_id in ACTIVE_JOBS: return 0 items = list(EXCEL_QUEUE.queue) for i, item in enumerate(items): if item["job_id"] == job_id: return i + 1 return -1 # ========================================= # WORKER # ========================================= def _worker(worker_id: int): logger.info(f"🟢 Excel worker-{worker_id} started") while True: job = EXCEL_QUEUE.get() job_id = job["job_id"] try: with EXCEL_LOCK: ACTIVE_JOBS.add(job_id) logger.info(f"🚀 [worker-{worker_id}] Processing {job_id}") job["fn"](*job["args"], **job["kwargs"]) logger.info(f"✅ [worker-{worker_id}] Finished {job_id}") except Exception as e: logger.exception(f"❌ [worker-{worker_id}] Failed {job_id}: {e}") finally: with EXCEL_LOCK: ACTIVE_JOBS.discard(job_id) EXCEL_QUEUE.task_done() # ========================================= # START POOL # ========================================= def start_excel_worker(): """ Inicia pool com N workers simultâneos """ for i in range(MAX_CONCURRENT_EXCEL): threading.Thread( target=_worker, args=(i + 1,), daemon=True ).start() logger.info(f"🔥 Excel queue started with {MAX_CONCURRENT_EXCEL} workers") # ========================================= # ENQUEUE # ========================================= def enqueue_excel_job(job_id, fn, *args, **kwargs): job = { "job_id": job_id, "fn": fn, "args": args, "kwargs": kwargs } with EXCEL_LOCK: EXCEL_QUEUE.put(job) position = EXCEL_QUEUE.qsize() return position