trigger.dev 3.0.0-beta.53 → 3.0.0-beta.54
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -8,7 +8,7 @@ import { ZodMessageSender } from "@trigger.dev/core/v3/zodMessageHandler";
|
|
|
8
8
|
import "source-map-support/register.js";
|
|
9
9
|
|
|
10
10
|
// package.json
|
|
11
|
-
var version = "3.0.0-beta.
|
|
11
|
+
var version = "3.0.0-beta.54";
|
|
12
12
|
|
|
13
13
|
// src/workers/dev/worker-setup.ts
|
|
14
14
|
__SETUP_IMPORTED_PROJECT_CONFIG__;
|
|
@@ -1085,7 +1085,6 @@ import { randomUUID } from "node:crypto";
|
|
|
1085
1085
|
import { readFile } from "node:fs/promises";
|
|
1086
1086
|
import { createServer } from "node:http";
|
|
1087
1087
|
import { setTimeout as timeout2 } from "node:timers/promises";
|
|
1088
|
-
import { Evt as Evt2 } from "evt";
|
|
1089
1088
|
var HTTP_SERVER_PORT = Number(process.env.HTTP_SERVER_PORT || getRandomPortNumber());
|
|
1090
1089
|
var COORDINATOR_HOST = process.env.COORDINATOR_HOST || "127.0.0.1";
|
|
1091
1090
|
var COORDINATOR_PORT = Number(process.env.COORDINATOR_PORT || 50080);
|
|
@@ -1118,14 +1117,13 @@ var ProdWorker = class {
|
|
|
1118
1117
|
completed = /* @__PURE__ */ new Set();
|
|
1119
1118
|
paused = false;
|
|
1120
1119
|
attemptFriendlyId;
|
|
1121
|
-
attemptNumber;
|
|
1122
1120
|
nextResumeAfter;
|
|
1123
1121
|
waitForPostStart = false;
|
|
1124
1122
|
connectionCount = 0;
|
|
1125
|
-
restoreNotification = Evt2.create();
|
|
1126
1123
|
waitForTaskReplay;
|
|
1127
1124
|
waitForBatchReplay;
|
|
1128
1125
|
readyForLazyAttemptReplay;
|
|
1126
|
+
submitAttemptCompletionReplay;
|
|
1129
1127
|
durationResumeFallback;
|
|
1130
1128
|
#httpPort;
|
|
1131
1129
|
#backgroundWorker;
|
|
@@ -1185,118 +1183,98 @@ var ProdWorker = class {
|
|
|
1185
1183
|
}
|
|
1186
1184
|
}
|
|
1187
1185
|
// MARK: TASK WAIT
|
|
1188
|
-
#
|
|
1189
|
-
|
|
1190
|
-
logger.log("
|
|
1191
|
-
if (this.
|
|
1192
|
-
logger.error("
|
|
1193
|
-
|
|
1194
|
-
});
|
|
1195
|
-
return;
|
|
1186
|
+
async #waitForTaskHandler(message, replayIdempotencyKey) {
|
|
1187
|
+
const waitForTask = await defaultBackoff.execute(async ({ retry }) => {
|
|
1188
|
+
logger.log("Wait for task with backoff", { retry });
|
|
1189
|
+
if (!this.attemptFriendlyId) {
|
|
1190
|
+
logger.error("Failed to send wait message, attempt friendly ID not set", { message });
|
|
1191
|
+
throw new ExponentialBackoff.StopRetrying("No attempt ID");
|
|
1196
1192
|
}
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
throw new ExponentialBackoff.StopRetrying("No attempt ID");
|
|
1202
|
-
}
|
|
1203
|
-
return await this.#coordinatorSocket.socket.timeout(2e4).emitWithAck("WAIT_FOR_TASK", {
|
|
1204
|
-
version: "v2",
|
|
1205
|
-
friendlyId: message.friendlyId,
|
|
1206
|
-
attemptFriendlyId: this.attemptFriendlyId
|
|
1207
|
-
});
|
|
1193
|
+
return await this.#coordinatorSocket.socket.timeout(2e4).emitWithAck("WAIT_FOR_TASK", {
|
|
1194
|
+
version: "v2",
|
|
1195
|
+
friendlyId: message.friendlyId,
|
|
1196
|
+
attemptFriendlyId: this.attemptFriendlyId
|
|
1208
1197
|
});
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
}
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
this.waitForTaskReplay.attempt++;
|
|
1198
|
+
});
|
|
1199
|
+
if (!waitForTask.success) {
|
|
1200
|
+
logger.error("Failed to wait for task with backoff", {
|
|
1201
|
+
cause: waitForTask.cause,
|
|
1202
|
+
error: waitForTask.error
|
|
1203
|
+
});
|
|
1204
|
+
this.#emitUnrecoverableError(
|
|
1205
|
+
"WaitForTaskFailed",
|
|
1206
|
+
`${waitForTask.cause}: ${waitForTask.error}`
|
|
1207
|
+
);
|
|
1208
|
+
return;
|
|
1209
|
+
}
|
|
1210
|
+
const { willCheckpointAndRestore } = waitForTask.result;
|
|
1211
|
+
await this.#prepareForWait("WAIT_FOR_TASK", willCheckpointAndRestore);
|
|
1212
|
+
if (willCheckpointAndRestore) {
|
|
1213
|
+
if (!this.waitForTaskReplay) {
|
|
1214
|
+
this.waitForTaskReplay = {
|
|
1215
|
+
message,
|
|
1216
|
+
attempt: 1,
|
|
1217
|
+
idempotencyKey: randomUUID()
|
|
1218
|
+
};
|
|
1219
|
+
} else {
|
|
1220
|
+
if (replayIdempotencyKey && replayIdempotencyKey !== this.waitForTaskReplay.idempotencyKey) {
|
|
1221
|
+
logger.error(
|
|
1222
|
+
"wait for task handler called with mismatched idempotency key, won't overwrite replay request"
|
|
1223
|
+
);
|
|
1224
|
+
return;
|
|
1237
1225
|
}
|
|
1226
|
+
this.waitForTaskReplay.attempt++;
|
|
1238
1227
|
}
|
|
1239
|
-
}
|
|
1228
|
+
}
|
|
1240
1229
|
}
|
|
1241
1230
|
// MARK: BATCH WAIT
|
|
1242
|
-
#
|
|
1243
|
-
|
|
1244
|
-
logger.log("
|
|
1245
|
-
if (this.
|
|
1246
|
-
logger.error("
|
|
1247
|
-
|
|
1248
|
-
});
|
|
1249
|
-
return;
|
|
1231
|
+
async #waitForBatchHandler(message, replayIdempotencyKey) {
|
|
1232
|
+
const waitForBatch = await defaultBackoff.execute(async ({ retry }) => {
|
|
1233
|
+
logger.log("Wait for batch with backoff", { retry });
|
|
1234
|
+
if (!this.attemptFriendlyId) {
|
|
1235
|
+
logger.error("Failed to send wait message, attempt friendly ID not set", { message });
|
|
1236
|
+
throw new ExponentialBackoff.StopRetrying("No attempt ID");
|
|
1250
1237
|
}
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
}
|
|
1257
|
-
return await this.#coordinatorSocket.socket.timeout(2e4).emitWithAck("WAIT_FOR_BATCH", {
|
|
1258
|
-
version: "v2",
|
|
1259
|
-
batchFriendlyId: message.batchFriendlyId,
|
|
1260
|
-
runFriendlyIds: message.runFriendlyIds,
|
|
1261
|
-
attemptFriendlyId: this.attemptFriendlyId
|
|
1262
|
-
});
|
|
1238
|
+
return await this.#coordinatorSocket.socket.timeout(2e4).emitWithAck("WAIT_FOR_BATCH", {
|
|
1239
|
+
version: "v2",
|
|
1240
|
+
batchFriendlyId: message.batchFriendlyId,
|
|
1241
|
+
runFriendlyIds: message.runFriendlyIds,
|
|
1242
|
+
attemptFriendlyId: this.attemptFriendlyId
|
|
1263
1243
|
});
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
}
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
this.waitForBatchReplay.attempt++;
|
|
1244
|
+
});
|
|
1245
|
+
if (!waitForBatch.success) {
|
|
1246
|
+
logger.error("Failed to wait for batch with backoff", {
|
|
1247
|
+
cause: waitForBatch.cause,
|
|
1248
|
+
error: waitForBatch.error
|
|
1249
|
+
});
|
|
1250
|
+
this.#emitUnrecoverableError(
|
|
1251
|
+
"WaitForBatchFailed",
|
|
1252
|
+
`${waitForBatch.cause}: ${waitForBatch.error}`
|
|
1253
|
+
);
|
|
1254
|
+
return;
|
|
1255
|
+
}
|
|
1256
|
+
const { willCheckpointAndRestore } = waitForBatch.result;
|
|
1257
|
+
await this.#prepareForWait("WAIT_FOR_BATCH", willCheckpointAndRestore);
|
|
1258
|
+
if (willCheckpointAndRestore) {
|
|
1259
|
+
if (!this.waitForBatchReplay) {
|
|
1260
|
+
this.waitForBatchReplay = {
|
|
1261
|
+
message,
|
|
1262
|
+
attempt: 1,
|
|
1263
|
+
idempotencyKey: randomUUID()
|
|
1264
|
+
};
|
|
1265
|
+
} else {
|
|
1266
|
+
if (replayIdempotencyKey && replayIdempotencyKey !== this.waitForBatchReplay.idempotencyKey) {
|
|
1267
|
+
logger.error(
|
|
1268
|
+
"wait for task handler called with mismatched idempotency key, won't overwrite replay request"
|
|
1269
|
+
);
|
|
1270
|
+
return;
|
|
1292
1271
|
}
|
|
1272
|
+
this.waitForBatchReplay.attempt++;
|
|
1293
1273
|
}
|
|
1294
|
-
}
|
|
1274
|
+
}
|
|
1295
1275
|
}
|
|
1296
1276
|
// MARK: WORKER CREATION
|
|
1297
1277
|
#createBackgroundWorker() {
|
|
1298
|
-
const workerId = randomUUID();
|
|
1299
|
-
logger.log("Creating background worker", { workerId });
|
|
1300
1278
|
const backgroundWorker = new ProdBackgroundWorker("worker.js", {
|
|
1301
1279
|
projectConfig: __PROJECT_CONFIG__,
|
|
1302
1280
|
env: {
|
|
@@ -1308,27 +1286,18 @@ var ProdWorker = class {
|
|
|
1308
1286
|
contentHash: this.contentHash
|
|
1309
1287
|
});
|
|
1310
1288
|
backgroundWorker.onTaskHeartbeat.attach((attemptFriendlyId) => {
|
|
1311
|
-
logger.log("onTaskHeartbeat", {
|
|
1312
|
-
workerId,
|
|
1313
|
-
attemptFriendlyId
|
|
1314
|
-
});
|
|
1289
|
+
logger.log("onTaskHeartbeat", { attemptFriendlyId });
|
|
1315
1290
|
this.#coordinatorSocket.socket.volatile.emit("TASK_HEARTBEAT", {
|
|
1316
1291
|
version: "v1",
|
|
1317
1292
|
attemptFriendlyId
|
|
1318
1293
|
});
|
|
1319
1294
|
});
|
|
1320
1295
|
backgroundWorker.onTaskRunHeartbeat.attach((runId) => {
|
|
1321
|
-
logger.log("onTaskRunHeartbeat", {
|
|
1322
|
-
workerId,
|
|
1323
|
-
runId
|
|
1324
|
-
});
|
|
1296
|
+
logger.log("onTaskRunHeartbeat", { runId });
|
|
1325
1297
|
this.#coordinatorSocket.socket.volatile.emit("TASK_RUN_HEARTBEAT", { version: "v1", runId });
|
|
1326
1298
|
});
|
|
1327
1299
|
backgroundWorker.onCreateTaskRunAttempt.attach(async (message) => {
|
|
1328
|
-
logger.log("onCreateTaskRunAttempt()", {
|
|
1329
|
-
workerId,
|
|
1330
|
-
message
|
|
1331
|
-
});
|
|
1300
|
+
logger.log("onCreateTaskRunAttempt()", { message });
|
|
1332
1301
|
const createAttempt = await defaultBackoff.execute(async ({ retry }) => {
|
|
1333
1302
|
logger.log("Create task run attempt with backoff", { retry });
|
|
1334
1303
|
return await this.#coordinatorSocket.socket.timeout(15e3).emitWithAck("CREATE_TASK_RUN_ATTEMPT", {
|
|
@@ -1357,7 +1326,6 @@ var ProdWorker = class {
|
|
|
1357
1326
|
});
|
|
1358
1327
|
backgroundWorker.attemptCreatedNotification.attach((message) => {
|
|
1359
1328
|
logger.log("attemptCreatedNotification", {
|
|
1360
|
-
workerId,
|
|
1361
1329
|
success: message.success,
|
|
1362
1330
|
...message.success ? {
|
|
1363
1331
|
attempt: message.execution.attempt,
|
|
@@ -1372,20 +1340,9 @@ var ProdWorker = class {
|
|
|
1372
1340
|
return;
|
|
1373
1341
|
}
|
|
1374
1342
|
this.attemptFriendlyId = message.execution.attempt.id;
|
|
1375
|
-
this.attemptNumber = message.execution.attempt.number;
|
|
1376
1343
|
});
|
|
1377
1344
|
backgroundWorker.onWaitForDuration.attach(async (message) => {
|
|
1378
|
-
logger.log("onWaitForDuration", {
|
|
1379
|
-
workerId,
|
|
1380
|
-
...message,
|
|
1381
|
-
drift: Date.now() - message.now
|
|
1382
|
-
});
|
|
1383
|
-
if (this.nextResumeAfter) {
|
|
1384
|
-
logger.error("Already waiting for resume, skipping wait for duration", {
|
|
1385
|
-
nextResumeAfter: this.nextResumeAfter
|
|
1386
|
-
});
|
|
1387
|
-
return;
|
|
1388
|
-
}
|
|
1345
|
+
logger.log("onWaitForDuration", { ...message, drift: Date.now() - message.now });
|
|
1389
1346
|
noResume: {
|
|
1390
1347
|
const { ms, waitThresholdInMs } = message;
|
|
1391
1348
|
const internalTimeout = unboundedTimeout(ms, "internal");
|
|
@@ -1423,15 +1380,6 @@ var ProdWorker = class {
|
|
|
1423
1380
|
}
|
|
1424
1381
|
await this.#prepareForWait("WAIT_FOR_DURATION", willCheckpointAndRestore);
|
|
1425
1382
|
await Promise.race([internalTimeout, checkpointSafeInternalTimeout]);
|
|
1426
|
-
const idempotencyKey = randomUUID();
|
|
1427
|
-
this.durationResumeFallback = { idempotencyKey };
|
|
1428
|
-
try {
|
|
1429
|
-
await this.restoreNotification.waitFor(5e3);
|
|
1430
|
-
} catch (error) {
|
|
1431
|
-
logger.error("Did not receive restore notification in time", {
|
|
1432
|
-
error
|
|
1433
|
-
});
|
|
1434
|
-
}
|
|
1435
1383
|
try {
|
|
1436
1384
|
const { checkpointCanceled } = await this.#coordinatorSocket.socket.timeout(15e3).emitWithAck("CANCEL_CHECKPOINT", {
|
|
1437
1385
|
version: "v2",
|
|
@@ -1442,6 +1390,8 @@ var ProdWorker = class {
|
|
|
1442
1390
|
break noResume;
|
|
1443
1391
|
}
|
|
1444
1392
|
logger.log("Waiting for external duration resume as we may have been restored");
|
|
1393
|
+
const idempotencyKey = randomUUID();
|
|
1394
|
+
this.durationResumeFallback = { idempotencyKey };
|
|
1445
1395
|
setTimeout(() => {
|
|
1446
1396
|
if (!this.durationResumeFallback) {
|
|
1447
1397
|
logger.error("Already resumed after duration, skipping fallback");
|
|
@@ -1455,32 +1405,19 @@ var ProdWorker = class {
|
|
|
1455
1405
|
this.#resumeAfterDuration();
|
|
1456
1406
|
}, 15e3);
|
|
1457
1407
|
} catch (error) {
|
|
1458
|
-
logger.debug("Checkpoint cancellation timed out", {
|
|
1459
|
-
|
|
1460
|
-
message,
|
|
1461
|
-
error
|
|
1462
|
-
});
|
|
1408
|
+
logger.debug("Checkpoint cancellation timed out", { error });
|
|
1409
|
+
break noResume;
|
|
1463
1410
|
}
|
|
1464
1411
|
return;
|
|
1465
1412
|
}
|
|
1466
1413
|
this.#resumeAfterDuration();
|
|
1467
1414
|
});
|
|
1468
|
-
backgroundWorker.onWaitForTask.attach(this.#
|
|
1469
|
-
backgroundWorker.onWaitForBatch.attach(this.#
|
|
1415
|
+
backgroundWorker.onWaitForTask.attach(this.#waitForTaskHandler.bind(this));
|
|
1416
|
+
backgroundWorker.onWaitForBatch.attach(this.#waitForBatchHandler.bind(this));
|
|
1470
1417
|
return backgroundWorker;
|
|
1471
1418
|
}
|
|
1472
1419
|
async #prepareForWait(reason, willCheckpointAndRestore) {
|
|
1473
1420
|
logger.log(`prepare for ${reason}`, { willCheckpointAndRestore });
|
|
1474
|
-
if (this.nextResumeAfter) {
|
|
1475
|
-
logger.error("Already waiting for resume, skipping prepare for wait", {
|
|
1476
|
-
nextResumeAfter: this.nextResumeAfter,
|
|
1477
|
-
params: {
|
|
1478
|
-
reason,
|
|
1479
|
-
willCheckpointAndRestore
|
|
1480
|
-
}
|
|
1481
|
-
});
|
|
1482
|
-
return;
|
|
1483
|
-
}
|
|
1484
1421
|
if (!willCheckpointAndRestore) {
|
|
1485
1422
|
return;
|
|
1486
1423
|
}
|
|
@@ -1490,9 +1427,12 @@ var ProdWorker = class {
|
|
|
1490
1427
|
await this.#prepareForCheckpoint();
|
|
1491
1428
|
}
|
|
1492
1429
|
// MARK: RETRY PREP
|
|
1493
|
-
async #prepareForRetry(shouldExit, exitCode) {
|
|
1494
|
-
logger.log("prepare for retry", { shouldExit, exitCode });
|
|
1430
|
+
async #prepareForRetry(willCheckpointAndRestore, shouldExit, exitCode) {
|
|
1431
|
+
logger.log("prepare for retry", { willCheckpointAndRestore, shouldExit, exitCode });
|
|
1495
1432
|
if (shouldExit) {
|
|
1433
|
+
if (willCheckpointAndRestore) {
|
|
1434
|
+
logger.error("WARNING: Will checkpoint but also requested exit. This won't end well.");
|
|
1435
|
+
}
|
|
1496
1436
|
await this.#exitGracefully(false, exitCode);
|
|
1497
1437
|
return;
|
|
1498
1438
|
}
|
|
@@ -1500,7 +1440,11 @@ var ProdWorker = class {
|
|
|
1500
1440
|
this.waitForPostStart = false;
|
|
1501
1441
|
this.executing = false;
|
|
1502
1442
|
this.attemptFriendlyId = void 0;
|
|
1503
|
-
|
|
1443
|
+
if (!willCheckpointAndRestore) {
|
|
1444
|
+
return;
|
|
1445
|
+
}
|
|
1446
|
+
this.waitForPostStart = true;
|
|
1447
|
+
await this.#prepareForCheckpoint(false);
|
|
1504
1448
|
}
|
|
1505
1449
|
// MARK: CHECKPOINT PREP
|
|
1506
1450
|
async #prepareForCheckpoint(flush = true) {
|
|
@@ -1528,7 +1472,6 @@ var ProdWorker = class {
|
|
|
1528
1472
|
this.paused = false;
|
|
1529
1473
|
this.nextResumeAfter = void 0;
|
|
1530
1474
|
this.waitForPostStart = false;
|
|
1531
|
-
this.durationResumeFallback = void 0;
|
|
1532
1475
|
this.#backgroundWorker.waitCompletedNotification();
|
|
1533
1476
|
}
|
|
1534
1477
|
async #readyForLazyAttempt() {
|
|
@@ -1593,7 +1536,7 @@ var ProdWorker = class {
|
|
|
1593
1536
|
const taskRunCompleted = await defaultBackoff.execute(async ({ retry }) => {
|
|
1594
1537
|
logger.log("Submit attempt completion with backoff", { retry });
|
|
1595
1538
|
return await this.#coordinatorSocket.socket.timeout(2e4).emitWithAck("TASK_RUN_COMPLETED", {
|
|
1596
|
-
version: "
|
|
1539
|
+
version: "v1",
|
|
1597
1540
|
execution,
|
|
1598
1541
|
completion
|
|
1599
1542
|
});
|
|
@@ -1609,9 +1552,26 @@ var ProdWorker = class {
|
|
|
1609
1552
|
const { willCheckpointAndRestore, shouldExit } = taskRunCompleted.result;
|
|
1610
1553
|
logger.log("completion acknowledged", { willCheckpointAndRestore, shouldExit });
|
|
1611
1554
|
const exitCode = !completion.ok && completion.error.type === "INTERNAL_ERROR" && completion.error.code === TaskRunErrorCodes2.TASK_PROCESS_EXITED_WITH_NON_ZERO_CODE ? EXIT_CODE_CHILD_NONZERO : 0;
|
|
1612
|
-
await this.#prepareForRetry(shouldExit, exitCode);
|
|
1555
|
+
await this.#prepareForRetry(willCheckpointAndRestore, shouldExit, exitCode);
|
|
1613
1556
|
if (willCheckpointAndRestore) {
|
|
1614
|
-
|
|
1557
|
+
if (!this.submitAttemptCompletionReplay) {
|
|
1558
|
+
this.submitAttemptCompletionReplay = {
|
|
1559
|
+
message: {
|
|
1560
|
+
execution,
|
|
1561
|
+
completion
|
|
1562
|
+
},
|
|
1563
|
+
attempt: 1,
|
|
1564
|
+
idempotencyKey: randomUUID()
|
|
1565
|
+
};
|
|
1566
|
+
} else {
|
|
1567
|
+
if (replayIdempotencyKey && replayIdempotencyKey !== this.submitAttemptCompletionReplay.idempotencyKey) {
|
|
1568
|
+
logger.error(
|
|
1569
|
+
"attempt completion handler called with mismatched idempotency key, won't overwrite replay request"
|
|
1570
|
+
);
|
|
1571
|
+
return;
|
|
1572
|
+
}
|
|
1573
|
+
this.submitAttemptCompletionReplay.attempt++;
|
|
1574
|
+
}
|
|
1615
1575
|
}
|
|
1616
1576
|
}
|
|
1617
1577
|
#returnValidatedExtraHeaders(headers) {
|
|
@@ -1637,9 +1597,6 @@ var ProdWorker = class {
|
|
|
1637
1597
|
if (this.attemptFriendlyId) {
|
|
1638
1598
|
extraHeaders["x-trigger-attempt-friendly-id"] = this.attemptFriendlyId;
|
|
1639
1599
|
}
|
|
1640
|
-
if (this.attemptNumber !== void 0) {
|
|
1641
|
-
extraHeaders["x-trigger-attempt-number"] = String(this.attemptNumber);
|
|
1642
|
-
}
|
|
1643
1600
|
logger.log(`connecting to coordinator: ${host}:${COORDINATOR_PORT}`);
|
|
1644
1601
|
logger.debug(`connecting with extra headers`, { extraHeaders });
|
|
1645
1602
|
const coordinatorConnection = new ZodSocketConnection({
|
|
@@ -1711,13 +1668,31 @@ var ProdWorker = class {
|
|
|
1711
1668
|
});
|
|
1712
1669
|
return;
|
|
1713
1670
|
}
|
|
1671
|
+
this.durationResumeFallback = void 0;
|
|
1714
1672
|
this.#resumeAfterDuration();
|
|
1715
1673
|
},
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
"
|
|
1720
|
-
|
|
1674
|
+
// Deprecated: This will never get called as this worker supports lazy attempts. It's only here for a quick view of the flow old workers use.
|
|
1675
|
+
EXECUTE_TASK_RUN: async ({ executionPayload }) => {
|
|
1676
|
+
if (this.executing) {
|
|
1677
|
+
logger.error("dropping execute request, already executing");
|
|
1678
|
+
return;
|
|
1679
|
+
}
|
|
1680
|
+
if (this.completed.has(executionPayload.execution.attempt.id)) {
|
|
1681
|
+
logger.error("dropping execute request, already completed");
|
|
1682
|
+
return;
|
|
1683
|
+
}
|
|
1684
|
+
this.executing = true;
|
|
1685
|
+
this.attemptFriendlyId = executionPayload.execution.attempt.id;
|
|
1686
|
+
const completion = await this.#backgroundWorker.executeTaskRun(executionPayload);
|
|
1687
|
+
logger.log("completed", completion);
|
|
1688
|
+
this.completed.add(executionPayload.execution.attempt.id);
|
|
1689
|
+
const { willCheckpointAndRestore, shouldExit } = await this.#coordinatorSocket.socket.emitWithAck("TASK_RUN_COMPLETED", {
|
|
1690
|
+
version: "v1",
|
|
1691
|
+
execution: executionPayload.execution,
|
|
1692
|
+
completion
|
|
1693
|
+
});
|
|
1694
|
+
logger.log("completion acknowledged", { willCheckpointAndRestore, shouldExit });
|
|
1695
|
+
await this.#prepareForRetry(willCheckpointAndRestore, shouldExit);
|
|
1721
1696
|
},
|
|
1722
1697
|
EXECUTE_TASK_RUN_LAZY_ATTEMPT: async (message) => {
|
|
1723
1698
|
this.readyForLazyAttemptReplay = void 0;
|
|
@@ -1765,6 +1740,7 @@ var ProdWorker = class {
|
|
|
1765
1740
|
logger.error("Received READY_FOR_RETRY but no completions yet. This is a bug.");
|
|
1766
1741
|
return;
|
|
1767
1742
|
}
|
|
1743
|
+
this.submitAttemptCompletionReplay = void 0;
|
|
1768
1744
|
await this.#readyForLazyAttempt();
|
|
1769
1745
|
}
|
|
1770
1746
|
},
|
|
@@ -1774,11 +1750,7 @@ var ProdWorker = class {
|
|
|
1774
1750
|
status: this.#status,
|
|
1775
1751
|
connectionCount: ++this.connectionCount
|
|
1776
1752
|
});
|
|
1777
|
-
socket.emit("SET_STATE", {
|
|
1778
|
-
version: "v1",
|
|
1779
|
-
attemptFriendlyId: this.attemptFriendlyId,
|
|
1780
|
-
attemptNumber: this.attemptNumber ? String(this.attemptNumber) : void 0
|
|
1781
|
-
});
|
|
1753
|
+
socket.emit("SET_STATE", { version: "v1", attemptFriendlyId: this.attemptFriendlyId });
|
|
1782
1754
|
try {
|
|
1783
1755
|
if (this.waitForPostStart) {
|
|
1784
1756
|
logger2.log("skip connection handler, waiting for post start hook");
|
|
@@ -1794,25 +1766,16 @@ var ProdWorker = class {
|
|
|
1794
1766
|
return;
|
|
1795
1767
|
}
|
|
1796
1768
|
if (!this.attemptFriendlyId) {
|
|
1797
|
-
logger2.error("Missing
|
|
1769
|
+
logger2.error("Missing friendly ID", { status: this.#status });
|
|
1798
1770
|
this.#emitUnrecoverableError(
|
|
1799
1771
|
"NoAttemptId",
|
|
1800
1772
|
"Attempt ID not set while resuming from paused state"
|
|
1801
1773
|
);
|
|
1802
1774
|
return;
|
|
1803
1775
|
}
|
|
1804
|
-
if (!this.attemptNumber) {
|
|
1805
|
-
logger2.error("Missing attempt number", { status: this.#status });
|
|
1806
|
-
this.#emitUnrecoverableError(
|
|
1807
|
-
"NoAttemptNumber",
|
|
1808
|
-
"Attempt number not set while resuming from paused state"
|
|
1809
|
-
);
|
|
1810
|
-
return;
|
|
1811
|
-
}
|
|
1812
1776
|
socket.emit("READY_FOR_RESUME", {
|
|
1813
|
-
version: "
|
|
1777
|
+
version: "v1",
|
|
1814
1778
|
attemptFriendlyId: this.attemptFriendlyId,
|
|
1815
|
-
attemptNumber: this.attemptNumber,
|
|
1816
1779
|
type: this.nextResumeAfter
|
|
1817
1780
|
});
|
|
1818
1781
|
return;
|
|
@@ -1949,7 +1912,7 @@ var ProdWorker = class {
|
|
|
1949
1912
|
}
|
|
1950
1913
|
try {
|
|
1951
1914
|
await backoff.wait(attempt + 1);
|
|
1952
|
-
await this.#
|
|
1915
|
+
await this.#waitForTaskHandler(message);
|
|
1953
1916
|
} catch (error) {
|
|
1954
1917
|
if (error instanceof ExponentialBackoff.RetryLimitExceeded) {
|
|
1955
1918
|
logger.error("wait for task replay retry limit exceeded", { error });
|
|
@@ -1981,7 +1944,7 @@ var ProdWorker = class {
|
|
|
1981
1944
|
}
|
|
1982
1945
|
try {
|
|
1983
1946
|
await backoff.wait(attempt + 1);
|
|
1984
|
-
await this.#
|
|
1947
|
+
await this.#waitForBatchHandler(message);
|
|
1985
1948
|
} catch (error) {
|
|
1986
1949
|
if (error instanceof ExponentialBackoff.RetryLimitExceeded) {
|
|
1987
1950
|
logger.error("wait for batch replay retry limit exceeded", { error });
|
|
@@ -1991,6 +1954,38 @@ var ProdWorker = class {
|
|
|
1991
1954
|
}
|
|
1992
1955
|
return;
|
|
1993
1956
|
}
|
|
1957
|
+
if (this.submitAttemptCompletionReplay) {
|
|
1958
|
+
logger.log("replaying attempt completion", {
|
|
1959
|
+
...this.submitAttemptCompletionReplay,
|
|
1960
|
+
cancellationDelay: replayCancellationDelay
|
|
1961
|
+
});
|
|
1962
|
+
const { idempotencyKey, message, attempt } = this.submitAttemptCompletionReplay;
|
|
1963
|
+
await timeout2(replayCancellationDelay);
|
|
1964
|
+
if (!this.submitAttemptCompletionReplay) {
|
|
1965
|
+
logger.error("attempt completion replay cancelled, discarding", {
|
|
1966
|
+
originalMessage: { idempotencyKey, message, attempt }
|
|
1967
|
+
});
|
|
1968
|
+
return;
|
|
1969
|
+
}
|
|
1970
|
+
if (idempotencyKey !== this.submitAttemptCompletionReplay.idempotencyKey) {
|
|
1971
|
+
logger.error("attempt completion replay idempotency key mismatch, discarding", {
|
|
1972
|
+
originalMessage: { idempotencyKey, message, attempt },
|
|
1973
|
+
newMessage: this.submitAttemptCompletionReplay
|
|
1974
|
+
});
|
|
1975
|
+
return;
|
|
1976
|
+
}
|
|
1977
|
+
try {
|
|
1978
|
+
await backoff.wait(attempt + 1);
|
|
1979
|
+
await this.#submitAttemptCompletion(message.execution, message.completion, idempotencyKey);
|
|
1980
|
+
} catch (error) {
|
|
1981
|
+
if (error instanceof ExponentialBackoff.RetryLimitExceeded) {
|
|
1982
|
+
logger.error("attempt completion replay retry limit exceeded", { error });
|
|
1983
|
+
} else {
|
|
1984
|
+
logger.error("attempt completion replay error", { error });
|
|
1985
|
+
}
|
|
1986
|
+
}
|
|
1987
|
+
return;
|
|
1988
|
+
}
|
|
1994
1989
|
}
|
|
1995
1990
|
// MARK: HTTP SERVER
|
|
1996
1991
|
#createHttpServer() {
|
|
@@ -2053,7 +2048,6 @@ var ProdWorker = class {
|
|
|
2053
2048
|
}
|
|
2054
2049
|
case "restore": {
|
|
2055
2050
|
await this.#reconnectAfterPostStart();
|
|
2056
|
-
this.restoreNotification.post();
|
|
2057
2051
|
break;
|
|
2058
2052
|
}
|
|
2059
2053
|
default: {
|
|
@@ -2134,7 +2128,6 @@ var ProdWorker = class {
|
|
|
2134
2128
|
nextResumeAfter: this.nextResumeAfter,
|
|
2135
2129
|
waitForPostStart: this.waitForPostStart,
|
|
2136
2130
|
attemptFriendlyId: this.attemptFriendlyId,
|
|
2137
|
-
attemptNumber: this.attemptNumber,
|
|
2138
2131
|
waitForTaskReplay: this.waitForTaskReplay,
|
|
2139
2132
|
waitForBatchReplay: this.waitForBatchReplay
|
|
2140
2133
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "trigger.dev",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.54",
|
|
4
4
|
"description": "A Command-Line Interface for Trigger.dev (v3) projects",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -53,8 +53,8 @@
|
|
|
53
53
|
"typescript": "^5.3.3",
|
|
54
54
|
"vitest": "^1.6.0",
|
|
55
55
|
"xdg-app-paths": "^8.3.0",
|
|
56
|
-
"@trigger.dev/
|
|
57
|
-
"@trigger.dev/
|
|
56
|
+
"@trigger.dev/tsconfig": "0.0.0",
|
|
57
|
+
"@trigger.dev/core-apps": "3.0.0-beta.54"
|
|
58
58
|
},
|
|
59
59
|
"dependencies": {
|
|
60
60
|
"@anatine/esbuild-decorators": "^0.2.19",
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
"@opentelemetry/sdk-trace-base": "^1.22.0",
|
|
73
73
|
"@opentelemetry/sdk-trace-node": "^1.22.0",
|
|
74
74
|
"@opentelemetry/semantic-conventions": "^1.22.0",
|
|
75
|
-
"@trigger.dev/core": "3.0.0-beta.
|
|
75
|
+
"@trigger.dev/core": "3.0.0-beta.54",
|
|
76
76
|
"@types/degit": "^2.8.3",
|
|
77
77
|
"chalk": "^5.2.0",
|
|
78
78
|
"chokidar": "^3.5.3",
|