@effect-agent/storage-sqlite 0.0.1-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,37 @@
1
+ import { Context, Schema } from "effect";
2
+
3
+ const ObservationPollInterval = Schema.Int.check(Schema.isGreaterThanOrEqualTo(0));
4
+ const BusyTimeoutMillis = Schema.Int.check(Schema.isGreaterThanOrEqualTo(0));
5
+ const OwnershipLeaseMillis = Schema.Int.check(Schema.isGreaterThan(0));
6
+
7
+ /**
8
+ * Validated construction configuration consumed by the SQLite storage Layer. The database
9
+ * identity itself belongs to the SqlClient Layer; duplicating it here could silently diverge
10
+ * from the connection actually in use.
11
+ */
12
+ export class SqliteStorageConfigValue extends Schema.Class<SqliteStorageConfigValue>(
13
+ "@effect-agent/storage-sqlite/SqliteStorageConfigValue",
14
+ )({
15
+ observationPollInterval: ObservationPollInterval,
16
+ /** Bounded SQLITE_BUSY retry window for write-lock acquisition, in milliseconds. */
17
+ busyTimeout: BusyTimeoutMillis,
18
+ /**
19
+ * Submission ownership lease duration in milliseconds (D5). The lease is a liveness hint
20
+ * that makes an abandoned claim reclaimable; correctness never depends on it because every
21
+ * canonical append is fenced by producer epoch. Convenience layers default this to
22
+ * `DEFAULT_OWNERSHIP_LEASE_DURATION` from `@effect-agent/session`.
23
+ */
24
+ ownershipLeaseDuration: OwnershipLeaseMillis,
25
+ /**
26
+ * Re-verify every stored payload and digest chain while opening the store. Per-operation
27
+ * Schema decoding and the digest chain already fail clearly on corrupt rows, so the full
28
+ * scan is an explicit opt-in integrity audit rather than a startup requirement.
29
+ */
30
+ verifyOnOpen: Schema.Boolean,
31
+ }) {}
32
+
33
+ /** Explicit SQLite storage configuration authority. */
34
+ export class SqliteStorageConfig extends Context.Service<
35
+ SqliteStorageConfig,
36
+ SqliteStorageConfigValue
37
+ >()("@effect-agent/storage-sqlite/SqliteStorageConfig") {}
@@ -0,0 +1,50 @@
1
+ import { Context, Effect, Layer, Ref } from "effect";
2
+
3
+ import { SqliteStorageFailpointError, type SqliteStorageFailpointLocation } from "./errors.ts";
4
+
5
+ export type SqliteStorageFailpointHandler = (
6
+ location: SqliteStorageFailpointLocation,
7
+ ) => Effect.Effect<void, SqliteStorageFailpointError>;
8
+
9
+ const noFailpoint: SqliteStorageFailpointHandler = () => Effect.void;
10
+
11
+ /** Test-only control for replacing the active SQLite failpoint handler. */
12
+ export class SqliteStorageFailpointTestControl extends Context.Service<
13
+ SqliteStorageFailpointTestControl,
14
+ {
15
+ readonly clear: Effect.Effect<void>;
16
+ readonly setHandler: (handler: SqliteStorageFailpointHandler) => Effect.Effect<void>;
17
+ }
18
+ >()("@effect-agent/storage-sqlite/SqliteStorageFailpointTestControl") {}
19
+
20
+ /** Explicit fault-injection authority used at SQLite operation boundaries. */
21
+ export class SqliteStorageFailpoint extends Context.Service<
22
+ SqliteStorageFailpoint,
23
+ {
24
+ readonly hit: SqliteStorageFailpointHandler;
25
+ }
26
+ >()("@effect-agent/storage-sqlite/SqliteStorageFailpoint") {
27
+ /** Production default: no fault injection. */
28
+ static readonly layer = Layer.succeed(this)({ hit: noFailpoint });
29
+
30
+ /** Reusable test Layer with a control service backed by the same handler Ref. */
31
+ static readonly layerTest = Layer.effectContext(
32
+ Effect.gen(function* () {
33
+ const handler = yield* Ref.make<SqliteStorageFailpointHandler>(noFailpoint);
34
+ return Context.make(
35
+ SqliteStorageFailpoint,
36
+ SqliteStorageFailpoint.of({
37
+ hit: (location) => Ref.get(handler).pipe(Effect.flatMap((current) => current(location))),
38
+ }),
39
+ ).pipe(
40
+ Context.add(
41
+ SqliteStorageFailpointTestControl,
42
+ SqliteStorageFailpointTestControl.of({
43
+ clear: Ref.set(handler, noFailpoint),
44
+ setHandler: (next) => Ref.set(handler, next),
45
+ }),
46
+ ),
47
+ );
48
+ }),
49
+ );
50
+ }