EventJournal: after #7461, a custom journal cannot decode EventLog payloads with one union codec
Los mantenedores suelen responder en 1 día
Evaluación
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Aptitud para principiantes
- 55/100
- Tipo de issue
- Error
- Claridad
- Bastante claro
- Estado de actividad
- Activo
- Stack tecnológico
- typescript
- Área
- backend
Línea de trabajo
Run the supplied repro with bun repro.ts, then inspect the EventJournal.write and Entry.payload contracts alongside the #7461 changeset. Determine whether the documentation, migration note, or a group decoding helper best makes the per-event payloadSchemaBinary requirement explicit, and confirm the repro no longer leaves custom journals decoding payloads with an incompatible union codec.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
What version of Effect is running?
effect 4.0.0-rc.117 (upgrading from 4.0.0-rc.112)
What steps can reproduce the bug?
A custom EventJournal receives write({ event, primaryKey, payload }) from EventLog and must decode payload itself, for example to validate the entry or to store it in its own format. On rc.112 the payload was MessagePack, which describes itself, so a journal could decode every event in a group with one codec built from the union of the payload schemas.
#7461 removed effect/unstable/encoding/Msgpack. The obvious port, Msgpack.schema(Union) → SchemaBinary.toCodec(Union), compiles and type-checks, but it rejects every payload that EventLog writes. SchemaBinary bytes follow the layout of the codec that wrote them, and EventLog writes each payload with its own event's payloadSchemaBinary, not with a codec for the union.
Minimal repro (both versions installed side by side):
{
"type": "module",
"dependencies": {
"effect-old": "npm:[email protected]",
"effect": "4.0.0-rc.117"
}
}
import * as OldSchema from 'effect-old/Schema'
import * as OldMsgpack from 'effect-old/unstable/encoding/Msgpack'
import * as OldEventGroup from 'effect-old/unstable/eventlog/EventGroup'
import * as Schema from 'effect/Schema'
import * as SchemaBinary from 'effect/unstable/encoding/SchemaBinary'
import * as EventGroup from 'effect/unstable/eventlog/EventGroup'
const oldPayloads = [
OldSchema.Struct({ name: OldSchema.Literal('user/create'), id: OldSchema.String }),
OldSchema.Struct({ name: OldSchema.Literal('user/rename'), id: OldSchema.String, to: OldSchema.String })
] as const
const payloads = [
Schema.Struct({ name: Schema.Literal('user/create'), id: Schema.String }),
Schema.Struct({ name: Schema.Literal('user/rename'), id: Schema.String, to: Schema.String })
] as const
const OldGroup = OldEventGroup.empty
.add({ tag: 'user/create', primaryKey: (p) => p.id, payload: oldPayloads[0] })
.add({ tag: 'user/rename', primaryKey: (p) => p.id, payload: oldPayloads[1] })
const Group = EventGroup.empty
.add({ tag: 'user/create', primaryKey: (p) => p.id, payload: payloads[0] })
.add({ tag: 'user/rename', primaryKey: (p) => p.id, payload: payloads[1] })
const input = { name: 'user/rename', id: 'u1', to: 'Ada' } as const
// rc.112: EventLog writes event.payloadMsgPack bytes; one union codec decodes them.
const oldBytes = OldSchema.encodeSync(OldGroup.events['user/rename'].payloadMsgPack)(input)
console.log('rc.112 union decode:', OldSchema.decodeUnknownSync(OldMsgpack.schema(OldSchema.Union(oldPayloads)))(oldBytes))
// rc.117: EventLog writes event.payloadSchemaBinary bytes; the direct port of the same journal code fails.
const bytes = Schema.encodeSync(Group.events['user/rename'].payloadSchemaBinary)(input)
Schema.decodeUnknownSync(SchemaBinary.toCodec(Schema.Union(payloads)))(bytes)
Run it with bun repro.ts.
What is the expected behavior?
Either a journal can decode an EventLog payload without knowing which event wrote it, as on rc.112, or the API makes the per-event contract hard to miss.
What do you see instead?
rc.112 union decode: { name: "user/rename", id: "u1", to: "Ada" }
SchemaError(Missing key)
The union codec fails for every member of the union, not only for later ones. So every EventLog write through such a journal fails at runtime, and nothing in the types warns about it. The fix is to look up group.events[tag].payloadSchemaBinary for each entry, but nothing in the EventJournal docs or the #7461 changeset points to it.
Additional information
Possible fixes, from smallest to largest:
- Document on
EventJournal.writeandEntry.payloadthat the bytes are encoded with the writing event'spayloadSchemaBinary, so a reader must decode them with that same codec. - Add a migration note to the #7461 changeset:
SchemaBinary.toCodec(schema)is not a drop-in replacement forMsgpack.schema(schema)when the reader's schema differs from the writer's, for example a union reading a member's bytes. - Export a helper that decodes an entry for a group, for example
EventGroup.decodePayload(group, entry), so custom journals do not have to write their own lookup by tag.
- Lenguaje dominante
- TypeScript
- Estrellas
- 16.7k
- Forks
- 808
- Merge medio
- 11 h 11 min
- PR fusionados (30 d)
- 840
Preparar el entorno
Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de Effect-TS/effect
-
Dificultad 1/5 Menos de una hora Aptitud para principiantes 82/100
Los mantenedores suelen responder en 1 día
-
@effect/ai-anthropic: text_editor_20250728 insert decodes `new_str`, but the API sends `insert_text`Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
Los mantenedores suelen responder en 1 día
-
[email protected]: crypto/KeyFormat declarations require the global JsonWebKey, breaking Node-only type-checksPosiblemente ocupada @effect-bot la tomó hoy. Abierto
Effect-TS/effect#10115 · 1 asignado ·
Los mantenedores suelen responder en 1 día
-
bug
Dificultad 4/5 1-2 días Aptitud para principiantes 55/100
Los mantenedores suelen responder en 1 día
-
sql-pg: send several statements in one extended-query Sync (transaction-local context without extra round trips)Posiblemente ocupada @effect-bot la tomó hoy. Abierto
Effect-TS/effect#10113 · 1 asignado ·
Los mantenedores suelen responder en 1 día
Todos los issues de Effect-TS/effect
Issues similares
-
b:minor bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
software-mansion/argent#1698 ·
Los mantenedores suelen responder en 1 día
-
e2e-failure ready-to-code
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
redhat-developer/rhdh-plugin-export-overlays#4624 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
better-auth/better-auth#12132 · 1 reacción ·
Los mantenedores suelen responder en 1 día
-
automation missing-model model-sync provider:tinfoil
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
anomalyco/models.dev#12053 ·
Los mantenedores suelen responder en 1 día
-
o8 next debug build aborts on Glass to Dark appearance switch (nil identifier messaged before check)Abiertobug
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
hurttlocker/o8#5112 ·