@@ -14,6 +14,9 @@ import { IndexEndpointStats } from "@trigger.dev/core";
14
14
import { RegisterHttpEndpointService } from "../triggers/registerHttpEndpoint.server" ;
15
15
import { RegisterWebhookService } from "../triggers/registerWebhook.server" ;
16
16
import { EndpointIndex } from "@trigger.dev/database" ;
17
+ import { env } from "~/env.server" ;
18
+
19
+ const MAX_SEQUENTIAL_FAILURE_COUNT = env . MAX_SEQUENTIAL_INDEX_FAILURE_COUNT ;
17
20
18
21
export class PerformEndpointIndexService {
19
22
#prismaClient: PrismaClient ;
@@ -56,9 +59,16 @@ export class PerformEndpointIndexService {
56
59
57
60
if ( ! endpointIndex . endpoint . url ) {
58
61
logger . debug ( "Endpoint URL is not set" , endpointIndex ) ;
59
- return updateEndpointIndexWithError ( this . #prismaClient, id , {
60
- message : "Endpoint URL is not set" ,
61
- } ) ;
62
+
63
+ return updateEndpointIndexWithError (
64
+ this . #prismaClient,
65
+ id ,
66
+ endpointIndex . endpoint . id ,
67
+ {
68
+ message : "Endpoint URL is not set" ,
69
+ } ,
70
+ false
71
+ ) ;
62
72
}
63
73
64
74
// Make a request to the endpoint to fetch a list of jobs
@@ -69,9 +79,15 @@ export class PerformEndpointIndexService {
69
79
const { response, parser, headerParser, errorParser } = await client . indexEndpoint ( ) ;
70
80
71
81
if ( ! response ) {
72
- return updateEndpointIndexWithError ( this . #prismaClient, id , {
73
- message : `Could not connect to endpoint ${ endpointIndex . endpoint . url } ` ,
74
- } ) ;
82
+ return updateEndpointIndexWithError (
83
+ this . #prismaClient,
84
+ id ,
85
+ endpointIndex . endpoint . id ,
86
+ {
87
+ message : `Could not connect to endpoint ${ endpointIndex . endpoint . url } ` ,
88
+ } ,
89
+ endpointIndex . endpoint . environment . type !== "DEVELOPMENT"
90
+ ) ;
75
91
}
76
92
77
93
if ( isRedirect ( response . status ) ) {
@@ -83,15 +99,27 @@ export class PerformEndpointIndexService {
83
99
const location = response . headers . get ( "location" ) ;
84
100
85
101
if ( ! location ) {
86
- return updateEndpointIndexWithError ( this . #prismaClient, id , {
87
- message : `Endpoint ${ endpointIndex . endpoint . url } is redirecting but no location header is present` ,
88
- } ) ;
102
+ return updateEndpointIndexWithError (
103
+ this . #prismaClient,
104
+ id ,
105
+ endpointIndex . endpoint . id ,
106
+ {
107
+ message : `Endpoint ${ endpointIndex . endpoint . url } is redirecting but no location header is present` ,
108
+ } ,
109
+ endpointIndex . endpoint . environment . type !== "DEVELOPMENT"
110
+ ) ;
89
111
}
90
112
91
113
if ( redirectCount > 5 ) {
92
- return updateEndpointIndexWithError ( this . #prismaClient, id , {
93
- message : `Endpoint ${ endpointIndex . endpoint . url } is redirecting too many times` ,
94
- } ) ;
114
+ return updateEndpointIndexWithError (
115
+ this . #prismaClient,
116
+ id ,
117
+ endpointIndex . endpoint . id ,
118
+ {
119
+ message : `Endpoint ${ endpointIndex . endpoint . url } is redirecting too many times` ,
120
+ } ,
121
+ endpointIndex . endpoint . environment . type !== "DEVELOPMENT"
122
+ ) ;
95
123
}
96
124
97
125
await this . #prismaClient. endpoint . update ( {
@@ -111,20 +139,38 @@ export class PerformEndpointIndexService {
111
139
const body = await safeBodyFromResponse ( response , errorParser ) ;
112
140
113
141
if ( body ) {
114
- return updateEndpointIndexWithError ( this . #prismaClient, id , {
115
- message : body . message ,
116
- } ) ;
142
+ return updateEndpointIndexWithError (
143
+ this . #prismaClient,
144
+ id ,
145
+ endpointIndex . endpoint . id ,
146
+ {
147
+ message : body . message ,
148
+ } ,
149
+ endpointIndex . endpoint . environment . type !== "DEVELOPMENT"
150
+ ) ;
117
151
}
118
152
119
- return updateEndpointIndexWithError ( this . #prismaClient, id , {
120
- message : "Trigger API key is invalid" ,
121
- } ) ;
153
+ return updateEndpointIndexWithError (
154
+ this . #prismaClient,
155
+ id ,
156
+ endpointIndex . endpoint . id ,
157
+ {
158
+ message : "Trigger API key is invalid" ,
159
+ } ,
160
+ endpointIndex . endpoint . environment . type !== "DEVELOPMENT"
161
+ ) ;
122
162
}
123
163
124
164
if ( ! response . ok ) {
125
- return updateEndpointIndexWithError ( this . #prismaClient, id , {
126
- message : `Could not connect to endpoint ${ endpointIndex . endpoint . url } . Status code: ${ response . status } ` ,
127
- } ) ;
165
+ return updateEndpointIndexWithError (
166
+ this . #prismaClient,
167
+ id ,
168
+ endpointIndex . endpoint . id ,
169
+ {
170
+ message : `Could not connect to endpoint ${ endpointIndex . endpoint . url } . Status code: ${ response . status } ` ,
171
+ } ,
172
+ endpointIndex . endpoint . environment . type !== "DEVELOPMENT"
173
+ ) ;
128
174
}
129
175
130
176
const anyBody = await response . json ( ) ;
@@ -152,21 +198,33 @@ export class PerformEndpointIndexService {
152
198
} ) . message ;
153
199
}
154
200
155
- return updateEndpointIndexWithError ( this . #prismaClient, id , {
156
- message : friendlyError ,
157
- raw : fromZodError ( bodyResult . error ) . message ,
158
- } ) ;
201
+ return updateEndpointIndexWithError (
202
+ this . #prismaClient,
203
+ id ,
204
+ endpointIndex . endpoint . id ,
205
+ {
206
+ message : friendlyError ,
207
+ raw : fromZodError ( bodyResult . error ) . message ,
208
+ } ,
209
+ endpointIndex . endpoint . environment . type !== "DEVELOPMENT"
210
+ ) ;
159
211
}
160
212
161
213
const headerResult = headerParser . safeParse ( Object . fromEntries ( response . headers . entries ( ) ) ) ;
162
214
if ( ! headerResult . success ) {
163
215
const friendlyError = fromZodError ( headerResult . error , {
164
216
prefix : "Your headers are invalid" ,
165
217
} ) ;
166
- return updateEndpointIndexWithError ( this . #prismaClient, id , {
167
- message : friendlyError . message ,
168
- raw : headerResult . error . issues ,
169
- } ) ;
218
+ return updateEndpointIndexWithError (
219
+ this . #prismaClient,
220
+ id ,
221
+ endpointIndex . endpoint . id ,
222
+ {
223
+ message : friendlyError . message ,
224
+ raw : headerResult . error . issues ,
225
+ } ,
226
+ endpointIndex . endpoint . environment . type !== "DEVELOPMENT"
227
+ ) ;
170
228
}
171
229
172
230
const { jobs, sources, dynamicTriggers, dynamicSchedules, httpEndpoints, webhooks } =
@@ -407,8 +465,44 @@ export class PerformEndpointIndexService {
407
465
async function updateEndpointIndexWithError (
408
466
prismaClient : PrismaClient ,
409
467
id : string ,
410
- error : EndpointIndexError
468
+ endpointId : string ,
469
+ error : EndpointIndexError ,
470
+ checkDisabling = true
411
471
) {
472
+ // Check here to see if this endpoint has only failed for the last 50 times
473
+ // And if so, we disable the endpoint by setting the url to null
474
+ if ( checkDisabling ) {
475
+ const recentIndexes = await prismaClient . endpointIndex . findMany ( {
476
+ where : {
477
+ endpointId,
478
+ id : {
479
+ not : id ,
480
+ } ,
481
+ } ,
482
+ orderBy : {
483
+ createdAt : "desc" ,
484
+ } ,
485
+ take : MAX_SEQUENTIAL_FAILURE_COUNT - 1 ,
486
+ select : {
487
+ status : true ,
488
+ } ,
489
+ } ) ;
490
+
491
+ if (
492
+ recentIndexes . length === MAX_SEQUENTIAL_FAILURE_COUNT - 1 &&
493
+ recentIndexes . every ( ( index ) => index . status === "FAILURE" )
494
+ ) {
495
+ await prismaClient . endpoint . update ( {
496
+ where : {
497
+ id : endpointId ,
498
+ } ,
499
+ data : {
500
+ url : null ,
501
+ } ,
502
+ } ) ;
503
+ }
504
+ }
505
+
412
506
return await prismaClient . endpointIndex . update ( {
413
507
where : {
414
508
id,
0 commit comments