From 04c2ab5fdef1a9bee3cf43fab4303e77f8eca462 Mon Sep 17 00:00:00 2001 From: Pablo Pettinari Date: Tue, 3 Feb 2026 14:17:02 +0100 Subject: [PATCH] feat(data-layer): add Discord notifications for task failures Add global onFailure handler that sends formatted embeds to Discord when any data fetch task fails. Uses DISCORD_WEBHOOK_URL env var. Trigger.dev's built-in alerts don't format payloads for Discord's webhook API, so this custom handler ensures proper embed formatting. --- src/data-layer/tasks.ts | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/data-layer/tasks.ts b/src/data-layer/tasks.ts index def277b642c..929bef14d3e 100644 --- a/src/data-layer/tasks.ts +++ b/src/data-layer/tasks.ts @@ -5,7 +5,7 @@ * Hourly tasks run every hour. */ -import { schedules, task } from "@trigger.dev/sdk/v3" +import { schedules, task, tasks } from "@trigger.dev/sdk/v3" import { fetchApps } from "./fetchers/fetchApps" import { fetchBeaconChain } from "./fetchers/fetchBeaconChain" @@ -122,3 +122,24 @@ export const hourlyTask = schedules.task({ cron: "0 * * * *", run: () => Promise.all(hourlyFetchTasks.map((t) => t.trigger())), }) + +// ─── Global failure handler → Discord ─── +tasks.onFailure(async ({ ctx, error }) => { + const webhookUrl = process.env.DISCORD_WEBHOOK_URL + if (!webhookUrl) return + + await fetch(webhookUrl, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + embeds: [ + { + title: `Data Fetch Failed: ${ctx.task.id}`, + color: 0xff0000, + description: String(error).slice(0, 2000), + timestamp: new Date().toISOString(), + }, + ], + }), + }) +})