Skip to content

EventLog

Runtime for writing typed events to an event journal.

EventLog combines event groups, handlers, a journal, local identity, optional remote replicas, and reactivity hooks. Writers send typed payloads through a client; the matching handler runs first, and the journal entry is committed only after the handler succeeds. This module also contains the layers and helpers needed to assemble that runtime.

25 exports Added in v4.0.0 Source

Compaction

Registers a compaction handler for an event group.

Details

During remote replay, matching entries are decoded, grouped by primary key, and passed to the compaction effect, which may write replacement entries.

Signature

declare function groupCompaction<Events extends Any, R>(group: EventGroup<Events>, effect: (options: {
  readonly entries: readonly Array<Entry>;
  readonly events: readonly Array<TaggedPayload<Events>>;
  readonly primaryKey: string;
  readonly write: <Tag extends string>(tag: Tag, payload: Type<PayloadSchema<Extract<Events, {
    readonly tag: Tag;
  }>>>) => Effect<void, never, PayloadSchemaWithTag<Events, Tag>["EncodingServices"]>;
}) => Effect<void, never, R>): Layer<never, never, Registry | R | PayloadSchema<Events>["DecodingServices"]>

Constructors

Decodes a base64url identity string produced by encodeIdentityString.

Gotchas

Invalid input throws a schema decoding error.

Signature

declare function decodeIdentityString(value: string): {
  readonly privateKey: Redacted<Uint8Array<ArrayBuffer>>;
  readonly publicKey: string;
};

Encodes an event-log identity as a base64url string containing the public key and private key bytes.

Signature

declare function encodeIdentityString(identity: {
  readonly privateKey: Redacted<Uint8Array<ArrayBuffer>>;
  readonly publicKey: string;
}): string;

makeClient

Added in v4.0.0 Source

Creates a typed client function for writing events defined by an EventLogSchema.

Details

The returned function delegates to the EventLog service and preserves each event's success and error types.

Signature

declare function makeClient<Groups extends Any>(
  schema: EventLogSchema<Groups>,
): Effect<
  <Tag extends string>(
    event: Tag,
    payload: Type<
      PayloadSchema<
        Extract<
          Events<Groups>,
          {
            readonly tag: Tag;
          }
        >
      >
    >,
  ) => Effect<
    Type<
      SuccessSchema<
        Extract<
          Events<Groups>,
          {
            readonly tag: Tag;
          }
        >
      >
    >,
    | EventJournalError
    | Type<
        ErrorSchema<
          Extract<
            Events<Groups>,
            {
              readonly tag: Tag;
            }
          >
        >
      >
  >,
  never,
  EventLog
>;

makeIdentity

Added in v4.0.0 Source

Generates a new event-log identity using the configured EventLogEncryption service.

Signature

declare const makeIdentity: Effect.Effect<
  Identity["Service"],
  never,
  EventLogEncryption.EventLogEncryption
>;

Guards

Returns true when a value carries the EventLogSchema marker.

Signature

declare function isEventLogSchema(u: unknown): u is EventLogSchema<Any>;

Handlers

group

Added in v4.0.0 Source

Creates a layer that registers handlers for every event in an event group.

Details

The callback receives a Handlers builder; its return type is checked so every event in the group is handled.

Signature

declare function group<Events extends Any, Return>(
  group: EventGroup<Events>,
  f: (handlers: Handlers<never, Events>) => ValidateReturn<Return>,
): Layer<ToService<Events>, Error<Return>, Registry | Exclude<Services<Return>, Scope | Identity>>;

Handlers interface

Added in v4.0.0 Source

Builder for the handlers associated with an EventGroup.

Details

The Events type parameter tracks the event tags that still need handlers, and each call to handle records a handler while accumulating any required services.

Signature

interface Handlers<R, Events extends Event.Any = never> extends Pipeable {
  readonly "~effect/eventlog/EventLog/Handlers": {
    _Events: Covariant<Events>;
  };
  readonly context: Context<R>;
  readonly group: AnyWithProps;
  readonly handlers: Record.ReadonlyRecord<string, Handlers.Item<R>>;
  handle<Tag extends string, R1>(name: Tag, handler: (options: {
    readonly conflicts: readonly Array<{
      readonly entry: Entry;
      readonly payload: Type<PayloadSchema<Extract<Events, {
        readonly tag: Tag;
      }>>>;
    }>;
    readonly entry: Entry;
    readonly payload: Type<PayloadSchema<Extract<Events, {
      readonly tag: Tag;
    }>>>;
    readonly storeId: StoreId;
  }) => Effect<Type<SuccessSchema<Extract<Events, {
    readonly tag: Tag;
  }>>>, Type<ErrorSchema<Extract<Events, {
    readonly tag: Tag;
  }>>>, R1>): Handlers<R | R1, Exclude<Events, {
    readonly tag: Tag;
  }>>;
}

Builds the effect used to replay entries received from a remote event log.

Details

The returned handler decodes the entry and conflicts with the registered event schema, runs the matching handler with the supplied identity and store id, logs failures, and invalidates configured reactivity keys.

