fix(web): дождаться ответа backend при длительной speed-команде

This commit is contained in:
Denozordec committed 2026-10-08 09:38:17 +07:00
1 parent fc1a60d413
commit aa7dbdf608
8 files changed
+117 -4

No files matched your search

+4
View File
@@ -141,3 +141,7 @@ BGP-prefix evaluator, отдельное live GRE расписание и recove
## Реальный отказ bandwidth-аутентификации — 2026-10-08
12.5.25 [native/API/browser evidence](ux-ui/acceptance/speed-auth-error-2026-10-08.json): authentication failed→HTTP502/русская UI-ошибка, history error/TXRXnull; probe previousTX42 сохранён. Native1/POST[502]/refresh/reload/320fits/JS0, без HTTP/RouterOS-моков. Тестовое имя изменялось только в выделенной app DB и восстановлено; RouterOS accounts не менялись. Temporarycontainers/network/3018 закрыты, testprobe удалена; основнаяhistory5/runtime8782054 сохранены. Подготовительный слишком длинныйuser отклонён по длине; accepted run отдельно. ROS-2 authentication failure принят; остальные native failures ещё открыты. Следующий12.5.26 — unreachable destination.
## Исправление Next proxy timeout — 2026-10-08
12.5.26 [real frontend500/backend error-history](ux-ui/acceptance/speed-unreachable-proxy-before-2026-10-08.json) выявил30s proxy timeout. Локально proxyTimeout180s; реальная Next proxy regression31s/TypeScript/ESLint passed. Backend сохраняет предыдущий TX42; native can not connect не подтверждён. Runtime8782054 прежний; destination восстановлен/testprobe удалена/temporarycontainers-network-3018 закрыты. Следующий12.5.27 — build/real browser retry/deployment исправленного frontend.
+2 -2
View File
@@ -1,12 +1,12 @@
# План реализации UX/UI по пятичасовым окнам
Актуальное продолжение 2026-10-08: 12.5.25 завершён — реальный CHR authentication failed → HTTP502/понятная UI-ошибка/history error с null скоростями; предыдущий TX42 сохранён, native1/без автоповтора, refresh/reload/320px/JS0. Runtime8782054 сохранён. Следующий12.5.26 — ROS-2: недоступное назначение bandwidth-test и согласованность HTTP/UI/history. Полный12.5 открыт.
Актуальное продолжение 2026-10-08: 12.5.26 обнаружил proxy-дефект: при недоступном назначении Next обрывал запрос через30s/HTTP500, backend сохранил error/history и прежний TX42. Локально proxyTimeout180s исправлен, regression31s/typecheck/ESLint прошли. Runtime8782054 прежний. Следующий12.5.27 — frontend build, повторная real browser timeout-проверка и deployment. Native can not connect ещё не подтверждён.
Общий план проекта MikrotikManager. Основан на согласованном плане из задачи; точка продолжения обновлена 2026-10-08. Источник фактического прогресса, проверок и ограничений — [журнал реализации](ux-ui-progress.md). Этот документ задаёт объём и критерии завершения, журнал фиксирует результат.
## Актуальная точка продолжения — 2026-10-08
Этапы0–11 завершены в описанных локальных границах. Этап12 остаётся открытым. На161.104.46.222 развёрнуты backend/frontend8782054; два CHR подключены. PG backup/restore/rollback, single-instance quiescence, JWT/RBAC и browser restore приняты в границах журнала. PG-8 проверен с настоящими PG/native и введённой после COMMIT ошибкой подтверждения; новый browser UI сохраняет snapshot и сверяет историю. ROS-8/9 API/SQL/native приняты в описанных границах. Browser-смена пары/длительности и удаление во время native-теста приняты в12.5.24. Реальный отказ bandwidth-аутентификации принят в12.5.25. Следующий12.5.26 — ROS-2: недоступное назначение и согласованность HTTP/UI/history. [Протокол](ux-ui-external-acceptance.md) и [журнал](ux-ui-stage-12.md) сохраняют точные доказательства и ограничения.
Этапы0–11 завершены в описанных локальных границах. Этап12 остаётся открытым. На161.104.46.222 развёрнуты backend/frontend8782054; два CHR подключены. PG backup/restore/rollback, single-instance quiescence, JWT/RBAC и browser restore приняты в границах журнала. PG-8 проверен с настоящими PG/native и введённой после COMMIT ошибкой подтверждения; новый browser UI сохраняет snapshot и сверяет историю. ROS-8/9 API/SQL/native приняты в описанных границах. Browser-смена пары/длительности и удаление во время native-теста приняты в12.5.24. Реальный отказ bandwidth-аутентификации принят в12.5.25. 12.5.26 обнаружил и локально исправил30s timeout Next proxy. Следующий12.5.27 — новый frontend build/real browser timeout/deployment. [Протокол](ux-ui-external-acceptance.md) и [журнал](ux-ui-stage-12.md) сохраняют точные доказательства и ограничения.
Реальные pg_dump/pg_restore, PG rollback и остановка UDP worker требуют внешней приёмки. Датированные продолжения ниже — история; точный следующий шаг также указан в начале [журнала](ux-ui-progress.md).
+9 -1
View File
@@ -1,6 +1,6 @@
# UX/UI: журнал реализации
Актуальное продолжение 2026-10-08: 12.5.25 завершён — реальный CHR authentication failed → HTTP502/понятная UI-ошибка/history error с null скоростями; предыдущий TX42 сохранён, native1/без автоповтора, refresh/reload/320px/JS0. Runtime8782054 сохранён. Следующий12.5.26 — ROS-2: недоступное назначение bandwidth-test и согласованность HTTP/UI/history. Полный12.5 открыт.
Актуальное продолжение 2026-10-08: 12.5.26 обнаружил proxy-дефект: при недоступном назначении Next обрывал запрос через30s/HTTP500, backend сохранил error/history и прежний TX42. Локально proxyTimeout180s исправлен, regression31s/typecheck/ESLint прошли. Runtime8782054 прежний. Следующий12.5.27 — frontend build, повторная real browser timeout-проверка и deployment. Native can not connect ещё не подтверждён.
Общий план: [UX/UI по этапам и пятичасовым окнам](ux-ui-plan.md). План задаёт объём, этот журнал фиксирует выполненные блоки и ограничения. Записи расположены от новых к старым; подробная история этапа12 также сохранена в [ux-ui-stage-12.md](ux-ui-stage-12.md).
@@ -34,6 +34,14 @@
| 11Б | Оповещения, сбор данных, интеграции, релизы и настройки | Завершён в границах локальной приёмки 2026-10-03; ограничения и evidence в11Б.7 |
| 12 | Итоговая доступность, адаптивность, производительность и регрессия | Локальная приёмка завершена в описанных границах:12.3.83,main1186/1186,context221/221. Этап остаётся в работе: стенд12.5.1–3 развёрнут,bootstrap/smoke проверены;остальные сценарии12.5 не выполнены. |
## 12.5.26 — тайм-аут недоступного назначения и исправление Next proxy (2026-10-08)
[Real failure evidence](ux-ui/acceptance/speed-unreachable-proxy-before-2026-10-08.json): source8782054, выделенная БД, назначение2 временно заменено в app DB на192.0.2.250. Реальный bandwidth POST от CHR1 не вернул native rows до30s. Backend записал history error/TXRXnull и сохранил предыдущий probeTX42; frontend rewrite оборвал запрос с socket hang up/ECONNRESET и вернулHTTP500 раньше структурированного ответа backend. Целевая UI-проверка отклонила500; она не объявлена passed. Это транспортный timeout, не подтверждённый native can not connect.
В установленном Next16.2.4 найден default proxyTimeout30000. В next.config.ts задан experimental.proxyTimeout180000, дольше120s ожидания speed-команды в UI. Добавлен tests/integration/next-proxy-timeout.mjs: загрузка реальной конфигурации проекта, настоящие loopback sockets и установленный Next proxy; delayed backend502JSON после31s доходит до caller. Регрессия, scoped frontend TypeScript и ESLint прошли. Сценарий использует fixture backend response для проверки proxy, не выдаётся за RouterOS proof. Backend/общие UI-компоненты не менялись.
Temporarycontainers/network/3018 закрыты; destinationhost восстановлен и проверен, testprobe удалена. Основной runtime8782054 прежний. Исправление требует нового frontend build: следующий12.5.27 — real browser timeout-проверка на новом образе и deployment после успеха. ROS-2 native can not connect/busy/disconnect/abort остаются открытыми. План и журнал обновлены, локальный коммит без push.
## 12.5.25 — реальный отказ bandwidth-аутентификации (2026-10-08)
[Real API/native/browser evidence](ux-ui/acceptance/speed-auth-error-2026-10-08.json): production8782054, выделенная БД mmapp_acceptance_20261007, изолированная Docker network/SSH3018. Только в app DB временно изменён username назначения2 на несуществующий тестовый; исходное значение сохранено в памяти и восстановлено при штатном завершении. Учётные записи и конфигурация RouterOS не менялись. Scheduler admission закрыт только внутри isolated backend. Guard подтвердил выделенную БД до команды; предыдущий TX42 был явно подготовлен как DB fixture.
+9 -1
View File
@@ -1,6 +1,6 @@
# Этап 12: итоговая приёмка UX/UI
Актуальное продолжение 2026-10-08: 12.5.25 завершён — реальный CHR authentication failed → HTTP502/понятная UI-ошибка/history error с null скоростями; предыдущий TX42 сохранён, native1/без автоповтора, refresh/reload/320px/JS0. Runtime8782054 сохранён. Следующий12.5.26 — ROS-2: недоступное назначение bandwidth-test и согласованность HTTP/UI/history. Полный12.5 открыт.
Актуальное продолжение 2026-10-08: 12.5.26 обнаружил proxy-дефект: при недоступном назначении Next обрывал запрос через30s/HTTP500, backend сохранил error/history и прежний TX42. Локально proxyTimeout180s исправлен, regression31s/typecheck/ESLint прошли. Runtime8782054 прежний. Следующий12.5.27 — frontend build, повторная real browser timeout-проверка и deployment. Native can not connect ещё не подтверждён.
План: [ux-ui-plan.md](ux-ui-plan.md). Фактические результаты: [ux-ui-progress.md](ux-ui-progress.md). Подготовлен после сводных проверок 11Б; завершение каждого блока требует локального коммита без push.
@@ -1218,3 +1218,11 @@ Temporaryfrontend/backend/network удалены,3018туннель закрыт
После «Обновить» и reload история error сохранена; nativeCalls1/POST[502], автоповтора нет, JSerrors0/320px fits. HTTP/RouterOS-моков нет. Подготовительный запрос с чрезмерно длинным тестовым именем был отклонён RouterOSHTTP400 по длинеuser до целевого сценария; после исправления fixture выполнен отдельный принятый прогон. Это ручная валидация, не retry продукта.
Temporaryfrontend/backend/network удалены,3018туннель закрыт, fixtureprobe удалена. В выделенной БД username назначения восстановлен и проверен без вывода секрета; основная история5 сохранена, runtime8782054 исправен. Продуктовый код не менялся, build/deployment не выполнялся. ROS-2 authentication failure принят; unreachable/busy/disconnect/abort и PortalSSO остаются открытыми. Следующий12.5.26 — недоступное назначение bandwidth-test и проверка HTTP/UI/history. План/паспорт/протокол обновлены; локальный коммит без push.
## 12.5.26 — тайм-аут недоступного назначения и исправление Next proxy (2026-10-08)
[Real failure evidence](ux-ui/acceptance/speed-unreachable-proxy-before-2026-10-08.json): source8782054, выделенная БД, назначение2 временно заменено в app DB на192.0.2.250. Реальный bandwidth POST от CHR1 не вернул native rows до30s. Backend записал history error/TXRXnull и сохранил предыдущий probeTX42; frontend rewrite оборвал запрос с socket hang up/ECONNRESET и вернулHTTP500 раньше структурированного ответа backend. Целевая UI-проверка отклонила500; она не объявлена passed. Это транспортный timeout, не подтверждённый native can not connect.
В установленном Next16.2.4 найден default proxyTimeout30000. В next.config.ts задан experimental.proxyTimeout180000, дольше120s ожидания speed-команды в UI. Добавлен tests/integration/next-proxy-timeout.mjs: загрузка реальной конфигурации проекта, настоящие loopback sockets и установленный Next proxy; delayed backend502JSON после31s доходит до caller. Регрессия, scoped frontend TypeScript и ESLint прошли. Сценарий использует fixture backend response для проверки proxy, не выдаётся за RouterOS proof. Backend/общие UI-компоненты не менялись.
Temporarycontainers/network/3018 закрыты; destinationhost восстановлен и проверен, testprobe удалена. Основной runtime8782054 прежний. Исправление требует нового frontend build: следующий12.5.27 — real browser timeout-проверка на новом образе и deployment после успеха. ROS-2 native can not connect/busy/disconnect/abort остаются открытыми. План и журнал обновлены, локальный коммит без push.
+4
View File
@@ -149,3 +149,7 @@ ssh -N -L 3000:127.0.0.1:3000 -L 8000:127.0.0.1:8000 [email protected]
## Реальный отказ bandwidth-аутентификации — 2026-10-08
12.5.25 [native/API/browser evidence](ux-ui/acceptance/speed-auth-error-2026-10-08.json): authentication failed→HTTP502/русская UI-ошибка, history error/TXRXnull; probe previousTX42 сохранён. Native1/POST[502]/refresh/reload/320fits/JS0, без HTTP/RouterOS-моков. Тестовое имя изменялось только в выделенной app DB и восстановлено; RouterOS accounts не менялись. Temporarycontainers/network/3018 закрыты, testprobe удалена; основнаяhistory5/runtime8782054 сохранены. Подготовительный слишком длинныйuser отклонён по длине; accepted run отдельно. ROS-2 authentication failure принят; остальные native failures ещё открыты. Следующий12.5.26 — unreachable destination.
## Исправление Next proxy timeout — 2026-10-08
12.5.26 [real frontend500/backend error-history](ux-ui/acceptance/speed-unreachable-proxy-before-2026-10-08.json) выявил30s proxy timeout. Локально proxyTimeout180s; реальная Next proxy regression31s/TypeScript/ESLint passed. Backend сохраняет предыдущий TX42; native can not connect не подтверждён. Runtime8782054 прежний; destination восстановлен/testprobe удалена/temporarycontainers-network-3018 закрыты. Следующий12.5.27 — build/real browser retry/deployment исправленного frontend.
@@ -0,0 +1,40 @@
{
"date": "2026-10-08",
"source": "8782054",
"database": "mmapp_acceptance_20261007",
"frontendReceipt": 500,
"proxyLog": "Failed to proxy speed-test: socket hang up ECONNRESET",
"nativeCalls": 1,
"nativeStatuses": [],
"snapshot": {
"last_status": "error",
"last_tx_avg_mbps": 42,
"last_rx_avg_mbps": null,
"last_run_at": "2026-10-08T02:33:03.080Z"
},
"history": {
"id": "speed-1791426754414",
"probeId": "acceptance-browser-unreachable",
"srcServerId": "1",
"dstServerId": "2",
"srcInterface": "",
"dstInterface": "",
"protocol": "tcp",
"direction": "transmit",
"durationSec": 3,
"txAvgMbps": null,
"rxAvgMbps": null,
"status": "error",
"error": "BTTest timeout/socket hang up: \u043f\u0440\u043e\u0432\u0435\u0440\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u044c destination, /tool bandwidth-server, firewall \u0438 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0441\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u0432",
"createdAt": "2026-10-08T02:33:03.083Z",
"srcAddress": null,
"dstAddress": null,
"srcInterfaceAddress": null,
"dstInterfaceAddress": null,
"afterBtPing": {
"rttMs": null,
"lossPct": null,
"error": null
}
}
}
+3
View File
@@ -5,6 +5,9 @@ const nextConfig: NextConfig = {
output: "standalone",
experimental: {
proxyClientMaxBodySize: "512mb",
// Speed commands include RouterOS waits and post-test Ping; the UI allows 120s.
// Let the backend return its structured outcome before the rewrite times out.
proxyTimeout: 180_000,
},
async rewrites() {
const backendUrl = backendInternalUrl();
+46
View File
@@ -0,0 +1,46 @@
import assert from 'node:assert/strict';
import http from 'node:http';
import url from 'node:url';
import configExports from 'next/dist/server/config.js';
import constants from 'next/constants.js';
import proxyExports from 'next/dist/server/lib/router-utils/proxy-request.js';
const loadConfig = configExports.default;
const { PHASE_DEVELOPMENT_SERVER } = constants;
const { proxyRequest } = proxyExports;
// Exercise the installed Next proxy with the project's loaded config and real sockets.
// A delayed structured failure must reach the caller beyond Next's default 30s.
(async () => {
const config = await loadConfig(PHASE_DEVELOPMENT_SERVER, process.cwd());
const pending = new Set();
const backend = http.createServer((request, response) => {
request.resume();
const timer = setTimeout(() => {
pending.delete(timer);
response.writeHead(502, { 'content-type': 'application/json' });
response.end(JSON.stringify({ error: 'Backend timeout receipt', outcome: 'unknown' }));
}, 31_000);
pending.add(timer);
});
const proxy = http.createServer((request, response) => {
const target = url.parse(`http://127.0.0.1:${backend.address().port}${request.url}`, true);
proxyRequest(request, response, target, undefined, undefined, config.experimental.proxyTimeout)
.catch(() => { if (!response.headersSent) response.writeHead(500); response.end(); });
});
const listen = server => new Promise(resolve => server.listen(0, '127.0.0.1', resolve));
try {
await listen(backend); await listen(proxy);
const started = Date.now();
const response = await fetch(`http://127.0.0.1:${proxy.address().port}/api/uptime/speed-test`, {
method: 'POST', body: '{}', headers: { 'content-type': 'application/json' }, signal: AbortSignal.timeout(60_000),
});
assert.equal(response.status, 502, 'Next must preserve the backend failure receipt after 30s');
assert.deepEqual(await response.json(), { error: 'Backend timeout receipt', outcome: 'unknown' });
assert(Date.now() - started >= 31_000);
console.log('Next proxy: delayed 502 JSON preserved beyond 30s');
} finally {
for (const timer of pending) clearTimeout(timer);
proxy.closeAllConnections(); backend.closeAllConnections();
await Promise.all([proxy, backend].map(server => new Promise(resolve => server.close(resolve))));
}
})().catch(error => { console.error(error.message); process.exitCode = 1; });