| @@ -28,14 +28,23 @@ def _load_tasks() -> dict[str, Task]: |
| 28 | return tasks | 28 | return tasks |
| 29 | | 29 | |
| 30 | | 30 | |
| 31 | -def _execute(job: jobs.Job, task: Task) -> None: | 31 | +def _log(message: str) -> None: |
| | 32 | + """Une ligne de log, à l'heure : pour savoir quand un job a démarré, fini ou planté.""" |
| | 33 | + print(f"{time.strftime('%Y-%m-%d %H:%M:%S')} {message}", flush=True) |
| | 34 | + |
| | 35 | + |
| | 36 | +def _execute(job: jobs.Job, task: Task, queue: str) -> None: |
| 32 | ctx = TaskContext(job) | 37 | ctx = TaskContext(job) |
| | 38 | + start = time.time() |
| | 39 | + end = lambda status: _log(f"[{queue}] {job.kind} {job.id} : {status} en {time.time() - start:.0f} s") |
| 33 | try: | 40 | try: |
| 34 | task.run(ctx) | 41 | task.run(ctx) |
| 35 | except Cancelled: | 42 | except Cancelled: |
| 36 | ctx.save(force=True) | 43 | ctx.save(force=True) |
| 37 | jobs.update(job.id, status="cancelled", finished_at=time.time()) | 44 | jobs.update(job.id, status="cancelled", finished_at=time.time()) |
| | 45 | + end("annulé") |
| 38 | except Exception as e: # noqa: BLE001 l'erreur est affichee dans l'UI | 46 | except Exception as e: # noqa: BLE001 l'erreur est affichee dans l'UI |
| | 47 | + end("erreur") |
| 39 | traceback.print_exc() | 48 | traceback.print_exc() |
| 40 | ctx.save(force=True) | 49 | ctx.save(force=True) |
| 41 | jobs.update(job.id, status="error", error=str(e), finished_at=time.time()) | 50 | jobs.update(job.id, status="error", error=str(e), finished_at=time.time()) |
| @@ -43,6 +52,7 @@ def _execute(job: jobs.Job, task: Task) -> None: |
| 43 | ctx.progress = 1.0 | 52 | ctx.progress = 1.0 |
| 44 | ctx.save(force=True) | 53 | ctx.save(force=True) |
| 45 | jobs.update(job.id, status="done", finished_at=time.time()) | 54 | jobs.update(job.id, status="done", finished_at=time.time()) |
| | 55 | + end("terminé") |
| 46 | | 56 | |
| 47 | | 57 | |
| 48 | def _consume(queue: str, tasks: dict[str, Task]) -> None: | 58 | def _consume(queue: str, tasks: dict[str, Task]) -> None: |
| @@ -56,8 +66,8 @@ def _consume(queue: str, tasks: dict[str, Task]) -> None: |
| 56 | if job is None: | 66 | if job is None: |
| 57 | time.sleep(IDLE_POLL) | 67 | time.sleep(IDLE_POLL) |
| 58 | continue | 68 | continue |
| 59 | - print(f"[{queue}] {job.kind} {job.id}") | 69 | + _log(f"[{queue}] {job.kind} {job.id}") |
| 60 | - _execute(job, tasks[job.kind]) | 70 | + _execute(job, tasks[job.kind], queue) |
| 61 | | 71 | |
| 62 | | 72 | |
| 63 | def _heartbeat(queues: list[str]) -> None: | 73 | def _heartbeat(queues: list[str]) -> None: |
| @@ -74,13 +84,13 @@ def main() -> None: |
| 74 | jobs.init() | 84 | jobs.init() |
| 75 | requeued = jobs.requeue_interrupted() | 85 | requeued = jobs.requeue_interrupted() |
| 76 | if requeued: | 86 | if requeued: |
| 77 | - print(f"{requeued} job(s) interrompu(s) remis en file.") | 87 | + _log(f"{requeued} job(s) interrompu(s) remis en file.") |
| 78 | by_queue: dict[str, dict[str, Task]] = defaultdict(dict) | 88 | by_queue: dict[str, dict[str, Task]] = defaultdict(dict) |
| 79 | for kind, task in _load_tasks().items(): | 89 | for kind, task in _load_tasks().items(): |
| 80 | by_queue[task.queue][kind] = task | 90 | by_queue[task.queue][kind] = task |
| 81 | for queue, tasks in by_queue.items(): | 91 | for queue, tasks in by_queue.items(): |
| 82 | threading.Thread(target=_consume, args=(queue, tasks), daemon=True, name=queue).start() | 92 | threading.Thread(target=_consume, args=(queue, tasks), daemon=True, name=queue).start() |
| 83 | - print(f"Worker pret · files : {', '.join(by_queue)}") | 93 | + _log(f"Worker pret · files : {', '.join(by_queue)}") |
| 84 | _heartbeat(list(by_queue)) | 94 | _heartbeat(list(by_queue)) |
| 85 | | 95 | |
| 86 | | 96 | |