EdgeAIG's picture
download
raw
3.76 kB
/**
* Initial messages for worker-backed RPC protocols.
*
* A worker-backed RPC client can send one schema-encoded value before normal RPC
* requests are handled. This module defines the `InitialMessage` service, a
* helper for encoding that value while collecting transferables, a layer for
* providing it to the client protocol, and a decoder for reading it from the
* worker server protocol.
*
* @since 4.0.0
*/
import type { NoSuchElementError } from "../../Cause.ts"
import * as Context from "../../Context.ts"
import * as Effect from "../../Effect.ts"
import * as Layer from "../../Layer.ts"
import * as Schema from "../../Schema.ts"
import * as Transferable from "../workers/Transferable.ts"
import type { Protocol } from "./RpcServer.ts"
/**
* Context service that supplies the initial RPC worker message as encoded data
* paired with any transferables that should be posted with it.
*
* @category initial message
* @since 4.0.0
*/
export class InitialMessage extends Context.Service<
InitialMessage,
Effect.Effect<
readonly [
data: unknown,
transfers: ReadonlyArray<Transferable>
]
>
>()("effect/rpc/RpcWorker/InitialMessage") {}
/**
* Types related to the encoded initial message exchanged with an RPC worker.
*
* @since 4.0.0
*/
export declare namespace InitialMessage {
/**
* Tagged wire representation of an RPC worker initial message after schema
* encoding.
*
* @category initial message
* @since 4.0.0
*/
export interface Encoded {
readonly _tag: "InitialMessage"
readonly value: unknown
}
}
const ProtocolTag = Context.Service<Protocol, Protocol["Service"]>(
"effect/rpc/RpcServer/Protocol" satisfies Protocol["key"]
)
/**
* Runs an effect, encodes its result with the schema's JSON codec, and returns
* the encoded value together with collected transferables.
*
* @category initial message
* @since 4.0.0
*/
export const makeInitialMessage = <S extends Schema.Top, E, R2>(
schema: S,
effect: Effect.Effect<S["Type"], E, R2>
): Effect.Effect<
readonly [data: unknown, transferables: ReadonlyArray<globalThis.Transferable>],
E | Schema.SchemaError,
S["EncodingServices"] | R2
> => {
const schemaJson = Schema.toCodecJson(schema)
return Effect.flatMap(effect, (value) => {
const collector = Transferable.makeCollectorUnsafe()
return Schema.encodeEffect(schemaJson)(value).pipe(
Effect.provideService(Transferable.Collector, collector),
Effect.map((encoded) => [encoded, collector.clearUnsafe()] as const)
)
})
}
/**
* Provides the `InitialMessage` service from a schema and build effect,
* capturing the layer context and dying if schema encoding fails.
*
* @category initial message
* @since 4.0.0
*/
export const layerInitialMessage = <S extends Schema.Top, R2>(
schema: S,
build: Effect.Effect<S["Type"], never, R2>
): Layer.Layer<InitialMessage, never, S["EncodingServices"] | R2> =>
Layer.effect(InitialMessage)(
Effect.contextWith((context: Context.Context<S["EncodingServices"] | R2>) =>
Effect.succeed(
Effect.provideContext(Effect.orDie(makeInitialMessage(schema, build)), context)
)
)
)
/**
* Reads the protocol initial message and decodes it with the supplied schema,
* failing if no initial message is available or decoding fails.
*
* @category initial message
* @since 4.0.0
*/
export const initialMessage = <S extends Schema.Top>(
schema: S
): Effect.Effect<S["Type"], NoSuchElementError | Schema.SchemaError, Protocol | S["DecodingServices"]> =>
ProtocolTag.pipe(
Effect.flatMap((protocol) => protocol.initialMessage),
Effect.flatMap(Effect.fromOption),
Effect.flatMap(Schema.decodeUnknownEffect(Schema.toCodecJson(schema)))
)

Xet Storage Details

Size:
3.76 kB
·
Xet hash:
e989d21a4093b93d1c6113f20740e0a7a05408b1164f1819f3fff6ee78fda66c

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.