CheckpointStore.ts overview

Create-only SQLite checkpoints. Applications own capture, database provisioning, migration timing, and restoration into a fresh volume.

Since v0.1.0


errors

CheckpointError (class)

Checkpoint lookup, naming, or storage failure. Rejected limits and unusable images fail with core's VfsError instead, reporting the image code, such as InvalidStructure or LimitExceeded. Every failure names the entry point that raised it as its operation: CheckpointStore.make, CheckpointStore.save, CheckpointStore.load or CheckpointStore.migrate.

Example

// `NotFound` is expected on a first run; other codes are real failures.
import { CheckpointStore } from "@effect-vfs/persistence"
import { ByteSize, Effect } from "effect"
 
const limits = {
  maxEncodedBytes: ByteSize.megabytes(4),
  maxRecords: 10_000,
  maxEntries: 10_000,
  maxDecodedBytes: ByteSize.megabytes(16)
}
 
const loadOrStartFresh = Effect.gen(function* () {
  const store = yield* CheckpointStore.make(limits)
 
  return yield* store.load("nightly").pipe(
    Effect.asSome,
    Effect.catchTag("CheckpointError", (error) => (error.code === "NotFound" ? Effect.succeedNone : Effect.fail(error)))
  )
})

Signature

declare class CheckpointError

Source

Since v0.1.0

services

CheckpointStore (class)

SQLite checkpoint service. Supply a SQLite SqlClient and run migrate before use. Driver lifetime belongs to the application's layer scope.

Details

CheckpointStore.migrate applies the package's numbered migrations through a separate ledger table, effect_vfs_checkpoint_migrations. Run it once during application startup, before providing the store to consumers; it is safe to run again on later startups. Neither make nor layer runs it.

Example

import { CheckpointStore } from "@effect-vfs/persistence"
import { ByteSize, Effect, Layer } from "effect"
import type { SqlClient } from "effect/sql/SqlClient"
 
const limits = {
  maxEncodedBytes: ByteSize.megabytes(4),
  maxRecords: 10_000,
  maxEntries: 10_000,
  maxDecodedBytes: ByteSize.megabytes(16)
}
 
// `migrate` creates the package tables and must run before the store is used.
const checkpoints = (sqlite: Layer.Layer<SqlClient>) =>
  CheckpointStore.layer(limits).pipe(Layer.provide(Layer.effectDiscard(CheckpointStore.migrate)), Layer.provide(sqlite))
 
const program = (sqlite: Layer.Layer<SqlClient>) =>
  Effect.gen(function* () {
    const store = yield* CheckpointStore
 
    return yield* store.load("nightly")
  }).pipe(Effect.provide(checkpoints(sqlite)))

See

  • The SQLite checkpoints guide at /guides/sqlite-checkpoints for driver selection, transaction semantics, and durability caveats.

Signature

declare class CheckpointStore

Source

Since v0.1.0

make (static method)

Creates a store with an owned copy of mandatory image limits. Saving encodes under the same limits loading decodes under and fails where loading would, so a saved checkpoint is known to load without being decoded.

Example

import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
import { CheckpointStore } from "@effect-vfs/persistence"
import { ByteSize, Effect, Layer } from "effect"
import type { SqlClient } from "effect/sql/SqlClient"
 
const limits = {
  maxEncodedBytes: ByteSize.megabytes(4),
  maxRecords: 10_000,
  maxEntries: 10_000,
  maxDecodedBytes: ByteSize.megabytes(16)
}
 
const program = Effect.gen(function* () {
  const store = yield* CheckpointStore.make(limits)
 
  const volume = yield* Vfs.fromFixture({
    entries: [{ kind: "file", path: "/notes.txt", bytes: new Uint8Array([104, 105]) }]
  })
 
  yield* store.save("nightly", yield* volume.snapshot)
 
  // Restoration always produces a fresh volume.
  return yield* store.load("nightly").pipe(Effect.flatMap(Vfs.fromSnapshot()))
})
 
// The package does not choose a driver; supply your own SQLite client.
const runnable = (sqlite: Layer.Layer<SqlClient>) => program.pipe(Effect.provide(sqlite))

Signature

declare const make: (
  limits: Vfs.DecodeLimits
) => Effect.Effect<
  {
    readonly save: (name: string, snapshot: Vfs.Snapshot) => Effect.Effect<void, CheckpointError | Vfs.VfsError>
    readonly load: (name: string) => Effect.Effect<Vfs.Snapshot, CheckpointError | Vfs.VfsError>
  },
  VfsError.VfsError & { readonly code: "InvalidArgument" },
  SqlClient
>

Source

Since v0.1.0

layer (static method)

Provides a store using the application-supplied SQLite client. Does not run migrations.

Example

import { CheckpointStore } from "@effect-vfs/persistence"
import { ByteSize, Layer } from "effect"
import type { SqlClient } from "effect/sql/SqlClient"
 
const limits = {
  maxEncodedBytes: ByteSize.megabytes(4),
  maxRecords: 10_000,
  maxEntries: 10_000,
  maxDecodedBytes: ByteSize.megabytes(16)
}
 
// The application chooses the driver, for example SqliteClient.layer(...)
// from @effect/sql-sqlite-bun. Migrations are a separate startup step.
const checkpoints = (sqlite: Layer.Layer<SqlClient>) => CheckpointStore.layer(limits).pipe(Layer.provide(sqlite))

Signature

declare const layer: (
  limits: Vfs.DecodeLimits
) => Layer.Layer<CheckpointStore, VfsError.VfsError & { readonly code: "InvalidArgument" }, SqlClient>

Source

Since v0.1.0