fix(core): preserve event routing semantics

This commit is contained in:
Kit Langton 2026-06-25 12:41:44 -04:00
commit 603b334b7f
13 changed files with 277 additions and 129 deletions

View file

@ -138,6 +138,50 @@ describe("EventV2", () => {
}),
)
it.effect("preserves same-type projector routing across durable versions", () =>
Effect.gen(function* () {
const events = yield* EventV2.Service
const historical = EventV2.define({
type: "test.projector-version",
durable: { version: 1, aggregate: "id" },
schema: { id: Schema.String },
})
const current = EventV2.define({
type: "test.projector-version",
durable: { version: 2, aggregate: "id" },
schema: { id: Schema.String },
})
const received = new Array<EventV2.Payload>()
yield* events.project(historical, (event) => Effect.sync(() => received.push(event)))
const published = yield* events.publish(current, { id: "aggregate" })
expect(received).toEqual([published])
}),
)
it.effect("preserves same-type subscription routing across durable versions", () =>
Effect.gen(function* () {
const events = yield* EventV2.Service
const historical = EventV2.define({
type: "test.subscription-version",
durable: { version: 1, aggregate: "id" },
schema: { id: Schema.String },
})
const current = EventV2.define({
type: "test.subscription-version",
durable: { version: 2, aggregate: "id" },
schema: { id: Schema.String },
})
const fiber = yield* events.subscribe(historical).pipe(Stream.take(1), Stream.runCollect, Effect.forkScoped)
yield* Effect.yieldNow
const published = yield* events.publish(current, { id: "aggregate" })
expect(Array.from(yield* Fiber.join(fiber))).toEqual([published])
}),
)
it.effect("publishes to typed and wildcard subscriptions", () =>
Effect.gen(function* () {
const events = yield* EventV2.Service

View file

@ -17,7 +17,14 @@ const capture = () => {
const events = EventV2.Service.of({
publish: (definition, data) =>
Effect.sync(() => {
const event = { id: EventV2.ID.create(), type: definition.type, data } as EventV2.Payload<typeof definition>
const event = {
id: EventV2.ID.create(),
type: definition.type,
...(definition.durable
? { durable: { aggregateID: sessionID, seq: published.length, version: definition.durable.version } }
: {}),
data,
} as EventV2.Payload<typeof definition>
published.push({
type: definition.durable
? EventV2.versionedType(definition.type, definition.durable.version)