@sshkeda/task 0.0.0-stage → 1.0.1
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/LICENSE +21 -0
- package/README.md +131 -2
- package/package.json +41 -4
- package/src/index.ts +2 -0
- package/src/lib/errors/index.ts +15 -0
- package/src/lib/errors/internal/errors.ts +147 -0
- package/src/lib/kill-leftover-processes/index.ts +17 -0
- package/src/lib/kill-leftover-processes/internal/command-words.ts +16 -0
- package/src/lib/kill-leftover-processes/internal/find-process-ids.ts +36 -0
- package/src/lib/kill-leftover-processes/internal/kill-process-groups.ts +270 -0
- package/src/lib/kill-leftover-processes/internal/list-linux-processes-from-proc.ts +191 -0
- package/src/lib/kill-leftover-processes/internal/list-macos-processes-with-sysctl.ts +335 -0
- package/src/lib/kill-leftover-processes/internal/list-processes.ts +58 -0
- package/src/lib/kill-leftover-processes/internal/mark-run-processes.ts +367 -0
- package/src/lib/kill-leftover-processes/internal/process-cleanup-errors.ts +17 -0
- package/src/lib/kill-leftover-processes/internal/send-signal.ts +32 -0
- package/src/lib/kill-leftover-processes/internal/signal-run-processes.ts +48 -0
- package/src/lib/kill-leftover-processes/internal/started-process-groups.ts +107 -0
- package/src/lib/main-thread/index.ts +3 -0
- package/src/lib/main-thread/internal/listen-for-stop-requests.ts +102 -0
- package/src/lib/main-thread/internal/run-main-thread.ts +81 -0
- package/src/lib/main-thread/internal/run-root-task-fiber.ts +191 -0
- package/src/lib/main-thread/internal/stops-at-first-failure.ts +20 -0
- package/src/lib/main-thread/internal/trace-the-run.ts +107 -0
- package/src/lib/main-thread/lib/find-code-each-task-depends-on/index.ts +7 -0
- package/src/lib/main-thread/lib/find-code-each-task-depends-on/internal/follow-imports-from-entry-files.ts +306 -0
- package/src/lib/main-thread/lib/find-code-each-task-depends-on/internal/load-all-reporting-first-failure.ts +11 -0
- package/src/lib/main-thread/lib/find-code-each-task-depends-on/internal/make-module-graph.ts +48 -0
- package/src/lib/main-thread/lib/find-code-each-task-depends-on/internal/read-configured-loaders.ts +64 -0
- package/src/lib/main-thread/lib/find-code-each-task-depends-on/internal/resolve-module-specifiers.ts +60 -0
- package/src/lib/main-thread/lib/find-code-each-task-depends-on/internal/rewrite-worker-imports.ts +118 -0
- package/src/lib/main-thread/lib/find-code-each-task-depends-on/internal/worker-import-errors.ts +19 -0
- package/src/lib/main-thread/lib/run-tasks-on-workers/index.ts +7 -0
- package/src/lib/main-thread/lib/run-tasks-on-workers/internal/handle-worker-events.ts +348 -0
- package/src/lib/main-thread/lib/run-tasks-on-workers/internal/make-task-runs.ts +207 -0
- package/src/lib/main-thread/lib/run-tasks-on-workers/lib/run-requested-task-once/index.ts +1 -0
- package/src/lib/main-thread/lib/run-tasks-on-workers/lib/run-requested-task-once/internal/await-within-counted-limit.ts +29 -0
- package/src/lib/main-thread/lib/run-tasks-on-workers/lib/run-requested-task-once/internal/execute-task.ts +272 -0
- package/src/lib/main-thread/lib/run-tasks-on-workers/lib/run-requested-task-once/internal/make-task-setup-clock.ts +129 -0
- package/src/lib/main-thread/lib/run-tasks-on-workers/lib/run-requested-task-once/internal/run-requested-tasks.ts +135 -0
- package/src/lib/main-thread/lib/run-tasks-on-workers/shared/define-task-run-state.ts +288 -0
- package/src/lib/main-thread/lib/run-tasks-on-workers/shared/make-stopwatch.ts +39 -0
- package/src/lib/main-thread/lib/run-tasks-on-workers/shared/share-standard-input-with-root-task.ts +36 -0
- package/src/lib/main-thread/lib/run-tasks-on-workers/shared/stop-task.ts +166 -0
- package/src/lib/main-thread/lib/scan-module-source/index.ts +1 -0
- package/src/lib/main-thread/lib/scan-module-source/internal/find-lexical-bindings.ts +154 -0
- package/src/lib/main-thread/lib/scan-module-source/internal/find-task-declarations.ts +205 -0
- package/src/lib/main-thread/lib/scan-module-source/internal/parse-module-text.ts +34 -0
- package/src/lib/main-thread/lib/scan-module-source/internal/read-literal-string.ts +15 -0
- package/src/lib/main-thread/lib/scan-module-source/internal/read-module-loads.ts +316 -0
- package/src/lib/main-thread/lib/scan-module-source/internal/scan-module-text.ts +70 -0
- package/src/lib/main-thread/lib/scan-module-source/internal/unwrap-type-assertions.ts +10 -0
- package/src/lib/main-thread/lib/scan-module-source/internal/visit-non-reference-identifiers.ts +21 -0
- package/src/lib/main-thread/shared/fail-run.ts +36 -0
- package/src/lib/main-thread/shared/find-failure-reason.ts +43 -0
- package/src/lib/main-thread/shared/find-package-directories.ts +34 -0
- package/src/lib/main-thread/shared/find-tasks-reachable-from-root-task-file.ts +246 -0
- package/src/lib/main-thread/shared/list-directory-paths-up-to-root.ts +13 -0
- package/src/lib/main-thread/shared/main-thread-errors.ts +373 -0
- package/src/lib/main-thread/shared/package-json-errors.ts +93 -0
- package/src/lib/main-thread/shared/provide-discovered-tasks.ts +26 -0
- package/src/lib/main-thread/shared/provide-process-groups.ts +63 -0
- package/src/lib/main-thread/shared/provide-run-root-task-config.ts +66 -0
- package/src/lib/main-thread/shared/provide-stop-state.ts +150 -0
- package/src/lib/main-thread/shared/provide-worker-pool.ts +607 -0
- package/src/lib/main-thread/shared/read-bare-package-name.ts +3 -0
- package/src/lib/main-thread/shared/read-package-json.ts +149 -0
- package/src/lib/main-thread/shared/report-task-failure.ts +31 -0
- package/src/lib/preload-rewritten-imports-into-each-worker/index.ts +5 -0
- package/src/lib/preload-rewritten-imports-into-each-worker/internal/load-rewritten-imports.ts +34 -0
- package/src/lib/supervise-the-run/index.ts +15 -0
- package/src/lib/supervise-the-run/internal/adopt-orphans-on-linux.ts +73 -0
- package/src/lib/supervise-the-run/internal/check-root-task-file.ts +8 -0
- package/src/lib/supervise-the-run/internal/report-ready.ts +12 -0
- package/src/lib/supervise-the-run/internal/share-process-groups.ts +25 -0
- package/src/lib/supervise-the-run/internal/start-watching-the-supervisor.ts +6 -0
- package/src/lib/supervise-the-run/internal/supervise-run.ts +155 -0
- package/src/lib/supervise-the-run/internal/talk-to-the-supervisor.ts +53 -0
- package/src/lib/supervise-the-run/internal/watch-the-supervisor.ts +61 -0
- package/src/lib/task/index.ts +5 -0
- package/src/lib/task/internal/make-tasks.ts +82 -0
- package/src/lib/task/internal/run-command.ts +194 -0
- package/src/lib/task/internal/run-root-task.ts +263 -0
- package/src/lib/task/internal/run-task-lists.ts +51 -0
- package/src/lib/task/internal/trust-output-mode-names.ts +18 -0
- package/src/lib/task/internal/trust-task-results.ts +35 -0
- package/src/lib/task/internal/use-task-services.ts +4 -0
- package/src/lib/worker-thread/index.ts +3 -0
- package/src/lib/worker-thread/internal/answer-main-thread-messages.ts +141 -0
- package/src/lib/worker-thread/internal/describe-task-body-result.ts +91 -0
- package/src/lib/worker-thread/internal/name-config-key-not-set.ts +57 -0
- package/src/lib/worker-thread/internal/run-task-body.ts +117 -0
- package/src/lib/worker-thread/internal/serve-on-the-parent-port.ts +63 -0
- package/src/lib/worker-thread/internal/start-worker-thread.ts +41 -0
- package/src/lib/worker-thread/lib/provide-task-services/index.ts +1 -0
- package/src/lib/worker-thread/lib/provide-task-services/internal/make-task-logger.ts +34 -0
- package/src/lib/worker-thread/lib/provide-task-services/internal/provide-task-services.ts +86 -0
- package/src/lib/worker-thread/lib/provide-task-services/internal/read-standard-input-from-main-thread.ts +58 -0
- package/src/lib/worker-thread/lib/provide-task-services/internal/resolve-paths-from-package-directory.ts +61 -0
- package/src/lib/worker-thread/lib/provide-task-services/internal/run-commands-in-package-directory.ts +24 -0
- package/src/lib/worker-thread/lib/provide-task-services/internal/spawn-commands-with-bun.ts +545 -0
- package/src/lib/worker-thread/lib/provide-task-services/internal/spawn-reported-process.ts +151 -0
- package/src/lib/worker-thread/shared/await-main-thread-answers.ts +76 -0
- package/src/lib/worker-thread/shared/decode-task-result-json.ts +114 -0
- package/src/lib/worker-thread/shared/define-task-body-record.ts +11 -0
- package/src/lib/worker-thread/shared/describe-issue-input.ts +52 -0
- package/src/lib/worker-thread/shared/plain-object.ts +8 -0
- package/src/lib/worker-thread/shared/provide-worker-state.ts +160 -0
- package/src/lib/worker-thread/shared/worker-thread-errors.ts +41 -0
- package/src/shared/attribute-reported-failures.ts +25 -0
- package/src/shared/claim-processes-to-report.ts +22 -0
- package/src/shared/command-errors.ts +44 -0
- package/src/shared/complete-discarded-calls-once-sent.ts +12 -0
- package/src/shared/cut-to-graphemes.ts +12 -0
- package/src/shared/environment-config-errors.ts +74 -0
- package/src/shared/error-fields.ts +13 -0
- package/src/shared/find-bun-loader-for-script.ts +32 -0
- package/src/shared/find-node-modules-package-directory.ts +35 -0
- package/src/shared/find-user-locations-in-stack-traces.ts +64 -0
- package/src/shared/format-error-lines.ts +53 -0
- package/src/shared/format-task-lines.ts +21 -0
- package/src/shared/hold-task-logs.ts +24 -0
- package/src/shared/invariant-errors.ts +28 -0
- package/src/shared/mark-task-worker-thread-contexts.ts +29 -0
- package/src/shared/module-graph-errors.ts +49 -0
- package/src/shared/name-config-key.ts +42 -0
- package/src/shared/names-from-package-json.ts +7 -0
- package/src/shared/print-to-standard-error.ts +48 -0
- package/src/shared/process-errors.ts +191 -0
- package/src/shared/read-environment-config.ts +239 -0
- package/src/shared/record-tasks-made.ts +10 -0
- package/src/shared/report-cause.ts +140 -0
- package/src/shared/report-errors.ts +121 -0
- package/src/shared/resolve-task-options.ts +20 -0
- package/src/shared/rpc.ts +161 -0
- package/src/shared/run-in-child-fiber-and-join.ts +16 -0
- package/src/shared/run-marker.ts +7 -0
- package/src/shared/save-standard-stream-flags.ts +57 -0
- package/src/shared/select-cause-reasons.ts +14 -0
- package/src/shared/signal-run-called-twice.ts +11 -0
- package/src/shared/standard-input-streams.ts +41 -0
- package/src/shared/stop-signals.ts +41 -0
- package/src/shared/task-errors.ts +224 -0
- package/src/shared/task-package.ts +5 -0
- package/src/shared/task-results.ts +55 -0
- package/src/shared/task-services.ts +30 -0
- package/src/shared/write-trace-file.ts +112 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { Cause, Clock, Deferred, Effect, Exit, Logger, Result, Schema, Tracer } from "effect";
|
|
2
|
+
import { RpcServer } from "effect/rpc";
|
|
3
|
+
|
|
4
|
+
import { TASK_ERROR_FIELDS } from "../../../shared/error-fields.ts";
|
|
5
|
+
import { reportCause } from "../../../shared/report-cause.ts";
|
|
6
|
+
import {
|
|
7
|
+
describeCauseMessage,
|
|
8
|
+
THROWN_VALUE_WITHOUT_MESSAGE,
|
|
9
|
+
} from "../../../shared/report-errors.ts";
|
|
10
|
+
import { TaskEvent, TaskFiberResult, TaskWorkerRpcs } from "../../../shared/rpc.ts";
|
|
11
|
+
import type { StartTaskFiber } from "../../../shared/rpc.ts";
|
|
12
|
+
import { makeTraceFile } from "../../../shared/write-trace-file.ts";
|
|
13
|
+
import {
|
|
14
|
+
forgetEndedProcessGroups,
|
|
15
|
+
killTaskProcessGroups,
|
|
16
|
+
} from "../../kill-leftover-processes/index.ts";
|
|
17
|
+
import { makeTaskBodyRecord } from "../shared/define-task-body-record.ts";
|
|
18
|
+
import { WorkerState, reportToMainThread } from "../shared/provide-worker-state.ts";
|
|
19
|
+
import { describeCleanupFailure, describeTaskBodyResult } from "./describe-task-body-result.ts";
|
|
20
|
+
import { runTaskBody } from "./run-task-body.ts";
|
|
21
|
+
|
|
22
|
+
class TaskResultNotHandedOver extends Schema.TaggedError<TaskResultNotHandedOver>()(
|
|
23
|
+
"TaskResultNotHandedOver",
|
|
24
|
+
{ ...TASK_ERROR_FIELDS, taskName: Schema.String, cause: Schema.Defect() },
|
|
25
|
+
) {
|
|
26
|
+
public override get message() {
|
|
27
|
+
return `could not hand the result of "${this.taskName}" to the main thread because ${describeCauseMessage(this.cause)}`;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const describeResultNotHandedOver = (notHandedOver: TaskResultNotHandedOver) =>
|
|
32
|
+
TaskFiberResult.cases.Failed.make(reportCause(Cause.fail(notHandedOver)));
|
|
33
|
+
|
|
34
|
+
const endTaskBody = Effect.fn("endTaskBody")(function* (
|
|
35
|
+
startMessage: typeof StartTaskFiber.Type,
|
|
36
|
+
body: ReturnType<typeof makeTaskBodyRecord>,
|
|
37
|
+
taskExit: Exit.Exit<unknown, unknown>,
|
|
38
|
+
) {
|
|
39
|
+
const elapsedMilliseconds = (yield* Clock.currentTimeMillis) - body.startedAtMilliseconds;
|
|
40
|
+
const workerState = yield* WorkerState;
|
|
41
|
+
const cleanupExit = yield* Effect.exit(
|
|
42
|
+
killTaskProcessGroups(body.startedProcessGroups, startMessage.taskName, (processes) =>
|
|
43
|
+
workerState.claimProcessesToReport(startMessage.taskName, processes),
|
|
44
|
+
).pipe(Effect.flatMap(forgetEndedProcessGroups(body.startedProcessGroups))),
|
|
45
|
+
);
|
|
46
|
+
const sendTaskFiberEnded = (result: typeof TaskFiberResult.Type) =>
|
|
47
|
+
reportToMainThread(
|
|
48
|
+
TaskEvent.cases.TaskFiberEnded.make({
|
|
49
|
+
taskName: startMessage.taskName,
|
|
50
|
+
result,
|
|
51
|
+
logs: body.logs,
|
|
52
|
+
}),
|
|
53
|
+
);
|
|
54
|
+
yield* Effect.suspend((): Effect.Effect<typeof TaskFiberResult.Type> => {
|
|
55
|
+
const cleanupFailure = describeCleanupFailure(body, cleanupExit, taskExit);
|
|
56
|
+
return cleanupFailure === null
|
|
57
|
+
? describeTaskBodyResult(
|
|
58
|
+
startMessage,
|
|
59
|
+
body,
|
|
60
|
+
Exit.isFailure(cleanupExit) ? cleanupExit : taskExit,
|
|
61
|
+
elapsedMilliseconds,
|
|
62
|
+
)
|
|
63
|
+
: Effect.succeed(cleanupFailure);
|
|
64
|
+
}).pipe(
|
|
65
|
+
Effect.flatMap(sendTaskFiberEnded),
|
|
66
|
+
Effect.matchCauseEffect({
|
|
67
|
+
onFailure: (failureCause) => {
|
|
68
|
+
const defect = Cause.findDefect(failureCause);
|
|
69
|
+
return Result.isFailure(defect)
|
|
70
|
+
? Effect.failCause(defect.failure)
|
|
71
|
+
: Effect.try(() =>
|
|
72
|
+
describeResultNotHandedOver(
|
|
73
|
+
new TaskResultNotHandedOver({
|
|
74
|
+
taskName: startMessage.taskName,
|
|
75
|
+
cause: defect.success,
|
|
76
|
+
}),
|
|
77
|
+
),
|
|
78
|
+
).pipe(
|
|
79
|
+
Effect.catchTag("UnknownError", () =>
|
|
80
|
+
Effect.sync(() =>
|
|
81
|
+
describeResultNotHandedOver(
|
|
82
|
+
new TaskResultNotHandedOver({
|
|
83
|
+
taskName: startMessage.taskName,
|
|
84
|
+
cause: THROWN_VALUE_WITHOUT_MESSAGE,
|
|
85
|
+
}),
|
|
86
|
+
),
|
|
87
|
+
),
|
|
88
|
+
),
|
|
89
|
+
Effect.flatMap(sendTaskFiberEnded),
|
|
90
|
+
);
|
|
91
|
+
},
|
|
92
|
+
onSuccess: (success) => Effect.succeed(success),
|
|
93
|
+
}),
|
|
94
|
+
);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
const startTaskFiber = Effect.fn("startTaskFiber")(function* (start: typeof StartTaskFiber.Type) {
|
|
98
|
+
const workerState = yield* WorkerState;
|
|
99
|
+
const body = makeTaskBodyRecord();
|
|
100
|
+
yield* workerState.startTaskBodyFiber(
|
|
101
|
+
start.taskName,
|
|
102
|
+
runTaskBody(start, body).pipe(
|
|
103
|
+
Effect.withParentSpan(Tracer.externalSpan({ traceId: start.traceId, spanId: start.spanId })),
|
|
104
|
+
Effect.onExit((taskExit) => endTaskBody(start, body, taskExit)),
|
|
105
|
+
),
|
|
106
|
+
);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
const serveUntilExitRequested = Effect.gen(function* () {
|
|
110
|
+
const workerState = yield* WorkerState;
|
|
111
|
+
const exitRequested = yield* Deferred.make<void>();
|
|
112
|
+
const handlers = yield* TaskWorkerRpcs.toHandlers({
|
|
113
|
+
StartTaskFiber: startTaskFiber,
|
|
114
|
+
StopTaskFiber: (stop) => workerState.requestTaskBodyInterruption(stop.taskName),
|
|
115
|
+
AnswerIfResponsive: () => Effect.void,
|
|
116
|
+
ExitWorker: () => Deferred.done(exitRequested, Exit.void).pipe(Effect.asVoid),
|
|
117
|
+
});
|
|
118
|
+
yield* RpcServer.make(TaskWorkerRpcs, { disableTracing: true }).pipe(
|
|
119
|
+
Effect.provideContext(handlers),
|
|
120
|
+
Effect.interruptible,
|
|
121
|
+
Effect.forkScoped,
|
|
122
|
+
);
|
|
123
|
+
yield* Deferred.await(exitRequested);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
export const serveTheMainThread = Effect.gen(function* () {
|
|
127
|
+
const workerState = yield* WorkerState;
|
|
128
|
+
const traceFile = yield* makeTraceFile({
|
|
129
|
+
traceFilePath: workerState.traceFilePath,
|
|
130
|
+
thread: "worker",
|
|
131
|
+
maxBatchSize: 1,
|
|
132
|
+
onIncomplete: (reason) =>
|
|
133
|
+
Effect.sync(() => {
|
|
134
|
+
workerState.reportToMainThreadNow(TaskEvent.cases.TraceWriteFailed.make({ reason }));
|
|
135
|
+
}),
|
|
136
|
+
});
|
|
137
|
+
yield* serveUntilExitRequested.pipe(
|
|
138
|
+
Effect.provideService(Tracer.Tracer, traceFile.tracer),
|
|
139
|
+
Effect.provideService(Logger.CurrentLoggers, new Set([traceFile.logger])),
|
|
140
|
+
);
|
|
141
|
+
});
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { Cause, Effect, Exit, Option, Schema } from "effect";
|
|
2
|
+
|
|
3
|
+
import { reportCause } from "../../../shared/report-cause.ts";
|
|
4
|
+
import { TaskFiberResult } from "../../../shared/rpc.ts";
|
|
5
|
+
import type { StartTaskFiber } from "../../../shared/rpc.ts";
|
|
6
|
+
import { failuresOfCause } from "../../../shared/select-cause-reasons.ts";
|
|
7
|
+
import { isAwaitedTasksFailure } from "../../../shared/task-errors.ts";
|
|
8
|
+
import { CommandFailed } from "../../errors/index.ts";
|
|
9
|
+
import { decodeTaskResultJson } from "../shared/decode-task-result-json.ts";
|
|
10
|
+
import type { makeTaskBodyRecord } from "../shared/define-task-body-record.ts";
|
|
11
|
+
|
|
12
|
+
const isCommandFailed = Schema.is(CommandFailed);
|
|
13
|
+
|
|
14
|
+
export const describeBodyFailure = (cause: Cause.Cause<unknown>) => {
|
|
15
|
+
const failureCause = failuresOfCause(cause);
|
|
16
|
+
const hasOnlyOneFailure = failureCause.reasons.length === 1;
|
|
17
|
+
const firstFailure = Cause.findErrorOption(failureCause);
|
|
18
|
+
const awaitedTasksFailure = Option.filter(firstFailure, isAwaitedTasksFailure);
|
|
19
|
+
const hasOnlyAwaitedFailure = hasOnlyOneFailure && Option.isSome(awaitedTasksFailure);
|
|
20
|
+
if (hasOnlyAwaitedFailure) {
|
|
21
|
+
return TaskFiberResult.cases.AwaitedTasksFailed.make({ failure: awaitedTasksFailure.value });
|
|
22
|
+
}
|
|
23
|
+
const failedCommand = Option.filter(firstFailure, isCommandFailed);
|
|
24
|
+
const hasOnlyCommandFailure = hasOnlyOneFailure && Option.isSome(failedCommand);
|
|
25
|
+
return TaskFiberResult.cases.Failed.make({
|
|
26
|
+
...reportCause(cause),
|
|
27
|
+
...(hasOnlyCommandFailure ? { failedCommandExitCode: failedCommand.value.code } : {}),
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const describeTaskBodyResult = (
|
|
32
|
+
startMessage: typeof StartTaskFiber.Type,
|
|
33
|
+
body: ReturnType<typeof makeTaskBodyRecord>,
|
|
34
|
+
taskExit: Exit.Exit<unknown, unknown>,
|
|
35
|
+
elapsedMilliseconds: number,
|
|
36
|
+
) => {
|
|
37
|
+
if (Exit.isSuccess(taskExit)) {
|
|
38
|
+
return decodeTaskResultJson(startMessage.taskName, "returned", taskExit.value).pipe(
|
|
39
|
+
Effect.map((returnedValue) =>
|
|
40
|
+
TaskFiberResult.cases.Returned.make({
|
|
41
|
+
...(returnedValue === undefined ? {} : { value: returnedValue }),
|
|
42
|
+
elapsedMilliseconds,
|
|
43
|
+
}),
|
|
44
|
+
),
|
|
45
|
+
Effect.catchTag("TaskResultNotJson", (error) =>
|
|
46
|
+
Effect.succeed(TaskFiberResult.cases.Failed.make(reportCause(Cause.fail(error)))),
|
|
47
|
+
),
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
if (!Cause.hasInterruptsOnly(taskExit.cause)) {
|
|
51
|
+
return Effect.succeed(describeBodyFailure(taskExit.cause));
|
|
52
|
+
}
|
|
53
|
+
return Effect.succeed(
|
|
54
|
+
Option.match(body.causeReportedBeforeCleanup, {
|
|
55
|
+
onNone: () => TaskFiberResult.cases.Interrupted.make({}),
|
|
56
|
+
onSome: describeBodyFailure,
|
|
57
|
+
}),
|
|
58
|
+
);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const failureValueOf = (reason: Cause.Reason<unknown>): unknown => {
|
|
62
|
+
if (Cause.isFailReason(reason)) {
|
|
63
|
+
return reason.error;
|
|
64
|
+
}
|
|
65
|
+
return Cause.isDieReason(reason) ? reason.defect : reason;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export const describeCleanupFailure = (
|
|
69
|
+
body: ReturnType<typeof makeTaskBodyRecord>,
|
|
70
|
+
cleanupExit: Exit.Exit<unknown, unknown>,
|
|
71
|
+
taskExit: Exit.Exit<unknown, unknown>,
|
|
72
|
+
) => {
|
|
73
|
+
if (Option.isNone(body.causeReportedBeforeCleanup)) {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
const causeReportedBeforeCleanup = body.causeReportedBeforeCleanup.value;
|
|
77
|
+
const reportedFailureValues = new Set(causeReportedBeforeCleanup.reasons.map(failureValueOf));
|
|
78
|
+
const reasonsAddedByFinalizers = Exit.isFailure(taskExit)
|
|
79
|
+
? taskExit.cause.reasons.filter(
|
|
80
|
+
(reason) =>
|
|
81
|
+
!Cause.isInterruptReason(reason) && !reportedFailureValues.has(failureValueOf(reason)),
|
|
82
|
+
)
|
|
83
|
+
: [];
|
|
84
|
+
const reasonsOfProcessCleanup = Exit.isFailure(cleanupExit) ? cleanupExit.cause.reasons : [];
|
|
85
|
+
const cleanupFailureReasons = [...reasonsOfProcessCleanup, ...reasonsAddedByFinalizers];
|
|
86
|
+
return cleanupFailureReasons.length === 0
|
|
87
|
+
? null
|
|
88
|
+
: TaskFiberResult.cases.CleanupFailed.make(
|
|
89
|
+
reportCause(Cause.fromReasons(cleanupFailureReasons)),
|
|
90
|
+
);
|
|
91
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { Config, Effect, Exit, Option, Schema, SchemaAST, SchemaIssue } from "effect";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
nameConfigKey,
|
|
5
|
+
nameEnvironmentConfigVariable,
|
|
6
|
+
observeConfigLoads,
|
|
7
|
+
} from "../../../shared/name-config-key.ts";
|
|
8
|
+
import { ConfigKeyNotSet } from "../../../shared/task-errors.ts";
|
|
9
|
+
|
|
10
|
+
const isConfigError = Schema.is(Schema.instanceOf(Config.ConfigError));
|
|
11
|
+
|
|
12
|
+
const decodeConfigErrorAtPath = Schema.decodeUnknownOption(
|
|
13
|
+
Schema.Struct({ cause: Schema.Struct({ issue: Schema.instanceOf(SchemaIssue.Pointer) }) }),
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
const expectsManyVariables = (issue: SchemaIssue.Issue) =>
|
|
17
|
+
issue instanceof SchemaIssue.InvalidType &&
|
|
18
|
+
(SchemaAST.isObjects(issue.ast) || SchemaAST.isArrays(issue.ast));
|
|
19
|
+
|
|
20
|
+
export const nameConfigKeyNotSet = <Success, Failure, Services>(
|
|
21
|
+
effect: Effect.Effect<Success, Failure, Services>,
|
|
22
|
+
) =>
|
|
23
|
+
Effect.suspend(() => {
|
|
24
|
+
const missingKeys = new Map<string, { readonly readsRuntimeConfigProvider: boolean }>();
|
|
25
|
+
return effect.pipe(
|
|
26
|
+
observeConfigLoads(({ configPath, readsRuntimeConfigProvider, loaded }) => {
|
|
27
|
+
const loadedNothing = Exit.isSuccess(loaded) && loaded.value === undefined;
|
|
28
|
+
if (loadedNothing) {
|
|
29
|
+
missingKeys.set(nameConfigKey(configPath), { readsRuntimeConfigProvider });
|
|
30
|
+
}
|
|
31
|
+
}),
|
|
32
|
+
Effect.mapError((failure): ConfigKeyNotSet | Failure => {
|
|
33
|
+
if (!isConfigError(failure)) {
|
|
34
|
+
return failure;
|
|
35
|
+
}
|
|
36
|
+
const configError = failure;
|
|
37
|
+
const decodedConfigError = decodeConfigErrorAtPath(configError);
|
|
38
|
+
if (Option.isNone(decodedConfigError)) {
|
|
39
|
+
return configError;
|
|
40
|
+
}
|
|
41
|
+
const pointer = decodedConfigError.value.cause.issue;
|
|
42
|
+
const configPath = pointer.path.map(String);
|
|
43
|
+
const missing = missingKeys.get(nameConfigKey(configPath));
|
|
44
|
+
if (missing === undefined) {
|
|
45
|
+
return configError;
|
|
46
|
+
}
|
|
47
|
+
const namesOneEnvironmentConfigVariable =
|
|
48
|
+
missing.readsRuntimeConfigProvider && !expectsManyVariables(pointer.issue);
|
|
49
|
+
return new ConfigKeyNotSet({
|
|
50
|
+
configKey: nameConfigKey(configPath),
|
|
51
|
+
environmentConfigVariable: namesOneEnvironmentConfigVariable
|
|
52
|
+
? nameEnvironmentConfigVariable(configPath)
|
|
53
|
+
: null,
|
|
54
|
+
});
|
|
55
|
+
}),
|
|
56
|
+
);
|
|
57
|
+
});
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { Effect, Exit, Schema, Cause, Clock, Option } from "effect";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
InsideTaskBody,
|
|
5
|
+
markImportingTaskModule,
|
|
6
|
+
} from "../../../shared/mark-task-worker-thread-contexts.ts";
|
|
7
|
+
import { TASK_TRACE_LABEL_PREFIX } from "../../../shared/names-from-package-json.ts";
|
|
8
|
+
import { findTasksMadeWithName } from "../../../shared/record-tasks-made.ts";
|
|
9
|
+
import { CauseWithoutFailure } from "../../../shared/report-errors.ts";
|
|
10
|
+
import { TaskEvent } from "../../../shared/rpc.ts";
|
|
11
|
+
import type { StartTaskFiber } from "../../../shared/rpc.ts";
|
|
12
|
+
import { runInChildFiberAndJoin } from "../../../shared/run-in-child-fiber-and-join.ts";
|
|
13
|
+
import { RunCalledDuringImport, TaskModuleImportFailed } from "../../../shared/task-errors.ts";
|
|
14
|
+
import { provideTaskServices } from "../lib/provide-task-services/index.ts";
|
|
15
|
+
import type { makeTaskBodyRecord } from "../shared/define-task-body-record.ts";
|
|
16
|
+
import { WorkerState, reportToMainThread } from "../shared/provide-worker-state.ts";
|
|
17
|
+
import {
|
|
18
|
+
TaskNotRegisteredInWorker,
|
|
19
|
+
TaskRegisteredAgainInWorker,
|
|
20
|
+
} from "../shared/worker-thread-errors.ts";
|
|
21
|
+
import { describeBodyFailure } from "./describe-task-body-result.ts";
|
|
22
|
+
import { nameConfigKeyNotSet } from "./name-config-key-not-set.ts";
|
|
23
|
+
|
|
24
|
+
const isRunCalledDuringImport = Schema.is(RunCalledDuringImport);
|
|
25
|
+
|
|
26
|
+
export const runTaskBody = Effect.fn("runTaskBody")(
|
|
27
|
+
function* (
|
|
28
|
+
startMessage: typeof StartTaskFiber.Type,
|
|
29
|
+
body: ReturnType<typeof makeTaskBodyRecord>,
|
|
30
|
+
) {
|
|
31
|
+
yield* reportToMainThread(
|
|
32
|
+
TaskEvent.cases.TaskFiberLoading.make({ taskName: startMessage.taskName }),
|
|
33
|
+
);
|
|
34
|
+
yield* markImportingTaskModule(
|
|
35
|
+
Effect.tryPromise({
|
|
36
|
+
try: () => import(startMessage.taskFilePath),
|
|
37
|
+
catch: (cause) =>
|
|
38
|
+
isRunCalledDuringImport(cause)
|
|
39
|
+
? cause
|
|
40
|
+
: new TaskModuleImportFailed({ filePath: startMessage.taskFilePath, cause }),
|
|
41
|
+
}),
|
|
42
|
+
);
|
|
43
|
+
const tasksMade = findTasksMadeWithName(startMessage.taskName);
|
|
44
|
+
const [task] = tasksMade;
|
|
45
|
+
if (task === undefined) {
|
|
46
|
+
return yield* new TaskNotRegisteredInWorker({
|
|
47
|
+
taskName: startMessage.taskName,
|
|
48
|
+
filePath: startMessage.taskFilePath,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
if (tasksMade.length > 1) {
|
|
52
|
+
return yield* new TaskRegisteredAgainInWorker({
|
|
53
|
+
taskName: startMessage.taskName,
|
|
54
|
+
filePath: startMessage.taskFilePath,
|
|
55
|
+
madeCount: tasksMade.length,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
body.startedAtMilliseconds = yield* Clock.currentTimeMillis;
|
|
59
|
+
yield* reportToMainThread(
|
|
60
|
+
TaskEvent.cases.TaskFiberStarted.make({ taskName: startMessage.taskName }),
|
|
61
|
+
);
|
|
62
|
+
const workerState = yield* WorkerState;
|
|
63
|
+
return yield* Effect.uninterruptibleMask((restore) =>
|
|
64
|
+
restore(task.body).pipe(
|
|
65
|
+
nameConfigKeyNotSet,
|
|
66
|
+
Effect.provideService(InsideTaskBody, true),
|
|
67
|
+
Effect.onExit((bodyExit) =>
|
|
68
|
+
Effect.gen(function* () {
|
|
69
|
+
const endedWithOnlyInterrupts =
|
|
70
|
+
Exit.isFailure(bodyExit) && Cause.hasInterruptsOnly(bodyExit.cause);
|
|
71
|
+
if (!endedWithOnlyInterrupts) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (yield* workerState.wasAskedToStop(startMessage.taskName)) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const interruptedItself = Cause.fail(
|
|
78
|
+
new CauseWithoutFailure({ details: Cause.pretty(bodyExit.cause) }),
|
|
79
|
+
);
|
|
80
|
+
body.causeReportedBeforeCleanup = Option.some(interruptedItself);
|
|
81
|
+
yield* reportToMainThread(
|
|
82
|
+
TaskEvent.cases.TaskFiberFailedBeforeCleanup.make({
|
|
83
|
+
taskName: startMessage.taskName,
|
|
84
|
+
failure: describeBodyFailure(interruptedItself),
|
|
85
|
+
}),
|
|
86
|
+
);
|
|
87
|
+
}),
|
|
88
|
+
),
|
|
89
|
+
Effect.tapCause((cause) => {
|
|
90
|
+
if (Cause.hasInterruptsOnly(cause)) {
|
|
91
|
+
return Effect.void;
|
|
92
|
+
}
|
|
93
|
+
body.causeReportedBeforeCleanup = Option.some(cause);
|
|
94
|
+
return reportToMainThread(
|
|
95
|
+
TaskEvent.cases.TaskFiberFailedBeforeCleanup.make({
|
|
96
|
+
taskName: startMessage.taskName,
|
|
97
|
+
failure: describeBodyFailure(cause),
|
|
98
|
+
}),
|
|
99
|
+
);
|
|
100
|
+
}),
|
|
101
|
+
),
|
|
102
|
+
);
|
|
103
|
+
},
|
|
104
|
+
(effect, startMessage, body) =>
|
|
105
|
+
Effect.gen(function* () {
|
|
106
|
+
const workerState = yield* WorkerState;
|
|
107
|
+
yield* Effect.annotateCurrentSpan({
|
|
108
|
+
[`${TASK_TRACE_LABEL_PREFIX}.task`]: startMessage.taskName,
|
|
109
|
+
[`${TASK_TRACE_LABEL_PREFIX}.worker`]: workerState.workerId,
|
|
110
|
+
});
|
|
111
|
+
return yield* effect.pipe(
|
|
112
|
+
Effect.scoped,
|
|
113
|
+
runInChildFiberAndJoin,
|
|
114
|
+
provideTaskServices(startMessage, workerState, body),
|
|
115
|
+
);
|
|
116
|
+
}),
|
|
117
|
+
);
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { parentPort } from "node:worker_threads";
|
|
2
|
+
|
|
3
|
+
import { Deferred, Effect, Exit, FiberSet, Layer } from "effect";
|
|
4
|
+
import { WorkerRunner } from "effect/workers";
|
|
5
|
+
import { WorkerError, WorkerSpawnError } from "effect/workers/WorkerError";
|
|
6
|
+
|
|
7
|
+
export const ParentPortWorkerRunnerLive = Layer.succeed(WorkerRunner.WorkerRunnerPlatform)({
|
|
8
|
+
start: <Outgoing, Incoming>(): Effect.Effect<
|
|
9
|
+
WorkerRunner.WorkerRunner<Outgoing, Incoming>,
|
|
10
|
+
WorkerError
|
|
11
|
+
> =>
|
|
12
|
+
Effect.gen(function* () {
|
|
13
|
+
const port = yield* Effect.fromNullishOr(parentPort).pipe(
|
|
14
|
+
Effect.mapError(
|
|
15
|
+
() =>
|
|
16
|
+
new WorkerError({
|
|
17
|
+
reason: new WorkerSpawnError({ message: "not running in a worker thread" }),
|
|
18
|
+
}),
|
|
19
|
+
),
|
|
20
|
+
);
|
|
21
|
+
const sendUnsafe = (_portId: number, message: Outgoing) => {
|
|
22
|
+
port.postMessage([1, message]);
|
|
23
|
+
};
|
|
24
|
+
return {
|
|
25
|
+
run: <Success, Failure, Services>(
|
|
26
|
+
handler: (
|
|
27
|
+
portId: number,
|
|
28
|
+
message: Incoming,
|
|
29
|
+
) => Effect.Effect<Success, Failure, Services> | void,
|
|
30
|
+
) =>
|
|
31
|
+
Effect.gen(function* () {
|
|
32
|
+
const runInWorkerScope = yield* FiberSet.makeRuntime<Services, Success, Failure>();
|
|
33
|
+
const closed = yield* Deferred.make<void>();
|
|
34
|
+
const onMessage = (message: WorkerRunner.PlatformMessage<Incoming>) => {
|
|
35
|
+
if (message[0] === 1) {
|
|
36
|
+
Deferred.doneUnsafe(closed, Exit.void);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const handled = handler(0, message[1]);
|
|
40
|
+
if (Effect.isEffect(handled)) {
|
|
41
|
+
runInWorkerScope(handled);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
yield* Effect.acquireRelease(
|
|
45
|
+
Effect.sync(() => {
|
|
46
|
+
port.on("message", onMessage);
|
|
47
|
+
port.postMessage([0]);
|
|
48
|
+
}),
|
|
49
|
+
() =>
|
|
50
|
+
Effect.sync(() => {
|
|
51
|
+
port.off("message", onMessage);
|
|
52
|
+
}),
|
|
53
|
+
);
|
|
54
|
+
yield* Deferred.await(closed);
|
|
55
|
+
}).pipe(Effect.scoped),
|
|
56
|
+
send: (portId: number, message: Outgoing) =>
|
|
57
|
+
Effect.sync(() => {
|
|
58
|
+
sendUnsafe(portId, message);
|
|
59
|
+
}),
|
|
60
|
+
sendUnsafe,
|
|
61
|
+
};
|
|
62
|
+
}),
|
|
63
|
+
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { parentPort } from "node:worker_threads";
|
|
2
|
+
|
|
3
|
+
import * as BunCrypto from "@effect/platform-bun/BunCrypto";
|
|
4
|
+
import * as BunServices from "@effect/platform-bun/BunServices";
|
|
5
|
+
import { Layer, Effect, Exit } from "effect";
|
|
6
|
+
import { FetchHttpClient } from "effect/http";
|
|
7
|
+
import { OtlpExporter, OtlpSerialization } from "effect/observability";
|
|
8
|
+
import { RpcServer } from "effect/rpc";
|
|
9
|
+
|
|
10
|
+
import { runtimeConfigProviderLayer } from "../../../shared/read-environment-config.ts";
|
|
11
|
+
import { WorkerStateLive } from "../shared/provide-worker-state.ts";
|
|
12
|
+
import { serveTheMainThread } from "./answer-main-thread-messages.ts";
|
|
13
|
+
import { ParentPortWorkerRunnerLive } from "./serve-on-the-parent-port.ts";
|
|
14
|
+
|
|
15
|
+
const workerThreadLayer = WorkerStateLive.pipe(
|
|
16
|
+
Layer.provideMerge(RpcServer.layerProtocolWorkerRunner),
|
|
17
|
+
Layer.provide(ParentPortWorkerRunnerLive),
|
|
18
|
+
Layer.provideMerge(
|
|
19
|
+
Layer.mergeAll(
|
|
20
|
+
BunServices.layer,
|
|
21
|
+
BunCrypto.layerDigest,
|
|
22
|
+
BunCrypto.layerSecureRandom,
|
|
23
|
+
FetchHttpClient.layer,
|
|
24
|
+
runtimeConfigProviderLayer,
|
|
25
|
+
OtlpExporter.layerFlusher,
|
|
26
|
+
OtlpSerialization.layerJson,
|
|
27
|
+
),
|
|
28
|
+
),
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
export const startWorkerThread = () => {
|
|
32
|
+
if (parentPort !== null) {
|
|
33
|
+
Effect.runFork(
|
|
34
|
+
serveTheMainThread.pipe(
|
|
35
|
+
Effect.provide(workerThreadLayer),
|
|
36
|
+
Effect.scoped,
|
|
37
|
+
Effect.onExit((exit) => Effect.sync(() => process.exit(Exit.isSuccess(exit) ? 0 : 1))),
|
|
38
|
+
),
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { provideTaskServices } from "./internal/provide-task-services.ts";
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Array as Arrays, Logger, Formatter } from "effect";
|
|
2
|
+
|
|
3
|
+
import { formatCauseLines } from "../../../../../shared/format-error-lines.ts";
|
|
4
|
+
import { prefixLines } from "../../../../../shared/format-task-lines.ts";
|
|
5
|
+
import { waitWhileTaskLogsAreHeld } from "../../../../../shared/hold-task-logs.ts";
|
|
6
|
+
import { TaskEvent } from "../../../../../shared/rpc.ts";
|
|
7
|
+
import type { StartTaskFiber } from "../../../../../shared/rpc.ts";
|
|
8
|
+
import type { makeTaskBodyRecord } from "../../../shared/define-task-body-record.ts";
|
|
9
|
+
|
|
10
|
+
export const makeTaskLogger = (
|
|
11
|
+
startMessage: typeof StartTaskFiber.Type,
|
|
12
|
+
body: ReturnType<typeof makeTaskBodyRecord>,
|
|
13
|
+
taskLogHold: Int32Array,
|
|
14
|
+
reportToMainThreadNow: (event: typeof TaskEvent.Type) => void,
|
|
15
|
+
) =>
|
|
16
|
+
Logger.make((logEntry) => {
|
|
17
|
+
const text = Arrays.ensure(logEntry.message)
|
|
18
|
+
.map((part) => (typeof part === "string" ? part : Formatter.format(part)))
|
|
19
|
+
.join(" ");
|
|
20
|
+
const line = [
|
|
21
|
+
...(text === "" ? [] : [text]),
|
|
22
|
+
...(logEntry.cause.reasons.length === 0
|
|
23
|
+
? []
|
|
24
|
+
: [formatCauseLines(logEntry.cause, startMessage.taskName)]),
|
|
25
|
+
].join("\n");
|
|
26
|
+
body.logs.push(line);
|
|
27
|
+
waitWhileTaskLogsAreHeld(taskLogHold);
|
|
28
|
+
reportToMainThreadNow(
|
|
29
|
+
TaskEvent.cases.StandardErrorLineRequested.make({
|
|
30
|
+
logLevel: logEntry.logLevel,
|
|
31
|
+
text: prefixLines(startMessage.taskName, line),
|
|
32
|
+
}),
|
|
33
|
+
);
|
|
34
|
+
});
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { Effect, FileSystem, Logger, Path } from "effect";
|
|
2
|
+
import { ChildProcessSpawner } from "effect/process";
|
|
3
|
+
|
|
4
|
+
import { TASK_TRACE_LABEL_PREFIX } from "../../../../../shared/names-from-package-json.ts";
|
|
5
|
+
import { TaskEvent } from "../../../../../shared/rpc.ts";
|
|
6
|
+
import type { StartTaskFiber } from "../../../../../shared/rpc.ts";
|
|
7
|
+
import { Serving, Tasks } from "../../../../../shared/task-services.ts";
|
|
8
|
+
import { decodeTaskResultJson } from "../../../shared/decode-task-result-json.ts";
|
|
9
|
+
import type { OptionalJson } from "../../../shared/decode-task-result-json.ts";
|
|
10
|
+
import type { makeTaskBodyRecord } from "../../../shared/define-task-body-record.ts";
|
|
11
|
+
import { reportToMainThread, WorkerState } from "../../../shared/provide-worker-state.ts";
|
|
12
|
+
import { makeTaskLogger } from "./make-task-logger.ts";
|
|
13
|
+
import { provideTaskStdio } from "./read-standard-input-from-main-thread.ts";
|
|
14
|
+
import { resolvePathsFromPackageDirectory } from "./resolve-paths-from-package-directory.ts";
|
|
15
|
+
import { runCommandsInPackageDirectory } from "./run-commands-in-package-directory.ts";
|
|
16
|
+
import { spawnReportedProcess } from "./spawn-reported-process.ts";
|
|
17
|
+
|
|
18
|
+
const serve = (startMessage: typeof StartTaskFiber.Type, served: typeof OptionalJson.Type) =>
|
|
19
|
+
reportToMainThread(
|
|
20
|
+
TaskEvent.cases.TaskFiberServed.make({
|
|
21
|
+
taskName: startMessage.taskName,
|
|
22
|
+
...(served === undefined ? {} : { value: served }),
|
|
23
|
+
}),
|
|
24
|
+
).pipe(Effect.andThen(Effect.never));
|
|
25
|
+
|
|
26
|
+
export const provideTaskServices =
|
|
27
|
+
(
|
|
28
|
+
startMessage: typeof StartTaskFiber.Type,
|
|
29
|
+
workerState: WorkerState["Service"],
|
|
30
|
+
body: ReturnType<typeof makeTaskBodyRecord>,
|
|
31
|
+
) =>
|
|
32
|
+
<Success, Failure, Services>(effect: Effect.Effect<Success, Failure, Services>) =>
|
|
33
|
+
Effect.gen(function* () {
|
|
34
|
+
const { fileSystem, path } = resolvePathsFromPackageDirectory(
|
|
35
|
+
yield* Path.Path,
|
|
36
|
+
yield* FileSystem.FileSystem,
|
|
37
|
+
startMessage.taskPackageDirectoryPath,
|
|
38
|
+
);
|
|
39
|
+
return yield* effect.pipe(
|
|
40
|
+
provideTaskStdio(startMessage, workerState),
|
|
41
|
+
Effect.provideService(Path.Path, path),
|
|
42
|
+
Effect.provideService(FileSystem.FileSystem, fileSystem),
|
|
43
|
+
Effect.provideService(
|
|
44
|
+
Tasks,
|
|
45
|
+
Tasks.of({
|
|
46
|
+
requestResult: (dependencyTaskDefinition) =>
|
|
47
|
+
workerState.requestDependencyTaskResult(
|
|
48
|
+
dependencyTaskDefinition.name,
|
|
49
|
+
startMessage.taskName,
|
|
50
|
+
),
|
|
51
|
+
}),
|
|
52
|
+
),
|
|
53
|
+
Effect.provideService(
|
|
54
|
+
Serving,
|
|
55
|
+
Serving.of({
|
|
56
|
+
serve: (servedValue) =>
|
|
57
|
+
decodeTaskResultJson(startMessage.taskName, "served", servedValue).pipe(
|
|
58
|
+
Effect.flatMap((served) => serve(startMessage, served)),
|
|
59
|
+
Effect.provideService(WorkerState, workerState),
|
|
60
|
+
),
|
|
61
|
+
}),
|
|
62
|
+
),
|
|
63
|
+
Effect.provideService(
|
|
64
|
+
ChildProcessSpawner.ChildProcessSpawner,
|
|
65
|
+
runCommandsInPackageDirectory(path, startMessage.taskPackageDirectoryPath, (command) =>
|
|
66
|
+
spawnReportedProcess(startMessage, body, command).pipe(
|
|
67
|
+
Effect.provideService(WorkerState, workerState),
|
|
68
|
+
),
|
|
69
|
+
),
|
|
70
|
+
),
|
|
71
|
+
Effect.provideService(
|
|
72
|
+
Logger.CurrentLoggers,
|
|
73
|
+
new Set([
|
|
74
|
+
...(yield* Logger.CurrentLoggers),
|
|
75
|
+
makeTaskLogger(
|
|
76
|
+
startMessage,
|
|
77
|
+
body,
|
|
78
|
+
workerState.taskLogHold,
|
|
79
|
+
workerState.reportToMainThreadNow,
|
|
80
|
+
),
|
|
81
|
+
]),
|
|
82
|
+
),
|
|
83
|
+
Effect.annotateLogs(`${TASK_TRACE_LABEL_PREFIX}.task`, startMessage.taskName),
|
|
84
|
+
workerState.provideRuntimeServices,
|
|
85
|
+
);
|
|
86
|
+
});
|