@graftland/plugin-remote 0.3.1 → 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.
Files changed (147) hide show
  1. package/dist/Auth.d.ts +2 -2
  2. package/dist/Auth.d.ts.map +1 -1
  3. package/dist/Auth.js.map +1 -1
  4. package/dist/{Bootstrap-Dr6sX7el.js → Bootstrap-H9gDsgsC.js} +2 -2
  5. package/dist/{Contract-DL2mHvaT.js → Contract-DsJtisvL.js} +2 -2
  6. package/dist/Contract.js +1 -1
  7. package/dist/{Errors-BMKmu5Y7.js → Errors-DYhsGZcZ.js} +3 -1
  8. package/dist/Errors.d.ts +7 -0
  9. package/dist/Errors.d.ts.map +1 -1
  10. package/dist/Errors.js +3 -1
  11. package/dist/Errors.js.map +1 -1
  12. package/dist/{FailureGroup-BcH0XOBi.js → FailureGroup-BgT73AaR.js} +14 -4
  13. package/dist/{Framing-zaYdOJnT.js → Framing-G9eSaeLb.js} +1 -1
  14. package/dist/{Graft-CVyueNOf.js → Graft-B71CPA2Y.js} +20 -16
  15. package/dist/{Packages-JNL34JpS.js → Packages-AgoCGotL.js} +23 -26
  16. package/dist/{Peer-BT7eAGmh.js → Peer-DXeVrGBh.js} +5 -5
  17. package/dist/{ProcessObservation-DEGrEMfP.js → ProcessObservation-gLgGirYv.js} +1 -1
  18. package/dist/{ServeLifecycle-CJM0gG5B.js → ServeLifecycle-Bd1FPJ6e.js} +1 -1
  19. package/dist/Transport.d.ts +2 -2
  20. package/dist/Transport.d.ts.map +1 -1
  21. package/dist/Transport.js.map +1 -1
  22. package/dist/bin.js +48 -47
  23. package/dist/bin.js.map +1 -1
  24. package/dist/{childRuntime-An0HsIzl.js → childRuntime-Bm3iSg_N.js} +29 -26
  25. package/dist/{connectionEnded-DCpFCjMX.js → connectionEnded-BwcxQ7W8.js} +4 -4
  26. package/dist/{entry-B89sepMU.js → entry-psOpX3Bj.js} +72 -35
  27. package/dist/host/auth/bearer.js +1 -1
  28. package/dist/host/auth/jwt.js +1 -1
  29. package/dist/host/auth/mtls.js +2 -2
  30. package/dist/host/auth/none.js +1 -1
  31. package/dist/host/command.js +4 -4
  32. package/dist/host/local.js +3 -3
  33. package/dist/host/unix.js +3 -3
  34. package/dist/host/websocket.js +3 -3
  35. package/dist/host/worker.js +4 -5
  36. package/dist/{importer-Bk6U_sn4.js → importer-Cvf88eAY.js} +5 -8
  37. package/dist/index.js +9 -9
  38. package/dist/index.js.map +1 -1
  39. package/dist/internal/Certificates.js +4 -4
  40. package/dist/internal/Certificates.js.map +1 -1
  41. package/dist/internal/FailureGroup.js +3 -2
  42. package/dist/internal/FailureGroup.js.map +1 -1
  43. package/dist/internal/assembly.js +9 -2
  44. package/dist/internal/assembly.js.map +1 -1
  45. package/dist/internal/auth/mtls.js +1 -1
  46. package/dist/internal/auth/mtls.js.map +1 -1
  47. package/dist/internal/child.js +20 -17
  48. package/dist/internal/child.js.map +1 -1
  49. package/dist/internal/childRuntime.js +4 -4
  50. package/dist/internal/childRuntime.js.map +1 -1
  51. package/dist/internal/directTransport.d.ts +1 -1
  52. package/dist/internal/entry.d.ts.map +1 -1
  53. package/dist/internal/entry.js +1 -1
  54. package/dist/internal/entry.js.map +1 -1
  55. package/dist/internal/execution.js +40 -5
  56. package/dist/internal/execution.js.map +1 -1
  57. package/dist/internal/host/runner.js +7 -6
  58. package/dist/internal/host/runner.js.map +1 -1
  59. package/dist/internal/host.js +5 -5
  60. package/dist/internal/host.js.map +1 -1
  61. package/dist/internal/port.js +5 -5
  62. package/dist/internal/port.js.map +1 -1
  63. package/dist/internal/release.js +1 -1
  64. package/dist/internal/release.js.map +1 -1
  65. package/dist/internal/runner/Connection.d.ts +1 -1
  66. package/dist/internal/runner/Connection.js +4 -4
  67. package/dist/internal/runner/Connection.js.map +1 -1
  68. package/dist/internal/runner/Execution.js +3 -3
  69. package/dist/internal/runner/Execution.js.map +1 -1
  70. package/dist/internal/runner/Framing.js +1 -1
  71. package/dist/internal/runner/Framing.js.map +1 -1
  72. package/dist/internal/runner/Local.js +1 -1
  73. package/dist/internal/runner/Local.js.map +1 -1
  74. package/dist/internal/runner/Lock.js +1 -1
  75. package/dist/internal/runner/Lock.js.map +1 -1
  76. package/dist/internal/runner/Packages.d.ts +1 -1
  77. package/dist/internal/runner/Packages.js +22 -25
  78. package/dist/internal/runner/Packages.js.map +1 -1
  79. package/dist/internal/runner/Processes.js +7 -9
  80. package/dist/internal/runner/Processes.js.map +1 -1
  81. package/dist/internal/runner/Store.js +3 -3
  82. package/dist/internal/runner/Store.js.map +1 -1
  83. package/dist/internal/runner/Supervisor.js +46 -47
  84. package/dist/internal/runner/Supervisor.js.map +1 -1
  85. package/dist/internal/runner/accept.js +3 -3
  86. package/dist/internal/runner/accept.js.map +1 -1
  87. package/dist/internal/runner/model.js +1 -1
  88. package/dist/internal/runner/model.js.map +1 -1
  89. package/dist/internal/serve.js +1 -1
  90. package/dist/internal/serve.js.map +1 -1
  91. package/dist/internal/supervisorPlugin.js +1 -1
  92. package/dist/internal/watchdogMain.js +5 -5
  93. package/dist/internal/watchdogMain.js.map +1 -1
  94. package/dist/internal/websocketServer.js +3 -1
  95. package/dist/internal/websocketServer.js.map +1 -1
  96. package/dist/internal/workerMain.js +3 -3
  97. package/dist/{port-DSVUY8Bq.js → port--3x2zJ4D.js} +8 -8
  98. package/dist/{release-BY4Mlluy.js → release-DfZPuIcK.js} +1 -1
  99. package/dist/runner/auth/bearer.js +2 -2
  100. package/dist/runner/auth/jwt.js +4 -4
  101. package/dist/runner/auth/jwt.js.map +1 -1
  102. package/dist/runner/auth/mtls.js +3 -3
  103. package/dist/runner/auth/none.js +1 -1
  104. package/dist/runner/index.js +5 -5
  105. package/dist/runner/stdio.js +3 -3
  106. package/dist/runner/unix.js +3 -3
  107. package/dist/runner/websocket.js +4 -4
  108. package/dist/{socketChannel-C_ppdSzz.js → socketChannel-CJvL2DiB.js} +2 -2
  109. package/dist/{supervisorPlugin-CivhM7x5.js → supervisorPlugin-t6Z6PrhD.js} +72 -76
  110. package/dist/{token-Cc_1CTbE.js → token-CYBNNlhS.js} +1 -1
  111. package/dist/{tokenCredentials-CI6mMRRd.js → tokenCredentials-CbCuk-Rt.js} +3 -3
  112. package/dist/{websocketServer-D2Hk7wsA.js → websocketServer-NQhODlEt.js} +5 -3
  113. package/dist/{workerChannel-cmLc13vm.js → workerChannel-C8hhBJzA.js} +1 -1
  114. package/package.json +3 -3
  115. package/src/Auth.ts +9 -2
  116. package/src/Errors.ts +8 -0
  117. package/src/Transport.ts +6 -2
  118. package/src/bin.ts +28 -30
  119. package/src/index.ts +5 -3
  120. package/src/internal/Certificates.ts +10 -13
  121. package/src/internal/FailureGroup.ts +128 -121
  122. package/src/internal/assembly.ts +19 -10
  123. package/src/internal/auth/mtls.ts +19 -20
  124. package/src/internal/child.ts +248 -239
  125. package/src/internal/childRuntime.ts +81 -80
  126. package/src/internal/entry.ts +10 -11
  127. package/src/internal/execution.ts +69 -12
  128. package/src/internal/host/runner.ts +153 -153
  129. package/src/internal/host.ts +116 -120
  130. package/src/internal/port.ts +100 -103
  131. package/src/internal/release.ts +3 -2
  132. package/src/internal/runner/Connection.ts +52 -60
  133. package/src/internal/runner/Execution.ts +163 -164
  134. package/src/internal/runner/Framing.ts +9 -10
  135. package/src/internal/runner/Local.ts +26 -27
  136. package/src/internal/runner/Lock.ts +23 -25
  137. package/src/internal/runner/Packages.ts +67 -70
  138. package/src/internal/runner/Processes.ts +89 -92
  139. package/src/internal/runner/Store.ts +110 -114
  140. package/src/internal/runner/Supervisor.ts +392 -405
  141. package/src/internal/runner/accept.ts +76 -84
  142. package/src/internal/runner/model.ts +20 -21
  143. package/src/internal/serve.ts +15 -13
  144. package/src/internal/watchdogMain.ts +16 -11
  145. package/src/internal/websocketServer.ts +18 -3
  146. package/src/runner/auth/jwt.ts +10 -6
  147. package/dist/cleanup-CXLa1Wd9.js +0 -13
