Sync / foldkit-durable

JournalShape

interface · packages/durable/src/journal.ts:237

interface Journal<Operation, Snapshot, Principal, OperationEncoded = unknown> {
  readonly load: (key: DocumentId) => Effect.Effect<
    {
      readonly snapshot: Snapshot
      readonly cursor: Cursor
    },
    JournalError
  >
  readonly cursor: (key: DocumentId) => Effect.Effect<Cursor, JournalError>
  readonly epoch: (key: DocumentId) => Effect.Effect<string, JournalError>
  readonly floor: (key: DocumentId) => Effect.Effect<Sequence, JournalError>
  readonly read: (
    key: DocumentId,
    after: Cursor,
    options?: {
      readonly limit?: number
    },
  ) => Effect.Effect<
    ReadonlyArray<Committed<Operation>>,
    InvalidCursorError | CompactedCursorError | JournalError
  >
  readonly append: (
    key: DocumentId,
    input: OperationEncoded,
    principal: Principal,
  ) => Effect.Effect<AppendResult<Operation>, AppendError>
  readonly appendAll: (
    key: DocumentId,
    inputs: ReadonlyArray<OperationEncoded>,
    principal: Principal,
  ) => Effect.Effect<ReadonlyArray<AppendResult<Operation>>, AppendError>
  readonly compact: (
    key: DocumentId,
    through: Sequence,
  ) => Effect.Effect<void, InvalidCompactionError | JournalError>
  readonly vacuum: () => Effect.Effect<void, JournalError>
  readonly keys: () => Effect.Effect<ReadonlyArray<DocumentId>, JournalError>
  readonly unfinished: () => Effect.Effect<
    ReadonlyArray<EffectRecord>,
    JournalError
  >
  readonly effect: (
    key: string,
  ) => Effect.Effect<Option.Option<EffectRecord>, JournalError>
  readonly runEffect: <Result, E>(
    key: string,
    run: Effect.Effect<Result, E>,
    options?: {
      readonly retryFailed?: boolean | ((record: EffectRecord) => boolean)
    },
  ) => Effect.Effect<Result, E | JournalError | EffectFailedError>
  readonly clearEffect: (key: string) => Effect.Effect<void, JournalError>
  readonly recover: (
    options: RecoveryOptions<Operation>,
  ) => Effect.Effect<
    Cursor,
    InvalidCursorError | CompactedCursorError | JournalError
  >
  readonly reset: (key: DocumentId) => Effect.Effect<void, JournalError>
  readonly subscribe: Stream.Stream<string>
}

Members

JournalShape.load

property · packages/durable/src/journal.ts:238

readonly load: (key: DocumentId) => Effect.Effect<
  {
    readonly snapshot: Snapshot
    readonly cursor: Cursor
  },
  JournalError
>

JournalShape.cursor

property · packages/durable/src/journal.ts:246

readonly cursor: (key: DocumentId) => Effect.Effect<Cursor, JournalError>

The sequence of the document's last commit; 0 if none. Unlike load, it decodes nothing, so an exchange can check a client's cursor before it appends anything.

JournalShape.epoch

property · packages/durable/src/journal.ts:252

readonly epoch: (key: DocumentId) => Effect.Effect<string, JournalError>

The identity of the document's history: the same while its operations are kept, new after reset or on a new database file. A client that saw another epoch holds a cursor into history this journal does not have, and must start again from 0.

JournalShape.floor

property · packages/durable/src/journal.ts:254

readonly floor: (key: DocumentId) => Effect.Effect<Sequence, JournalError>

The highest sequence whose payload has been compacted away; 0 if none.

JournalShape.read

property · packages/durable/src/journal.ts:259

readonly read: (
  key: DocumentId,
  after: Cursor,
  options?: {
    readonly limit?: number
  },
) => Effect.Effect<
  ReadonlyArray<Committed<Operation>>,
  InvalidCursorError | CompactedCursorError | JournalError
>

The committed operations after after, in order: at most limit of them when given, so a caller far behind can catch up in bounded steps.

JournalShape.append

property · packages/durable/src/journal.ts:274

