@yielded/agent-storage-cloudflare 0.1.0-beta.166
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.
- package/LICENSE +21 -0
- package/dist/DoMemoryStore.d.mts +30 -0
- package/dist/DoMemoryStore.mjs +66 -0
- package/dist/DoMemoryStore.mjs.map +1 -0
- package/dist/DoMessageDeliveryStore.d.mts +17 -0
- package/dist/DoMessageDeliveryStore.mjs +30 -0
- package/dist/DoMessageDeliveryStore.mjs.map +1 -0
- package/dist/DoScheduleStore.d.mts +36 -0
- package/dist/DoScheduleStore.mjs +388 -0
- package/dist/DoScheduleStore.mjs.map +1 -0
- package/dist/DoStorageConfig.d.mts +45 -0
- package/dist/DoStorageConfig.mjs +52 -0
- package/dist/DoStorageConfig.mjs.map +1 -0
- package/dist/DoStorageError-CGuAfSwF.d.mts +101 -0
- package/dist/DoStorageError.d.mts +2 -0
- package/dist/DoStorageError.mjs +167 -0
- package/dist/DoStorageError.mjs.map +1 -0
- package/dist/DoStorageFailpoint.d.mts +17 -0
- package/dist/DoStorageFailpoint.mjs +14 -0
- package/dist/DoStorageFailpoint.mjs.map +1 -0
- package/dist/DoStorageFailpointTesting.d.mts +24 -0
- package/dist/DoStorageFailpointTesting.mjs +22 -0
- package/dist/DoStorageFailpointTesting.mjs.map +1 -0
- package/dist/DoStorageVersion-iNSyi3cJ.d.mts +12 -0
- package/dist/DoStorageVersion.d.mts +2 -0
- package/dist/DoStorageVersion.mjs +8 -0
- package/dist/DoStorageVersion.mjs.map +1 -0
- package/dist/DoSubmissionLedger.d.mts +23 -0
- package/dist/DoSubmissionLedger.mjs +1979 -0
- package/dist/DoSubmissionLedger.mjs.map +1 -0
- package/dist/DoSubscriptionStore.d.mts +25 -0
- package/dist/DoSubscriptionStore.mjs +186 -0
- package/dist/DoSubscriptionStore.mjs.map +1 -0
- package/dist/DoThreadStore-D_83OjCH.d.mts +72 -0
- package/dist/DoThreadStore.d.mts +2 -0
- package/dist/DoThreadStore.mjs +529 -0
- package/dist/DoThreadStore.mjs.map +1 -0
- package/dist/MemoryProtocol.d.mts +38160 -0
- package/dist/MemoryProtocol.mjs +219 -0
- package/dist/MemoryProtocol.mjs.map +1 -0
- package/dist/PortProtocol.d.mts +7726 -0
- package/dist/PortProtocol.mjs +234 -0
- package/dist/PortProtocol.mjs.map +1 -0
- package/dist/PortRouting.d.mts +97 -0
- package/dist/PortRouting.mjs +544 -0
- package/dist/PortRouting.mjs.map +1 -0
- package/dist/do-journal-DUhjZkOf.mjs +1352 -0
- package/dist/do-journal-DUhjZkOf.mjs.map +1 -0
- package/dist/index.d.mts +14 -0
- package/dist/index.mjs +14 -0
- package/dist/migrations-DtKz_Gxr.mjs +306 -0
- package/dist/migrations-DtKz_Gxr.mjs.map +1 -0
- package/dist/owned-state-DHm2aRXx.mjs +119 -0
- package/dist/owned-state-DHm2aRXx.mjs.map +1 -0
- package/dist/rolldown-runtime-D7D4PA-g.mjs +13 -0
- package/package.json +1 -0
- package/src/DoMemoryStore.ts +73 -0
- package/src/DoMessageDeliveryStore.ts +39 -0
- package/src/DoScheduleStore.ts +622 -0
- package/src/DoStorageConfig.ts +53 -0
- package/src/DoStorageError.ts +180 -0
- package/src/DoStorageFailpoint.ts +20 -0
- package/src/DoStorageFailpointTesting.ts +41 -0
- package/src/DoStorageVersion.ts +2 -0
- package/src/DoSubmissionLedger.ts +4027 -0
- package/src/DoSubscriptionStore.ts +327 -0
- package/src/DoThreadStore.ts +1121 -0
- package/src/MemoryProtocol.ts +355 -0
- package/src/PortProtocol.ts +436 -0
- package/src/PortRouting.ts +1464 -0
- package/src/index.ts +13 -0
- package/src/internal/do-journal.ts +2282 -0
- package/src/internal/message-delivery-schema.ts +24 -0
- package/src/internal/migrations.ts +304 -0
- package/src/internal/owned-state.ts +228 -0
- package/src/internal/recovery-checkpoint-schema.ts +17 -0
- package/src/internal/storage-span.ts +44 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { CanonicalSequence, ProducerEpoch } from "@yielded/agent/records";
|
|
2
|
+
import { ThreadStoreDiagnostic } from "@yielded/agent/thread-store";
|
|
3
|
+
import { Schema } from "effect";
|
|
4
|
+
|
|
5
|
+
/** The Durable Object's SQLite storage uses a private-development format this adapter cannot read. */
|
|
6
|
+
export class DoStorageCompatibilityError extends Schema.TaggedError<DoStorageCompatibilityError>()(
|
|
7
|
+
"DoStorageCompatibilityError",
|
|
8
|
+
{
|
|
9
|
+
actualVersion: Schema.Int,
|
|
10
|
+
message: Schema.String,
|
|
11
|
+
supportedVersion: Schema.Int,
|
|
12
|
+
},
|
|
13
|
+
) {}
|
|
14
|
+
|
|
15
|
+
/** Stored bytes failed the current Schema and cannot be used as recovery truth. */
|
|
16
|
+
export class DoStorageCorruptionError extends Schema.TaggedError<DoStorageCorruptionError>()(
|
|
17
|
+
"DoStorageCorruptionError",
|
|
18
|
+
{
|
|
19
|
+
message: Schema.String,
|
|
20
|
+
rowKey: Schema.String,
|
|
21
|
+
table: Schema.String,
|
|
22
|
+
diagnostic: Schema.optionalKey(ThreadStoreDiagnostic),
|
|
23
|
+
},
|
|
24
|
+
) {}
|
|
25
|
+
|
|
26
|
+
/** Durable Object SQLite infrastructure failed while opening or operating the store. */
|
|
27
|
+
export class DoStorageError extends Schema.TaggedError<DoStorageError>()("DoStorageError", {
|
|
28
|
+
cause: Schema.optionalKey(Schema.Defect()),
|
|
29
|
+
message: Schema.String,
|
|
30
|
+
operation: Schema.String,
|
|
31
|
+
diagnostic: Schema.optionalKey(ThreadStoreDiagnostic),
|
|
32
|
+
}) {}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Durable Object SQLite infrastructure failed while operating the Submission Ledger. Surfaces
|
|
36
|
+
* at the SubmissionLedger port as the typed `LedgerError` with this error preserved as its
|
|
37
|
+
* cause, so the adapter-level tag is never erased.
|
|
38
|
+
*/
|
|
39
|
+
export class DoLedgerError extends Schema.TaggedError<DoLedgerError>()("DoLedgerError", {
|
|
40
|
+
cause: Schema.optionalKey(Schema.Defect()),
|
|
41
|
+
message: Schema.String,
|
|
42
|
+
operation: Schema.String,
|
|
43
|
+
}) {}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* A value to be stored exceeds the configured Durable Object per-value bound
|
|
47
|
+
* (`DoStorageConfigValue.maxStoredValueBytes`, kept under the platform's 2 MB SQLite value
|
|
48
|
+
* limit). The refusal happens typed BEFORE any durable mutation; no partial state is written.
|
|
49
|
+
* Payloads of this size are the designed overflow case for a future R2-backed AttachmentStore
|
|
50
|
+
* (deployment spec §3.1, deferred until a real attachment requirement exists).
|
|
51
|
+
*/
|
|
52
|
+
export class DoValueBoundExceeded extends Schema.TaggedError<DoValueBoundExceeded>()(
|
|
53
|
+
"DoValueBoundExceeded",
|
|
54
|
+
{
|
|
55
|
+
actualBytes: Schema.Int,
|
|
56
|
+
maxBytes: Schema.Int,
|
|
57
|
+
operation: Schema.String,
|
|
58
|
+
},
|
|
59
|
+
) {
|
|
60
|
+
override get message() {
|
|
61
|
+
return (
|
|
62
|
+
`A stored value of ${this.actualBytes} bytes exceeds the Durable Object per-value bound ` +
|
|
63
|
+
`of ${this.maxBytes} bytes during ${this.operation}. Nothing was written. Values of this ` +
|
|
64
|
+
"size are the designed R2 AttachmentStore overflow path (deferred, deployment spec §3.1)."
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* A canonical batch retry conflicts with existing append state. Tail conflicts carry the
|
|
71
|
+
* actual committed tail as a diagnostic resume hint.
|
|
72
|
+
*/
|
|
73
|
+
export class DoAppendConflict extends Schema.TaggedError<DoAppendConflict>()("DoAppendConflict", {
|
|
74
|
+
message: Schema.String,
|
|
75
|
+
reason: Schema.Literals(["batch-digest", "record-identity", "tail"]),
|
|
76
|
+
actualTailSequence: Schema.optionalKey(CanonicalSequence),
|
|
77
|
+
actualTailDigest: Schema.optionalKey(Schema.String),
|
|
78
|
+
}) {}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* A producer epoch does not match the Thread's current writer registration. Appends
|
|
82
|
+
* require the exact registered epoch, so both older and newer unregistered epochs are fenced;
|
|
83
|
+
* a newer epoch takes over by materializing first.
|
|
84
|
+
*/
|
|
85
|
+
export class DoFenceRejected extends Schema.TaggedError<DoFenceRejected>()("DoFenceRejected", {
|
|
86
|
+
actualEpoch: ProducerEpoch,
|
|
87
|
+
message: Schema.String,
|
|
88
|
+
producerEpoch: ProducerEpoch,
|
|
89
|
+
}) {}
|
|
90
|
+
|
|
91
|
+
/** A checkpoint conflicts with a previously stored checkpoint at the same offset. */
|
|
92
|
+
export class DoCheckpointConflict extends Schema.TaggedError<DoCheckpointConflict>()(
|
|
93
|
+
"DoCheckpointConflict",
|
|
94
|
+
{
|
|
95
|
+
message: Schema.String,
|
|
96
|
+
},
|
|
97
|
+
) {}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Deterministic fault-injection locations at Durable Object storage operation boundaries.
|
|
101
|
+
*
|
|
102
|
+
* The string list is copied VERBATIM from `SqliteStorageFailpointLocation`
|
|
103
|
+
* (`packages/storage-sqlite/src/errors.ts`) so every crash-matrix row keeps the same name on
|
|
104
|
+
* both platforms — the DN process-kill evidence and the DC eviction evidence address identical
|
|
105
|
+
* locations. There is intentionally no Cloudflare-only location.
|
|
106
|
+
*/
|
|
107
|
+
export const DoStorageFailpointLocation = Schema.Literals([
|
|
108
|
+
"upgrade:before-mutation",
|
|
109
|
+
"upgrade:after-mutation",
|
|
110
|
+
"upgrade:before-version",
|
|
111
|
+
"upgrade:after-version",
|
|
112
|
+
"materialize:before",
|
|
113
|
+
"materialize:after",
|
|
114
|
+
"append:before",
|
|
115
|
+
"append:after-batch-insert",
|
|
116
|
+
"append:after-record-insert",
|
|
117
|
+
"append:after-tail-update",
|
|
118
|
+
"append:after",
|
|
119
|
+
"export:after-thread-read",
|
|
120
|
+
"save-checkpoint:before",
|
|
121
|
+
"save-checkpoint:after",
|
|
122
|
+
"save-recovery-checkpoint:before",
|
|
123
|
+
"save-recovery-checkpoint:after",
|
|
124
|
+
"ledger:admit:before",
|
|
125
|
+
"ledger:admit:after",
|
|
126
|
+
"ledger:mark-ready:before",
|
|
127
|
+
"ledger:mark-ready:after",
|
|
128
|
+
"ledger:claim:before",
|
|
129
|
+
"ledger:claim:after",
|
|
130
|
+
"ledger:mark-input-applied:before",
|
|
131
|
+
"ledger:mark-input-applied:after",
|
|
132
|
+
"ledger:renew:before",
|
|
133
|
+
"ledger:renew:after",
|
|
134
|
+
"ledger:reserve-settlement:before",
|
|
135
|
+
"ledger:reserve-settlement:after",
|
|
136
|
+
"ledger:finalize-settlement:before",
|
|
137
|
+
"ledger:finalize-settlement:after",
|
|
138
|
+
"ledger:request-abort:before",
|
|
139
|
+
"ledger:request-abort:after",
|
|
140
|
+
"ledger:release:before",
|
|
141
|
+
"ledger:release:after",
|
|
142
|
+
"ledger:claim-joining:before",
|
|
143
|
+
"ledger:claim-joining:after",
|
|
144
|
+
"ledger:mark-joined:before",
|
|
145
|
+
"ledger:mark-joined:after",
|
|
146
|
+
"ledger:revert-joining:before",
|
|
147
|
+
"ledger:revert-joining:after",
|
|
148
|
+
"ledger:suspend:before",
|
|
149
|
+
"ledger:suspend:after",
|
|
150
|
+
"ledger:approval-decision:before",
|
|
151
|
+
"ledger:approval-decision:after",
|
|
152
|
+
"ledger:mark-unknown:before",
|
|
153
|
+
"ledger:mark-unknown:after",
|
|
154
|
+
"ledger:unknown-resolution:before",
|
|
155
|
+
"ledger:unknown-resolution:after",
|
|
156
|
+
"ledger:child-reservation:before",
|
|
157
|
+
"ledger:child-reservation:after",
|
|
158
|
+
"ledger:child-attach:before",
|
|
159
|
+
"ledger:child-attach:after",
|
|
160
|
+
"ledger:child-release-pending:before",
|
|
161
|
+
"ledger:child-release-pending:after",
|
|
162
|
+
"ledger:child-release:before",
|
|
163
|
+
"ledger:child-release:after",
|
|
164
|
+
"ledger:child-settled:before",
|
|
165
|
+
"ledger:child-settled:after",
|
|
166
|
+
]);
|
|
167
|
+
|
|
168
|
+
export type DoStorageFailpointLocation = typeof DoStorageFailpointLocation.Type;
|
|
169
|
+
|
|
170
|
+
/** Deterministic test-only fault or pause injected at a Durable Object storage boundary. */
|
|
171
|
+
export class DoStorageFailpointError extends Schema.TaggedError<DoStorageFailpointError>()(
|
|
172
|
+
"DoStorageFailpointError",
|
|
173
|
+
{
|
|
174
|
+
location: DoStorageFailpointLocation,
|
|
175
|
+
},
|
|
176
|
+
) {
|
|
177
|
+
override get message() {
|
|
178
|
+
return `Injected Durable Object storage failure at ${this.location}.`;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Context, Effect, Layer } from "effect";
|
|
2
|
+
|
|
3
|
+
import type { DoStorageFailpointError, DoStorageFailpointLocation } from "./DoStorageError.ts";
|
|
4
|
+
|
|
5
|
+
export type DoStorageFailpointHandler = (
|
|
6
|
+
location: DoStorageFailpointLocation,
|
|
7
|
+
) => Effect.Effect<void, DoStorageFailpointError>;
|
|
8
|
+
|
|
9
|
+
const noFailpoint: DoStorageFailpointHandler = () => Effect.void;
|
|
10
|
+
|
|
11
|
+
/** Explicit fault-injection authority used at Durable Object storage operation boundaries. */
|
|
12
|
+
export class DoStorageFailpoint extends Context.Service<
|
|
13
|
+
DoStorageFailpoint,
|
|
14
|
+
{
|
|
15
|
+
readonly hit: DoStorageFailpointHandler;
|
|
16
|
+
}
|
|
17
|
+
>()("@effect-agent/storage-cloudflare/DoStorageFailpoint") {
|
|
18
|
+
/** Production default: no fault injection. */
|
|
19
|
+
static readonly layer = Layer.succeed(this)({ hit: noFailpoint });
|
|
20
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
|
|
3
|
+
import type { DoStorageFailpointLocation } from "./DoStorageError.ts";
|
|
4
|
+
import type { DoStorageFailpointHandler } from "./DoStorageFailpoint.ts";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The DC-specific eviction failpoint mode: instead of failing typed, an armed hit evicts the
|
|
8
|
+
* Durable Object through an injected `evict` thunk — in production-shaped harnesses that thunk
|
|
9
|
+
* is `() => ctx.abort()`, the platform's real failure mode. `ctx.abort()` never returns (it
|
|
10
|
+
* throws while destroying the in-memory instance and every in-flight implicit or explicit
|
|
11
|
+
* storage transaction rolls back), so an armed hit ends the current Attempt exactly like an
|
|
12
|
+
* unannounced platform eviction; DO storage — the only correctness-critical state — survives
|
|
13
|
+
* for the next incarnation, which the persisted alarm wakes without any incoming request.
|
|
14
|
+
*
|
|
15
|
+
* The handles stay injected: this package never imports `cloudflare:workers`, so the harness
|
|
16
|
+
* that owns a `DurableObjectState` supplies the thunk.
|
|
17
|
+
*/
|
|
18
|
+
export const evictionFailpointHandler =
|
|
19
|
+
(options: {
|
|
20
|
+
readonly isArmed: (location: DoStorageFailpointLocation) => Effect.Effect<boolean>;
|
|
21
|
+
/** Kills the incarnation — e.g. `() => ctx.abort()`. Typed `void` because the platform
|
|
22
|
+
* declares `abort` as returning, but it throws while destroying the instance. */
|
|
23
|
+
readonly evict: (location: DoStorageFailpointLocation) => void;
|
|
24
|
+
}): DoStorageFailpointHandler =>
|
|
25
|
+
(location) =>
|
|
26
|
+
options.isArmed(location).pipe(
|
|
27
|
+
Effect.flatMap((armed) =>
|
|
28
|
+
armed
|
|
29
|
+
? // `ctx.abort()` throws while destroying the instance; that throw surfaces as a
|
|
30
|
+
// defect in the (already dying) incarnation. The defensive throw below keeps the
|
|
31
|
+
// guarantee — nothing after an armed hit may observe in-memory state — even if a
|
|
32
|
+
// harness supplies an evict thunk that returns.
|
|
33
|
+
Effect.sync((): never => {
|
|
34
|
+
options.evict(location);
|
|
35
|
+
throw new Error(
|
|
36
|
+
`Durable Object eviction did not interrupt execution at ${location}.`,
|
|
37
|
+
);
|
|
38
|
+
})
|
|
39
|
+
: Effect.void,
|
|
40
|
+
),
|
|
41
|
+
);
|