v1.0.178: логи + lock-файл + guard от двойного classify. Ответ Опуса: минимум сейчас.

This commit is contained in:
2026-06-25 13:29:06 +04:00
parent aa1b801e94
commit 4e9dd94433
2 changed files with 23 additions and 2 deletions
+5
View File
@@ -25,9 +25,14 @@ if __name__ == "__main__":
sys.exit(1) sys.exit(1)
batch_id = sys.argv[1] batch_id = sys.argv[1]
lock_path = f"/tmp/classify_{batch_id}.lock"
try: try:
result = classify_batch(batch_id) result = classify_batch(batch_id)
print(f"classify_worker DONE: {result}") print(f"classify_worker DONE: {result}")
except Exception as e: except Exception as e:
print(f"classify_worker FAILED: {e}", file=sys.stderr) print(f"classify_worker FAILED: {e}", file=sys.stderr)
sys.exit(1) sys.exit(1)
finally:
# Убрать lock-файл в любом случае
if os.path.exists(lock_path):
os.remove(lock_path)
+18 -2
View File
@@ -252,6 +252,12 @@ class Handler(BaseHTTPRequestHandler):
from db import documents as db_docs from db import documents as db_docs
import subprocess, os import subprocess, os
# Guard: если classify для этого batch уже запущен — не запускать повторно
lock_path = f"/tmp/classify_{batch_id}.lock"
if os.path.exists(lock_path):
self._json({"ok": False, "error": "classify already running for this batch"}, 409)
return
# Посчитать сколько файлов — ответить сразу, classify в отдельном процессе # Посчитать сколько файлов — ответить сразу, classify в отдельном процессе
pending = db_docs.list_pending(batch_id) pending = db_docs.list_pending(batch_id)
total = len(pending) total = len(pending)
@@ -260,12 +266,22 @@ class Handler(BaseHTTPRequestHandler):
return return
# Запустить classify_worker.py в отдельном процессе # Запустить classify_worker.py в отдельном процессе
# Лог в /home/naeel/contracts/logs/ вместо DEVNULL
log_dir = "/home/naeel/contracts/logs"
os.makedirs(log_dir, exist_ok=True)
log_path = os.path.join(log_dir, f"classify_{batch_id}.log")
log_file = open(log_path, "w")
# Создать lock-файл (воркер удалит при завершении)
with open(lock_path, "w") as lf:
lf.write(str(os.getpid()))
worker_path = os.path.join(os.path.dirname(__file__), "classify_worker.py") worker_path = os.path.join(os.path.dirname(__file__), "classify_worker.py")
subprocess.Popen( subprocess.Popen(
[sys.executable, worker_path, batch_id], [sys.executable, worker_path, batch_id],
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, stdout=log_file, stderr=subprocess.STDOUT,
) )
self._json({"ok": True, "total": total}, 202) self._json({"ok": True, "total": total, "log": log_path}, 202)
# ── POST /apply-groups ─────────────────────────────────────────────── # ── POST /apply-groups ───────────────────────────────────────────────