v1.0.178: classify → subprocess.Popen (classify_worker.py). Изолированный процесс — свои коннекты к БД. HTTP-сервер продолжает отвечать.

This commit is contained in:
2026-06-25 13:14:39 +04:00
parent 88039fb750
commit aa1b801e94
2 changed files with 51 additions and 5 deletions
+18 -5
View File
@@ -3,7 +3,7 @@
from http.server import HTTPServer, BaseHTTPRequestHandler
from socketserver import ThreadingMixIn, TCPServer
from urllib.parse import urlparse, parse_qs
import json, re, os
import json, re, os, sys
# ── DB auto-seed ──────────────────────────────────────────────────────────
from db import prompts as db_prompts
@@ -234,24 +234,37 @@ class Handler(BaseHTTPRequestHandler):
# ── POST /classify-batch ─────────────────────────────────────────────
def _handle_classify_batch(self):
"""
POST /api/classify-batch — запустить классификацию в фоне.
ЗАЧЕМ subprocess вместо threading.Thread:
ThreadPoolExecutor(4) + HTTP-поток делят коннекты к PostgreSQL.
При 50+ файлах пул исчерпывается → сервер не отвечает → 502.
Отдельный процесс — свои коннекты, своя память.
HTTP-сервер продолжает отвечать на batch-progress.
"""
length = int(self.headers.get("Content-Length", 0))
body = json.loads(self.rfile.read(length))
batch_id = body.get("batch_id")
if not batch_id:
self._json({"ok": False, "error": "batch_id required"}, 400)
return
from services.classify import classify_batch
from db import documents as db_docs
import threading
import subprocess, os
# Посчитать сколько файлов — ответить сразу, классифицировать в фоне
# Посчитать сколько файлов — ответить сразу, classify в отдельном процессе
pending = db_docs.list_pending(batch_id)
total = len(pending)
if total == 0:
self._json({"ok": False, "error": "no pending documents"}, 400)
return
threading.Thread(target=classify_batch, args=(batch_id,), daemon=True).start()
# Запустить classify_worker.py в отдельном процессе
worker_path = os.path.join(os.path.dirname(__file__), "classify_worker.py")
subprocess.Popen(
[sys.executable, worker_path, batch_id],
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
)
self._json({"ok": True, "total": total}, 202)
# ── POST /apply-groups ───────────────────────────────────────────────