From 0597993c5db97cef899eaa0f24ba7f84e28572b1 Mon Sep 17 00:00:00 2001 From: Guilherme Jansen Date: Fri, 21 Mar 2025 14:56:45 -0300 Subject: [PATCH] =?UTF-8?q?fix(webhook):=20implementar=20timeout=20configu?= =?UTF-8?q?r=C3=A1vel=20e=20sistema=20de=20retentativas=20inteligente?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/integrations/event/webhook/webhook.controller.ts | 8 ++++---- src/config/env.config.ts | 8 +++++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/api/integrations/event/webhook/webhook.controller.ts b/src/api/integrations/event/webhook/webhook.controller.ts index b77c7829..49d85824 100644 --- a/src/api/integrations/event/webhook/webhook.controller.ts +++ b/src/api/integrations/event/webhook/webhook.controller.ts @@ -157,7 +157,7 @@ export class WebhookController extends EventController implements EventControlle try { if (isURL(globalURL)) { - const httpService = axios.create({ + const httpService = axios.create({ baseURL: globalURL, timeout: webhookConfig.REQUEST?.TIMEOUT_MS ?? 30000, }); @@ -221,10 +221,10 @@ export class WebhookController extends EventController implements EventControlle return; } catch (error) { attempts++; - + // Verificar se é um erro de timeout const isTimeout = error.code === 'ECONNABORTED'; - + // Verificar se o erro não deve gerar retry com base no status code if (error?.response?.status && nonRetryableStatusCodes.includes(error.response.status)) { this.logger.error({ @@ -261,7 +261,7 @@ export class WebhookController extends EventController implements EventControlle if (useExponentialBackoff) { // Fórmula: initialDelay * (2^attempts) com limite máximo nextDelay = Math.min(initialDelay * Math.pow(2, attempts - 1), maxDelay); - + // Adicionar jitter para evitar "thundering herd" const jitter = nextDelay * jitterFactor * (Math.random() * 2 - 1); nextDelay = Math.max(initialDelay, nextDelay + jitter); diff --git a/src/config/env.config.ts b/src/config/env.config.ts index c5b7d191..7e58d50d 100644 --- a/src/config/env.config.ts +++ b/src/config/env.config.ts @@ -220,8 +220,8 @@ export type CacheConfLocal = { TTL: number; }; export type SslConf = { PRIVKEY: string; FULLCHAIN: string }; -export type Webhook = { - GLOBAL?: GlobalWebhook; +export type Webhook = { + GLOBAL?: GlobalWebhook; EVENTS: EventsWebhook; REQUEST?: { TIMEOUT_MS?: number; @@ -520,7 +520,9 @@ export class ConfigService { USE_EXPONENTIAL_BACKOFF: process.env?.WEBHOOK_RETRY_USE_EXPONENTIAL_BACKOFF !== 'false', MAX_DELAY_SECONDS: Number.parseInt(process.env?.WEBHOOK_RETRY_MAX_DELAY_SECONDS) || 300, JITTER_FACTOR: Number.parseFloat(process.env?.WEBHOOK_RETRY_JITTER_FACTOR) || 0.2, - NON_RETRYABLE_STATUS_CODES: process.env?.WEBHOOK_RETRY_NON_RETRYABLE_STATUS_CODES?.split(',').map(Number) || [400, 401, 403, 404, 422], + NON_RETRYABLE_STATUS_CODES: process.env?.WEBHOOK_RETRY_NON_RETRYABLE_STATUS_CODES?.split(',').map(Number) || [ + 400, 401, 403, 404, 422, + ], }, }, CONFIG_SESSION_PHONE: {