refactor(sync): make session events schema-first (#24019)
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import z from "zod"
|
||||
import { Effect, Exit, Layer, PubSub, Scope, Context, Stream } from "effect"
|
||||
import { Effect, Exit, Layer, PubSub, Scope, Context, Stream, Schema as EffectSchema, Types } from "effect"
|
||||
import { EffectBridge } from "@/effect"
|
||||
import { Log } from "../util"
|
||||
import { BusEvent } from "./bus-event"
|
||||
@@ -9,6 +9,12 @@ import { makeRuntime } from "@/effect/run-service"
|
||||
|
||||
const log = Log.create({ service: "bus" })
|
||||
|
||||
type BusProperties<D extends BusEvent.Definition = BusEvent.Definition> = D extends {
|
||||
effectProperties: infer Properties extends EffectSchema.Top
|
||||
}
|
||||
? Types.DeepMutable<EffectSchema.Schema.Type<Properties>>
|
||||
: z.infer<D["properties"]>
|
||||
|
||||
export const InstanceDisposed = BusEvent.define(
|
||||
"server.instance.disposed",
|
||||
z.object({
|
||||
@@ -18,7 +24,7 @@ export const InstanceDisposed = BusEvent.define(
|
||||
|
||||
type Payload<D extends BusEvent.Definition = BusEvent.Definition> = {
|
||||
type: D["type"]
|
||||
properties: z.infer<D["properties"]>
|
||||
properties: BusProperties<D>
|
||||
}
|
||||
|
||||
type State = {
|
||||
@@ -29,7 +35,7 @@ type State = {
|
||||
export interface Interface {
|
||||
readonly publish: <D extends BusEvent.Definition>(
|
||||
def: D,
|
||||
properties: z.output<D["properties"]>,
|
||||
properties: BusProperties<D>,
|
||||
) => Effect.Effect<void>
|
||||
readonly subscribe: <D extends BusEvent.Definition>(def: D) => Stream.Stream<Payload<D>>
|
||||
readonly subscribeAll: () => Stream.Stream<Payload>
|
||||
@@ -79,7 +85,10 @@ export const layer = Layer.effect(
|
||||
})
|
||||
}
|
||||
|
||||
function publish<D extends BusEvent.Definition>(def: D, properties: z.output<D["properties"]>) {
|
||||
function publish<D extends BusEvent.Definition>(
|
||||
def: D,
|
||||
properties: BusProperties<D>,
|
||||
) {
|
||||
return Effect.gen(function* () {
|
||||
const s = yield* InstanceState.get(state)
|
||||
const payload: Payload = { type: def.type, properties }
|
||||
@@ -175,13 +184,16 @@ const { runPromise, runSync } = makeRuntime(Service, layer)
|
||||
|
||||
// runSync is safe here because the subscribe chain (InstanceState.get, PubSub.subscribe,
|
||||
// Scope.make, Effect.forkScoped) is entirely synchronous. If any step becomes async, this will throw.
|
||||
export async function publish<D extends BusEvent.Definition>(def: D, properties: z.output<D["properties"]>) {
|
||||
export async function publish<D extends BusEvent.Definition>(
|
||||
def: D,
|
||||
properties: BusProperties<D>,
|
||||
) {
|
||||
return runPromise((svc) => svc.publish(def, properties))
|
||||
}
|
||||
|
||||
export function subscribe<D extends BusEvent.Definition>(
|
||||
def: D,
|
||||
callback: (event: { type: D["type"]; properties: z.infer<D["properties"]> }) => unknown,
|
||||
callback: (event: Payload<D>) => unknown,
|
||||
) {
|
||||
return runSync((svc) => svc.subscribeCallback(def, callback))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user