@@ -46,121 +46,118 @@ const race = <A, E, R>(
46
46
  effect: Effect.Effect<A, E, R>,
47
47
  ) => Effect.raceFirst(effect, connection.transport.failure)
48
48
 
49
- const forwardEvents = <E extends ErrorSchema>(
49
+ const forwardEvents = Effect.fnUntraced(function* <E extends ErrorSchema>(
50
50
  contract: Contract<E>,
51
51
  client: Client<E>,
52
52
  connection: Connection["Service"],
53
- ) =>
54
- Effect.gen(function* () {
55
- const stopped = yield* Deferred.make<void>()
56
- const remoteFailure = yield* FailureGroup.make<
57
- | E["Type"]
58
- | ContractModule.UndeclaredFailure
59
- | ChildFailure
60
- | RemoteWithdrawn
61
- >()
62
- const events = yield* race(
63
- connection,
64
- client.Events().pipe(
65
- Stream.runForEach((event) => {
66
- switch (event._tag) {
67
- case "Stopped":
68
- return Deferred.succeed(stopped, undefined)
69
- case "Withdrawing":
70
- return remoteFailure.fail(RemoteWithdrawn.make({}))
71
- case "Failed":
72
- return contract
73
- .decodeCause(event.cause)
74
- .pipe(Effect.flatMap((cause) => remoteFailure.failCause(cause)))
75
- }
76
- }),
77
- ),
78
- ).pipe(
79
- Effect.tapCause(connection.transport.report),
80
- Effect.forkIn(connection.resources),
81
- )
82
- return { stopped, remoteFailure, events }
83
- })
84
- const forwardLogs = <E extends ErrorSchema>(
53
+ ) {
54
+ const stopped = yield* Deferred.make<void>()
55
+ const remoteFailure = yield* FailureGroup.make<
56
+ | E["Type"]
57
+ | ContractModule.UndeclaredFailure
58
+ | ChildFailure
59
+ | RemoteWithdrawn
60
+ >()
61
+ const events = yield* race(
62
+ connection,
63
+ client.Events().pipe(
64
+ Stream.runForEach((event) => {
65
+ switch (event._tag) {
66
+ case "Stopped":
67
+ return Deferred.succeed(stopped, undefined)
68
+ case "Withdrawing":
69
+ return remoteFailure.fail(RemoteWithdrawn.make({}))
70
+ case "Failed":
71
+ return contract
72
+ .decodeCause(event.cause)
73
+ .pipe(Effect.flatMap((cause) => remoteFailure.failCause(cause)))
74
+ }
75
+ }),
76
+ ),
77
+ ).pipe(
78
+ Effect.tapCause(connection.transport.report),
79
+ Effect.forkIn(connection.resources),
80
+ )
81
+ return { stopped, remoteFailure, events }
82
+ })
83
+ const forwardLogs = Effect.fnUntraced(function* <E extends ErrorSchema>(
85
84
  contract: Contract<E>,
86
85
  client: Client<E>,
87
86
  connection: Connection["Service"],
88
- ) =>
89
- Effect.gen(function* () {
90
- const logsEnded = yield* Deferred.make<void>()
91
- const reportedDrops = yield* Ref.make(0)
92
- yield* race(
93
- connection,
94
- client.Logs().pipe(
95
- Stream.runForEach((event) =>
96
- Effect.gen(function* () {
97
- const previous = yield* Ref.getAndSet(reportedDrops, event.dropped)
98
- if (event.dropped > previous)
99
- yield* Effect.logWarning("Remote logs were dropped").pipe(
100
- Effect.annotateLogs({
101
- ...(Option.isSome(connection.pid)
102
- ? { "remote.pid": connection.pid.value }
103
- : {}),
104
- "remote.logs.dropped": event.dropped - previous,
105
- "remote.logs.droppedTotal": event.dropped,
106
- }),
107
- )
108
- if (event._tag === "LogsEnded") {
109
- yield* Deferred.succeed(logsEnded, undefined)
110
- return
111
- }
112
- const entry = event.entry
113
- const cause = yield* contract.decodeCause(entry.cause)
114
- yield* Effect.logWithLevel(
115
- entry.level === "All" || entry.level === "None"
116
- ? "Info"
117
- : entry.level,
118
- )(
119
- ...(Array.isArray(entry.message)
120
- ? entry.message
121
- : [entry.message]),
122
- cause,
123
- ).pipe(
87
+ ) {
88
+ const logsEnded = yield* Deferred.make<void>()
89
+ const reportedDrops = yield* Ref.make(0)
90
+ yield* race(
91
+ connection,
92
+ client.Logs().pipe(
93
+ Stream.runForEach(
94
+ Effect.fnUntraced(function* (event) {
95
+ const previous = yield* Ref.getAndSet(reportedDrops, event.dropped)
96
+ if (event.dropped > previous)
97
+ yield* Effect.logWarning("Remote logs were dropped").pipe(
124
98
  Effect.annotateLogs({
125
99
  ...(Option.isSome(connection.pid)
126
100
  ? { "remote.pid": connection.pid.value }
127
101
  : {}),
128
- ...(connection.threadId === undefined
129
- ? {}
130
- : { "remote.threadId": connection.threadId }),
131
- "remote.annotations": entry.annotations,
102
+ "remote.logs.dropped": event.dropped - previous,
103
+ "remote.logs.droppedTotal": event.dropped,
132
104
  }),
133
105
  )
134
- }),
135
- ),
136
- ),
137
- ).pipe(
138
- Effect.tapCause(connection.transport.report),
139
- Effect.forkIn(connection.resources),
140
- )
141
- return logsEnded
142
- })
143
- export const initialize = <E extends ErrorSchema>(contract: Contract<E>) =>
144
- Effect.gen(function* () {
145
- const connection = yield* Connection
146
- const client = yield* RpcClient.make(contract.control).pipe(
147
- Effect.provideService(
148
- RpcClient.Protocol,
149
- connection.transport.clientProtocol(Control.endpoint),
106
+ if (event._tag === "LogsEnded") {
107
+ yield* Deferred.succeed(logsEnded, undefined)
108
+ return
109
+ }
110
+ const entry = event.entry
111
+ const cause = yield* contract.decodeCause(entry.cause)
112
+ yield* Effect.logWithLevel(
113
+ entry.level === "All" || entry.level === "None"
114
+ ? "Info"
115
+ : entry.level,
116
+ )(
117
+ ...(Array.isArray(entry.message) ? entry.message : [entry.message]),
118
+ cause,
119
+ ).pipe(
120
+ Effect.annotateLogs({
121
+ ...(Option.isSome(connection.pid)
122
+ ? { "remote.pid": connection.pid.value }
123
+ : {}),
124
+ ...(connection.threadId === undefined
125
+ ? {}
126
+ : { "remote.threadId": connection.threadId }),
127
+ "remote.annotations": entry.annotations,
128
+ }),
129
+ )
130
+ }),
150
131
  ),
151
- Scope.provide(connection.resources),
152
- )
153
- for (const service of contract.inject)
154
- yield* service
155
- .serve(connection.transport)
156
- .pipe(
157
- Effect.tapCause(connection.transport.report),
158
- Effect.forkIn(connection.resources),
159
- )
160
- const events = yield* forwardEvents(contract, client, connection)
161
- const logsEnded = yield* forwardLogs(contract, client, connection)
162
- return { connection, client, ...events, logsEnded }
163
- })
132
+ ),
133
+ ).pipe(
134
+ Effect.tapCause(connection.transport.report),
135
+ Effect.forkIn(connection.resources),
136
+ )
137
+ return logsEnded
138
+ })
139
+ export const initialize = Effect.fnUntraced(function* <E extends ErrorSchema>(
140
+ contract: Contract<E>,
141
+ ) {
142
+ const connection = yield* Connection
143
+ const client = yield* RpcClient.make(contract.control).pipe(
144
+ Effect.provideService(
145
+ RpcClient.Protocol,
146
+ connection.transport.clientProtocol(Control.endpoint),
147
+ ),
148
+ Scope.provide(connection.resources),
149
+ )
150
+ for (const service of contract.inject)
151
+ yield* service
152
+ .serve(connection.transport)
153
+ .pipe(
154
+ Effect.tapCause(connection.transport.report),
155
+ Effect.forkIn(connection.resources),
156
+ )
157
+ const events = yield* forwardEvents(contract, client, connection)
158
+ const logsEnded = yield* forwardLogs(contract, client, connection)
159
+ return { connection, client, ...events, logsEnded }
160
+ })
164
161
  type Active<E extends ErrorSchema> = Effect.Success<
165
162
  ReturnType<typeof initialize<E>>
166
163
  >
@@ -186,21 +183,20 @@ export const load = <E extends ErrorSchema>(
186
183
  active.remoteFailure.await,
187
184
  ),
188
185
  )
189
- export const dispose = <E extends ErrorSchema>(active: Active<E>) =>
190
- Effect.gen(function* () {
191
- const result = yield* race(
192
- active.connection,
193
- active.client
194
- .Dispose()
195
- .pipe(Effect.catchIf(Cause.isCause, Effect.succeed)),
196
- )
197
- const cause = Cause.isCause(result) ? result : Cause.empty
198
- // A remote cleanup failure still permits the bounded event and log tail to drain.
199
- yield* race(
200
- active.connection,
201
- Deferred.await(active.stopped).pipe(
202
- Effect.andThen(Deferred.await(active.logsEnded)),
203
- ),
204
- ).pipe(Effect.onError(() => Effect.failCause(cleanupCause(cause))))
205
- return cause
206
- })
186
+ export const dispose = Effect.fnUntraced(function* <E extends ErrorSchema>(
187
+ active: Active<E>,
188
+ ) {
189
+ const result = yield* race(
190
+ active.connection,
191
+ active.client.Dispose().pipe(Effect.catchIf(Cause.isCause, Effect.succeed)),
192
+ )
193
+ const cause = Cause.isCause(result) ? result : Cause.empty
194
+ // A remote cleanup failure still permits the bounded event and log tail to drain.
195
+ yield* race(
196
+ active.connection,
197
+ Deferred.await(active.stopped).pipe(
198
+ Effect.andThen(Deferred.await(active.logsEnded)),
199
+ ),
200
+ ).pipe(Effect.onError(() => Effect.failCause(cleanupCause(cause))))
201
+ return cause
202
+ })
@@ -167,64 +167,66 @@ interface State {
167
167
  readonly servers: HashMap.HashMap<string, ServerEndpoint>
168
168
  readonly clients: HashMap.HashMap<string, ClientEndpoint>
169
169
  }
170
- const initialize = (bytes: Channel, options: Options) =>
171
- Effect.gen(function* (): Effect.gen.Return<State, never, Scope.Scope> {
172
- const limits = { ...defaults, ...options.limits }
173
- const workers = yield* FailureGroup.make<TransportError>()
174
- const incoming = yield* TxRef.make(
175
- HashMap.empty<RequestKey, RequestState<RpcMessage.FromClientEncoded>>(),
176
- )
177
- const outgoing = yield* TxRef.make(
178
- HashMap.empty<RequestKey, RequestState<RpcMessage.FromServerEncoded>>(),
179
- )
180
- const queues = {
181
- control: yield* TxQueue.unbounded<Pending, Cause.Done>(),
182
- data: yield* TxQueue.unbounded<Pending, Cause.Done>(),
183
- log: yield* TxQueue.unbounded<Pending, Cause.Done>(),
184
- }
185
- const servers = yield* Effect.forEach(
186
- Record.toEntries(options.serve),
187
- Effect.fnUntraced(function* ([name, group]) {
188
- return [
189
- name,
190
- {
191
- group,
192
- ready:
193
- yield* Deferred.make<
194
- Parameters<RpcServer.Protocol["Service"]["run"]>[0]
195
- >(),
196
- disconnects: yield* Queue.dropping<number>(1),
197
- },
198
- ] satisfies readonly [string, unknown]
199
- }),
200
- ).pipe(Effect.map(HashMap.fromIterable))
201
- const clients = yield* Effect.forEach(
202
- Record.toEntries(options.call),
203
- Effect.fnUntraced(function* ([name, group]) {
204
- return [
205
- name,
206
- {
207
- group,
208
- ready:
209
- yield* Deferred.make<
210
- Parameters<RpcClient.Protocol["Service"]["run"]>[1]
211
- >(),
212
- },
213
- ] satisfies readonly [string, unknown]
214
- }),
215
- ).pipe(Effect.map(HashMap.fromIterable))
216
- return {
217
- bytes,
218
- options,
219
- limits,
220
- workers,
221
- incoming,
222
- outgoing,
223
- queues,
224
- servers,
225
- clients,
226
- }
227
- })
170
+ const initialize = Effect.fnUntraced(function* (
171
+ bytes: Channel,
172
+ options: Options,
173
+ ): Effect.fn.Return<State, never, Scope.Scope> {
174
+ const limits = { ...defaults, ...options.limits }
175
+ const workers = yield* FailureGroup.make<TransportError>()
176
+ const incoming = yield* TxRef.make(
177
+ HashMap.empty<RequestKey, RequestState<RpcMessage.FromClientEncoded>>(),
178
+ )
179
+ const outgoing = yield* TxRef.make(
180
+ HashMap.empty<RequestKey, RequestState<RpcMessage.FromServerEncoded>>(),
181
+ )
182
+ const queues = {
183
+ control: yield* TxQueue.unbounded<Pending, Cause.Done>(),
184
+ data: yield* TxQueue.unbounded<Pending, Cause.Done>(),
185
+ log: yield* TxQueue.unbounded<Pending, Cause.Done>(),
186
+ }
187
+ const servers = yield* Effect.forEach(
188
+ Record.toEntries(options.serve),
189
+ Effect.fnUntraced(function* ([name, group]) {
190
+ return [
191
+ name,
192
+ {
193
+ group,
194
+ ready:
195
+ yield* Deferred.make<
196
+ Parameters<RpcServer.Protocol["Service"]["run"]>[0]
197
+ >(),
198
+ disconnects: yield* Queue.dropping<number>(1),
199
+ },
200
+ ] satisfies readonly [string, unknown]
201
+ }),
202
+ ).pipe(Effect.map(HashMap.fromIterable))
203
+ const clients = yield* Effect.forEach(
204
+ Record.toEntries(options.call),
205
+ Effect.fnUntraced(function* ([name, group]) {
206
+ return [
207
+ name,
208
+ {
209
+ group,
210
+ ready:
211
+ yield* Deferred.make<
212
+ Parameters<RpcClient.Protocol["Service"]["run"]>[1]
213
+ >(),
214
+ },
215
+ ] satisfies readonly [string, unknown]
216
+ }),
217
+ ).pipe(Effect.map(HashMap.fromIterable))
218
+ return {
219
+ bytes,
220
+ options,
221
+ limits,
222
+ workers,
223
+ incoming,
224
+ outgoing,
225
+ queues,
226
+ servers,
227
+ clients,
228
+ }
229
+ })
228
230
 
229
231
  const admit = Effect.fnUntraced(function* <A>(
230
232
  state: State,
@@ -447,41 +449,38 @@ const serverProtocol = (
447
449
  ),
448
450
  })
449
451
  }
