@graftland/plugin-remote 0.3.0 → 0.3.2
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/dist/Auth.d.ts +2 -2
- package/dist/Auth.d.ts.map +1 -1
- package/dist/Auth.js.map +1 -1
- package/dist/{Bootstrap-MCwivGN1.js → Bootstrap-H9gDsgsC.js} +2 -2
- package/dist/{Contract-CcpSIJm4.js → Contract-DsJtisvL.js} +8 -46
- package/dist/Contract.d.ts +50 -53
- package/dist/Contract.d.ts.map +1 -1
- package/dist/Contract.js +1 -1
- package/dist/Contract.js.map +1 -1
- package/dist/{Errors-oPsTLY7l.js → Errors-DYhsGZcZ.js} +14 -1
- package/dist/Errors.d.ts +19 -0
- package/dist/Errors.d.ts.map +1 -1
- package/dist/Errors.js +14 -1
- package/dist/Errors.js.map +1 -1
- package/dist/{FailureGroup-BcH0XOBi.js → FailureGroup-BgT73AaR.js} +14 -4
- package/dist/{Framing-zaYdOJnT.js → Framing-G9eSaeLb.js} +1 -1
- package/dist/{Graft-BsYq3F-J.js → Graft-B71CPA2Y.js} +46 -35
- package/dist/{Packages-B1TPk8pa.js → Packages-AgoCGotL.js} +23 -26
- package/dist/{Peer-IJgFK6mD.js → Peer-DXeVrGBh.js} +5 -5
- package/dist/{ProcessObservation-DEGrEMfP.js → ProcessObservation-gLgGirYv.js} +1 -1
- package/dist/{ServeLifecycle-CJM0gG5B.js → ServeLifecycle-Bd1FPJ6e.js} +1 -1
- package/dist/Testing.d.ts +4 -4
- package/dist/Testing.d.ts.map +1 -1
- package/dist/Testing.js +10 -4
- package/dist/Testing.js.map +1 -1
- package/dist/Transport.d.ts +2 -2
- package/dist/Transport.d.ts.map +1 -1
- package/dist/Transport.js.map +1 -1
- package/dist/bin.js +48 -47
- package/dist/bin.js.map +1 -1
- package/dist/{childRuntime-DSqtFN9o.js → childRuntime-Bm3iSg_N.js} +30 -26
- package/dist/connectionEnded-BwcxQ7W8.js +54 -0
- package/dist/{entry-SYsx9VNb.js → entry-psOpX3Bj.js} +76 -48
- package/dist/host/auth/bearer.d.ts +1 -2
- package/dist/host/auth/bearer.d.ts.map +1 -1
- package/dist/host/auth/bearer.js +1 -1
- package/dist/host/auth/bearer.js.map +1 -1
- package/dist/host/auth/jwt.d.ts +1 -2
- package/dist/host/auth/jwt.d.ts.map +1 -1
- package/dist/host/auth/jwt.js +1 -1
- package/dist/host/auth/jwt.js.map +1 -1
- package/dist/host/auth/mtls.js +2 -2
- package/dist/host/auth/none.js +1 -1
- package/dist/host/command.d.ts +1 -1
- package/dist/host/command.d.ts.map +1 -1
- package/dist/host/command.js +4 -4
- package/dist/host/command.js.map +1 -1
- package/dist/host/local.d.ts +1 -2
- package/dist/host/local.d.ts.map +1 -1
- package/dist/host/local.js +3 -3
- package/dist/host/local.js.map +1 -1
- package/dist/host/unix.d.ts +1 -1
- package/dist/host/unix.d.ts.map +1 -1
- package/dist/host/unix.js +3 -3
- package/dist/host/unix.js.map +1 -1
- package/dist/host/websocket.d.ts +1 -1
- package/dist/host/websocket.d.ts.map +1 -1
- package/dist/host/websocket.js +3 -3
- package/dist/host/websocket.js.map +1 -1
- package/dist/host/worker.d.ts +1 -2
- package/dist/host/worker.d.ts.map +1 -1
- package/dist/host/worker.js +4 -5
- package/dist/host/worker.js.map +1 -1
- package/dist/{importer-D7zSgqxq.js → importer-Cvf88eAY.js} +5 -8
- package/dist/index.d.ts +2 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -10
- package/dist/index.js.map +1 -1
- package/dist/internal/Certificates.js +4 -4
- package/dist/internal/Certificates.js.map +1 -1
- package/dist/internal/FailureGroup.js +3 -2
- package/dist/internal/FailureGroup.js.map +1 -1
- package/dist/internal/assembly.js +9 -2
- package/dist/internal/assembly.js.map +1 -1
- package/dist/internal/auth/mtls.js +1 -1
- package/dist/internal/auth/mtls.js.map +1 -1
- package/dist/internal/auth/tokenCredentials.d.ts +0 -1
- package/dist/internal/auth/tokenCredentials.d.ts.map +1 -1
- package/dist/internal/auth/tokenCredentials.js.map +1 -1
- package/dist/internal/child.js +20 -17
- package/dist/internal/child.js.map +1 -1
- package/dist/internal/childRuntime.js +6 -4
- package/dist/internal/childRuntime.js.map +1 -1
- package/dist/internal/contract.js +26 -0
- package/dist/internal/contract.js.map +1 -0
- package/dist/internal/credentials.d.ts +6 -6
- package/dist/internal/credentials.d.ts.map +1 -1
- package/dist/internal/credentials.js.map +1 -1
- package/dist/internal/directTransport.d.ts +1 -1
- package/dist/internal/entry.d.ts +1 -2
- package/dist/internal/entry.d.ts.map +1 -1
- package/dist/internal/entry.js +4 -14
- package/dist/internal/entry.js.map +1 -1
- package/dist/internal/execution.js +44 -7
- package/dist/internal/execution.js.map +1 -1
- package/dist/internal/host/runner.js +7 -6
- package/dist/internal/host/runner.js.map +1 -1
- package/dist/internal/host.js +5 -5
- package/dist/internal/host.js.map +1 -1
- package/dist/internal/port.d.ts +2 -10
- package/dist/internal/port.js +5 -5
- package/dist/internal/port.js.map +1 -1
- package/dist/internal/release.js +1 -1
- package/dist/internal/release.js.map +1 -1
- package/dist/internal/runner/Connection.d.ts +1 -1
- package/dist/internal/runner/Connection.js +4 -4
- package/dist/internal/runner/Connection.js.map +1 -1
- package/dist/internal/runner/Execution.js +3 -3
- package/dist/internal/runner/Execution.js.map +1 -1
- package/dist/internal/runner/Framing.d.ts +1 -11
- package/dist/internal/runner/Framing.js +1 -1
- package/dist/internal/runner/Framing.js.map +1 -1
- package/dist/internal/runner/Local.js +1 -1
- package/dist/internal/runner/Local.js.map +1 -1
- package/dist/internal/runner/Lock.js +1 -1
- package/dist/internal/runner/Lock.js.map +1 -1
- package/dist/internal/runner/Packages.d.ts +1 -1
- package/dist/internal/runner/Packages.js +22 -25
- package/dist/internal/runner/Packages.js.map +1 -1
- package/dist/internal/runner/Processes.js +7 -9
- package/dist/internal/runner/Processes.js.map +1 -1
- package/dist/internal/runner/Store.js +3 -3
- package/dist/internal/runner/Store.js.map +1 -1
- package/dist/internal/runner/Supervisor.js +46 -47
- package/dist/internal/runner/Supervisor.js.map +1 -1
- package/dist/internal/runner/accept.js +3 -3
- package/dist/internal/runner/accept.js.map +1 -1
- package/dist/internal/runner/model.js +1 -1
- package/dist/internal/runner/model.js.map +1 -1
- package/dist/internal/serve.js +1 -1
- package/dist/internal/serve.js.map +1 -1
- package/dist/internal/services.d.ts +2 -12
- package/dist/internal/services.d.ts.map +1 -1
- package/dist/internal/services.js.map +1 -1
- package/dist/internal/supervisorPlugin.js +1 -1
- package/dist/internal/watchdogMain.js +5 -5
- package/dist/internal/watchdogMain.js.map +1 -1
- package/dist/internal/websocketServer.js +3 -1
- package/dist/internal/websocketServer.js.map +1 -1
- package/dist/internal/workerMain.js +3 -3
- package/dist/{port-Blbh8tms.js → port--3x2zJ4D.js} +8 -8
- package/dist/{release-BY4Mlluy.js → release-DfZPuIcK.js} +1 -1
- package/dist/runner/auth/bearer.js +2 -2
- package/dist/runner/auth/jwt.js +4 -4
- package/dist/runner/auth/jwt.js.map +1 -1
- package/dist/runner/auth/mtls.js +3 -3
- package/dist/runner/auth/none.js +1 -1
- package/dist/runner/index.js +5 -5
- package/dist/runner/stdio.js +3 -3
- package/dist/runner/unix.js +3 -3
- package/dist/runner/websocket.js +4 -4
- package/dist/{socketChannel-KmtzF-9G.js → socketChannel-CJvL2DiB.js} +2 -2
- package/dist/{supervisorPlugin-Inb1S5IV.js → supervisorPlugin-t6Z6PrhD.js} +72 -76
- package/dist/{token-v5ne2I0-.js → token-CYBNNlhS.js} +1 -1
- package/dist/{tokenCredentials-WUJm2AKm.js → tokenCredentials-CbCuk-Rt.js} +3 -3
- package/dist/{websocketServer-MXcCJx0v.js → websocketServer-NQhODlEt.js} +5 -3
- package/dist/{workerChannel-P82YdNjh.js → workerChannel-C8hhBJzA.js} +1 -1
- package/package.json +3 -3
- package/src/Auth.ts +9 -2
- package/src/Contract.ts +67 -51
- package/src/Errors.ts +23 -0
- package/src/Testing.ts +16 -2
- package/src/Transport.ts +6 -2
- package/src/bin.ts +28 -30
- package/src/host/auth/bearer.ts +1 -6
- package/src/host/auth/jwt.ts +1 -6
- package/src/host/command.ts +2 -0
- package/src/host/local.ts +5 -9
- package/src/host/unix.ts +2 -0
- package/src/host/websocket.ts +2 -0
- package/src/host/worker.ts +4 -6
- package/src/index.ts +8 -4
- package/src/internal/Certificates.ts +10 -13
- package/src/internal/FailureGroup.ts +128 -121
- package/src/internal/assembly.ts +19 -10
- package/src/internal/auth/mtls.ts +19 -20
- package/src/internal/auth/tokenCredentials.ts +1 -7
- package/src/internal/child.ts +249 -240
- package/src/internal/childRuntime.ts +84 -81
- package/src/internal/contract.ts +47 -0
- package/src/internal/credentials.ts +12 -9
- package/src/internal/entry.ts +11 -25
- package/src/internal/execution.ts +73 -14
- package/src/internal/host/runner.ts +153 -153
- package/src/internal/host.ts +123 -130
- package/src/internal/port.ts +100 -103
- package/src/internal/release.ts +3 -2
- package/src/internal/runner/Connection.ts +52 -60
- package/src/internal/runner/Execution.ts +163 -164
- package/src/internal/runner/Framing.ts +9 -10
- package/src/internal/runner/Local.ts +26 -27
- package/src/internal/runner/Lock.ts +23 -25
- package/src/internal/runner/Packages.ts +67 -70
- package/src/internal/runner/Processes.ts +89 -92
- package/src/internal/runner/Store.ts +110 -114
- package/src/internal/runner/Supervisor.ts +392 -405
- package/src/internal/runner/accept.ts +76 -84
- package/src/internal/runner/model.ts +20 -21
- package/src/internal/serve.ts +15 -13
- package/src/internal/services.ts +1 -19
- package/src/internal/watchdogMain.ts +16 -11
- package/src/internal/websocketServer.ts +18 -3
- package/src/runner/auth/jwt.ts +10 -6
- package/dist/cleanup-BPWr-5U9.js +0 -13
- package/dist/connectionEnded-DUgcobEd.js +0 -9
- package/dist/internal/childErrors.d.ts +0 -33
- package/dist/internal/childErrors.d.ts.map +0 -1
- package/dist/internal/port.d.ts.map +0 -1
- package/dist/internal/runner/Framing.d.ts.map +0 -1
|
@@ -45,192 +45,191 @@ export class Channels extends Context.Service<
|
|
|
45
45
|
}
|
|
46
46
|
>()("@graftland/plugin-remote/internal/runner/Execution/Channels") {}
|
|
47
47
|
|
|
48
|
-
export const make = (root: string)
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
).pipe(Context.add(FileSystem.FileSystem, fs), Context.add(Path.Path, path))
|
|
48
|
+
export const make = Effect.fnUntraced(function* (root: string) {
|
|
49
|
+
const spawner = yield* ChildProcessSpawner.ChildProcessSpawner
|
|
50
|
+
const fs = yield* FileSystem.FileSystem
|
|
51
|
+
const path = yield* Path.Path
|
|
52
|
+
const platform = Context.make(
|
|
53
|
+
ChildProcessSpawner.ChildProcessSpawner,
|
|
54
|
+
spawner,
|
|
55
|
+
).pipe(Context.add(FileSystem.FileSystem, fs), Context.add(Path.Path, path))
|
|
57
56
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
},
|
|
84
|
-
limits,
|
|
85
|
-
}),
|
|
86
|
-
],
|
|
87
|
-
{
|
|
88
|
-
stdin: "pipe",
|
|
89
|
-
stdout: "pipe",
|
|
90
|
-
stderr: "pipe",
|
|
91
|
-
additionalFds: {
|
|
92
|
-
fd3: { type: "output" },
|
|
93
|
-
fd4: { type: "input" },
|
|
57
|
+
const peers = yield* Ref.make(HashMap.empty<string, Multiplex.Peer>())
|
|
58
|
+
const claimed = yield* Ref.make(HashSet.empty<string>())
|
|
59
|
+
const driver = Execution.of({
|
|
60
|
+
recover: (child) =>
|
|
61
|
+
Processes.recover(child).pipe(Effect.provideContext(platform)),
|
|
62
|
+
spawn: Effect.fnUntraced(
|
|
63
|
+
function* (handle, request, limits) {
|
|
64
|
+
const resolved = yield* Packages.resolve(
|
|
65
|
+
root,
|
|
66
|
+
request.specifier,
|
|
67
|
+
request.digest,
|
|
68
|
+
)
|
|
69
|
+
const argv = yield* command()
|
|
70
|
+
const child = yield* spawner.spawn(
|
|
71
|
+
ChildProcess.make(
|
|
72
|
+
argv[0],
|
|
73
|
+
[
|
|
74
|
+
...Array.drop(argv, 1),
|
|
75
|
+
"child",
|
|
76
|
+
resolved.entry,
|
|
77
|
+
handle.token,
|
|
78
|
+
yield* Schema.encodeEffect(Schema.fromJsonString(Bootstrap))({
|
|
79
|
+
identity: {
|
|
80
|
+
id: handle.key.instance,
|
|
81
|
+
generation: handle.generation,
|
|
94
82
|
},
|
|
95
|
-
|
|
83
|
+
limits,
|
|
84
|
+
}),
|
|
85
|
+
],
|
|
86
|
+
{
|
|
87
|
+
stdin: "pipe",
|
|
88
|
+
stdout: "pipe",
|
|
89
|
+
stderr: "pipe",
|
|
90
|
+
additionalFds: {
|
|
91
|
+
fd3: { type: "output" },
|
|
92
|
+
fd4: { type: "input" },
|
|
96
93
|
},
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
94
|
+
forceKillAfter: "1 second",
|
|
95
|
+
},
|
|
96
|
+
),
|
|
97
|
+
)
|
|
98
|
+
const observation = yield* ProcessObservation.observe(child)
|
|
99
|
+
const exited = observation.exited.pipe(
|
|
100
|
+
Effect.mapError((error) =>
|
|
101
|
+
ExecutionError.make({
|
|
102
|
+
detail: "Observing child exit failed",
|
|
103
|
+
cause: Cause.fail(error),
|
|
104
|
+
}),
|
|
105
|
+
),
|
|
106
|
+
)
|
|
107
|
+
const failures = yield* FailureGroup.make<ExecutionError>()
|
|
108
|
+
yield* failures.run(
|
|
109
|
+
observation.failure.pipe(
|
|
101
110
|
Effect.mapError((error) =>
|
|
102
111
|
ExecutionError.make({
|
|
103
|
-
detail: "
|
|
112
|
+
detail: "Reading child output failed",
|
|
104
113
|
cause: Cause.fail(error),
|
|
105
114
|
}),
|
|
106
115
|
),
|
|
107
|
-
)
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
observation.failure.pipe(
|
|
111
|
-
Effect.mapError((error) =>
|
|
112
|
-
ExecutionError.make({
|
|
113
|
-
detail: "Reading child output failed",
|
|
114
|
-
cause: Cause.fail(error),
|
|
115
|
-
}),
|
|
116
|
-
),
|
|
117
|
-
),
|
|
118
|
-
)
|
|
119
|
-
const controls = yield* Queue.bounded<string>(4)
|
|
116
|
+
),
|
|
117
|
+
)
|
|
118
|
+
const controls = yield* Queue.bounded<string>(4)
|
|
120
119
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
120
|
+
yield* failures.run(
|
|
121
|
+
Stream.fromQueue(controls).pipe(
|
|
122
|
+
Stream.map((line) => new TextEncoder().encode(line + "\n")),
|
|
123
|
+
Stream.run(child.getInputFd(4)),
|
|
124
|
+
Effect.mapError((error) =>
|
|
125
|
+
ExecutionError.make({
|
|
126
|
+
detail: "Child supervision channel failed",
|
|
127
|
+
cause: Cause.fail(error),
|
|
128
|
+
}),
|
|
129
|
+
),
|
|
130
|
+
),
|
|
131
|
+
)
|
|
132
|
+
const send = (value: typeof Command.Type) =>
|
|
133
|
+
Effect.raceFirst(
|
|
134
|
+
Schema.encodeEffect(CommandJson)(value).pipe(
|
|
135
|
+
Effect.flatMap((line) => Queue.offer(controls, line)),
|
|
136
|
+
Effect.asVoid,
|
|
125
137
|
Effect.mapError((error) =>
|
|
126
138
|
ExecutionError.make({
|
|
127
|
-
detail: "
|
|
139
|
+
detail: "Encoding watchdog command failed",
|
|
128
140
|
cause: Cause.fail(error),
|
|
129
141
|
}),
|
|
130
142
|
),
|
|
131
143
|
),
|
|
144
|
+
failures.await,
|
|
132
145
|
)
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
Effect.mapError((error) =>
|
|
139
|
-
ExecutionError.make({
|
|
140
|
-
detail: "Encoding watchdog command failed",
|
|
141
|
-
cause: Cause.fail(error),
|
|
142
|
-
}),
|
|
143
|
-
),
|
|
144
|
-
),
|
|
145
|
-
failures.await,
|
|
146
|
-
)
|
|
147
|
-
const peer = yield* Multiplex.make({
|
|
148
|
-
input: child
|
|
149
|
-
.getOutputFd(3)
|
|
150
|
-
.pipe(
|
|
151
|
-
Stream.mapError((error) =>
|
|
152
|
-
TransportError.make({ cause: Cause.fail(error) }),
|
|
153
|
-
),
|
|
154
|
-
),
|
|
155
|
-
output: child.stdin.pipe(
|
|
156
|
-
Sink.mapError((error) =>
|
|
146
|
+
const peer = yield* Multiplex.make({
|
|
147
|
+
input: child
|
|
148
|
+
.getOutputFd(3)
|
|
149
|
+
.pipe(
|
|
150
|
+
Stream.mapError((error) =>
|
|
157
151
|
TransportError.make({ cause: Cause.fail(error) }),
|
|
158
152
|
),
|
|
159
153
|
),
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
yield* Effect.addFinalizer(() =>
|
|
164
|
-
Ref.update(peers, HashMap.remove(handle.token)),
|
|
165
|
-
)
|
|
166
|
-
return {
|
|
167
|
-
code: resolved.identity,
|
|
168
|
-
start: send({ kind: "start" }),
|
|
169
|
-
identity,
|
|
170
|
-
exited,
|
|
171
|
-
interrupt: send({ kind: "stop" }),
|
|
172
|
-
kill: child.kill({ killSignal: "SIGKILL" }).pipe(
|
|
173
|
-
Effect.mapError((error) =>
|
|
174
|
-
ExecutionError.make({
|
|
175
|
-
detail: "Killing the child failed",
|
|
176
|
-
cause: Cause.fail(error),
|
|
177
|
-
}),
|
|
178
|
-
),
|
|
154
|
+
output: child.stdin.pipe(
|
|
155
|
+
Sink.mapError((error) =>
|
|
156
|
+
TransportError.make({ cause: Cause.fail(error) }),
|
|
179
157
|
),
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
),
|
|
199
|
-
}),
|
|
200
|
-
),
|
|
201
|
-
})
|
|
202
|
-
return {
|
|
203
|
-
driver,
|
|
204
|
-
peer: (token: string) =>
|
|
205
|
-
Effect.acquireRelease(
|
|
206
|
-
Effect.gen(function* () {
|
|
207
|
-
const peer = yield* Ref.get(peers).pipe(
|
|
208
|
-
Effect.flatMap((all) => {
|
|
209
|
-
const peer = HashMap.get(all, token)
|
|
210
|
-
return peer._tag === "Some"
|
|
211
|
-
? Effect.succeed(peer.value)
|
|
212
|
-
: Effect.fail(
|
|
213
|
-
SessionStopped.make({
|
|
214
|
-
detail: "The execution channel is no longer available",
|
|
215
|
-
}),
|
|
216
|
-
)
|
|
158
|
+
),
|
|
159
|
+
})
|
|
160
|
+
const identity = yield* Processes.identity(child.pid)
|
|
161
|
+
yield* Ref.update(peers, HashMap.set(handle.token, peer))
|
|
162
|
+
yield* Effect.addFinalizer(() =>
|
|
163
|
+
Ref.update(peers, HashMap.remove(handle.token)),
|
|
164
|
+
)
|
|
165
|
+
return {
|
|
166
|
+
code: resolved.identity,
|
|
167
|
+
start: send({ kind: "start" }),
|
|
168
|
+
identity,
|
|
169
|
+
exited,
|
|
170
|
+
interrupt: send({ kind: "stop" }),
|
|
171
|
+
kill: child.kill({ killSignal: "SIGKILL" }).pipe(
|
|
172
|
+
Effect.mapError((error) =>
|
|
173
|
+
ExecutionError.make({
|
|
174
|
+
detail: "Killing the child failed",
|
|
175
|
+
cause: Cause.fail(error),
|
|
217
176
|
}),
|
|
218
|
-
)
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
177
|
+
),
|
|
178
|
+
),
|
|
179
|
+
renew: (millis: number) => send({ kind: "renew", millis }),
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
Effect.provideContext(platform),
|
|
183
|
+
Effect.catchTags({
|
|
184
|
+
PlatformError: (error) =>
|
|
185
|
+
Effect.fail(
|
|
186
|
+
ExecutionError.make({
|
|
187
|
+
detail: "Starting the child failed",
|
|
188
|
+
cause: Cause.fail(error),
|
|
189
|
+
}),
|
|
190
|
+
),
|
|
191
|
+
SchemaError: (error) =>
|
|
192
|
+
Effect.fail(
|
|
193
|
+
ExecutionError.make({
|
|
194
|
+
detail: "Encoding child bootstrap failed",
|
|
195
|
+
cause: Cause.fail(error),
|
|
196
|
+
}),
|
|
197
|
+
),
|
|
198
|
+
}),
|
|
199
|
+
),
|
|
233
200
|
})
|
|
201
|
+
return {
|
|
202
|
+
driver,
|
|
203
|
+
peer: (token: string) =>
|
|
204
|
+
Effect.acquireRelease(
|
|
205
|
+
Effect.gen(function* () {
|
|
206
|
+
const peer = yield* Ref.get(peers).pipe(
|
|
207
|
+
Effect.flatMap((all) => {
|
|
208
|
+
const peer = HashMap.get(all, token)
|
|
209
|
+
return peer._tag === "Some"
|
|
210
|
+
? Effect.succeed(peer.value)
|
|
211
|
+
: Effect.fail(
|
|
212
|
+
SessionStopped.make({
|
|
213
|
+
detail: "The execution channel is no longer available",
|
|
214
|
+
}),
|
|
215
|
+
)
|
|
216
|
+
}),
|
|
217
|
+
)
|
|
218
|
+
const occupied = yield* Ref.modify(
|
|
219
|
+
claimed,
|
|
220
|
+
(all) =>
|
|
221
|
+
[HashSet.has(all, token), HashSet.add(all, token)] as const,
|
|
222
|
+
)
|
|
223
|
+
if (occupied)
|
|
224
|
+
return yield* SessionConflict.make({
|
|
225
|
+
detail: "The instance channel is already attached",
|
|
226
|
+
})
|
|
227
|
+
return peer
|
|
228
|
+
}),
|
|
229
|
+
() => Ref.update(claimed, HashSet.remove(token)),
|
|
230
|
+
),
|
|
231
|
+
}
|
|
232
|
+
})
|
|
234
233
|
|
|
235
234
|
export const layer = (root: string) =>
|
|
236
235
|
Layer.effectContext(
|
|
@@ -27,16 +27,15 @@ export const maxPayload = 1024 * 1024
|
|
|
27
27
|
const invalid = (detail: string) => FrameError.make({ detail })
|
|
28
28
|
|
|
29
29
|
/** Version 2 carries only channel and length; request admission belongs to port. */
|
|
30
|
-
export const encode = (frame: Frame)
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
})
|
|
30
|
+
export const encode = Effect.fnUntraced(function* (frame: Frame) {
|
|
31
|
+
if (frame.payload.byteLength > maxPayload)
|
|
32
|
+
return yield* invalid("Runner frame exceeds the payload limit")
|
|
33
|
+
const bytes = new Uint8Array(headerSize + frame.payload.byteLength)
|
|
34
|
+
bytes.set([2, frame.channel, 0, 0])
|
|
35
|
+
new DataView(bytes.buffer).setUint32(4, frame.payload.byteLength)
|
|
36
|
+
bytes.set(frame.payload, headerSize)
|
|
37
|
+
return bytes
|
|
38
|
+
})
|
|
40
39
|
|
|
41
40
|
/** Check a message boundary; the decoder still validates the frame's contents. */
|
|
42
41
|
export const isCompleteFrame = (bytes: Uint8Array): boolean =>
|
|
@@ -41,33 +41,32 @@ export const connect = Effect.fnUntraced(function* (
|
|
|
41
41
|
resources: yield* Effect.scope,
|
|
42
42
|
transport: { ...peer, failure: failures.await, report },
|
|
43
43
|
diagnostics: Fiber.await(exited).pipe(Effect.andThen(failures.cause)),
|
|
44
|
-
terminate: (graceful: boolean)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
onSome: (pid) => ({ pid }),
|
|
62
|
-
}),
|
|
63
|
-
...(execution.threadId === undefined
|
|
64
|
-
? {}
|
|
65
|
-
: { threadId: execution.threadId }),
|
|
44
|
+
terminate: Effect.fnUntraced(function* (graceful: boolean) {
|
|
45
|
+
// Stop observation before intentionally ending stdin or killing the process.
|
|
46
|
+
yield* failures.close
|
|
47
|
+
if (!graceful) return
|
|
48
|
+
// If this fails, the execution scope forces termination and waits for exit.
|
|
49
|
+
const status = yield* peer.end.pipe(
|
|
50
|
+
// Peer EOF can interrupt the writer as its output ends. Still confirm the unit's exit.
|
|
51
|
+
Effect.catchCauseIf(Cause.hasInterruptsOnly, () => Effect.void),
|
|
52
|
+
Effect.andThen(Fiber.join(exited)),
|
|
53
|
+
Effect.interruptible,
|
|
54
|
+
Effect.timeoutOrElse({
|
|
55
|
+
duration: stdinExitTimeout,
|
|
56
|
+
orElse: () =>
|
|
57
|
+
LocalTerminationTimeout.make({
|
|
58
|
+
...Option.match(execution.pid, {
|
|
59
|
+
onNone: () => ({}),
|
|
60
|
+
onSome: (pid) => ({ pid }),
|
|
66
61
|
}),
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
62
|
+
...(execution.threadId === undefined
|
|
63
|
+
? {}
|
|
64
|
+
: { threadId: execution.threadId }),
|
|
65
|
+
}),
|
|
66
|
+
}),
|
|
67
|
+
)
|
|
68
|
+
if (status.exitCode !== 0 || status.statusCause.reasons.length > 0)
|
|
69
|
+
return yield* status
|
|
70
|
+
}),
|
|
72
71
|
}
|
|
73
72
|
})
|
|
@@ -2,28 +2,26 @@ import { Cause, Effect, FileSystem, Path } from "effect"
|
|
|
2
2
|
import { StateDirectoryLocked } from "./model"
|
|
3
3
|
|
|
4
4
|
/** SQLite owns the local directory lock for the enclosing scope, including failed startup. */
|
|
5
|
-
export const acquire = (directory: string)
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
yield* Effect.try({ try: () => db.exec("BEGIN EXCLUSIVE"), catch: locked })
|
|
29
|
-
})
|
|
5
|
+
export const acquire = Effect.fnUntraced(function* (directory: string) {
|
|
6
|
+
const fs = yield* FileSystem.FileSystem
|
|
7
|
+
const path = yield* Path.Path
|
|
8
|
+
yield* fs
|
|
9
|
+
.makeDirectory(directory, { recursive: true })
|
|
10
|
+
.pipe(Effect.uninterruptible)
|
|
11
|
+
const { DatabaseSync } = yield* Effect.promise(
|
|
12
|
+
() => import("node:sqlite"),
|
|
13
|
+
).pipe(Effect.uninterruptible)
|
|
14
|
+
const locked = (cause: unknown) =>
|
|
15
|
+
StateDirectoryLocked.make({
|
|
16
|
+
detail: "The runner state directory is already owned or cannot be locked",
|
|
17
|
+
cause: Cause.die(cause),
|
|
18
|
+
})
|
|
19
|
+
const db = yield* Effect.acquireRelease(
|
|
20
|
+
Effect.try({
|
|
21
|
+
try: () => new DatabaseSync(path.join(directory, "owner.sqlite")),
|
|
22
|
+
catch: locked,
|
|
23
|
+
}),
|
|
24
|
+
(db) => Effect.sync(() => db.close()),
|
|
25
|
+
)
|
|
26
|
+
yield* Effect.try({ try: () => db.exec("BEGIN EXCLUSIVE"), catch: locked })
|
|
27
|
+
})
|
|
@@ -44,39 +44,38 @@ export const digest = Effect.fnUntraced(function* (directory: string) {
|
|
|
44
44
|
const hash = yield* Effect.sync(() =>
|
|
45
45
|
createHash("sha256").update("graft-package-sha256-v1\0"),
|
|
46
46
|
)
|
|
47
|
-
const visit = (
|
|
47
|
+
const visit = Effect.fnUntraced(function* (
|
|
48
48
|
relative: string,
|
|
49
|
-
): Effect.
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
detail: `Unsupported package entry: ${relative}`,
|
|
56
|
-
})
|
|
57
|
-
const name = new TextEncoder().encode(relative)
|
|
58
|
-
yield* Effect.sync(() => {
|
|
59
|
-
hash.update(
|
|
60
|
-
`${info.type}:${name.byteLength}:${info.type === "File" ? info.size : 0}:`,
|
|
61
|
-
)
|
|
62
|
-
hash.update(name)
|
|
49
|
+
): Effect.fn.Return<void, PackageError | PlatformError.PlatformError> {
|
|
50
|
+
const filename = path.join(directory, relative)
|
|
51
|
+
const info = yield* fs.stat(filename)
|
|
52
|
+
if (info.type !== "File" && info.type !== "Directory")
|
|
53
|
+
return yield* PackageError.make({
|
|
54
|
+
detail: `Unsupported package entry: ${relative}`,
|
|
63
55
|
})
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
),
|
|
71
|
-
)
|
|
72
|
-
} else {
|
|
73
|
-
const entries = yield* fs.readDirectory(filename)
|
|
74
|
-
for (const entry of Array.sort(entries, Order.String)) {
|
|
75
|
-
if (entry === "node_modules") continue
|
|
76
|
-
yield* visit(relative === "" ? entry : `${relative}/${entry}`)
|
|
77
|
-
}
|
|
78
|
-
}
|
|
56
|
+
const name = new TextEncoder().encode(relative)
|
|
57
|
+
yield* Effect.sync(() => {
|
|
58
|
+
hash.update(
|
|
59
|
+
`${info.type}:${name.byteLength}:${info.type === "File" ? info.size : 0}:`,
|
|
60
|
+
)
|
|
61
|
+
hash.update(name)
|
|
79
62
|
})
|
|
63
|
+
if (info.type === "File") {
|
|
64
|
+
yield* fs.stream(filename).pipe(
|
|
65
|
+
Stream.runForEach((bytes) =>
|
|
66
|
+
Effect.sync(() => {
|
|
67
|
+
hash.update(bytes)
|
|
68
|
+
}),
|
|
69
|
+
),
|
|
70
|
+
)
|
|
71
|
+
} else {
|
|
72
|
+
const entries = yield* fs.readDirectory(filename)
|
|
73
|
+
for (const entry of Array.sort(entries, Order.String)) {
|
|
74
|
+
if (entry === "node_modules") continue
|
|
75
|
+
yield* visit(relative === "" ? entry : `${relative}/${entry}`)
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
})
|
|
80
79
|
yield* visit("")
|
|
81
80
|
return yield* Effect.sync(() => hash.digest("hex"))
|
|
82
81
|
})
|
|
@@ -136,43 +135,41 @@ export const resolve = Effect.fnUntraced(
|
|
|
136
135
|
}),
|
|
137
136
|
)
|
|
138
137
|
|
|
139
|
-
export const resolveEntry = (
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
)
|
|
178
|
-
})
|
|
138
|
+
export const resolveEntry = Effect.fnUntraced(function* (
|
|
139
|
+
installation: string,
|
|
140
|
+
specifier: string,
|
|
141
|
+
) {
|
|
142
|
+
const spawner = yield* ChildProcessSpawner.ChildProcessSpawner
|
|
143
|
+
const child = yield* spawner.spawn(
|
|
144
|
+
ChildProcess.make(
|
|
145
|
+
process.execPath,
|
|
146
|
+
[
|
|
147
|
+
"--input-type=module",
|
|
148
|
+
"--eval",
|
|
149
|
+
"process.stdout.write(import.meta.resolve(process.argv[1]))",
|
|
150
|
+
"--",
|
|
151
|
+
specifier,
|
|
152
|
+
],
|
|
153
|
+
{
|
|
154
|
+
cwd: installation,
|
|
155
|
+
env: {},
|
|
156
|
+
stdin: "ignore",
|
|
157
|
+
stdout: "pipe",
|
|
158
|
+
stderr: "pipe",
|
|
159
|
+
},
|
|
160
|
+
),
|
|
161
|
+
)
|
|
162
|
+
const [code, stdout, stderr] = yield* Effect.all(
|
|
163
|
+
[
|
|
164
|
+
child.exitCode,
|
|
165
|
+
child.stdout.pipe(Stream.decodeText(), Stream.mkString),
|
|
166
|
+
child.stderr.pipe(Stream.decodeText(), Stream.mkString),
|
|
167
|
+
],
|
|
168
|
+
{ concurrency: "unbounded" },
|
|
169
|
+
)
|
|
170
|
+
if (code !== 0)
|
|
171
|
+
return yield* PackageError.make({
|
|
172
|
+
detail: `Package resolution failed: ${stderr}`,
|
|
173
|
+
})
|
|
174
|
+
return stdout
|
|
175
|
+
}, Effect.scoped)
|