Логирование в stdout (видно в Portainer) + асинхронные задания edit/upscale с опросом статуса (фикс 504/499 при длинных запросах)

This commit is contained in:
2026-08-26 14:10:45 +07:00
parent d9eccfb4b7
commit 27a2ac304c
4 changed files with 476 additions and 139 deletions

View File

@@ -342,8 +342,8 @@ async function runJob(kind) {
setJobStatus(
"loading",
isEdit
? "Codex редактирует фотографию… Обычно 1–3 минуты."
: "Увеличиваем разрешение фотографии…"
? "Codex редактирует фотографию… Обычно 1–3 минуты. Страницу можно закрыть — результат появится в истории."
: "Увеличиваем разрешение фотографии… Страницу можно закрыть — результат появится в истории."
);
try {
@@ -359,57 +359,118 @@ async function runJob(kind) {
throw new Error(data.error || "Не удалось обработать фотографию.");
}
const version = data.version;
if (version) {
historyVersions.push(version);
currentVersionId = version.id;
updateDownloadCurrent(version);
renderHistory();
if (!data.jobId) {
throw new Error("Сервер не вернул идентификатор задания.");
}
const url = version?.url || data.result?.url;
resultImage.src = url;
resultImage.hidden = false;
resultPlaceholder.hidden = true;
resultLabel.textContent = isEdit ? "Редактирование · Codex" : "4× upscale";
downloadLink.href = url;
downloadLink.download =
data.result?.filename ||
(isEdit ? "edited-photo.jpg" : "upscaled-photo.png");
downloadLink.hidden = false;
const summary = isEdit && data.summary
? String(data.summary).replace(/\s+/g, " ").trim().slice(0, 180)
: "";
setJobStatus(
"success",
isEdit
? summary
? `Готово — фотография отредактирована. Codex: ${summary}`
: "Готово — фотография отредактирована."
: `Готово — разрешение увеличено с помощью ${data.job?.model || "upscale-модели"}.`
);
if (window.matchMedia("(max-width: 1040px)").matches) {
resultImage.scrollIntoView({
behavior: "smooth",
block: "center"
});
}
pollJob(data.jobId, isEdit);
} catch (error) {
setBusy(false);
setJobStatus(
"error",
error instanceof Error
? error.message
: "Не удалось обработать фотографию."
);
} finally {
setBusy(false);
}
}
let jobPollFailures = 0;
async function pollJob(jobId, isEdit) {
try {
const response = await apiFetch(`/api/jobs/${jobId}/status`, {
cache: "no-store"
});
const data = await readJsonResponse(response);
if (!response.ok || !data.ok) {
throw new Error(data.error || "Не удалось получить статус задания.");
}
jobPollFailures = 0;
if (data.status === "running") {
setTimeout(() => pollJob(jobId, isEdit), 3000);
return;
}
if (data.status === "done") {
renderJobSuccess(data, isEdit);
setBusy(false);
return;
}
if (data.status === "error") {
throw new Error(data.error || "Задание завершилось с ошибкой.");
}
throw new Error("Неизвестный статус задания.");
} catch (error) {
if (error instanceof Error && error.message === "Требуется авторизация.") {
setBusy(false);
return;
}
jobPollFailures += 1;
if (jobPollFailures >= 5) {
setBusy(false);
setJobStatus(
"error",
error instanceof Error
? error.message
: "Ошибка связи с сервером. Проверьте результат в истории."
);
return;
}
setTimeout(() => pollJob(jobId, isEdit), 3000);
}
}
function renderJobSuccess(data, isEdit) {
const version = data.version;
if (version) {
historyVersions.push(version);
currentVersionId = version.id;
updateDownloadCurrent(version);
renderHistory();
}
const url = version?.url || data.result?.url;
resultImage.src = url;
resultImage.hidden = false;
resultPlaceholder.hidden = true;
resultLabel.textContent = isEdit ? "Редактирование · Codex" : "4× upscale";
downloadLink.href = url;
downloadLink.download =
data.result?.filename ||
(isEdit ? "edited-photo.jpg" : "upscaled-photo.png");
downloadLink.hidden = false;
const summary = isEdit && data.summary
? String(data.summary).replace(/\s+/g, " ").trim().slice(0, 180)
: "";
setJobStatus(
"success",
isEdit
? summary
? `Готово — фотография отредактирована. Codex: ${summary}`
: "Готово — фотография отредактирована."
: `Готово — разрешение увеличено с помощью ${data.job?.model || "upscale-модели"}.`
);
if (window.matchMedia("(max-width: 1040px)").matches) {
resultImage.scrollIntoView({
behavior: "smooth",
block: "center"
});
}
}

View File

@@ -15,7 +15,7 @@
rel="icon"
href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Crect width='64' height='64' rx='16' fill='%23202321'/%3E%3Ctext x='32' y='45' font-size='38' font-weight='bold' text-anchor='middle' fill='%23ffffff' font-family='sans-serif'%3E%D0%9A%3C/text%3E%3C/svg%3E"
>
<link rel="stylesheet" href="/style.css?v=9">
<link rel="stylesheet" href="/style.css?v=10">
</head>
<body>
<header class="topbar">
@@ -261,6 +261,6 @@
</div>
</noscript>
<script src="/app.js?v=9" defer></script>
<script src="/app.js?v=10" defer></script>
</body>
</html>