effect 4.0.0-beta.49 → 4.0.0-beta.50
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/Deferred.d.ts +5 -0
- package/dist/Deferred.d.ts.map +1 -1
- package/dist/Deferred.js +6 -0
- package/dist/Deferred.js.map +1 -1
- package/dist/unstable/ai/McpServer.js.map +1 -1
- package/dist/unstable/cluster/Entity.d.ts +1 -1
- package/dist/unstable/cluster/Entity.d.ts.map +1 -1
- package/dist/unstable/eventlog/EventLogServer.js +2 -2
- package/dist/unstable/eventlog/EventLogServer.js.map +1 -1
- package/dist/unstable/reactivity/AtomHttpApi.d.ts +1 -0
- package/dist/unstable/reactivity/AtomHttpApi.d.ts.map +1 -1
- package/dist/unstable/reactivity/AtomHttpApi.js +17 -15
- package/dist/unstable/reactivity/AtomHttpApi.js.map +1 -1
- package/dist/unstable/reactivity/AtomRpc.d.ts +1 -0
- package/dist/unstable/reactivity/AtomRpc.d.ts.map +1 -1
- package/dist/unstable/reactivity/AtomRpc.js +13 -11
- package/dist/unstable/reactivity/AtomRpc.js.map +1 -1
- package/dist/unstable/rpc/Rpc.d.ts +8 -2
- package/dist/unstable/rpc/Rpc.d.ts.map +1 -1
- package/dist/unstable/rpc/Rpc.js +5 -0
- package/dist/unstable/rpc/Rpc.js.map +1 -1
- package/dist/unstable/rpc/RpcServer.d.ts.map +1 -1
- package/dist/unstable/rpc/RpcServer.js +38 -8
- package/dist/unstable/rpc/RpcServer.js.map +1 -1
- package/package.json +1 -1
- package/src/Deferred.ts +7 -0
- package/src/unstable/ai/McpServer.ts +1 -1
- package/src/unstable/cluster/Entity.ts +1 -1
- package/src/unstable/eventlog/EventLogServer.ts +2 -2
- package/src/unstable/reactivity/AtomHttpApi.ts +14 -13
- package/src/unstable/reactivity/AtomRpc.ts +15 -12
- package/src/unstable/rpc/Rpc.ts +9 -2
- package/src/unstable/rpc/RpcServer.ts +43 -13
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
import * as Context from "../../Context.ts"
|
|
5
5
|
import * as Duration from "../../Duration.ts"
|
|
6
6
|
import * as Effect from "../../Effect.ts"
|
|
7
|
-
import * as Hash from "../../Hash.ts"
|
|
8
7
|
import * as Layer from "../../Layer.ts"
|
|
9
8
|
import type { ReadonlyRecord } from "../../Record.ts"
|
|
10
9
|
import * as Schema from "../../Schema.ts"
|
|
@@ -105,6 +104,7 @@ export interface AtomHttpApiClient<Self, Id extends string, Groups extends HttpA
|
|
|
105
104
|
| ReadonlyRecord<string, ReadonlyArray<unknown>>
|
|
106
105
|
| undefined
|
|
107
106
|
readonly timeToLive?: Duration.Input | undefined
|
|
107
|
+
readonly serializationKey?: string | undefined
|
|
108
108
|
}
|
|
109
109
|
>
|
|
110
110
|
: never
|
|
@@ -239,10 +239,10 @@ export const Service = <Self>() =>
|
|
|
239
239
|
HttpClientError.HttpClientError | SchemaError
|
|
240
240
|
>)
|
|
241
241
|
}))
|
|
242
|
-
if (opts.responseMode === "decoded-only") {
|
|
242
|
+
if (opts.responseMode === "decoded-only" && opts.serializationKey) {
|
|
243
243
|
const endpoint = options.api.groups[opts.group]!.endpoints[opts.endpoint]! as HttpApiEndpoint.AnyWithProps
|
|
244
244
|
atom = Atom.serializable(atom, {
|
|
245
|
-
key:
|
|
245
|
+
key: `AtomHttpApi:${opts.group}:${opts.endpoint}:${opts.serializationKey}`,
|
|
246
246
|
schema: AsyncResult.Schema({
|
|
247
247
|
success: Schema.Union(HttpApiEndpoint.getSuccessSchemas(endpoint)),
|
|
248
248
|
error: Schema.Union(HttpApiEndpoint.getErrorSchemas(endpoint))
|
|
@@ -270,9 +270,10 @@ export const Service = <Self>() =>
|
|
|
270
270
|
readonly responseMode?: HttpApiEndpoint.ClientResponseMode
|
|
271
271
|
readonly reactivityKeys?: ReadonlyArray<unknown> | ReadonlyRecord<string, ReadonlyArray<unknown>> | undefined
|
|
272
272
|
readonly timeToLive?: Duration.Input | undefined
|
|
273
|
+
readonly serializationKey?: string | undefined
|
|
273
274
|
}
|
|
274
|
-
) =>
|
|
275
|
-
|
|
275
|
+
) => {
|
|
276
|
+
const key: QueryKey = {
|
|
276
277
|
group,
|
|
277
278
|
endpoint,
|
|
278
279
|
params: request.params,
|
|
@@ -283,8 +284,11 @@ export const Service = <Self>() =>
|
|
|
283
284
|
reactivityKeys: request.reactivityKeys,
|
|
284
285
|
timeToLive: request.timeToLive
|
|
285
286
|
? Duration.fromInputUnsafe(request.timeToLive)
|
|
286
|
-
: undefined
|
|
287
|
-
|
|
287
|
+
: undefined,
|
|
288
|
+
serializationKey: request.serializationKey
|
|
289
|
+
}
|
|
290
|
+
return queryFamily(key)
|
|
291
|
+
}) as any
|
|
288
292
|
|
|
289
293
|
return self as AtomHttpApiClient<Self, Id, Groups>
|
|
290
294
|
}
|
|
@@ -303,15 +307,12 @@ interface QueryKey {
|
|
|
303
307
|
headers: any
|
|
304
308
|
payload: any
|
|
305
309
|
responseMode: HttpApiEndpoint.ClientResponseMode
|
|
306
|
-
reactivityKeys
|
|
307
|
-
timeToLive
|
|
310
|
+
reactivityKeys: ReadonlyArray<unknown> | ReadonlyRecord<string, ReadonlyArray<unknown>> | undefined
|
|
311
|
+
timeToLive: Duration.Duration | undefined
|
|
312
|
+
serializationKey: string | undefined
|
|
308
313
|
}
|
|
309
314
|
|
|
310
315
|
type ResponseByMode<Success, ResponseMode extends HttpApiEndpoint.ClientResponseMode> = [ResponseMode] extends
|
|
311
316
|
["decoded-and-response"] ? [Success, HttpClientResponse]
|
|
312
317
|
: [ResponseMode] extends ["response-only"] ? HttpClientResponse
|
|
313
318
|
: Success
|
|
314
|
-
|
|
315
|
-
const makeSerializableKey = (
|
|
316
|
-
key: QueryKey
|
|
317
|
-
): string => `AtomHttpApi:${key.group}:${key.endpoint}:${Hash.hash(key)}`
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
import * as Context from "../../Context.ts"
|
|
5
5
|
import * as Duration from "../../Duration.ts"
|
|
6
6
|
import * as Effect from "../../Effect.ts"
|
|
7
|
-
import * as Hash from "../../Hash.ts"
|
|
8
7
|
import * as Layer from "../../Layer.ts"
|
|
9
8
|
import type { ReadonlyRecord } from "../../Record.ts"
|
|
10
9
|
import * as Schema from "../../Schema.ts"
|
|
@@ -73,6 +72,7 @@ export interface AtomRpcClient<Self, Id extends string, Rpcs extends Rpc.Any> ex
|
|
|
73
72
|
| ReadonlyRecord<string, ReadonlyArray<unknown>>
|
|
74
73
|
| undefined
|
|
75
74
|
readonly timeToLive?: Duration.Input | undefined
|
|
75
|
+
readonly serializationKey?: string | undefined
|
|
76
76
|
}
|
|
77
77
|
) => Rpc.ExtractTag<Rpcs, Tag> extends Rpc.Rpc<
|
|
78
78
|
infer _Tag,
|
|
@@ -212,9 +212,9 @@ export const Service = <Self>() =>
|
|
|
212
212
|
: self.runtime.atom(
|
|
213
213
|
self.use((client) => client(tag, payload, { headers } as any)) as any
|
|
214
214
|
)
|
|
215
|
-
if (!isStream) {
|
|
215
|
+
if (!isStream && key.serializationKey) {
|
|
216
216
|
atom = Atom.serializable(atom, {
|
|
217
|
-
key:
|
|
217
|
+
key: `AtomRpc:${key.tag}:${key.serializationKey}`,
|
|
218
218
|
schema: AsyncResult.Schema({
|
|
219
219
|
success: rpc.successSchema,
|
|
220
220
|
error: makeErrorSchema(rpc)
|
|
@@ -242,9 +242,10 @@ export const Service = <Self>() =>
|
|
|
242
242
|
| ReadonlyRecord<string, ReadonlyArray<unknown>>
|
|
243
243
|
| undefined
|
|
244
244
|
readonly timeToLive?: Duration.Input | undefined
|
|
245
|
+
readonly serializationKey?: string | undefined
|
|
245
246
|
}
|
|
246
|
-
) =>
|
|
247
|
-
|
|
247
|
+
) => {
|
|
248
|
+
const key: QueryKey = {
|
|
248
249
|
tag,
|
|
249
250
|
payload,
|
|
250
251
|
headers: options?.headers
|
|
@@ -253,8 +254,11 @@ export const Service = <Self>() =>
|
|
|
253
254
|
reactivityKeys: options?.reactivityKeys,
|
|
254
255
|
timeToLive: options?.timeToLive
|
|
255
256
|
? Duration.fromInputUnsafe(options.timeToLive)
|
|
256
|
-
: undefined
|
|
257
|
-
|
|
257
|
+
: undefined,
|
|
258
|
+
serializationKey: options?.serializationKey
|
|
259
|
+
}
|
|
260
|
+
return queryFamily(key) as any
|
|
261
|
+
}
|
|
258
262
|
|
|
259
263
|
return self as AtomRpcClient<Self, Id, Rpcs>
|
|
260
264
|
}
|
|
@@ -262,12 +266,13 @@ export const Service = <Self>() =>
|
|
|
262
266
|
interface QueryKey {
|
|
263
267
|
tag: string
|
|
264
268
|
payload: any
|
|
265
|
-
headers
|
|
266
|
-
reactivityKeys
|
|
269
|
+
headers: Headers.Headers | undefined
|
|
270
|
+
reactivityKeys:
|
|
267
271
|
| ReadonlyArray<unknown>
|
|
268
272
|
| ReadonlyRecord<string, ReadonlyArray<unknown>>
|
|
269
273
|
| undefined
|
|
270
|
-
timeToLive
|
|
274
|
+
timeToLive: Duration.Duration | undefined
|
|
275
|
+
serializationKey: string | undefined
|
|
271
276
|
}
|
|
272
277
|
|
|
273
278
|
const makeErrorSchema = (rpc: Rpc.AnyWithProps): Schema.Top =>
|
|
@@ -276,5 +281,3 @@ const makeErrorSchema = (rpc: Rpc.AnyWithProps): Schema.Top =>
|
|
|
276
281
|
...Array.from(rpc.middlewares, (middleware) => middleware.error),
|
|
277
282
|
RpcClientError
|
|
278
283
|
])
|
|
279
|
-
|
|
280
|
-
const makeSerializableKey = (key: QueryKey): string => `AtomRpc:${key.tag}:${Hash.hash(key)}`
|
package/src/unstable/rpc/Rpc.ts
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import type * as Cause from "../../Cause.ts"
|
|
5
5
|
import * as Context from "../../Context.ts"
|
|
6
|
+
import type { Deferred } from "../../Deferred.ts"
|
|
6
7
|
import type { Effect } from "../../Effect.ts"
|
|
7
8
|
import type { Exit as Exit_ } from "../../Exit.ts"
|
|
8
9
|
import * as Option from "../../Option.ts"
|
|
@@ -180,7 +181,7 @@ export interface Handler<Tag extends string> {
|
|
|
180
181
|
readonly requestId: RequestId
|
|
181
182
|
readonly headers: Headers
|
|
182
183
|
readonly rpc: Any
|
|
183
|
-
}) => Effect<any, any> | Stream<any, any>
|
|
184
|
+
}) => Effect<{} | Deferred<any, any>, any> | Stream<any, any>
|
|
184
185
|
readonly context: Context.Context<never>
|
|
185
186
|
}
|
|
186
187
|
|
|
@@ -591,7 +592,7 @@ export type ResultFrom<R extends Any, Services> = R extends Rpc<
|
|
|
591
592
|
Services
|
|
592
593
|
> :
|
|
593
594
|
Effect<
|
|
594
|
-
_Success["Type"],
|
|
595
|
+
_Success["Type"] | Deferred<_Success["Type"], _Error["Type"]>,
|
|
595
596
|
_Error["Type"],
|
|
596
597
|
Services
|
|
597
598
|
> :
|
|
@@ -866,6 +867,12 @@ export const wrap = (options: {
|
|
|
866
867
|
uninterruptible: options.uninterruptible ?? false
|
|
867
868
|
}
|
|
868
869
|
|
|
870
|
+
/**
|
|
871
|
+
* @since 4.0.0
|
|
872
|
+
* @category Wrapper
|
|
873
|
+
*/
|
|
874
|
+
export const unwrap = <A extends object>(value: WrapperOr<A>): A => isWrapper(value) ? value.value : value
|
|
875
|
+
|
|
869
876
|
/**
|
|
870
877
|
* @since 4.0.0
|
|
871
878
|
* @category Wrapper
|
|
@@ -252,28 +252,45 @@ export const makeNoSerialization: <Rpcs extends Rpc.Any>(
|
|
|
252
252
|
// unwrap the fork data type
|
|
253
253
|
const streamOrEffect = isWrapper ? result.value : result
|
|
254
254
|
const handler = isStream
|
|
255
|
-
? (streamEffect(client, request, streamOrEffect) as Effect.Effect<any
|
|
256
|
-
: (streamOrEffect as Effect.Effect<any
|
|
255
|
+
? (streamEffect(client, request, streamOrEffect) as Effect.Effect<{} | Deferred.Deferred<any, any>>)
|
|
256
|
+
: (streamOrEffect as Effect.Effect<{} | Deferred.Deferred<any, any>>)
|
|
257
257
|
|
|
258
258
|
const withMiddleware = rpc.middlewares.size > 0
|
|
259
259
|
? applyMiddleware(services, handler, metadata)
|
|
260
260
|
: handler
|
|
261
261
|
let responded = false
|
|
262
262
|
const scope = Scope.makeUnsafe()
|
|
263
|
+
let deferred: Deferred.Deferred<unknown, unknown> | undefined = undefined
|
|
263
264
|
let effect = Effect.onExit(withMiddleware, (exit) => {
|
|
264
265
|
responded = true
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
266
|
+
let write: Effect.Effect<void>
|
|
267
|
+
if (exit._tag === "Success") {
|
|
268
|
+
if (Deferred.isDeferred(exit.value)) {
|
|
269
|
+
deferred = exit.value
|
|
270
|
+
write = Effect.void
|
|
271
|
+
} else {
|
|
272
|
+
write = options.onFromServer({
|
|
273
|
+
_tag: "Exit",
|
|
274
|
+
clientId: client.id,
|
|
275
|
+
requestId: request.id,
|
|
276
|
+
exit: exit as any
|
|
277
|
+
})
|
|
278
|
+
}
|
|
279
|
+
} else if (
|
|
280
|
+
!disableFatalDefects &&
|
|
281
|
+
Cause.hasDies(exit.cause) &&
|
|
282
|
+
!Cause.hasInterrupts(exit.cause)
|
|
283
|
+
) {
|
|
284
|
+
write = sendDefect(client, Cause.squash(exit.cause))
|
|
285
|
+
} else {
|
|
286
|
+
write = options.onFromServer({
|
|
272
287
|
_tag: "Exit",
|
|
273
288
|
clientId: client.id,
|
|
274
289
|
requestId: request.id,
|
|
275
|
-
exit
|
|
290
|
+
exit: exit as any
|
|
276
291
|
})
|
|
292
|
+
}
|
|
293
|
+
const close = Scope.closeUnsafe(scope, exit)
|
|
277
294
|
if (exit._tag === "Failure") {
|
|
278
295
|
reportCauseUnsafe(Fiber.getCurrent()!, exit.cause)
|
|
279
296
|
}
|
|
@@ -304,7 +321,7 @@ export const makeNoSerialization: <Rpcs extends Rpc.Any>(
|
|
|
304
321
|
})
|
|
305
322
|
}
|
|
306
323
|
if (!isFork && concurrencySemaphore) {
|
|
307
|
-
effect = concurrencySemaphore.
|
|
324
|
+
effect = concurrencySemaphore.withPermit(effect)
|
|
308
325
|
}
|
|
309
326
|
const context = new Map(entry.context.mapUnsafe)
|
|
310
327
|
requestFiber.context.mapUnsafe.forEach((value, key) => context.set(key, value))
|
|
@@ -317,7 +334,20 @@ export const makeNoSerialization: <Rpcs extends Rpc.Any>(
|
|
|
317
334
|
)
|
|
318
335
|
)
|
|
319
336
|
client.fibers.set(request.id, fiber)
|
|
320
|
-
fiber.addObserver((exit)
|
|
337
|
+
fiber.addObserver(function onExit(exit: Exit.Exit<any, any>): void {
|
|
338
|
+
if (deferred) {
|
|
339
|
+
const fiber = trackFiber(runFork(Effect.onExit(Deferred.await(deferred), (exit) =>
|
|
340
|
+
options.onFromServer({
|
|
341
|
+
_tag: "Exit",
|
|
342
|
+
clientId: client.id,
|
|
343
|
+
requestId: request.id,
|
|
344
|
+
exit: exit as any
|
|
345
|
+
}))))
|
|
346
|
+
client.fibers.set(request.id, fiber)
|
|
347
|
+
deferred = undefined
|
|
348
|
+
fiber.addObserver(onExit)
|
|
349
|
+
return
|
|
350
|
+
}
|
|
321
351
|
if (!responded && exit._tag === "Failure") {
|
|
322
352
|
trackFiber(
|
|
323
353
|
runFork(
|
|
@@ -415,7 +445,7 @@ const applyMiddleware = <A, E, R>(
|
|
|
415
445
|
readonly client: Rpc.ServerClient
|
|
416
446
|
readonly requestId: RequestId
|
|
417
447
|
readonly headers: Headers.Headers
|
|
418
|
-
readonly payload:
|
|
448
|
+
readonly payload: unknown
|
|
419
449
|
}
|
|
420
450
|
) => {
|
|
421
451
|
for (const service of options.rpc.middlewares) {
|