fix(api): завершать запрос при обрыве ответа RouterOS

This commit is contained in:
Denozordec committed 2026-10-10 02:06:56 +07:00
1 parent 5944e5e751
commit 7f0c2aad0f
13 files changed
+1005 -31

No files matched your search

@@ -0,0 +1,22 @@
{
"date": "2026-10-10",
"cases": [
{
"width": 1280,
"errorHistoryVisible": true,
"previousSnapshot42and17Preserved": true,
"reload": true,
"documentFits": true
},
{
"width": 320,
"errorHistoryVisible": true,
"previousSnapshot42and17Preserved": true,
"reload": true,
"documentFits": true
}
],
"errors": [],
"httpMocks": false,
"uiNativePosts": 0
}
@@ -0,0 +1,703 @@
{
"date": "2026-10-10",
"runtime": {
"backend": "ux-speed98",
"frontend": "ux-ospf91"
},
"httpMocks": false,
"readOnly": true,
"cases": [
{
"route": "alerts",
"width": 1280,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [
{
"id": "color-contrast",
"impact": "serious",
"description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds",
"targets": [
[
".py-12 > p"
]
]
}
],
"apiFailures": []
},
{
"route": "alerts",
"width": 320,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [
{
"id": "color-contrast",
"impact": "serious",
"description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds",
"targets": [
[
".py-12 > .text-sm"
]
]
}
],
"apiFailures": []
},
{
"route": "asns",
"width": 1280,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "asns",
"width": 320,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "backups",
"width": 1280,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "backups",
"width": 320,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "bgp",
"width": 1280,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "bgp",
"width": 320,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "certificates",
"width": 1280,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [
{
"id": "color-contrast",
"impact": "serious",
"description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds",
"targets": [
[
".text-success-foreground"
]
]
},
{
"id": "scrollable-region-focusable",
"impact": "serious",
"description": "Ensure elements that have scrollable content are accessible by keyboard in Safari",
"targets": [
[
"div:nth-child(1) > pre"
],
[
"div:nth-child(3) > pre"
]
]
}
],
"apiFailures": []
},
{
"route": "certificates",
"width": 320,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [
{
"id": "color-contrast",
"impact": "serious",
"description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds",
"targets": [
[
".text-success-foreground"
]
]
},
{
"id": "scrollable-region-focusable",
"impact": "serious",
"description": "Ensure elements that have scrollable content are accessible by keyboard in Safari",
"targets": [
[
"div:nth-child(3) > pre"
]
]
}
],
"apiFailures": []
},
{
"route": "communities",
"width": 1280,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "communities",
"width": 320,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "containers",
"width": 1280,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [
{
"id": "color-contrast",
"impact": "serious",
"description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds",
"targets": [
[
".bg-info\\/5 > div > .text-info"
]
]
}
],
"apiFailures": []
},
{
"route": "containers",
"width": 320,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [
{
"id": "color-contrast",
"impact": "serious",
"description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds",
"targets": [
[
".bg-info\\/5 > div > .text-info"
]
]
}
],
"apiFailures": []
},
{
"route": "dashboard",
"width": 1280,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "dashboard",
"width": 320,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "data-collection",
"width": 1280,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "data-collection",
"width": 320,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "domains",
"width": 1280,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "domains",
"width": 320,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "filters",
"width": 1280,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "filters",
"width": 320,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [
{
"id": "color-contrast",
"impact": "serious",
"description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds",
"targets": [
[
".bg-primary"
]
]
}
],
"apiFailures": []
},
{
"route": "firewall",
"width": 1280,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "firewall",
"width": 320,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "gre",
"width": 1280,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "gre",
"width": 320,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "ip-ranges",
"width": 1280,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "ip-ranges",
"width": 320,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "ipsec",
"width": 1280,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "ipsec",
"width": 320,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "network-map",
"width": 1280,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "network-map",
"width": 320,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "ospf",
"width": 1280,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "ospf",
"width": 320,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "probes",
"width": 1280,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "probes",
"width": 320,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "recursive-routes",
"width": 1280,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "recursive-routes",
"width": 320,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "releases",
"width": 1280,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "releases",
"width": 320,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "route-optimizer",
"width": 1280,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "route-optimizer",
"width": 320,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "servers",
"width": 1280,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "servers",
"width": 320,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "settings",
"width": 1280,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "settings",
"width": 320,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "statistics",
"width": 1280,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "statistics",
"width": 320,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "terminal",
"width": 1280,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "terminal",
"width": 320,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "traffic",
"width": 1280,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": [
{
"path": "/api/traffic/servers/srv1/interfaces",
"status": 400
},
{
"path": "/api/traffic/servers/srv1",
"status": 400
}
]
},
{
"route": "traffic",
"width": 320,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": [
{
"path": "/api/traffic/servers/srv1/interfaces",
"status": 400
},
{
"path": "/api/traffic/servers/srv1",
"status": 400
}
]
},
{
"route": "uptime",
"width": 1280,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [
{
"id": "color-contrast",
"impact": "serious",
"description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds",
"targets": [
[
".text-muted-foreground\\/80"
]
]
}
],
"apiFailures": []
},
{
"route": "uptime",
"width": 320,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "users",
"width": 1280,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "users",
"width": 320,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "vxlan",
"width": 1280,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "vxlan",
"width": 320,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "wireguard",
"width": 1280,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
},
{
"route": "wireguard",
"width": 320,
"httpStatus": 200,
"fits": true,
"title": "MikrotikManager",
"violations": [],
"apiFailures": []
}
],
"errors": [],
"writes": [
{
"method": "POST",
"path": "/api/servers/1/ospf/optimize/preview"
},
{
"method": "POST",
"path": "/api/servers/1/ospf/optimize/preview"
}
],
"automaticReadOnlyRequests": [
{
"method": "POST",
"path": "/api/servers/1/ospf/optimize/preview"
},
{
"method": "POST",
"path": "/api/servers/1/ospf/optimize/preview"
}
],
"mutations": [],
"note": "Two automatic OSPF optimizer preview POSTs only; no apply/mutation requests. Scoped axe at700ms after fonts ready; not full WCAG or functional acceptance of all integrations."
}
@@ -0,0 +1,78 @@
{
"date": "2026-10-10",
"runtime": {
"backend": "ux-response100",
"version": "1.0.0-test.response100",
"imageId": "sha256:797979da82d6bd10147bd57557c65cc28a61b1e583abed13ed7326635d4e5adf",
"frontend": "ux-ospf91"
},
"source": {
"base": "build-speed98",
"archiveSha256": "08e9b4bb3a70c5d9d20e0ffef387d9bbba7bcc51f80968be740c7c64982dc5da",
"workingTreeOverrides": [
"backend/src/services/mikrotik.ts",
"backend/src/services/mikrotik-response.test.ts",
"backend/package.json"
],
"revisionLabel": "response100 (stage label, not Git SHA)"
},
"before": {
"boundedTests": 7,
"passed": 1,
"failed": 6,
"reason": "Incomplete IncomingMessage left promise pending past500ms timeout; test1200ms deadline rejected"
},
"after": {
"boundedTests": 7,
"passed": 7,
"failed": 0,
"methods": [
"GET",
"POST",
"PUT",
"PATCH",
"DELETE",
"raw file POST"
],
"completeSuccessAnd401": true,
"mutationRetries": 0,
"fileCompatibilityReadStrategies": 2
},
"checks": {
"abortSignalAndProbeCancellation": true,
"fileByteParser": true,
"localProductionBuild": true,
"dockerProductionBuild": true,
"entryNodeCheck": true,
"pgRestore": "18.6",
"composeHealthy": true,
"backendNpmTest": {
"groups": 24,
"nodeTestCases": 171,
"reportedFailures": 0,
"exitCode": 0,
"database": "Deliberately unavailable fixture URL; no external DB writes"
},
"lintNewTest": true,
"existingMikrotikPreferConstErrors": 2
},
"live": {
"nativeReport": "speed-response-body-2026-10-10.json",
"browserReport": "browser-speed-response-body-2026-10-10.json",
"nativeCommands": 1,
"durationSec": 3,
"rateLimitBps": 10000000,
"body": "First16 bytes of actual completed native JSON delivered; relay closed socket before remaining body",
"api502": true,
"unknownMessage": true,
"priorSnapshotPreserved": true,
"automaticRetry": false,
"uiCases": 2,
"cleanup": true
},
"limits": [
"HTTP localhost partial-response tests plus real RouterOS command through controlled relay; not independent physical WAN loss",
"Complete malformed PATCH JSON semantics, general response size limits and durable cancellation not changed",
"Main/context UI matrix still pending; frontend unchanged"
]
}
@@ -0,0 +1,54 @@
{
"date": "2026-10-10",
"name": "mm-body100-1791572367426",
"rateLimitBps": 10000000,
"durationSec": 3,
"syntheticPreviousSnapshot": {
"txAvgMbps": 42,
"rxAvgMbps": 17,
"pingRttMs": 15,
"pingLossPct": 0
},
"httpMocks": false,
"routerOsMocks": false,
"nativeCompletion": {
"status": "done testing",
"responseRows": 5,
"httpStatus": 200
},
"receiptPhase": "partial-response-body",
"receiptSocketDestroyed": true,
"httpStatus": 502,
"receipt": {
"error": "Результат теста скорости неизвестен: ответ устройства не получен. Проверьте его состояние перед повторным запуском."
},
"nativeCount": 1,
"probe": {
"id": "mm-body100-1791572367426",
"last_status": "error",
"last_tx_avg_mbps": 42,
"last_rx_avg_mbps": 17,
"last_ping_rtt_ms": 15,
"last_ping_loss_pct": 0,
"last_error": "Результат теста скорости неизвестен: ответ устройства не получен. Проверьте его состояние перед повторным запуском."
},
"history": [
{
"id": "mm-body100-1791572367426",
"status": "error",
"tx_avg_mbps": null,
"rx_avg_mbps": null,
"ping_rtt_ms": null,
"ping_loss_pct": null,
"error": "Результат теста скорости неизвестен: ответ устройства не получен. Проверьте его состояние перед повторным запуском."
}
],
"automaticRetry": false,
"limits": [
"Real Node HTTP client socket closed after request forwarded; RouterOS independently completed. Not physical WAN loss or cancelled native command.",
"Previous metrics deliberately seeded on own disabled probe, not new real measurements.",
"History error means application did not obtain confirmed test result; native completion was observed only by independent relay."
],
"cleanupHistory": true,
"cleanupProbes": true
}