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 CheckpointErrorSince 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-checkpointsfor driver selection, transaction semantics, and durability caveats.
Signature
declare class CheckpointStoreSince 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
>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>Since v0.1.0