Signature

declare function makeReplayFromRemote(options: {
  readonly handlers: ReadonlyMap<string, Item<any>>;
  readonly identity: {
    readonly privateKey: Redacted<Uint8Array<ArrayBuffer>>;
    readonly publicKey: string;
  };
  readonly logAnnotations: {
    readonly effect: string;
    readonly service: string;
  };
  readonly reactivity: {
    readonly invalidate: (keys: readonly Array<unknown> | ReadonlyRecord<string, readonly Array<unknown>>) => Effect<void>;
    readonly invalidateUnsafe: (keys: readonly Array<unknown> | ReadonlyRecord<string, readonly Array<unknown>>) => void;
    readonly mutation: <A, E, R>(keys: readonly Array<unknown> | ReadonlyRecord<string, readonly Array<unknown>>, effect: Effect<A, E, R>) => Effect<A, E, R>;
    readonly query: <A, E, R>(keys: readonly Array<unknown> | ReadonlyRecord<string, readonly Array<unknown>>, effect: Effect<A, E, R>) => Effect<Dequeue<A, E>, never, Scope | R>;
    readonly registerUnsafe: (keys: readonly Array<unknown> | ReadonlyRecord<string, readonly Array<unknown>>, handler: () => void) => () => void;
    readonly stream: <A, E, R>(keys: readonly Array<unknown> | ReadonlyRecord<string, readonly Array<unknown>>, effect: Effect<A, E, R>) => Stream<A, E, Exclude<R, Scope>>;
    readonly withBatch: <A, E, R>(effect: Effect<A, E, R>) => Effect<A, E, R>;
  };
  readonly reactivityKeys: Record<string, ReadonlyArray<string>>;
  readonly storeId: StoreId;
}): (...args: [{
  readonly conflicts: readonly Array<Entry>;
  readonly entry: Entry;
}]) => Effect

Layers

layer

Added in v4.0.0 Source

Combines event-group handler layers with the EventLog runtime for a schema.

When to use

Use when you need one layer that installs the shared EventLog runtime for an EventLogSchema and registers an event-group handler layer for typed writes.

Details

The supplied handler layer is provided with layerEventLog. The returned layer provides EventLog | Registry, preserves the handler layer's error type, and still requires its remaining services plus EventJournal and Identity.

Gotchas

The schema argument does not register handlers by itself. Handler registration comes from the supplied layer, and writing an event without a registered handler dies with Event handler not found for: "<tag>".

See

  • schema for creating the schema argument from event groups
  • group for building the handler layer consumed by this layer
  • layerEventLog for installing the runtime and registry without combining a handler layer

Signature

declare function layer<Groups extends Any, E, R>(
  _schema: EventLogSchema<Groups>,
  layer: Layer<ToService<Groups>, E, R>,
): Layer<EventLog | Registry, E, EventJournal | Identity | Exclude<R, EventLog | Registry>>;

Provides EventLog and Registry using the configured EventJournal and Identity.

Signature

declare const layerEventLog: Layer.Layer<EventLog | Registry, never, EventJournal | Identity>;

Provides an in-memory Registry for event handlers, compactors, remote replicas, and reactivity keys.

Signature

declare const layerRegistry: Layer<Registry, never, never>;

Other

Handlers

Added in v4.0.0 Source

Namespace containing helper types for Handlers values and handler-producing layers.

Reactivity

Registers reactivity keys to invalidate when events from a group are written or replayed.

Details

Pass a single key list for all events or a mapping from event tag to key list.

Signature

declare function groupReactivity<Events extends Any>(group: EventGroup<Events>, keys: readonly Array<string> | { [Tag in string]: readonly Array<string> }): Layer<never, never, Registry>

Schemas

EventLogSchema interface

Added in v4.0.0 Source

Schema describing the event groups that can be written through an EventLog.

Signature

interface EventLogSchema<Groups extends EventGroup.Any> {
  readonly "~effect/eventlog/EventLog/Schema": "~effect/eventlog/EventLog/Schema";
  readonly groups: readonly Array<Groups>;
}

Schema for an event-log identity with a string public key and redacted base64-encoded private key bytes.

Signature

declare const IdentitySchema: Struct<{
  readonly privateKey: decodeTo<Redacted<Uint8Array>, Uint8ArrayFromBase64, never, never>;
  readonly publicKey: String;
}>;

schema

Added in v4.0.0 Source

Creates an EventLogSchema from one or more event groups.

Signature

declare function schema<Groups extends readonly Array<Any>>(...groups: Groups): EventLogSchema<Groups[number]>

Services

Context reference for the store id used by event-log writes and remote replication.

Details

Defaults to the branded store id "default".

Signature

declare class CurrentStoreId extends ({}) {
  constructor(_: never);
}

EventLog

Added in v4.0.0 Source

Service for writing typed event-log events through registered handlers.

Details

write encodes the event payload, runs the matching handler, commits the entry only when the handler succeeds, and exposes access to the underlying journal entries and destroy operation.

Signature