readonly append: (
  key: DocumentId,
  input: OperationEncoded,
  principal: Principal,
) => Effect.Effect<AppendResult<Operation>, AppendError>

Commits an operation. A repeat of a known opId returns Committed with the stored operation while its payload is retained, and AlreadyCommitted without one once compaction has removed it. A reuse with different data or actor is an IdentityConflictError in either case, proven by a retained payload hash.

JournalShape.appendAll

property · packages/durable/src/journal.ts:280

readonly appendAll: (
  key: DocumentId,
  inputs: ReadonlyArray<OperationEncoded>,
  principal: Principal,
) => Effect.Effect<ReadonlyArray<AppendResult<Operation>>, AppendError>

Commits several operations in order, in one transaction.

JournalShape.compact

property · packages/durable/src/journal.ts:285

readonly compact: (
  key: DocumentId,
  through: Sequence,
) => Effect.Effect<void, InvalidCompactionError | JournalError>

JournalShape.vacuum

property · packages/durable/src/journal.ts:295

readonly vacuum: () => Effect.Effect<void, JournalError>

Rebuilds the database file, returning to the file system the space that compact freed: compaction empties payloads but leaves their pages allocated. It rewrites every table and holds the database while it runs, so it is maintenance, not something to run per commit.

JournalShape.keys

property · packages/durable/src/journal.ts:297

readonly keys: () => Effect.Effect<ReadonlyArray<DocumentId>, JournalError>

The document keys that have a snapshot or a committed operation.

JournalShape.unfinished

property · packages/durable/src/journal.ts:299

readonly unfinished: () => Effect.Effect<
  ReadonlyArray<EffectRecord>,
  JournalError
>

Every recorded effect that is not succeeded, for recovery.

JournalShape.effect

property · packages/durable/src/journal.ts:301

readonly effect: (
  key: string,
) => Effect.Effect<Option.Option<EffectRecord>, JournalError>

The recorded effect for a key, if it has ever run.

JournalShape.runEffect

property · packages/durable/src/journal.ts:313

readonly runEffect: <Result, E>(
  key: string,
  run: Effect.Effect<Result, E>,
  options?: {
    readonly retryFailed?: boolean | ((record: EffectRecord) => boolean)
  },
) => Effect.Effect<Result, E | JournalError | EffectFailedError>

Reuses recorded successes and shares concurrent runs within this journal instance. Pending and failed records are retried when called again, unless retryFailed says otherwise — false for every failed record, or a predicate that decides from the record itself. An external action can succeed before its result is recorded; recovery requires provider idempotency or reconciliation. Use a stable key including the document, operation, and semantic effect identity, and pass that same key to the provider. Results must be JSON-compatible. See the README's effect recovery policy before retrying work with uncertain outcomes.

JournalShape.clearEffect

property · packages/durable/src/journal.ts:319

readonly clearEffect: (key: string) => Effect.Effect<void, JournalError>

Removes an effect record so the next runEffect treats it as new work.

JournalShape.recover

property · packages/durable/src/journal.ts:327

readonly recover: (
  options: RecoveryOptions<Operation>,
) => Effect.Effect<
  Cursor,
  InvalidCursorError | CompactedCursorError | JournalError
>

Runs the effect intents of a document's committed operations after from, reusing recorded successes and stopping before any operation whose intent failed or was skipped. Returns the cursor up to which every intent settled, so a caller can persist it and resume. The journal does not schedule this; the application owns discovery and startup.

JournalShape.reset

property · packages/durable/src/journal.ts:336

readonly reset: (key: DocumentId) => Effect.Effect<void, JournalError>

Drops a document's snapshot and operations, and its epoch, so the next epoch differs. Replica bindings stay: they are who a replica is, not history. Effect records are keyed by the application's own effect identity, not by document, so they are not scoped to a key; clearEffect removes one.

JournalShape.subscribe

property · packages/durable/src/journal.ts:342

readonly subscribe: Stream.Stream<string>

The document keys a commit changed. Subscription is a Stream, so a subscriber never fails or slows a commit; a caller that needs a callback adapts it at the edge.