v1.0.178: fix async classify polling — frontend ждёт done>=total через batch-progress, fix путь логов
This commit is contained in:
+29
-2
@@ -1,3 +1,4 @@
|
||||
// ⛔ НЕ МЕНЯТЬ БЕЗ РАЗРЕШЕНИЯ НАЕЛЯ ⛔
|
||||
// Contracts App — весь JS на VM (contracts.kube5s.ru)
|
||||
// Lucee: только домен + index.cfm-скелет
|
||||
var VM_API = 'https://contracts.kube5s.ru';
|
||||
@@ -140,7 +141,10 @@ async function runClassify() {
|
||||
btn.innerHTML = '<span class="spinner"></span> Классификация... ' + Math.round((Date.now() - start) / 1000) + 'с';
|
||||
}, 1000);
|
||||
|
||||
// Poll progress каждые 2с
|
||||
var totalFiles = 0;
|
||||
var classifyDone = false;
|
||||
|
||||
// Poll progress каждые 2с — работает и для sync, и для async classify
|
||||
var pollTimer = setInterval(async function() {
|
||||
try {
|
||||
var r = await fetch(VM_API + '/api/batch-progress?batch=' + state.batchId);
|
||||
@@ -148,9 +152,16 @@ async function runClassify() {
|
||||
if (d.ok && d.counts) {
|
||||
var done = (d.counts.classified || 0) + (d.counts.failed || 0);
|
||||
var total = d.total || 0;
|
||||
if (total > 0) totalFiles = total;
|
||||
btn.innerHTML = '<span class="spinner"></span> Классификация... ' + done + '/' + total + ' (' + Math.round((Date.now() - start) / 1000) + 'с)';
|
||||
if (done >= total && total > 0) {
|
||||
clearInterval(pollTimer);
|
||||
clearInterval(timer);
|
||||
classifyDone = true;
|
||||
btn.innerHTML = '✓ ' + done + '/' + total + ' классифицировано (' + Math.round((Date.now() - start) / 1000) + 'с)';
|
||||
stepDone('stepClassify');
|
||||
stepActive('stepGroups');
|
||||
loadGroupsAction();
|
||||
}
|
||||
}
|
||||
} catch(e) {}
|
||||
@@ -163,23 +174,39 @@ async function runClassify() {
|
||||
body: JSON.stringify({batch_id: state.batchId})
|
||||
});
|
||||
var data = await resp.json();
|
||||
|
||||
// sync classify: ответ уже содержит done
|
||||
if (data.ok && data.done !== undefined) {
|
||||
clearInterval(timer);
|
||||
clearInterval(pollTimer);
|
||||
if (data.ok) {
|
||||
classifyDone = true;
|
||||
btn.innerHTML = '✓ ' + data.done + '/' + data.total + ' классифицировано (' + Math.round((Date.now() - start) / 1000) + 'с)';
|
||||
stepDone('stepClassify');
|
||||
stepActive('stepGroups');
|
||||
loadGroupsAction();
|
||||
} else if (data.ok) {
|
||||
// async classify: 202 — ждём poll до done>=total
|
||||
totalFiles = data.total || 0;
|
||||
if (totalFiles === 0) {
|
||||
clearInterval(timer);
|
||||
clearInterval(pollTimer);
|
||||
btn.innerHTML = '✗ нет файлов для классификации';
|
||||
btn.disabled = false;
|
||||
}
|
||||
} else {
|
||||
clearInterval(timer);
|
||||
clearInterval(pollTimer);
|
||||
btn.innerHTML = '✗ ' + (data.error || 'ошибка');
|
||||
btn.disabled = false;
|
||||
}
|
||||
} catch(e) {
|
||||
if (!classifyDone) {
|
||||
clearInterval(timer);
|
||||
clearInterval(pollTimer);
|
||||
btn.innerHTML = '✗ ' + e.message;
|
||||
btn.disabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// loadGroups, buildGroupCard, markGroupDone → groups.js (Фаза 2)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# ⛔ НЕ МЕНЯТЬ БЕЗ РАЗРЕШЕНИЯ НАЕЛЯ ⛔
|
||||
"""Contracts VM server — thin HTTP router. All logic in db/ and services/."""
|
||||
from http.server import HTTPServer, BaseHTTPRequestHandler
|
||||
from socketserver import ThreadingMixIn, TCPServer
|
||||
@@ -267,7 +268,7 @@ class Handler(BaseHTTPRequestHandler):
|
||||
|
||||
# Запустить classify_worker.py в отдельном процессе
|
||||
# Лог в /home/naeel/contracts/logs/ вместо DEVNULL
|
||||
log_dir = "/home/naeel/contracts/logs"
|
||||
log_dir = "/home/naeel/nubes/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")
|
||||
|
||||
Reference in New Issue
Block a user