declare class EventLog extends Shape<"effect/eventlog/EventLog", {
  readonly destroy: Effect<void, EventJournalError>;
  readonly entries: Effect<readonly Array<Entry>, EventJournalError>;
  readonly write: <Groups extends Any, Tag extends string>(options: {
    readonly event: Tag;
    readonly payload: Type<PayloadSchema<Extract<Events<Groups>, {
      readonly tag: Tag;
    }>>>;
    readonly schema: EventLogSchema<Groups>;
  }) => Effect<Type<SuccessSchema<Extract<Events<Groups>, {
    readonly tag: Tag;
  }>>>, EventJournalError | Type<ErrorSchema<Extract<Events<Groups>, {
    readonly tag: Tag;
  }>>>>;
}, this> {
  constructor(_: never);
}

Identity

Added in v4.0.0 Source

Context service for an event-log identity containing a public key and redacted private key material.

Details

The identity is used by remote replication for authentication and by the encryption service to derive signing and encryption keys.

Signature

declare class Identity extends Shape<
  "effect/eventlog/EventLog/Identity",
  {
    readonly privateKey: Redacted<Uint8Array<ArrayBuffer>>;
    readonly publicKey: string;
  },
  this
> {
  constructor(_: never);
}

Registry

Added in v4.0.0 Source

Service that collects event handlers, compaction handlers, remote replicas, and reactivity invalidation keys.

Signature

declare class Registry extends Shape<"effect/unstable/eventlog/EventLog/Registry", {
  readonly compactors: ReadonlyMap<string, {
    readonly effect: (options: {
      readonly entries: readonly Array<Entry>;
      readonly write: (entry: Entry) => Effect<void>;
    }) => Effect<void>;
    readonly events: ReadonlySet<string>;
  }>;
  readonly handleRemote: (handler: (remote: {
    readonly changes: (options: {
      readonly identity: {
        readonly privateKey: Redacted<Uint8Array<...>>;
        readonly publicKey: string;
      };
      readonly startSequence: number;
      readonly storeId: StoreId;
    }) => Effect<Dequeue<RemoteEntry, EventLogRemoteError>, never, Scope>;
    readonly id: RemoteId;
    readonly whenAuthenticated: <A, E, R>(effect: Effect<A, E, R>) => Effect<A, EventLogRemoteError | E, Identity | R>;
    readonly write: (options: {
      readonly entries: readonly Array<Entry>;
      readonly identity: {
        readonly privateKey: Redacted<Uint8Array<...>>;
        readonly publicKey: string;
      };
      readonly storeId: StoreId;
    }) => Effect<void, EventLogRemoteError>;
  }) => Effect<void>) => Effect<void>;
  readonly handlers: ReadonlyMap<string, Item<any>>;
  readonly reactivityKeys: Record<string, ReadonlyArray<string>>;
  readonly registerCompaction: (options: {
    readonly effect: (options: {
      readonly entries: readonly Array<Entry>;
      readonly write: (entry: Entry) => Effect<void>;
    }) => Effect<void>;
    readonly events: readonly Array<string>;
  }) => Effect<void, never, Scope>;
  readonly registerHandlerUnsafe: (options: {
    readonly event: string;
    readonly handler: Item<any>;
  }) => void;
  readonly registerReactivity: (keys: Record<string, ReadonlyArray<string>>) => Effect<void, never, Scope>;
  readonly registerRemote: (remote: {
    readonly changes: (options: {
      readonly identity: {
        readonly privateKey: Redacted<Uint8Array<ArrayBuffer>>;
        readonly publicKey: string;
      };
      readonly startSequence: number;
      readonly storeId: StoreId;
    }) => Effect<Dequeue<RemoteEntry, EventLogRemoteError>, never, Scope>;
    readonly id: RemoteId;
    readonly whenAuthenticated: <A, E, R>(effect: Effect<A, E, R>) => Effect<A, EventLogRemoteError | E, Identity | R>;
    readonly write: (options: {
      readonly entries: readonly Array<Entry>;
      readonly identity: {
        readonly privateKey: Redacted<Uint8Array<ArrayBuffer>>;
        readonly publicKey: string;
      };
      readonly storeId: StoreId;
    }) => Effect<void, EventLogRemoteError>;
  }) => Effect<void, never, Scope>;
}, this> {
  constructor(_: never);
}

Type IDs

Runtime property key used to identify Handlers values.

Signature

declare const HandlersTypeId: "~effect/eventlog/EventLog/Handlers";

HandlersTypeId type

Added in v4.0.0 Source

Type-level identifier used to brand Handlers values.

Signature

type HandlersTypeId = "~effect/eventlog/EventLog/Handlers";

SchemaTypeId

Added in v4.0.0 Source

Runtime property key used to identify EventLogSchema values.

Signature

declare const SchemaTypeId: "~effect/eventlog/EventLog/Schema";

SchemaTypeId type

Added in v4.0.0 Source

Type-level identifier used to brand EventLogSchema values.

Signature

type SchemaTypeId = "~effect/eventlog/EventLog/Schema";