450
- const next = (state: State) =>
451
- Effect.tx(
452
- Effect.gen(function* () {
453
- yield* state.workers.check
454
- for (const p of [
455
- "control",
456
- "data",
457
- "log",
458
- ] satisfies ReadonlyArray<Priority>) {
459
- const pending = yield* TxQueue.poll(state.queues[p])
460
- if (Option.isNone(pending)) continue
461
- const { frame, request } = pending.value
462
- if (Option.isSome(request)) {
463
- const table = yield* TxRef.get(state.outgoing)
464
- const requestState = HashMap.get(table, request.value)
465
- if (Option.isNone(requestState)) return Option.none<Frame>()
466
- yield* TxRef.set(
467
- state.outgoing,
468
- HashMap.set(table, request.value, {
469
- ...requestState.value,
470
- sent: true,
471
- }),
472
- )
473
- }
474
- return Option.some(frame)
475
- }
476
- if (
477
- (yield* TxQueue.isDone(state.queues.control)) &&
478
- (yield* TxQueue.isDone(state.queues.data)) &&
479
- (yield* TxQueue.isDone(state.queues.log))
452
+ const next = Effect.fnUntraced(function* (state: State) {
453
+ yield* state.workers.check
454
+ for (const p of [
455
+ "control",
456
+ "data",
457
+ "log",
458
+ ] satisfies ReadonlyArray<Priority>) {
459
+ const pending = yield* TxQueue.poll(state.queues[p])
460
+ if (Option.isNone(pending)) continue
461
+ const { frame, request } = pending.value
462
+ if (Option.isSome(request)) {
463
+ const table = yield* TxRef.get(state.outgoing)
464
+ const requestState = HashMap.get(table, request.value)
465
+ if (Option.isNone(requestState)) return Option.none<Frame>()
466
+ yield* TxRef.set(
467
+ state.outgoing,
468
+ HashMap.set(table, request.value, {
469
+ ...requestState.value,
470
+ sent: true,
471
+ }),
480
472
  )
481
- return yield* Cause.done()
482
- return yield* Effect.txRetry
483
- }),
473
+ }
474
+ return Option.some(frame)
475
+ }
476
+ if (
477
+ (yield* TxQueue.isDone(state.queues.control)) &&
478
+ (yield* TxQueue.isDone(state.queues.data)) &&
479
+ (yield* TxQueue.isDone(state.queues.log))
484
480
  )
481
+ return yield* Cause.done()
482
+ return yield* Effect.txRetry
483
+ }, Effect.tx)
485
484
  const writer = (state: State) =>
486
485
  Stream.fromEffectRepeat(next(state)).pipe(
487
486
  Stream.filterMap(Result.fromOption(() => undefined)),
@@ -592,18 +591,16 @@ export const make = Effect.fnUntraced(function* (
592
591
  // The same failure remains observable through Port.await and client requests.
593
592
  // This observer only publishes disconnects, even while the owner closes its scope.
594
593
  yield* state.workers.await.pipe(
595
- Effect.catchCause(() =>
596
- Effect.uninterruptible(
597
- Effect.gen(function* () {
598
- for (const server of HashMap.values(state.servers))
599
- yield* Queue.offer(server.disconnects, 0)
600
- yield* Effect.tx(
601
- TxRef.set(state.incoming, HashMap.empty()).pipe(
602
- Effect.andThen(TxRef.set(state.outgoing, HashMap.empty())),
603
- ),
604
- )
605
- }),
606
- ),
594
+ Effect.catchCause(
595
+ Effect.fnUntraced(function* () {
596
+ for (const server of HashMap.values(state.servers))
597
+ yield* Queue.offer(server.disconnects, 0)
598
+ yield* Effect.tx(
599
+ TxRef.set(state.incoming, HashMap.empty()).pipe(
600
+ Effect.andThen(TxRef.set(state.outgoing, HashMap.empty())),
601
+ ),
602
+ )
603
+ }, Effect.uninterruptible),
607
604
  ),
608
605
  Effect.forkScoped,
609
606
  )
@@ -19,8 +19,9 @@ export const close = (
19
19
  ) =>
20
20
  Effect.uninterruptible(
21
21
  Scope.close(scope, exit).pipe(
22
- Effect.catchCauseIf(Cause.hasInterruptsOnly, (cause) =>
23
- Effect.gen(function* () {
22
+ Effect.catchCauseIf(
23
+ Cause.hasInterruptsOnly,
24
+ Effect.fnUntraced(function* (cause) {
24
25
  // Re-entering interruptibility observes pending external cancellation without producing a self-interrupt.
25
26
  // Read it after release so cancellation arriving during a finalizer is included too.
26
27
  const pending = yield* Effect.exit(Effect.interruptible(Effect.void))
@@ -112,73 +112,65 @@ const finish = (causes: ReadonlyArray<Cause.Cause<unknown>>) => {
112
112
  /** Close partially acquired resources too; the normal release observes exit before stopping readers. */
113
113
  const scopes = Effect.acquireRelease(
114
114
  Effect.all({ resources: Scope.make(), process: Scope.make() }),
115
- (scopes, exit) =>
116
- Effect.gen(function* () {
117
- const process = yield* Effect.exit(Release.close(scopes.process, exit))
118
- const resources = yield* Effect.exit(
119
- Release.close(scopes.resources, exit),
120
- )
121
- yield* finish([reason(process), reason(resources)])
122
- }),
115
+ Effect.fnUntraced(function* (scopes, exit) {
116
+ const process = yield* Effect.exit(Release.close(scopes.process, exit))
117
+ const resources = yield* Effect.exit(Release.close(scopes.resources, exit))
118
+ yield* finish([reason(process), reason(resources)])
119
+ }),
123
120
  )
124
121
 
125
122
  /** Setup supplies a concrete control lifecycle; release never reads a later-installed effect. */
126
- export const acquire = <A, E, R, D, DR>(
123
+ export const acquire = Effect.fnUntraced(function* <A, E, R, D, DR>(
127
124
  target: Target,
128
125
  contractModule: string,
129
126
  options: Port.Options,
130
127
  setup: Effect.Effect<A, E, R | Connection>,
131
128
  dispose: (value: A) => Effect.Effect<Cause.Cause<unknown>, D, DR>,
132
129
  timeout: Duration.Input,
133
- ) =>
134
- Effect.gen(function* () {
135
- const owned = yield* scopes
136
- const connection = yield* Effect.acquireRelease(
137
- Effect.gen(function* () {
138
- return target._tag === "Local" || target._tag === "Worker"
139
- ? yield* Local(
140
- target,
141
- contractModule,
142
- options,
143
- owned.resources,
144
- owned.process,
145
- ).pipe(Effect.map(connected))
146
- : yield* RunnerConnection.connect(
147
- target,
148
- contractModule,
149
- options,
150
- owned.resources,
151
- owned.process,
152
- )
153
- }).pipe(Effect.interruptible),
154
- (connection, exit) =>
155
- Effect.gen(function* () {
156
- const process = yield* Effect.exit(Release.close(owned.process, exit))
157
- // Wait for exit while readers are alive; collect their final cause after resources close.
158
- yield* connection.diagnostics
159
- const resources = yield* Effect.exit(
160
- Release.close(owned.resources, exit),
161
- )
162
- const diagnostics = yield* connection.diagnostics
163
- yield* finish([reason(process), reason(resources), diagnostics])
164
- }),
165
- )
166
- return yield* Effect.acquireRelease(
167
- setup.pipe(Effect.provideService(Connection, connection)),
168
- (value) =>
169
- Effect.gen(function* () {
170
- const graceful = yield* dispose(value).pipe(
171
- Effect.interruptible,
172
- Effect.timeout(timeout),
173
- Effect.exit,
174
- )
175
- const terminated = yield* Effect.exit(
176
- connection.terminate(Exit.isSuccess(graceful)),
130
+ ) {
131
+ const owned = yield* scopes
132
+ const connection = yield* Effect.acquireRelease(
133
+ Effect.gen(function* () {
134
+ return target._tag === "Local" || target._tag === "Worker"
135
+ ? yield* Local(
136
+ target,
137
+ contractModule,
138
+ options,
139
+ owned.resources,
140
+ owned.process,
141
+ ).pipe(Effect.map(connected))
142
+ : yield* RunnerConnection.connect(
143
+ target,
144
+ contractModule,
145
+ options,
146
+ owned.resources,
147
+ owned.process,
177
148
  )
178
- yield* finish([
179
- Exit.isSuccess(graceful) ? graceful.value : graceful.cause,
180
- reason(terminated),
181
- ])
182
- }),
183
- )
184
- })
149
+ }).pipe(Effect.interruptible),
150
+ Effect.fnUntraced(function* (connection, exit) {
151
+ const process = yield* Effect.exit(Release.close(owned.process, exit))
152
+ // Wait for exit while readers are alive; collect their final cause after resources close.
153
+ yield* connection.diagnostics
154
+ const resources = yield* Effect.exit(Release.close(owned.resources, exit))
155
+ const diagnostics = yield* connection.diagnostics
156
+ yield* finish([reason(process), reason(resources), diagnostics])
157
+ }),
158
+ )
159
+ return yield* Effect.acquireRelease(
160
+ setup.pipe(Effect.provideService(Connection, connection)),
161
+ Effect.fnUntraced(function* (value) {
162
+ const graceful = yield* dispose(value).pipe(
163
+ Effect.interruptible,
164
+ Effect.timeout(timeout),
165
+ Effect.exit,
166
+ )
167
+ const terminated = yield* Effect.exit(
168
+ connection.terminate(Exit.isSuccess(graceful)),
169
+ )
170
+ yield* finish([
171
+ Exit.isSuccess(graceful) ? graceful.value : graceful.cause,
172
+ reason(terminated),
173
+ ])
174
+ }),
175
+ )
176
+ })