Change how we integrate with Bus
This commit is contained in:
@@ -14,18 +14,9 @@ export function initProjectors() {
|
||||
|
||||
SyncEvent.init({
|
||||
projectors: sessionProjectors,
|
||||
convertDefinition: (type, data) => {
|
||||
if (type === "session.updated") {
|
||||
return z.object({
|
||||
sessionID: SessionID.zod,
|
||||
info: Session.Info,
|
||||
})
|
||||
}
|
||||
return data
|
||||
},
|
||||
convertEvent: (type, data) => {
|
||||
if (type === "session.updated") {
|
||||
const sessionID = (data as z.infer<typeof Session.Event.Updated.data>).sessionID
|
||||
const sessionID = (data as z.infer<typeof Session.Event.Updated.schema>).sessionID
|
||||
return {
|
||||
sessionID: SessionID.zod,
|
||||
info: Session.get(sessionID),
|
||||
|
||||
@@ -233,8 +233,6 @@ export namespace Session {
|
||||
),
|
||||
}
|
||||
|
||||
type X = z.infer<(typeof Event.Updated)["properties"]>
|
||||
|
||||
export const create = fn(
|
||||
z
|
||||
.object({
|
||||
@@ -336,6 +334,16 @@ export namespace Session {
|
||||
// Silently ignore sharing errors during session creation
|
||||
})
|
||||
}
|
||||
|
||||
if (!Flag.OPENCODE_EXPERIMENTAL_WORKSPACES) {
|
||||
// This only exist for backwards compatibility. We should not be
|
||||
// manually publishing this event; it is a sync event now
|
||||
Bus.publish(Event.Updated, {
|
||||
sessionID: result.id,
|
||||
info: result,
|
||||
})
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
@@ -28,9 +28,6 @@ const log = Log.create({ service: "db" })
|
||||
|
||||
export namespace Database {
|
||||
export const Path = iife(() => {
|
||||
if (Installation.isTesting()) {
|
||||
return ":memory:"
|
||||
}
|
||||
if (Flag.OPENCODE_DB) {
|
||||
if (path.isAbsolute(Flag.OPENCODE_DB)) return Flag.OPENCODE_DB
|
||||
return path.join(Global.Path.data, Flag.OPENCODE_DB)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
# Goal
|
||||
|
||||
## Syncing with only one writer
|
||||
@@ -17,9 +16,9 @@ The difference in event sourcing is events are sent _before_ the mutation happen
|
||||
|
||||
So the goal is:
|
||||
|
||||
* Introduce a new syncing abstraction to handle event sourcing and projectors
|
||||
* Seamlessly integrate these new events into the same existing `Bus` abstraction
|
||||
* Maintain full backwards compatibility to reduce risk
|
||||
- Introduce a new syncing abstraction to handle event sourcing and projectors
|
||||
- Seamlessly integrate these new events into the same existing `Bus` abstraction
|
||||
- Maintain full backwards compatibility to reduce risk
|
||||
|
||||
## My approach
|
||||
|
||||
@@ -53,7 +52,6 @@ const Created = SyncEvent.define({
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
Not too different, except they track a version and an "aggregate" field (will explain that later).
|
||||
|
||||
You do this to run an event, which is kind of like `Bus.publish` except that it runs through the event sourcing system:
|
||||
@@ -68,7 +66,7 @@ Importantly, **sync events automatically re-publish as bus events**. This makes
|
||||
|
||||
### Event shape
|
||||
|
||||
* The shape of the events are slightly different. A sync event has the `type`, `id`, `seq`, `aggregateID`, and `data` fields. A bus event has the `type` and `properties` fields. `data` and `properties` are largely the same thing. This conversation is automatically handled when the sync system re-published the event throught the bus.
|
||||
- The shape of the events are slightly different. A sync event has the `type`, `id`, `seq`, `aggregateID`, and `data` fields. A bus event has the `type` and `properties` fields. `data` and `properties` are largely the same thing. This conversation is automatically handled when the sync system re-published the event throught the bus.
|
||||
|
||||
The reason for this is because sync events need to track more information. I chose not to copy the `properties` naming to more clearly disambiguate the event types.
|
||||
|
||||
@@ -84,11 +82,11 @@ You should never "publish" a sync event however: `Bus.publish(Created, ...)`. Th
|
||||
|
||||
The system install projectors in `server/projectors.js`. It calls `SyncEvent.init` to do this. It also installs two different hooks for providing backwards compatibility:
|
||||
|
||||
* `convertDefinition`: a function that convert a zod definition for an event schema
|
||||
* `convertEvent`: a function that converts an individual event's data
|
||||
- `convertDefinition`: a function that convert a zod definition for an event schema
|
||||
- `convertEvent`: a function that converts an individual event's data
|
||||
|
||||
These hooks allow for arbitrary conversions at runtime, allowing for us to provide a backwards compatible interface to clients.
|
||||
|
||||
For example, the sync system changed the `session.updated` event to only include the fields that were changed, compared to before where it returned the full session object. We install converters to load the full session object and return it to clients.
|
||||
|
||||
**Important**:
|
||||
**Important**:
|
||||
|
||||
@@ -15,6 +15,8 @@ export namespace SyncEvent {
|
||||
aggregate: string
|
||||
schema: z.ZodObject
|
||||
|
||||
// This is temporary and only exists for compatibility with bus
|
||||
// event definitions
|
||||
properties: z.ZodObject
|
||||
}
|
||||
|
||||
@@ -69,8 +71,8 @@ export namespace SyncEvent {
|
||||
Type extends string,
|
||||
Agg extends string,
|
||||
Schema extends ZodObject<Record<Agg, z.ZodType<string>>>,
|
||||
BusSchema extends ZodObject<Record<Agg, z.ZodType<string>>> | undefined,
|
||||
>(input: { type: Type; version: number; aggregate: Agg; schema: Schema; busSchema: BusSchema }) {
|
||||
BusSchema extends ZodObject = Schema,
|
||||
>(input: { type: Type; version: number; aggregate: Agg; schema: Schema; busSchema?: BusSchema }) {
|
||||
if (frozen) {
|
||||
throw new Error("Error defining sync event: sync system has been frozen")
|
||||
}
|
||||
@@ -80,9 +82,7 @@ export namespace SyncEvent {
|
||||
version: input.version,
|
||||
aggregate: input.aggregate,
|
||||
schema: input.schema,
|
||||
properties: (input.busSchema ?? input.schema) as BusSchema extends ZodObject<Record<Agg, z.ZodType<string>>>
|
||||
? BusSchema
|
||||
: Schema,
|
||||
properties: input.busSchema ? input.busSchema : input.schema,
|
||||
}
|
||||
|
||||
versions.set(def.type, Math.max(def.version, versions.get(def.type) || 0))
|
||||
|
||||
Reference in New Issue
Block a user