trigger.dev 0.0.0-v3-prerelease-20250108142426 → 0.0.0-v4-prerelease-20250916125920
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.
- package/README.md +28 -1
- package/dist/esm/apiClient.d.ts +158 -74
- package/dist/esm/apiClient.js +341 -76
- package/dist/esm/apiClient.js.map +1 -1
- package/dist/esm/build/buildWorker.d.ts +10 -6
- package/dist/esm/build/buildWorker.js +22 -38
- package/dist/esm/build/buildWorker.js.map +1 -1
- package/dist/esm/build/bundle.d.ts +18 -1
- package/dist/esm/build/bundle.js +142 -52
- package/dist/esm/build/bundle.js.map +1 -1
- package/dist/esm/build/entryPoints.d.ts +12 -0
- package/dist/esm/build/entryPoints.js +127 -0
- package/dist/esm/build/entryPoints.js.map +1 -0
- package/dist/esm/build/extensions.js +17 -0
- package/dist/esm/build/extensions.js.map +1 -1
- package/dist/esm/build/externals.js +184 -2
- package/dist/esm/build/externals.js.map +1 -1
- package/dist/esm/build/packageModules.d.ts +15 -5
- package/dist/esm/build/packageModules.js +154 -36
- package/dist/esm/build/packageModules.js.map +1 -1
- package/dist/esm/cli/common.d.ts +1 -1
- package/dist/esm/cli/common.js +38 -45
- package/dist/esm/cli/common.js.map +1 -1
- package/dist/esm/cli/index.js +19 -3
- package/dist/esm/cli/index.js.map +1 -1
- package/dist/esm/commands/analyze.d.ts +23 -0
- package/dist/esm/commands/analyze.js +122 -0
- package/dist/esm/commands/analyze.js.map +1 -0
- package/dist/esm/commands/deploy.d.ts +5 -2
- package/dist/esm/commands/deploy.js +271 -160
- package/dist/esm/commands/deploy.js.map +1 -1
- package/dist/esm/commands/dev.d.ts +36 -6
- package/dist/esm/commands/dev.js +71 -2
- package/dist/esm/commands/dev.js.map +1 -1
- package/dist/esm/commands/env.d.ts +2 -0
- package/dist/esm/commands/env.js +298 -0
- package/dist/esm/commands/env.js.map +1 -0
- package/dist/esm/commands/init.d.ts +9 -1
- package/dist/esm/commands/init.js +132 -65
- package/dist/esm/commands/init.js.map +1 -1
- package/dist/esm/commands/install-mcp.d.ts +50 -0
- package/dist/esm/commands/install-mcp.js +497 -0
- package/dist/esm/commands/install-mcp.js.map +1 -0
- package/dist/esm/commands/install-rules.d.ts +11 -0
- package/dist/esm/commands/install-rules.js +381 -0
- package/dist/esm/commands/install-rules.js.map +1 -0
- package/dist/esm/commands/list-profiles.d.ts +3 -7
- package/dist/esm/commands/list-profiles.js +7 -4
- package/dist/esm/commands/list-profiles.js.map +1 -1
- package/dist/esm/commands/login.d.ts +9 -5
- package/dist/esm/commands/login.js +40 -7
- package/dist/esm/commands/login.js.map +1 -1
- package/dist/esm/commands/logout.d.ts +1 -1
- package/dist/esm/commands/mcp.d.ts +38 -0
- package/dist/esm/commands/mcp.js +82 -0
- package/dist/esm/commands/mcp.js.map +1 -0
- package/dist/esm/commands/preview.d.ts +5 -0
- package/dist/esm/commands/preview.js +93 -0
- package/dist/esm/commands/preview.js.map +1 -0
- package/dist/esm/commands/promote.d.ts +3 -0
- package/dist/esm/commands/promote.js +86 -0
- package/dist/esm/commands/promote.js.map +1 -0
- package/dist/esm/commands/switch.d.ts +19 -0
- package/dist/esm/commands/switch.js +93 -0
- package/dist/esm/commands/switch.js.map +1 -0
- package/dist/esm/commands/trigger.d.ts +33 -0
- package/dist/esm/commands/trigger.js +88 -0
- package/dist/esm/commands/trigger.js.map +1 -0
- package/dist/esm/commands/update.d.ts +3 -2
- package/dist/esm/commands/update.js +23 -9
- package/dist/esm/commands/update.js.map +1 -1
- package/dist/esm/commands/whoami.d.ts +12 -1
- package/dist/esm/commands/whoami.js +36 -6
- package/dist/esm/commands/whoami.js.map +1 -1
- package/dist/esm/commands/workers/build.d.ts +4 -0
- package/dist/esm/commands/workers/build.js +345 -0
- package/dist/esm/commands/workers/build.js.map +1 -0
- package/dist/esm/commands/workers/create.d.ts +2 -0
- package/dist/esm/commands/workers/create.js +91 -0
- package/dist/esm/commands/workers/create.js.map +1 -0
- package/dist/esm/commands/workers/index.d.ts +2 -0
- package/dist/esm/commands/workers/index.js +13 -0
- package/dist/esm/commands/workers/index.js.map +1 -0
- package/dist/esm/commands/workers/list.d.ts +2 -0
- package/dist/esm/commands/workers/list.js +80 -0
- package/dist/esm/commands/workers/list.js.map +1 -0
- package/dist/esm/commands/workers/run.d.ts +2 -0
- package/dist/esm/commands/workers/run.js +105 -0
- package/dist/esm/commands/workers/run.js.map +1 -0
- package/dist/esm/config.d.ts +2 -1
- package/dist/esm/config.js +35 -8
- package/dist/esm/config.js.map +1 -1
- package/dist/esm/deploy/buildImage.d.ts +12 -11
- package/dist/esm/deploy/buildImage.js +360 -115
- package/dist/esm/deploy/buildImage.js.map +1 -1
- package/dist/esm/dev/backgroundWorker.d.ts +6 -245
- package/dist/esm/dev/backgroundWorker.js +11 -320
- package/dist/esm/dev/backgroundWorker.js.map +1 -1
- package/dist/esm/dev/devOutput.js +48 -9
- package/dist/esm/dev/devOutput.js.map +1 -1
- package/dist/esm/dev/devSession.d.ts +2 -1
- package/dist/esm/dev/devSession.js +68 -65
- package/dist/esm/dev/devSession.js.map +1 -1
- package/dist/esm/dev/devSupervisor.d.ts +12 -0
- package/dist/esm/dev/devSupervisor.js +568 -0
- package/dist/esm/dev/devSupervisor.js.map +1 -0
- package/dist/esm/dev/lock.d.ts +1 -0
- package/dist/esm/dev/lock.js +80 -0
- package/dist/esm/dev/lock.js.map +1 -0
- package/dist/esm/dev/mcpServer.d.ts +10 -0
- package/dist/esm/dev/mcpServer.js +201 -0
- package/dist/esm/dev/mcpServer.js.map +1 -0
- package/dist/esm/dev/taskRunProcessPool.d.ts +39 -0
- package/dist/esm/dev/taskRunProcessPool.js +220 -0
- package/dist/esm/dev/taskRunProcessPool.js.map +1 -0
- package/dist/esm/dev/workerRuntime.d.ts +2 -2
- package/dist/esm/dev/workerRuntime.js +1 -265
- package/dist/esm/dev/workerRuntime.js.map +1 -1
- package/dist/esm/entryPoints/dev-index-worker.js +45 -8
- package/dist/esm/entryPoints/dev-index-worker.js.map +1 -1
- package/dist/esm/entryPoints/dev-run-controller.d.ts +58 -0
- package/dist/esm/entryPoints/dev-run-controller.js +652 -0
- package/dist/esm/entryPoints/dev-run-controller.js.map +1 -0
- package/dist/esm/entryPoints/dev-run-worker.js +394 -199
- package/dist/esm/entryPoints/dev-run-worker.js.map +1 -1
- package/dist/esm/entryPoints/managed/controller.d.ts +63 -0
- package/dist/esm/entryPoints/managed/controller.js +482 -0
- package/dist/esm/entryPoints/managed/controller.js.map +1 -0
- package/dist/esm/entryPoints/managed/env.d.ts +170 -0
- package/dist/esm/entryPoints/managed/env.js +199 -0
- package/dist/esm/entryPoints/managed/env.js.map +1 -0
- package/dist/esm/entryPoints/managed/execution.d.ts +141 -0
- package/dist/esm/entryPoints/managed/execution.js +869 -0
- package/dist/esm/entryPoints/managed/execution.js.map +1 -0
- package/dist/esm/entryPoints/managed/logger.d.ts +30 -0
- package/dist/esm/entryPoints/managed/logger.js +47 -0
- package/dist/esm/entryPoints/managed/logger.js.map +1 -0
- package/dist/esm/entryPoints/managed/notifier.d.ts +30 -0
- package/dist/esm/entryPoints/managed/notifier.js +63 -0
- package/dist/esm/entryPoints/managed/notifier.js.map +1 -0
- package/dist/esm/entryPoints/managed/overrides.d.ts +18 -0
- package/dist/esm/entryPoints/managed/overrides.js +19 -0
- package/dist/esm/entryPoints/managed/overrides.js.map +1 -0
- package/dist/esm/entryPoints/managed/poller.d.ts +31 -0
- package/dist/esm/entryPoints/managed/poller.js +89 -0
- package/dist/esm/entryPoints/managed/poller.js.map +1 -0
- package/dist/esm/entryPoints/managed/snapshot.d.ts +54 -0
- package/dist/esm/entryPoints/managed/snapshot.js +293 -0
- package/dist/esm/entryPoints/managed/snapshot.js.map +1 -0
- package/dist/esm/entryPoints/managed/taskRunProcessProvider.d.ts +62 -0
- package/dist/esm/entryPoints/managed/taskRunProcessProvider.js +252 -0
- package/dist/esm/entryPoints/managed/taskRunProcessProvider.js.map +1 -0
- package/dist/esm/entryPoints/{deploy-index-controller.js → managed-index-controller.js} +27 -3
- package/dist/esm/entryPoints/managed-index-controller.js.map +1 -0
- package/dist/esm/entryPoints/{deploy-index-worker.js → managed-index-worker.js} +50 -21
- package/dist/esm/entryPoints/managed-index-worker.js.map +1 -0
- package/dist/esm/entryPoints/managed-run-controller.js +13 -0
- package/dist/esm/entryPoints/managed-run-controller.js.map +1 -0
- package/dist/esm/entryPoints/managed-run-worker.js +512 -0
- package/dist/esm/entryPoints/managed-run-worker.js.map +1 -0
- package/dist/esm/executions/taskRunProcess.d.ts +28 -82
- package/dist/esm/executions/taskRunProcess.js +130 -74
- package/dist/esm/executions/taskRunProcess.js.map +1 -1
- package/dist/esm/indexing/indexWorkerManifest.d.ts +21 -5
- package/dist/esm/indexing/indexWorkerManifest.js +4 -4
- package/dist/esm/indexing/indexWorkerManifest.js.map +1 -1
- package/dist/esm/indexing/registerResources.d.ts +5 -0
- package/dist/esm/indexing/registerResources.js +44 -0
- package/dist/esm/indexing/registerResources.js.map +1 -0
- package/dist/esm/mcp/auth.d.ts +12 -0
- package/dist/esm/mcp/auth.js +152 -0
- package/dist/esm/mcp/auth.js.map +1 -0
- package/dist/esm/mcp/capabilities.d.ts +4 -0
- package/dist/esm/mcp/capabilities.js +22 -0
- package/dist/esm/mcp/capabilities.js.map +1 -0
- package/dist/esm/mcp/config.d.ts +82 -0
- package/dist/esm/mcp/config.js +87 -0
- package/dist/esm/mcp/config.js.map +1 -0
- package/dist/esm/mcp/context.d.ts +45 -0
- package/dist/esm/mcp/context.js +129 -0
- package/dist/esm/mcp/context.js.map +1 -0
- package/dist/esm/mcp/formatters.d.ts +7 -0
- package/dist/esm/mcp/formatters.js +330 -0
- package/dist/esm/mcp/formatters.js.map +1 -0
- package/dist/esm/mcp/logger.d.ts +11 -0
- package/dist/esm/mcp/logger.js +34 -0
- package/dist/esm/mcp/logger.js.map +1 -0
- package/dist/esm/mcp/mintlifyClient.d.ts +1 -0
- package/dist/esm/mcp/mintlifyClient.js +65 -0
- package/dist/esm/mcp/mintlifyClient.js.map +1 -0
- package/dist/esm/mcp/schemas.d.ts +324 -0
- package/dist/esm/mcp/schemas.js +144 -0
- package/dist/esm/mcp/schemas.js.map +1 -0
- package/dist/esm/mcp/tools/deploys.d.ts +174 -0
- package/dist/esm/mcp/tools/deploys.js +161 -0
- package/dist/esm/mcp/tools/deploys.js.map +1 -0
- package/dist/esm/mcp/tools/docs.d.ts +77 -0
- package/dist/esm/mcp/tools/docs.js +18 -0
- package/dist/esm/mcp/tools/docs.js.map +1 -0
- package/dist/esm/mcp/tools/orgs.d.ts +172 -0
- package/dist/esm/mcp/tools/orgs.js +172 -0
- package/dist/esm/mcp/tools/orgs.js.map +1 -0
- package/dist/esm/mcp/tools/previewBranches.d.ts +78 -0
- package/dist/esm/mcp/tools/previewBranches.js +28 -0
- package/dist/esm/mcp/tools/previewBranches.js.map +1 -0
- package/dist/esm/mcp/tools/runs.d.ts +335 -0
- package/dist/esm/mcp/tools/runs.js +160 -0
- package/dist/esm/mcp/tools/runs.js.map +1 -0
- package/dist/esm/mcp/tools/tasks.d.ts +200 -0
- package/dist/esm/mcp/tools/tasks.js +117 -0
- package/dist/esm/mcp/tools/tasks.js.map +1 -0
- package/dist/esm/mcp/tools.d.ts +2 -0
- package/dist/esm/mcp/tools.js +40 -0
- package/dist/esm/mcp/tools.js.map +1 -0
- package/dist/esm/mcp/types.d.ts +6 -0
- package/dist/esm/mcp/types.js +2 -0
- package/dist/esm/mcp/types.js.map +1 -0
- package/dist/esm/mcp/utils.d.ts +89 -0
- package/dist/esm/mcp/utils.js +95 -0
- package/dist/esm/mcp/utils.js.map +1 -0
- package/dist/esm/rules/install.d.ts +1 -0
- package/dist/esm/rules/install.js +2 -0
- package/dist/esm/rules/install.js.map +1 -0
- package/dist/esm/rules/manifest.d.ts +145 -0
- package/dist/esm/rules/manifest.js +110 -0
- package/dist/esm/rules/manifest.js.map +1 -0
- package/dist/esm/rules/types.d.ts +3 -0
- package/dist/esm/rules/types.js +3 -0
- package/dist/esm/rules/types.js.map +1 -0
- package/dist/esm/utilities/accessTokens.d.ts +12 -0
- package/dist/esm/utilities/accessTokens.js +30 -0
- package/dist/esm/utilities/accessTokens.js.map +1 -0
- package/dist/esm/utilities/analyze.d.ts +13 -0
- package/dist/esm/utilities/analyze.js +463 -0
- package/dist/esm/utilities/analyze.js.map +1 -0
- package/dist/esm/utilities/cliOutput.d.ts +6 -1
- package/dist/esm/utilities/cliOutput.js +11 -2
- package/dist/esm/utilities/cliOutput.js.map +1 -1
- package/dist/esm/utilities/configFiles.d.ts +65 -15
- package/dist/esm/utilities/configFiles.js +124 -26
- package/dist/esm/utilities/configFiles.js.map +1 -1
- package/dist/esm/utilities/eventBus.d.ts +7 -3
- package/dist/esm/utilities/eventBus.js.map +1 -1
- package/dist/esm/utilities/fileSystem.d.ts +7 -1
- package/dist/esm/utilities/fileSystem.js +42 -4
- package/dist/esm/utilities/fileSystem.js.map +1 -1
- package/dist/esm/utilities/gitMeta.d.ts +2 -0
- package/dist/esm/utilities/gitMeta.js +220 -0
- package/dist/esm/utilities/gitMeta.js.map +1 -0
- package/dist/esm/utilities/githubActions.d.ts +4 -0
- package/dist/esm/utilities/githubActions.js +18 -0
- package/dist/esm/utilities/githubActions.js.map +1 -0
- package/dist/esm/utilities/initialBanner.js +18 -6
- package/dist/esm/utilities/initialBanner.js.map +1 -1
- package/dist/esm/utilities/localEnvVars.d.ts +3 -0
- package/dist/esm/utilities/localEnvVars.js +19 -0
- package/dist/esm/utilities/localEnvVars.js.map +1 -0
- package/dist/esm/utilities/sanitizeEnvVars.d.ts +16 -3
- package/dist/esm/utilities/sanitizeEnvVars.js +15 -0
- package/dist/esm/utilities/sanitizeEnvVars.js.map +1 -1
- package/dist/esm/utilities/session.d.ts +14 -0
- package/dist/esm/utilities/session.js +44 -47
- package/dist/esm/utilities/session.js.map +1 -1
- package/dist/esm/utilities/supportsHyperlinks.d.ts +15 -0
- package/dist/esm/utilities/supportsHyperlinks.js +122 -0
- package/dist/esm/utilities/supportsHyperlinks.js.map +1 -0
- package/dist/esm/utilities/tempDirectories.d.ts +1 -0
- package/dist/esm/utilities/tempDirectories.js +19 -2
- package/dist/esm/utilities/tempDirectories.js.map +1 -1
- package/dist/esm/utilities/terminalLink.d.ts +56 -0
- package/dist/esm/utilities/terminalLink.js +76 -0
- package/dist/esm/utilities/terminalLink.js.map +1 -0
- package/dist/esm/utilities/windows.js +51 -1
- package/dist/esm/utilities/windows.js.map +1 -1
- package/dist/esm/version.js +1 -1
- package/package.json +44 -25
- package/dist/esm/entryPoints/deploy-index-controller.js.map +0 -1
- package/dist/esm/entryPoints/deploy-index-worker.js.map +0 -1
- package/dist/esm/entryPoints/deploy-run-controller.js +0 -1099
- package/dist/esm/entryPoints/deploy-run-controller.js.map +0 -1
- package/dist/esm/entryPoints/deploy-run-worker.js +0 -366
- package/dist/esm/entryPoints/deploy-run-worker.js.map +0 -1
- package/dist/esm/indexing/registerTasks.d.ts +0 -2
- package/dist/esm/indexing/registerTasks.js +0 -62
- package/dist/esm/indexing/registerTasks.js.map +0 -1
- package/dist/esm/telemetry/tracing.d.ts +0 -3
- package/dist/esm/telemetry/tracing.js +0 -58
- package/dist/esm/telemetry/tracing.js.map +0 -1
- /package/dist/esm/entryPoints/{deploy-index-controller.d.ts → managed-index-controller.d.ts} +0 -0
- /package/dist/esm/entryPoints/{deploy-index-worker.d.ts → managed-index-worker.d.ts} +0 -0
- /package/dist/esm/entryPoints/{deploy-run-controller.d.ts → managed-run-controller.d.ts} +0 -0
- /package/dist/esm/entryPoints/{deploy-run-worker.d.ts → managed-run-worker.d.ts} +0 -0
|
@@ -0,0 +1,652 @@
|
|
|
1
|
+
import { IntervalService, SuspendedProcessError, } from "@trigger.dev/core/v3";
|
|
2
|
+
import { setTimeout as sleep } from "timers/promises";
|
|
3
|
+
import { TaskRunProcess } from "../executions/taskRunProcess.js";
|
|
4
|
+
import { assertExhaustive } from "../utilities/assertExhaustive.js";
|
|
5
|
+
import { logger } from "../utilities/logger.js";
|
|
6
|
+
import { sanitizeEnvVars } from "../utilities/sanitizeEnvVars.js";
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
import { eventBus } from "../utilities/eventBus.js";
|
|
9
|
+
export class DevRunController {
|
|
10
|
+
opts;
|
|
11
|
+
taskRunProcess;
|
|
12
|
+
worker;
|
|
13
|
+
httpClient;
|
|
14
|
+
snapshotPoller;
|
|
15
|
+
snapshotPollIntervalSeconds;
|
|
16
|
+
cwd;
|
|
17
|
+
isCompletingRun = false;
|
|
18
|
+
isShuttingDown = false;
|
|
19
|
+
state = { phase: "IDLE" };
|
|
20
|
+
enterRunPhase(run, snapshot) {
|
|
21
|
+
this.onExitRunPhase(run);
|
|
22
|
+
this.state = { phase: "RUN", run, snapshot };
|
|
23
|
+
this.snapshotPoller.start();
|
|
24
|
+
}
|
|
25
|
+
constructor(opts) {
|
|
26
|
+
this.opts = opts;
|
|
27
|
+
logger.debug("[DevRunController] Creating controller", {
|
|
28
|
+
run: opts.runFriendlyId,
|
|
29
|
+
});
|
|
30
|
+
this.worker = opts.worker;
|
|
31
|
+
this.snapshotPollIntervalSeconds = 5;
|
|
32
|
+
this.cwd = opts.cwd;
|
|
33
|
+
this.httpClient = opts.httpClient;
|
|
34
|
+
this.snapshotPoller = new IntervalService({
|
|
35
|
+
onInterval: async () => {
|
|
36
|
+
if (!this.runFriendlyId) {
|
|
37
|
+
logger.debug("[DevRunController] Skipping snapshot poll, no run ID");
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
logger.debug("[DevRunController] Polling for latest snapshot");
|
|
41
|
+
this.httpClient.dev.sendDebugLog(this.runFriendlyId, {
|
|
42
|
+
time: new Date(),
|
|
43
|
+
message: `snapshot poll: started`,
|
|
44
|
+
properties: {
|
|
45
|
+
snapshotId: this.snapshotFriendlyId,
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
const response = await this.httpClient.dev.getRunExecutionData(this.runFriendlyId);
|
|
49
|
+
if (!response.success) {
|
|
50
|
+
logger.debug("[DevRunController] Snapshot poll failed", { error: response.error });
|
|
51
|
+
this.httpClient.dev.sendDebugLog(this.runFriendlyId, {
|
|
52
|
+
time: new Date(),
|
|
53
|
+
message: `snapshot poll: failed`,
|
|
54
|
+
properties: {
|
|
55
|
+
snapshotId: this.snapshotFriendlyId,
|
|
56
|
+
error: response.error,
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
await this.handleSnapshotChange(response.data.execution);
|
|
62
|
+
},
|
|
63
|
+
intervalMs: this.snapshotPollIntervalSeconds * 1000,
|
|
64
|
+
leadingEdge: false,
|
|
65
|
+
onError: async (error) => {
|
|
66
|
+
logger.debug("[DevRunController] Failed to poll for snapshot", { error });
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
process.on("SIGTERM", this.sigterm.bind(this));
|
|
70
|
+
}
|
|
71
|
+
async sigterm() {
|
|
72
|
+
logger.debug("[DevRunController] Received SIGTERM, stopping worker");
|
|
73
|
+
await this.stop();
|
|
74
|
+
}
|
|
75
|
+
// This should only be used when we're already executing a run. Attempt number changes are not allowed.
|
|
76
|
+
updateRunPhase(run, snapshot) {
|
|
77
|
+
if (this.state.phase !== "RUN") {
|
|
78
|
+
this.httpClient.dev.sendDebugLog(run.friendlyId, {
|
|
79
|
+
time: new Date(),
|
|
80
|
+
message: `updateRunPhase: Invalid phase for updating snapshot: ${this.state.phase}`,
|
|
81
|
+
properties: {
|
|
82
|
+
currentPhase: this.state.phase,
|
|
83
|
+
snapshotId: snapshot.friendlyId,
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
throw new Error(`Invalid phase for updating snapshot: ${this.state.phase}`);
|
|
87
|
+
}
|
|
88
|
+
if (this.state.run.friendlyId !== run.friendlyId) {
|
|
89
|
+
this.httpClient.dev.sendDebugLog(run.friendlyId, {
|
|
90
|
+
time: new Date(),
|
|
91
|
+
message: `updateRunPhase: Mismatched run IDs`,
|
|
92
|
+
properties: {
|
|
93
|
+
currentRunId: this.state.run.friendlyId,
|
|
94
|
+
newRunId: run.friendlyId,
|
|
95
|
+
currentSnapshotId: this.state.snapshot.friendlyId,
|
|
96
|
+
newSnapshotId: snapshot.friendlyId,
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
|
+
throw new Error("Mismatched run IDs");
|
|
100
|
+
}
|
|
101
|
+
if (this.state.snapshot.friendlyId === snapshot.friendlyId) {
|
|
102
|
+
logger.debug("updateRunPhase: Snapshot not changed", { run, snapshot });
|
|
103
|
+
this.httpClient.dev.sendDebugLog(run.friendlyId, {
|
|
104
|
+
time: new Date(),
|
|
105
|
+
message: `updateRunPhase: Snapshot not changed`,
|
|
106
|
+
properties: {
|
|
107
|
+
snapshotId: snapshot.friendlyId,
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
if (this.state.run.attemptNumber !== run.attemptNumber) {
|
|
113
|
+
this.httpClient.dev.sendDebugLog(run.friendlyId, {
|
|
114
|
+
time: new Date(),
|
|
115
|
+
message: `updateRunPhase: Attempt number changed`,
|
|
116
|
+
properties: {
|
|
117
|
+
oldAttemptNumber: this.state.run.attemptNumber ?? undefined,
|
|
118
|
+
newAttemptNumber: run.attemptNumber ?? undefined,
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
throw new Error("Attempt number changed");
|
|
122
|
+
}
|
|
123
|
+
this.state = {
|
|
124
|
+
phase: "RUN",
|
|
125
|
+
run: {
|
|
126
|
+
friendlyId: run.friendlyId,
|
|
127
|
+
attemptNumber: run.attemptNumber,
|
|
128
|
+
},
|
|
129
|
+
snapshot: {
|
|
130
|
+
friendlyId: snapshot.friendlyId,
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
onExitRunPhase(newRun = undefined) {
|
|
135
|
+
// We're not in a run phase, nothing to do
|
|
136
|
+
if (this.state.phase !== "RUN") {
|
|
137
|
+
logger.debug("onExitRunPhase: Not in run phase, skipping", { phase: this.state.phase });
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
// This is still the same run, so we're not exiting the phase
|
|
141
|
+
if (newRun?.friendlyId === this.state.run.friendlyId) {
|
|
142
|
+
logger.debug("onExitRunPhase: Same run, skipping", { newRun });
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
logger.debug("onExitRunPhase: Exiting run phase", { newRun });
|
|
146
|
+
this.snapshotPoller.stop();
|
|
147
|
+
const { run, snapshot } = this.state;
|
|
148
|
+
this.unsubscribeFromRunNotifications({ run, snapshot });
|
|
149
|
+
}
|
|
150
|
+
subscribeToRunNotifications({ run, snapshot }) {
|
|
151
|
+
logger.debug("[DevRunController] Subscribing to run notifications", { run, snapshot });
|
|
152
|
+
this.opts.onSubscribeToRunNotifications(run, snapshot);
|
|
153
|
+
}
|
|
154
|
+
unsubscribeFromRunNotifications({ run, snapshot }) {
|
|
155
|
+
logger.debug("[DevRunController] Unsubscribing from run notifications", { run, snapshot });
|
|
156
|
+
this.opts.onUnsubscribeFromRunNotifications(run, snapshot);
|
|
157
|
+
}
|
|
158
|
+
get runFriendlyId() {
|
|
159
|
+
if (this.state.phase !== "RUN") {
|
|
160
|
+
return undefined;
|
|
161
|
+
}
|
|
162
|
+
return this.state.run.friendlyId;
|
|
163
|
+
}
|
|
164
|
+
get snapshotFriendlyId() {
|
|
165
|
+
if (this.state.phase !== "RUN") {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
return this.state.snapshot.friendlyId;
|
|
169
|
+
}
|
|
170
|
+
get workerFriendlyId() {
|
|
171
|
+
if (!this.opts.worker.serverWorker) {
|
|
172
|
+
throw new Error("No version for dev worker");
|
|
173
|
+
}
|
|
174
|
+
return this.opts.worker.serverWorker.id;
|
|
175
|
+
}
|
|
176
|
+
handleSnapshotChangeLock = false;
|
|
177
|
+
async handleSnapshotChange({ run, snapshot, completedWaitpoints, }) {
|
|
178
|
+
if (this.handleSnapshotChangeLock) {
|
|
179
|
+
logger.debug("handleSnapshotChange: already in progress");
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
this.handleSnapshotChangeLock = true;
|
|
183
|
+
// Reset the (fallback) snapshot poll interval so we don't do unnecessary work
|
|
184
|
+
this.snapshotPoller.resetCurrentInterval();
|
|
185
|
+
try {
|
|
186
|
+
if (!this.snapshotFriendlyId) {
|
|
187
|
+
logger.debug("handleSnapshotChange: Missing snapshot ID", {
|
|
188
|
+
runId: run.friendlyId,
|
|
189
|
+
snapshotId: this.snapshotFriendlyId,
|
|
190
|
+
});
|
|
191
|
+
this.httpClient.dev.sendDebugLog(run.friendlyId, {
|
|
192
|
+
time: new Date(),
|
|
193
|
+
message: `snapshot change: missing snapshot ID`,
|
|
194
|
+
properties: {
|
|
195
|
+
newSnapshotId: snapshot.friendlyId,
|
|
196
|
+
newSnapshotStatus: snapshot.executionStatus,
|
|
197
|
+
},
|
|
198
|
+
});
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
if (this.snapshotFriendlyId === snapshot.friendlyId) {
|
|
202
|
+
logger.debug("handleSnapshotChange: snapshot not changed, skipping", { snapshot });
|
|
203
|
+
this.httpClient.dev.sendDebugLog(run.friendlyId, {
|
|
204
|
+
time: new Date(),
|
|
205
|
+
message: `snapshot change: skipping, no change`,
|
|
206
|
+
properties: {
|
|
207
|
+
snapshotId: this.snapshotFriendlyId,
|
|
208
|
+
snapshotStatus: snapshot.executionStatus,
|
|
209
|
+
},
|
|
210
|
+
});
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
logger.debug(`handleSnapshotChange: ${snapshot.executionStatus}`, {
|
|
214
|
+
run,
|
|
215
|
+
oldSnapshotId: this.snapshotFriendlyId,
|
|
216
|
+
newSnapshot: snapshot,
|
|
217
|
+
completedWaitpoints: completedWaitpoints.length,
|
|
218
|
+
});
|
|
219
|
+
this.httpClient.dev.sendDebugLog(run.friendlyId, {
|
|
220
|
+
time: new Date(),
|
|
221
|
+
message: `snapshot change: ${snapshot.executionStatus}`,
|
|
222
|
+
properties: {
|
|
223
|
+
oldSnapshotId: this.snapshotFriendlyId,
|
|
224
|
+
newSnapshotId: snapshot.friendlyId,
|
|
225
|
+
completedWaitpoints: completedWaitpoints.length,
|
|
226
|
+
},
|
|
227
|
+
});
|
|
228
|
+
try {
|
|
229
|
+
this.updateRunPhase(run, snapshot);
|
|
230
|
+
}
|
|
231
|
+
catch (error) {
|
|
232
|
+
logger.debug("handleSnapshotChange: failed to update run phase", {
|
|
233
|
+
run,
|
|
234
|
+
snapshot,
|
|
235
|
+
error,
|
|
236
|
+
});
|
|
237
|
+
this.runFinished();
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
switch (snapshot.executionStatus) {
|
|
241
|
+
case "PENDING_CANCEL": {
|
|
242
|
+
try {
|
|
243
|
+
await this.cancelAttempt();
|
|
244
|
+
}
|
|
245
|
+
catch (error) {
|
|
246
|
+
logger.debug("Failed to cancel attempt, killing task run process", {
|
|
247
|
+
error,
|
|
248
|
+
});
|
|
249
|
+
try {
|
|
250
|
+
await this.taskRunProcess?.kill("SIGKILL");
|
|
251
|
+
}
|
|
252
|
+
catch (error) {
|
|
253
|
+
logger.debug("Failed to cancel attempt, failed to kill task run process", { error });
|
|
254
|
+
}
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
case "FINISHED": {
|
|
260
|
+
if (this.isCompletingRun) {
|
|
261
|
+
logger.debug("Run is finished but we're completing it, skipping");
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
await this.exitTaskRunProcessWithoutFailingRun({
|
|
265
|
+
flush: true,
|
|
266
|
+
reason: "already-finished",
|
|
267
|
+
});
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
case "EXECUTING_WITH_WAITPOINTS": {
|
|
271
|
+
logger.debug("Run is executing with waitpoints", { snapshot });
|
|
272
|
+
try {
|
|
273
|
+
await this.taskRunProcess?.cleanup(false);
|
|
274
|
+
}
|
|
275
|
+
catch (error) {
|
|
276
|
+
logger.debug("Failed to cleanup task run process", { error });
|
|
277
|
+
}
|
|
278
|
+
if (snapshot.friendlyId !== this.snapshotFriendlyId) {
|
|
279
|
+
logger.debug("Snapshot changed after cleanup, abort", {
|
|
280
|
+
oldSnapshotId: snapshot.friendlyId,
|
|
281
|
+
newSnapshotId: this.snapshotFriendlyId,
|
|
282
|
+
});
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
//no snapshots in DEV, so we just return.
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
case "SUSPENDED": {
|
|
289
|
+
logger.debug("Run shouldn't be suspended in DEV", {
|
|
290
|
+
run,
|
|
291
|
+
snapshot,
|
|
292
|
+
});
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
case "PENDING_EXECUTING": {
|
|
296
|
+
logger.debug("Run is pending execution", { run, snapshot });
|
|
297
|
+
if (completedWaitpoints.length === 0) {
|
|
298
|
+
logger.log("No waitpoints to complete, nothing to do");
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
logger.debug("Run shouldn't be PENDING_EXECUTING with completedWaitpoints in DEV", {
|
|
302
|
+
run,
|
|
303
|
+
snapshot,
|
|
304
|
+
});
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
case "EXECUTING": {
|
|
308
|
+
logger.debug("Run is now executing", { run, snapshot });
|
|
309
|
+
if (completedWaitpoints.length === 0) {
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
logger.debug("Processing completed waitpoints", { completedWaitpoints });
|
|
313
|
+
if (!this.taskRunProcess) {
|
|
314
|
+
logger.debug("No task run process, ignoring completed waitpoints", {
|
|
315
|
+
completedWaitpoints,
|
|
316
|
+
});
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
for (const waitpoint of completedWaitpoints) {
|
|
320
|
+
this.taskRunProcess.waitpointCompleted(waitpoint);
|
|
321
|
+
}
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
case "RUN_CREATED":
|
|
325
|
+
case "QUEUED_EXECUTING":
|
|
326
|
+
case "QUEUED": {
|
|
327
|
+
logger.debug("Status change not handled", { status: snapshot.executionStatus });
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
default: {
|
|
331
|
+
assertExhaustive(snapshot.executionStatus);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
catch (error) {
|
|
336
|
+
logger.debug("handleSnapshotChange: unexpected error", { error });
|
|
337
|
+
this.httpClient.dev.sendDebugLog(run.friendlyId, {
|
|
338
|
+
time: new Date(),
|
|
339
|
+
message: `snapshot change: unexpected error`,
|
|
340
|
+
properties: {
|
|
341
|
+
snapshotId: snapshot.friendlyId,
|
|
342
|
+
error: error instanceof Error ? error.message : String(error),
|
|
343
|
+
},
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
finally {
|
|
347
|
+
this.handleSnapshotChangeLock = false;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
async startAndExecuteRunAttempt({ runFriendlyId, snapshotFriendlyId, dequeuedAt, isWarmStart = false, }) {
|
|
351
|
+
this.subscribeToRunNotifications({
|
|
352
|
+
run: { friendlyId: runFriendlyId },
|
|
353
|
+
snapshot: { friendlyId: snapshotFriendlyId },
|
|
354
|
+
});
|
|
355
|
+
const attemptStartedAt = Date.now();
|
|
356
|
+
const start = await this.httpClient.dev.startRunAttempt(runFriendlyId, snapshotFriendlyId);
|
|
357
|
+
if (!start.success) {
|
|
358
|
+
logger.debug("[DevRunController] Failed to start run", { error: start.error });
|
|
359
|
+
this.runFinished();
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
const attemptDuration = Date.now() - attemptStartedAt;
|
|
363
|
+
const { run, snapshot, execution, envVars } = start.data;
|
|
364
|
+
eventBus.emit("runStarted", this.opts.worker, execution);
|
|
365
|
+
logger.debug("[DevRunController] Started run", {
|
|
366
|
+
runId: run.friendlyId,
|
|
367
|
+
snapshot: snapshot.friendlyId,
|
|
368
|
+
});
|
|
369
|
+
this.enterRunPhase(run, snapshot);
|
|
370
|
+
const metrics = [
|
|
371
|
+
{
|
|
372
|
+
name: "start",
|
|
373
|
+
event: "create_attempt",
|
|
374
|
+
timestamp: attemptStartedAt,
|
|
375
|
+
duration: attemptDuration,
|
|
376
|
+
},
|
|
377
|
+
].concat(dequeuedAt
|
|
378
|
+
? [
|
|
379
|
+
{
|
|
380
|
+
name: "start",
|
|
381
|
+
event: "dequeue",
|
|
382
|
+
timestamp: dequeuedAt.getTime(),
|
|
383
|
+
duration: 0,
|
|
384
|
+
},
|
|
385
|
+
]
|
|
386
|
+
: []);
|
|
387
|
+
try {
|
|
388
|
+
return await this.executeRun({ run, snapshot, execution, envVars, metrics });
|
|
389
|
+
}
|
|
390
|
+
catch (error) {
|
|
391
|
+
logger.debug("Error while executing attempt", {
|
|
392
|
+
error,
|
|
393
|
+
});
|
|
394
|
+
if (error instanceof SuspendedProcessError) {
|
|
395
|
+
logger.debug("Attempt execution suspended", { error });
|
|
396
|
+
this.runFinished();
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
logger.debug("Submitting attempt completion", {
|
|
400
|
+
runId: run.friendlyId,
|
|
401
|
+
snapshotId: snapshot.friendlyId,
|
|
402
|
+
updatedSnapshotId: this.snapshotFriendlyId,
|
|
403
|
+
});
|
|
404
|
+
const completion = {
|
|
405
|
+
id: execution.run.id,
|
|
406
|
+
ok: false,
|
|
407
|
+
retry: undefined,
|
|
408
|
+
error: TaskRunProcess.parseExecuteError(error),
|
|
409
|
+
};
|
|
410
|
+
const completionResult = await this.httpClient.dev.completeRunAttempt(run.friendlyId, this.snapshotFriendlyId ?? snapshot.friendlyId, { completion });
|
|
411
|
+
if (!completionResult.success) {
|
|
412
|
+
logger.debug("Failed to submit completion after error", {
|
|
413
|
+
error: completionResult.error,
|
|
414
|
+
});
|
|
415
|
+
this.runFinished();
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
logger.debug("Attempt completion submitted after error", completionResult.data.result);
|
|
419
|
+
try {
|
|
420
|
+
await this.handleCompletionResult(completion, completionResult.data.result, execution);
|
|
421
|
+
}
|
|
422
|
+
catch (error) {
|
|
423
|
+
logger.debug("Failed to handle completion result after error", { error });
|
|
424
|
+
this.runFinished();
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
async executeRun({ run, snapshot, execution, envVars, metrics, }) {
|
|
430
|
+
if (!this.opts.worker.serverWorker) {
|
|
431
|
+
throw new Error(`No server worker for Dev ${run.friendlyId}`);
|
|
432
|
+
}
|
|
433
|
+
if (!this.opts.worker.manifest) {
|
|
434
|
+
throw new Error(`No worker manifest for Dev ${run.friendlyId}`);
|
|
435
|
+
}
|
|
436
|
+
this.snapshotPoller.start();
|
|
437
|
+
logger.debug("getProcess", {
|
|
438
|
+
build: this.opts.worker.build,
|
|
439
|
+
});
|
|
440
|
+
this.isCompletingRun = false;
|
|
441
|
+
// Get process from pool instead of creating new one
|
|
442
|
+
const { taskRunProcess, isReused } = await this.opts.taskRunProcessPool.getProcess(this.opts.worker.manifest, {
|
|
443
|
+
id: "unmanaged",
|
|
444
|
+
contentHash: this.opts.worker.build.contentHash,
|
|
445
|
+
version: this.opts.worker.serverWorker?.version,
|
|
446
|
+
engine: "V2",
|
|
447
|
+
}, execution.machine, {
|
|
448
|
+
TRIGGER_WORKER_MANIFEST_PATH: join(this.opts.worker.build.outputPath, "index.json"),
|
|
449
|
+
RUN_WORKER_SHOW_LOGS: this.opts.logLevel === "debug" ? "true" : "false",
|
|
450
|
+
TRIGGER_WORKER_VERSION: this.opts.worker.serverWorker?.version,
|
|
451
|
+
}, this.cwd);
|
|
452
|
+
this.taskRunProcess = taskRunProcess;
|
|
453
|
+
taskRunProcess.unsafeDetachEvtHandlers();
|
|
454
|
+
taskRunProcess.onTaskRunHeartbeat.attach(async (runId) => {
|
|
455
|
+
if (!this.runFriendlyId || !this.snapshotFriendlyId) {
|
|
456
|
+
logger.debug("[DevRunController] Skipping heartbeat, no run ID or snapshot ID");
|
|
457
|
+
return;
|
|
458
|
+
}
|
|
459
|
+
logger.debug("[DevRunController] Sending heartbeat");
|
|
460
|
+
const response = await this.httpClient.dev.heartbeatRun(this.runFriendlyId, this.snapshotFriendlyId, {
|
|
461
|
+
cpu: 0,
|
|
462
|
+
memory: 0,
|
|
463
|
+
});
|
|
464
|
+
if (!response.success) {
|
|
465
|
+
logger.debug("[DevRunController] Heartbeat failed", { error: response.error });
|
|
466
|
+
}
|
|
467
|
+
});
|
|
468
|
+
// Update the process environment for this specific run
|
|
469
|
+
// Note: We may need to enhance TaskRunProcess to support updating env vars
|
|
470
|
+
logger.debug("executing task run process from pool", {
|
|
471
|
+
attemptNumber: execution.attempt.number,
|
|
472
|
+
runId: execution.run.id,
|
|
473
|
+
});
|
|
474
|
+
const completion = await this.taskRunProcess.execute({
|
|
475
|
+
payload: {
|
|
476
|
+
execution,
|
|
477
|
+
traceContext: execution.run.traceContext ?? {},
|
|
478
|
+
metrics,
|
|
479
|
+
},
|
|
480
|
+
messageId: run.friendlyId,
|
|
481
|
+
env: {
|
|
482
|
+
...sanitizeEnvVars(envVars ?? {}),
|
|
483
|
+
...sanitizeEnvVars(this.opts.worker.params.env),
|
|
484
|
+
TRIGGER_PROJECT_REF: execution.project.ref,
|
|
485
|
+
},
|
|
486
|
+
}, isReused);
|
|
487
|
+
logger.debug("Completed run", completion);
|
|
488
|
+
this.isCompletingRun = true;
|
|
489
|
+
// Return process to pool instead of killing it
|
|
490
|
+
try {
|
|
491
|
+
const version = this.opts.worker.serverWorker?.version || "unknown";
|
|
492
|
+
await this.opts.taskRunProcessPool.returnProcess(this.taskRunProcess, version);
|
|
493
|
+
this.taskRunProcess = undefined;
|
|
494
|
+
}
|
|
495
|
+
catch (error) {
|
|
496
|
+
logger.debug("Failed to return task run process to pool, submitting completion anyway", {
|
|
497
|
+
error,
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
if (!this.runFriendlyId || !this.snapshotFriendlyId) {
|
|
501
|
+
logger.debug("executeRun: Missing run ID or snapshot ID after execution", {
|
|
502
|
+
runId: this.runFriendlyId,
|
|
503
|
+
snapshotId: this.snapshotFriendlyId,
|
|
504
|
+
});
|
|
505
|
+
this.runFinished();
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
508
|
+
const completionResult = await this.httpClient.dev.completeRunAttempt(this.runFriendlyId, this.snapshotFriendlyId, {
|
|
509
|
+
completion,
|
|
510
|
+
});
|
|
511
|
+
if (!completionResult.success) {
|
|
512
|
+
logger.debug("Failed to submit completion", {
|
|
513
|
+
error: completionResult.error,
|
|
514
|
+
});
|
|
515
|
+
this.runFinished();
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
518
|
+
logger.debug("Attempt completion submitted", completionResult.data.result);
|
|
519
|
+
try {
|
|
520
|
+
await this.handleCompletionResult(completion, completionResult.data.result, execution);
|
|
521
|
+
}
|
|
522
|
+
catch (error) {
|
|
523
|
+
logger.debug("Failed to handle completion result", { error });
|
|
524
|
+
this.runFinished();
|
|
525
|
+
return;
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
async handleCompletionResult(completion, result, execution) {
|
|
529
|
+
logger.debug("[DevRunController] Handling completion result", { completion, result });
|
|
530
|
+
const { attemptStatus, snapshot: completionSnapshot, run } = result;
|
|
531
|
+
try {
|
|
532
|
+
this.updateRunPhase(run, completionSnapshot);
|
|
533
|
+
}
|
|
534
|
+
catch (error) {
|
|
535
|
+
logger.debug("Failed to update run phase after completion", { error });
|
|
536
|
+
this.runFinished();
|
|
537
|
+
return;
|
|
538
|
+
}
|
|
539
|
+
if (attemptStatus === "RETRY_QUEUED") {
|
|
540
|
+
logger.debug("Retry queued");
|
|
541
|
+
this.runFinished();
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
544
|
+
if (attemptStatus === "RETRY_IMMEDIATELY") {
|
|
545
|
+
if (completion.ok) {
|
|
546
|
+
throw new Error("Should retry but completion OK.");
|
|
547
|
+
}
|
|
548
|
+
if (!completion.retry) {
|
|
549
|
+
throw new Error("Should retry but missing retry params.");
|
|
550
|
+
}
|
|
551
|
+
await sleep(completion.retry.delay);
|
|
552
|
+
if (!this.snapshotFriendlyId) {
|
|
553
|
+
throw new Error("Missing snapshot ID after retry");
|
|
554
|
+
}
|
|
555
|
+
this.startAndExecuteRunAttempt({
|
|
556
|
+
runFriendlyId: run.friendlyId,
|
|
557
|
+
snapshotFriendlyId: this.snapshotFriendlyId,
|
|
558
|
+
}).finally(() => { });
|
|
559
|
+
return;
|
|
560
|
+
}
|
|
561
|
+
if (attemptStatus === "RUN_PENDING_CANCEL") {
|
|
562
|
+
logger.debug("Run pending cancel");
|
|
563
|
+
return;
|
|
564
|
+
}
|
|
565
|
+
eventBus.emit("runCompleted", this.opts.worker, execution, completion, completion.usage?.durationMs ?? 0);
|
|
566
|
+
if (attemptStatus === "RUN_FINISHED") {
|
|
567
|
+
logger.debug("Run finished");
|
|
568
|
+
this.runFinished();
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
assertExhaustive(attemptStatus);
|
|
572
|
+
}
|
|
573
|
+
async exitTaskRunProcessWithoutFailingRun({ flush, reason, }) {
|
|
574
|
+
await this.taskRunProcess?.suspend({ flush });
|
|
575
|
+
// No services should be left running after this line - let's make sure of it
|
|
576
|
+
this.shutdownExecution(`exitTaskRunProcessWithoutFailingRun: ${reason}`);
|
|
577
|
+
}
|
|
578
|
+
shutdownExecution(reason) {
|
|
579
|
+
if (this.isShuttingDown) {
|
|
580
|
+
logger.debug(`[shutdown] ${reason} (already shutting down)`, {
|
|
581
|
+
newReason: reason,
|
|
582
|
+
});
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
585
|
+
logger.debug(`[shutdown] ${reason}`);
|
|
586
|
+
this.isShuttingDown = true;
|
|
587
|
+
this.snapshotPoller.stop();
|
|
588
|
+
this.opts.onFinished();
|
|
589
|
+
this.taskRunProcess?.unsafeDetachEvtHandlers();
|
|
590
|
+
}
|
|
591
|
+
async runFinished() {
|
|
592
|
+
// Return the process to the pool instead of killing it directly
|
|
593
|
+
if (this.taskRunProcess) {
|
|
594
|
+
try {
|
|
595
|
+
const version = this.opts.worker.serverWorker?.version || "unknown";
|
|
596
|
+
await this.opts.taskRunProcessPool.returnProcess(this.taskRunProcess, version);
|
|
597
|
+
this.taskRunProcess = undefined;
|
|
598
|
+
}
|
|
599
|
+
catch (error) {
|
|
600
|
+
logger.debug("Failed to return task run process to pool during runFinished", { error });
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
this.snapshotPoller.stop();
|
|
604
|
+
this.opts.onFinished();
|
|
605
|
+
}
|
|
606
|
+
async cancelAttempt() {
|
|
607
|
+
logger.debug("Cancelling attempt", { runId: this.runFriendlyId });
|
|
608
|
+
await this.taskRunProcess?.cancel();
|
|
609
|
+
}
|
|
610
|
+
async start(dequeueMessage) {
|
|
611
|
+
logger.debug("[DevRunController] Starting up");
|
|
612
|
+
await this.startAndExecuteRunAttempt({
|
|
613
|
+
runFriendlyId: dequeueMessage.run.friendlyId,
|
|
614
|
+
snapshotFriendlyId: dequeueMessage.snapshot.friendlyId,
|
|
615
|
+
dequeuedAt: dequeueMessage.dequeuedAt,
|
|
616
|
+
}).finally(async () => { });
|
|
617
|
+
}
|
|
618
|
+
async stop() {
|
|
619
|
+
logger.debug("[DevRunController] Shutting down");
|
|
620
|
+
process.off("SIGTERM", this.sigterm);
|
|
621
|
+
if (this.taskRunProcess && !this.taskRunProcess.isBeingKilled) {
|
|
622
|
+
try {
|
|
623
|
+
const version = this.opts.worker.serverWorker?.version || "unknown";
|
|
624
|
+
await this.opts.taskRunProcessPool.returnProcess(this.taskRunProcess, version);
|
|
625
|
+
this.taskRunProcess = undefined;
|
|
626
|
+
}
|
|
627
|
+
catch (error) {
|
|
628
|
+
logger.debug("Failed to return task run process to pool during stop", { error });
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
this.snapshotPoller.stop();
|
|
632
|
+
}
|
|
633
|
+
async getLatestSnapshot() {
|
|
634
|
+
if (!this.runFriendlyId) {
|
|
635
|
+
return;
|
|
636
|
+
}
|
|
637
|
+
logger.debug("[DevRunController] Received notification, manually getting the latest snapshot.");
|
|
638
|
+
const response = await this.httpClient.dev.getRunExecutionData(this.runFriendlyId);
|
|
639
|
+
if (!response.success) {
|
|
640
|
+
logger.debug("Failed to get latest snapshot", { error: response.error });
|
|
641
|
+
return;
|
|
642
|
+
}
|
|
643
|
+
await this.handleSnapshotChange(response.data.execution);
|
|
644
|
+
}
|
|
645
|
+
resubscribeToRunNotifications() {
|
|
646
|
+
if (this.state.phase !== "RUN") {
|
|
647
|
+
return;
|
|
648
|
+
}
|
|
649
|
+
this.subscribeToRunNotifications(this.state);
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
//# sourceMappingURL=dev-run-controller.js.map
|