feat(webhooks): dispatch async generation_request.created and creative.created events to n8n with 60s retry

This commit is contained in:
Marcos Fargas
2026-10-13 01:17:26 +02:00
parent 66d34853e6
commit 2a1629cda8
4 changed files with 112 additions and 25 deletions

View File

@@ -3,7 +3,9 @@ import crypto from 'node:crypto';
export type CreativeWebhookEvent =
| 'creative.approved'
| 'creative.rejected'
| 'creative.sent_to_client';
| 'creative.sent_to_client'
| 'generation_request.created'
| 'creative.created';
export interface WebhookDispatchResult {
sent: boolean;
@@ -32,8 +34,18 @@ export function verifyWebhookSignature(payloadStr: string, signature: string, se
}
}
function resolveWebhookPath(event: CreativeWebhookEvent): string {
if (event === 'generation_request.created') {
return '/app4v/generation-request';
}
if (event === 'creative.created') {
return '/app4v/creative-created';
}
return '/app4v/creative-event';
}
/**
* Envía un webhook firmado hacia n8n (/webhook/app4v/creative-event)
* Envía un webhook firmado hacia n8n
*/
export async function dispatchN8nWebhook(
event: CreativeWebhookEvent,
@@ -46,8 +58,7 @@ export async function dispatchN8nWebhook(
return { sent: false, error: 'N8N_WEBHOOK_BASE is not configured' };
}
// WF4 listens on /webhook/app4v/creative-event
const endpoint = `${baseUrl.replace(/\/$/, '')}/app4v/creative-event`;
const endpoint = `${baseUrl.replace(/\/$/, '')}${resolveWebhookPath(event)}`;
const fullBody = {
event,
payload,
@@ -69,7 +80,7 @@ export async function dispatchN8nWebhook(
});
return {
sent: true,
sent: res.status === 200,
url: endpoint,
signature,
status: res.status,
@@ -83,3 +94,22 @@ export async function dispatchN8nWebhook(
};
}
}
/**
* Encola el envío asíncrono del webhook (setImmediate) con un reintento a los 60 s si n8n no responde 200
*/
export function dispatchN8nWebhookAsync(
event: CreativeWebhookEvent,
payload: Record<string, unknown>
): void {
const schedule = typeof setImmediate === 'function' ? setImmediate : (fn: () => void) => setTimeout(fn, 0);
schedule(() => {
void dispatchN8nWebhook(event, payload).then((result) => {
if (result.status !== 200) {
setTimeout(() => {
void dispatchN8nWebhook(event, payload);
}, 60_000);
}
});
});
}