BUR-68 убрал лишний код. Нашел причину неотлавливаемго экспешена.

This commit is contained in:
Первов Артем
2026-07-08 15:55:21 +03:00
parent fc8bfb6691
commit 85658225a3
4 changed files with 46 additions and 67 deletions

View File

@@ -89,7 +89,12 @@ async function postMetrics(metrics: Edge5ModbusV3Metric[]): Promise<void> {
throw new Error(text || `${response.status} ${response.statusText}`) throw new Error(text || `${response.status} ${response.statusText}`)
} }
void postDemoCloudIngest(metric); // для демо-системы const demoResponse = await postDemoCloudIngest(metric); // для демо-системы
if (!demoResponse.ok) {
const text = await demoResponse.text()
throw new Error(text || `${demoResponse.status} ${demoResponse.statusText}`)
}
} catch (error) { } catch (error) {
const message = error instanceof Error ? error.message : String(error) const message = error instanceof Error ? error.message : String(error)

View File

@@ -1,4 +1,3 @@
import './process-errors.js'
import './handlers/index.js' import './handlers/index.js'
import './http/server.js' import './http/server.js'
import './mqtt.js' import './mqtt.js'

View File

@@ -1,57 +0,0 @@
type ErrorWithCause = Error & {
cause?: unknown
}
type NodeError = Error & {
code?: string
address?: string
port?: number
}
// Undici кладёт системную ошибку соединения внутрь error.cause.
function getFetchCause(error: unknown): NodeError | null {
if (!(error instanceof Error)) {
return null
}
const cause = (error as ErrorWithCause).cause
return cause instanceof Error ? (cause as NodeError) : null
}
// Обрабатываем только подсвеченный кейс: backend отказал в TCP-соединении.
function isFetchConnectionRefused(error: unknown): boolean {
if (!(error instanceof Error)) {
return false
}
const cause = getFetchCause(error)
return error.message === 'fetch failed' && cause?.code === 'ECONNREFUSED'
}
// Логируем короткую диагностическую форму без огромного stack trace.
function formatFetchError(error: unknown): object {
if (!(error instanceof Error)) {
return { message: String(error) }
}
const cause = getFetchCause(error)
return {
message: error.message,
cause: cause?.message,
code: cause?.code,
address: cause?.address,
port: cause?.port,
}
}
// Последний рубеж защиты для fire-and-forget fetch-запросов.
// Если backend недоступен, Node.js 22 может превратить незахваченный
// fetch failed / ECONNREFUSED в падение всего процесса mqtt-worker.
process.on('unhandledRejection', (error) => {
if (isFetchConnectionRefused(error)) {
console.error('process.unhandled_fetch_refused', formatFetchError(error))
return
}
console.error('process.unhandled_rejection', error)
})

View File

@@ -1,9 +1,42 @@
import { resolveHandler } from './registry.js' import { resolveHandler } from './registry.js'
type ErrorWithCause = Error & {
cause?: unknown
}
type NodeError = Error & {
code?: string
address?: string
port?: number
}
function getErrorCause(error: Error): NodeError | null {
const cause = (error as ErrorWithCause).cause
return cause instanceof Error ? (cause as NodeError) : null
}
function formatHandlerError(error: unknown): object {
if (!(error instanceof Error)) {
return { message: String(error) }
}
const cause = getErrorCause(error)
return {
message: error.message,
cause: cause?.message,
code: cause?.code,
address: cause?.address,
port: cause?.port,
stack: error.stack,
}
}
export async function routeMessage( export async function routeMessage(
topic: string, topic: string,
payload: Buffer, payload: Buffer,
): Promise<void> { ): Promise<void> {
try {
const handler = resolveHandler(topic) const handler = resolveHandler(topic)
if (!handler) { if (!handler) {
@@ -11,9 +44,8 @@ export async function routeMessage(
return return
} }
try {
await handler(topic, payload) await handler(topic, payload)
} catch (err) { } catch (err) {
console.error('mqtt.handler_error', { topic, err }) console.error('mqtt.handler_error', { topic, error: formatHandlerError(err) })
} }
} }