File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -17,6 +17,7 @@ import { readFile } from "node:fs/promises";
1717import sourceMapSupport from "source-map-support" ;
1818import { registerResources } from "../indexing/registerResources.js" ;
1919import { reportTaskIdCollisions } from "../indexing/reportTaskIdCollisions.js" ;
20+ import { reportWebhookIdCollisions } from "../indexing/reportWebhookIdCollisions.js" ;
2021import { env } from "std-env" ;
2122import { normalizeImportPath } from "../utilities/normalizeImportPath.js" ;
2223import { detectRuntimeVersion } from "@trigger.dev/core/v3/build" ;
@@ -127,6 +128,11 @@ if (await reportTaskIdCollisions(safeSend)) {
127128 process . exit ( 0 ) ;
128129}
129130
131+ if ( await reportWebhookIdCollisions ( safeSend ) ) {
132+ await new Promise < void > ( ( resolve ) => setTimeout ( resolve , 10 ) ) ;
133+ process . exit ( 0 ) ;
134+ }
135+
130136let tasks = await convertSchemasToJsonSchemas ( resourceCatalog . listTaskManifests ( ) ) ;
131137
132138// If the config has retry defaults, we need to apply them to all tasks that don't have any retry settings
Original file line number Diff line number Diff line change @@ -17,6 +17,7 @@ import { readFile } from "node:fs/promises";
1717import sourceMapSupport from "source-map-support" ;
1818import { registerResources } from "../indexing/registerResources.js" ;
1919import { reportTaskIdCollisions } from "../indexing/reportTaskIdCollisions.js" ;
20+ import { reportWebhookIdCollisions } from "../indexing/reportWebhookIdCollisions.js" ;
2021import { env } from "std-env" ;
2122import { normalizeImportPath } from "../utilities/normalizeImportPath.js" ;
2223import { detectRuntimeVersion } from "@trigger.dev/core/v3/build" ;
@@ -121,6 +122,11 @@ if (await reportTaskIdCollisions(safeSend)) {
121122 process . exit ( 0 ) ;
122123}
123124
125+ if ( await reportWebhookIdCollisions ( safeSend ) ) {
126+ await new Promise < void > ( ( resolve ) => setTimeout ( resolve , 10 ) ) ;
127+ process . exit ( 0 ) ;
128+ }
129+
124130let tasks = await convertSchemasToJsonSchemas ( resourceCatalog . listTaskManifests ( ) ) ;
125131
126132// If the config has retry defaults, we need to apply them to all tasks that don't have any retry settings
Original file line number Diff line number Diff line change 11import { execPathForRuntime } from "@trigger.dev/core/v3/build" ;
22import {
33 DuplicateTaskIdsError ,
4+ DuplicateWebhookIdsError ,
45 TaskIndexingImportError ,
56 TaskMetadataParseError ,
67 UncaughtExceptionError ,
@@ -94,6 +95,13 @@ export async function indexWorkerManifest({
9495 child . kill ( "SIGKILL" ) ;
9596 break ;
9697 }
98+ case "WEBHOOKS_FAILED_TO_INDEX" : {
99+ clearTimeout ( timeout ) ;
100+ resolved = true ;
101+ reject ( new DuplicateWebhookIdsError ( message . payload . collisions ) ) ;
102+ child . kill ( "SIGKILL" ) ;
103+ break ;
104+ }
97105 case "UNCAUGHT_EXCEPTION" : {
98106 clearTimeout ( timeout ) ;
99107 resolved = true ;
Original file line number Diff line number Diff line change 1+ import { indexerToWorkerMessages , resourceCatalog } from "@trigger.dev/core/v3" ;
2+ import { sendMessageInCatalog } from "@trigger.dev/core/v3/zodMessageHandler" ;
3+
4+ /**
5+ * If the indexer registered any duplicate webhook ids (across files), report
6+ * them to the parent via WEBHOOKS_FAILED_TO_INDEX and return true. Callers must
7+ * stop indexing (skip INDEX_COMPLETE) when this returns true.
8+ */
9+ export async function reportWebhookIdCollisions (
10+ send : ( message : unknown ) => void
11+ ) : Promise < boolean > {
12+ const collisions = resourceCatalog . listWebhookIdCollisions ( ) ;
13+
14+ if ( collisions . length === 0 ) {
15+ return false ;
16+ }
17+
18+ await sendMessageInCatalog (
19+ indexerToWorkerMessages ,
20+ "WEBHOOKS_FAILED_TO_INDEX" ,
21+ { collisions } ,
22+ async ( msg ) => {
23+ send ( msg ) ;
24+ }
25+ ) ;
26+
27+ return true ;
28+ }
Original file line number Diff line number Diff line change @@ -606,6 +606,37 @@ export class DuplicateTaskIdsError extends Error {
606606 }
607607}
608608
609+ function formatDuplicateWebhookIds ( collisions : TaskIdCollision [ ] ) : string {
610+ const lines = collisions . map ( ( { id, filePaths } ) => {
611+ const distinct = Array . from ( new Set ( filePaths ) ) ;
612+
613+ if ( distinct . length === 1 ) {
614+ return ` - "${ id } " found more than once in ${ distinct [ 0 ] } ` ;
615+ }
616+
617+ const last = distinct [ distinct . length - 1 ] ;
618+ const head = distinct . slice ( 0 , - 1 ) . join ( ", " ) ;
619+
620+ return ` - "${ id } " found in ${ head } and ${ last } ` ;
621+ } ) ;
622+
623+ return [
624+ "Duplicate webhook ids detected:" ,
625+ "" ,
626+ ...lines ,
627+ "" ,
628+ "Webhook ids must be unique across your project. Please rename one of them." ,
629+ ] . join ( "\n" ) ;
630+ }
631+
632+ export class DuplicateWebhookIdsError extends Error {
633+ constructor ( public readonly collisions : TaskIdCollision [ ] ) {
634+ super ( formatDuplicateWebhookIds ( collisions ) ) ;
635+
636+ this . name = "DuplicateWebhookIdsError" ;
637+ }
638+ }
639+
609640export class UnexpectedExitError extends Error {
610641 constructor (
611642 public code : number ,
Original file line number Diff line number Diff line change @@ -43,6 +43,10 @@ export const indexerToWorkerMessages = {
4343 version : z . literal ( "v1" ) . default ( "v1" ) ,
4444 collisions : z . array ( z . object ( { id : z . string ( ) , filePaths : z . array ( z . string ( ) ) } ) ) ,
4545 } ) ,
46+ WEBHOOKS_FAILED_TO_INDEX : z . object ( {
47+ version : z . literal ( "v1" ) . default ( "v1" ) ,
48+ collisions : z . array ( z . object ( { id : z . string ( ) , filePaths : z . array ( z . string ( ) ) } ) ) ,
49+ } ) ,
4650 UNCAUGHT_EXCEPTION : UncaughtExceptionMessage ,
4751} ;
4852
You can’t perform that action at this time.
0 commit comments