@bjornpagen/bumbledb 1.0.0 → 1.1.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.
- package/COOKBOOK.md +64 -27
- package/README.md +21 -20
- package/dist/capacity.d.ts +1 -1
- package/dist/changes.d.ts +4 -5
- package/dist/changes.d.ts.map +1 -1
- package/dist/changes.js +37 -34
- package/dist/changes.js.map +1 -1
- package/dist/close.d.ts +2 -2
- package/dist/codec.d.ts +5 -6
- package/dist/codec.d.ts.map +1 -1
- package/dist/codec.js +6 -6
- package/dist/codec.js.map +1 -1
- package/dist/compile.d.ts +4 -6
- package/dist/compile.d.ts.map +1 -1
- package/dist/compile.js +6 -6
- package/dist/compile.js.map +1 -1
- package/dist/db-native.d.ts +43 -56
- package/dist/db-native.d.ts.map +1 -1
- package/dist/db-native.js.map +1 -1
- package/dist/db.d.ts +43 -28
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +77 -63
- package/dist/db.js.map +1 -1
- package/dist/errors.d.ts +4 -8
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +4 -8
- package/dist/errors.js.map +1 -1
- package/dist/fields.d.ts +4 -5
- package/dist/fields.d.ts.map +1 -1
- package/dist/fields.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/internal/log.d.ts +4 -4
- package/dist/internal/log.d.ts.map +1 -1
- package/dist/internal/log.js +1 -1
- package/dist/internal/log.js.map +1 -1
- package/dist/law.d.ts +1 -1
- package/dist/migration.d.ts +5 -7
- package/dist/migration.d.ts.map +1 -1
- package/dist/migration.js +8 -9
- package/dist/migration.js.map +1 -1
- package/dist/native.d.ts +2 -2
- package/dist/native.d.ts.map +1 -1
- package/dist/native.js.map +1 -1
- package/dist/query/lower.d.ts +1 -1
- package/dist/result.d.ts +10 -25
- package/dist/result.d.ts.map +1 -1
- package/dist/result.js +7 -12
- package/dist/result.js.map +1 -1
- package/dist/rows.d.ts +10 -16
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +8 -45
- package/dist/rows.js.map +1 -1
- package/dist/runtime-codes.d.ts +1 -1
- package/dist/runtime-codes.d.ts.map +1 -1
- package/dist/runtime-codes.js +1 -2
- package/dist/runtime-codes.js.map +1 -1
- package/dist/runtime-errors.d.ts +3 -15
- package/dist/runtime-errors.d.ts.map +1 -1
- package/dist/runtime-errors.js +1 -5
- package/dist/runtime-errors.js.map +1 -1
- package/dist/runtime-native.d.ts +18 -48
- package/dist/runtime-native.d.ts.map +1 -1
- package/dist/runtime-native.js.map +1 -1
- package/dist/runtime.d.ts +12 -29
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +16 -57
- package/dist/runtime.js.map +1 -1
- package/dist/shape.d.ts +3 -4
- package/dist/shape.d.ts.map +1 -1
- package/dist/spec.d.ts +2 -2
- package/dist/spec.js +1 -1
- package/dist/statements.js +2 -2
- package/dist/statements.js.map +1 -1
- package/pack-provenance.json +3 -3
- package/package.json +4 -4
- package/src/capacity.ts +1 -1
- package/src/changes.ts +50 -48
- package/src/close.ts +2 -2
- package/src/codec.ts +8 -24
- package/src/compile.ts +8 -10
- package/src/db-native.ts +37 -83
- package/src/db.ts +156 -135
- package/src/errors.ts +4 -8
- package/src/fields.ts +4 -5
- package/src/index.ts +6 -5
- package/src/internal/log.ts +2 -7
- package/src/law.ts +1 -1
- package/src/migration.ts +8 -16
- package/src/native.ts +2 -3
- package/src/query/lower.ts +1 -1
- package/src/result.ts +16 -45
- package/src/rows.ts +12 -65
- package/src/runtime-codes.ts +1 -2
- package/src/runtime-errors.ts +1 -5
- package/src/runtime-native.ts +15 -68
- package/src/runtime.ts +53 -122
- package/src/shape.ts +3 -4
- package/src/spec.ts +2 -2
- package/src/statements.ts +2 -2
package/src/db.ts
CHANGED
|
@@ -9,7 +9,7 @@ import type {
|
|
|
9
9
|
ApplyOutcomeWire,
|
|
10
10
|
DbInspectionWire,
|
|
11
11
|
ExpectedWire,
|
|
12
|
-
|
|
12
|
+
PreparedHandle,
|
|
13
13
|
SnapshotHandle,
|
|
14
14
|
WitnessWire
|
|
15
15
|
} from "#db-native.ts"
|
|
@@ -25,8 +25,8 @@ import type { CompleteResult } from "#result.ts"
|
|
|
25
25
|
import { internalResult, makeCompleteResult } from "#result.ts"
|
|
26
26
|
import type { CellValue } from "#rows.ts"
|
|
27
27
|
import { factOfCells, keyCellsOf } from "#rows.ts"
|
|
28
|
-
import type {
|
|
29
|
-
import { nativeOperationWith,
|
|
28
|
+
import type { NativeRuntime } from "#runtime.ts"
|
|
29
|
+
import { nativeOperationWith, runtimeHandle } from "#runtime.ts"
|
|
30
30
|
import type { CloseReport } from "#runtime-errors.ts"
|
|
31
31
|
import { DbError } from "#runtime-errors.ts"
|
|
32
32
|
import type { DirectoryHandle } from "#runtime-native.ts"
|
|
@@ -35,12 +35,12 @@ import type { AnySchema } from "#schema.ts"
|
|
|
35
35
|
import type { Key, QueryTemplate, Rel } from "#shape.ts"
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
|
-
* The
|
|
39
|
-
* `Snapshot`s, reusable `
|
|
38
|
+
* The core surface: `Db.create`/`Db.open`, scoped coherent
|
|
39
|
+
* `Snapshot`s, reusable `PreparedQuery`s, the shared `QueryReader`
|
|
40
40
|
* capability, one immutable final-state `apply`, bounded `inspect` and
|
|
41
41
|
* honest `close`. Effect-only: every method constructs a lazy effect; all
|
|
42
|
-
* native work runs on the
|
|
43
|
-
*
|
|
42
|
+
* native work runs on the shared executor with cooperative cancellation.
|
|
43
|
+
* Resources are scoped with `CloseFailure`-defect
|
|
44
44
|
* finalizers. There is no Promise/sync/disposal twin, no transaction
|
|
45
45
|
* callback, no per-row fiber and no Proxy row anywhere.
|
|
46
46
|
*
|
|
@@ -59,8 +59,8 @@ interface CoreWitness {
|
|
|
59
59
|
|
|
60
60
|
type ApplyExpected = { readonly kind: "any" } | { readonly kind: "exact"; readonly at: CoreWitness }
|
|
61
61
|
|
|
62
|
-
/**
|
|
63
|
-
type ApplyOptions =
|
|
62
|
+
/** Expected-state intent for an atomic apply. */
|
|
63
|
+
type ApplyOptions = { readonly expected: ApplyExpected }
|
|
64
64
|
|
|
65
65
|
type ApplyOutcome =
|
|
66
66
|
| { readonly kind: "accepted"; readonly witness: CoreWitness }
|
|
@@ -68,53 +68,66 @@ type ApplyOutcome =
|
|
|
68
68
|
| { readonly kind: "invariant-rejected"; readonly violations: readonly Violation[] }
|
|
69
69
|
| { readonly kind: "moved"; readonly witnessed: CoreWitness; readonly current: CoreWitness }
|
|
70
70
|
|
|
71
|
-
/**
|
|
71
|
+
/** Storage measurements, not heap usage or mapped-page residency. */
|
|
72
|
+
interface StorageInspection {
|
|
73
|
+
/** Reserved virtual address range for the LMDB mapping. */
|
|
74
|
+
readonly virtualMapBytes: bigint
|
|
75
|
+
/** File length; may include sparse regions and free pages. */
|
|
76
|
+
readonly populatedFileBytes: bigint
|
|
77
|
+
/** LMDB's non-free branch, leaf and overflow pages. Not resident RAM. */
|
|
78
|
+
readonly nonFreePageBytes: bigint
|
|
79
|
+
/** Allocated filesystem blocks, or null when the OS cannot report them. */
|
|
80
|
+
readonly allocatedDiskBytes: bigint | null
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** Database diagnostics: measurements, never retained rows. */
|
|
72
84
|
interface DbInspection {
|
|
73
85
|
readonly schemaId: SchemaId
|
|
74
86
|
readonly generation: bigint
|
|
75
|
-
readonly
|
|
76
|
-
readonly populatedBytes: bigint
|
|
77
|
-
readonly diskBytes: bigint
|
|
78
|
-
readonly residentEstimateBytes: bigint
|
|
87
|
+
readonly storage: StorageInspection
|
|
79
88
|
readonly retainedOperations: bigint
|
|
80
89
|
}
|
|
81
90
|
|
|
82
91
|
/**
|
|
83
|
-
* The
|
|
92
|
+
* The shared read capability: the same typed `get` and
|
|
84
93
|
* `execute` on a core snapshot and on a log published snapshot, so a
|
|
85
94
|
* cross-package read helper takes this interface with no adapter. Missing
|
|
86
95
|
* key is `Option.none`, never a fake I/O error or nullable row. It carries
|
|
87
96
|
* no writable authority — never a `Db`, an `apply`, or a raw transaction.
|
|
88
97
|
*/
|
|
89
98
|
interface QueryReader<S extends AnySchema> {
|
|
90
|
-
get<R extends Rel<S>>(relation: R, key: Key<R
|
|
99
|
+
get<R extends Rel<S>>(relation: R, key: Key<R>): Effect.Effect<Option.Option<Fact<R>>, DbError>
|
|
91
100
|
execute<P extends ParamsRecord, A>(
|
|
92
101
|
query: QueryTemplate<S, P, A>,
|
|
93
|
-
params: P
|
|
94
|
-
work: ExecutionPolicy
|
|
102
|
+
params: P
|
|
95
103
|
): Effect.Effect<CompleteResult<A>, DbError, Scope.Scope>
|
|
104
|
+
prepare<P extends ParamsRecord, A>(
|
|
105
|
+
query: QueryTemplate<S, P, A>
|
|
106
|
+
): Effect.Effect<PreparedQuery<P, A>, DbError, Scope.Scope>
|
|
96
107
|
}
|
|
97
108
|
|
|
98
109
|
interface Snapshot<S extends AnySchema> extends QueryReader<S> {
|
|
99
110
|
readonly witness: CoreWitness
|
|
100
|
-
session(work: ExecutionPolicy): Effect.Effect<ExecutionSession<S>, DbError, Scope.Scope>
|
|
101
111
|
close(): Effect.Effect<CloseReport>
|
|
102
112
|
}
|
|
103
113
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
114
|
+
/** One compiled plan and its reusable buffers, pinned to the preparing snapshot.
|
|
115
|
+
* Closing it releases its own state, not the snapshot or completed results.
|
|
116
|
+
*/
|
|
117
|
+
interface PreparedQuery<P extends ParamsRecord, A> {
|
|
118
|
+
execute(params: P): Effect.Effect<CompleteResult<A>, DbError, Scope.Scope>
|
|
119
|
+
/** Drop reusable execution buffers, keeping the compiled query and snapshot. */
|
|
120
|
+
releaseMemory(): Effect.Effect<void, DbError>
|
|
110
121
|
close(): Effect.Effect<CloseReport>
|
|
111
122
|
}
|
|
112
123
|
|
|
113
124
|
interface Db<S extends AnySchema> {
|
|
114
125
|
readonly schemaId: SchemaId
|
|
115
|
-
snapshot(
|
|
126
|
+
snapshot(): Effect.Effect<Snapshot<S>, DbError, Scope.Scope>
|
|
116
127
|
apply(changes: ChangeSet<S>, options: ApplyOptions): Effect.Effect<ApplyOutcome, DbError>
|
|
117
|
-
inspect(
|
|
128
|
+
inspect(): Effect.Effect<DbInspection, DbError>
|
|
129
|
+
/** Clear shared query caches without invalidating live snapshots or results. */
|
|
130
|
+
clearCache(): Effect.Effect<void, DbError>
|
|
118
131
|
close(): Effect.Effect<CloseReport>
|
|
119
132
|
}
|
|
120
133
|
|
|
@@ -142,7 +155,7 @@ function outcomeOf(wire: ApplyOutcomeWire): ApplyOutcome {
|
|
|
142
155
|
/**
|
|
143
156
|
* Validates the query template's schema binding (identity, the membership
|
|
144
157
|
* rule) and lowers it to IR plus wire params. Pure host preparation; the
|
|
145
|
-
* engine's IR validation
|
|
158
|
+
* engine's IR validation remains the authority.
|
|
146
159
|
*/
|
|
147
160
|
function preparedOf<S extends AnySchema>(
|
|
148
161
|
theory: S,
|
|
@@ -168,29 +181,29 @@ interface SnapshotState<S extends AnySchema> {
|
|
|
168
181
|
|
|
169
182
|
function executeOn<S extends AnySchema, A>(
|
|
170
183
|
state: SnapshotState<S>,
|
|
171
|
-
session: SessionHandle | undefined,
|
|
172
184
|
query: AnyQuery,
|
|
173
|
-
params: Readonly<Record<string, unknown
|
|
174
|
-
work: ExecutionPolicy
|
|
185
|
+
params: Readonly<Record<string, unknown>>
|
|
175
186
|
): Effect.Effect<CompleteResult<A>, DbError, Scope.Scope> {
|
|
176
|
-
return
|
|
187
|
+
return scopedResult(
|
|
177
188
|
Effect.gen(function* () {
|
|
178
189
|
const prepared = yield* Effect.try({
|
|
179
190
|
try: () => preparedOf(state.theory, query, params),
|
|
180
191
|
catch: (cause) => (cause instanceof DbError ? cause : refusal("QueryReader.execute", "InvalidArgument"))
|
|
181
192
|
})
|
|
182
|
-
const wire = policyWire(work, "QueryReader.execute")
|
|
183
193
|
const handle = yield* nativeOperationWith(
|
|
184
194
|
"QueryReader.execute",
|
|
185
|
-
(callback) =>
|
|
186
|
-
session === undefined
|
|
187
|
-
? dbNative.runtimeSnapshotExecute(state.handle, wire, prepared.ir, prepared.wire, callback)
|
|
188
|
-
: dbNative.runtimeSessionExecute(session, wire, prepared.ir, prepared.wire, callback),
|
|
195
|
+
(callback) => dbNative.runtimeSnapshotExecute(state.handle, prepared.ir, prepared.wire, callback),
|
|
189
196
|
dbNative.runtimeResultTake,
|
|
190
197
|
(value) => value
|
|
191
198
|
)
|
|
192
199
|
return makeCompleteResult<A>(handle, prepared.finds)
|
|
193
|
-
})
|
|
200
|
+
})
|
|
201
|
+
)
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function scopedResult<A>(acquire: Effect.Effect<CompleteResult<A>, DbError>) {
|
|
205
|
+
return Effect.acquireRelease(
|
|
206
|
+
acquire,
|
|
194
207
|
(result) =>
|
|
195
208
|
Effect.suspend(() => {
|
|
196
209
|
const internal = internalResultHandle(result)
|
|
@@ -210,8 +223,7 @@ function internalResultHandle(result: object) {
|
|
|
210
223
|
function getOn<S extends AnySchema, R extends Rel<S>>(
|
|
211
224
|
state: SnapshotState<S>,
|
|
212
225
|
relation: R,
|
|
213
|
-
key: Key<R
|
|
214
|
-
work: ExecutionPolicy
|
|
226
|
+
key: Key<R>
|
|
215
227
|
): Effect.Effect<Option.Option<Fact<R>>, DbError> {
|
|
216
228
|
return Effect.gen(function* () {
|
|
217
229
|
if (state.theory.relations[relation.name] !== relation) {
|
|
@@ -229,15 +241,7 @@ function getOn<S extends AnySchema, R extends Rel<S>>(
|
|
|
229
241
|
})
|
|
230
242
|
const row = yield* nativeOperationWith(
|
|
231
243
|
"QueryReader.get",
|
|
232
|
-
(callback) =>
|
|
233
|
-
dbNative.runtimeSnapshotGet(
|
|
234
|
-
state.handle,
|
|
235
|
-
policyWire(work, "QueryReader.get"),
|
|
236
|
-
relationId,
|
|
237
|
-
primary.statementId,
|
|
238
|
-
cells,
|
|
239
|
-
callback
|
|
240
|
-
),
|
|
244
|
+
(callback) => dbNative.runtimeSnapshotGet(state.handle, relationId, primary.statementId, cells, callback),
|
|
241
245
|
dbNative.runtimeRowTake,
|
|
242
246
|
(value) => value
|
|
243
247
|
)
|
|
@@ -248,46 +252,83 @@ function getOn<S extends AnySchema, R extends Rel<S>>(
|
|
|
248
252
|
})
|
|
249
253
|
}
|
|
250
254
|
|
|
251
|
-
function
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
+
function makePrepared<P extends ParamsRecord, A>(
|
|
256
|
+
handle: PreparedHandle,
|
|
257
|
+
definitions: AnyQuery["data"]["params"],
|
|
258
|
+
finds: AnyQuery["data"]["finds"]
|
|
259
|
+
): PreparedQuery<P, A> {
|
|
260
|
+
return Object.freeze({
|
|
261
|
+
releaseMemory() {
|
|
262
|
+
return nativeOperationWith(
|
|
263
|
+
"PreparedQuery.releaseMemory",
|
|
264
|
+
(callback) => dbNative.runtimePreparedReleaseMemory(handle, callback),
|
|
265
|
+
runtimeNative.runtimeTake,
|
|
266
|
+
() => undefined
|
|
267
|
+
)
|
|
268
|
+
},
|
|
269
|
+
execute(params: P) {
|
|
270
|
+
return scopedResult(
|
|
271
|
+
Effect.gen(function* () {
|
|
272
|
+
const args = yield* Effect.try({
|
|
273
|
+
try: () => wireParams(definitions, params),
|
|
274
|
+
catch: () => refusal("PreparedQuery.execute", "InvalidArgument")
|
|
275
|
+
})
|
|
276
|
+
const result = yield* nativeOperationWith(
|
|
277
|
+
"PreparedQuery.execute",
|
|
278
|
+
(callback) => dbNative.runtimePreparedExecute(handle, args, callback),
|
|
279
|
+
dbNative.runtimeResultTake,
|
|
280
|
+
(value) => makeCompleteResult<A>(value, finds)
|
|
281
|
+
)
|
|
282
|
+
return result
|
|
283
|
+
})
|
|
284
|
+
)
|
|
255
285
|
},
|
|
256
286
|
close() {
|
|
257
|
-
return drainClose("
|
|
287
|
+
return drainClose("PreparedQuery.close", (callback) => dbNative.runtimePreparedClose(handle, callback))
|
|
258
288
|
}
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
289
|
+
})
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function prepareOn<S extends AnySchema, P extends ParamsRecord, A>(
|
|
293
|
+
state: SnapshotState<S>,
|
|
294
|
+
query: QueryTemplate<S, P, A>
|
|
295
|
+
): Effect.Effect<PreparedQuery<P, A>, DbError, Scope.Scope> {
|
|
296
|
+
return Effect.gen(function* () {
|
|
297
|
+
const ir = yield* Effect.try({
|
|
298
|
+
try: () => {
|
|
299
|
+
if (query.schema !== state.theory) {
|
|
300
|
+
throw refusal("QueryReader.prepare", "InvalidArgument")
|
|
301
|
+
}
|
|
302
|
+
return lowerQuery(query)
|
|
303
|
+
},
|
|
304
|
+
catch: () => refusal("QueryReader.prepare", "InvalidArgument")
|
|
305
|
+
})
|
|
306
|
+
const handle = yield* Effect.acquireRelease(
|
|
307
|
+
nativeOperationWith(
|
|
308
|
+
"QueryReader.prepare",
|
|
309
|
+
(callback) => dbNative.runtimeSnapshotPrepare(state.handle, ir, callback),
|
|
310
|
+
dbNative.runtimePreparedTake,
|
|
311
|
+
(value) => value
|
|
312
|
+
),
|
|
313
|
+
(value) => releaseOwner("PreparedQuery.close", (callback) => dbNative.runtimePreparedClose(value, callback)),
|
|
314
|
+
{ interruptible: true }
|
|
315
|
+
)
|
|
316
|
+
return makePrepared<P, A>(handle, query.data.params, query.data.finds)
|
|
317
|
+
})
|
|
263
318
|
}
|
|
264
319
|
|
|
265
320
|
function makeSnapshot<S extends AnySchema>(theory: S, handle: SnapshotHandle, witness: CoreWitness): Snapshot<S> {
|
|
266
321
|
const state: SnapshotState<S> = { theory, handle }
|
|
267
322
|
const snapshot: Snapshot<S> = {
|
|
268
323
|
witness,
|
|
269
|
-
get(relation, key
|
|
270
|
-
return getOn(state, relation, key
|
|
324
|
+
get(relation, key) {
|
|
325
|
+
return getOn(state, relation, key)
|
|
271
326
|
},
|
|
272
|
-
execute(query, params
|
|
273
|
-
return executeOn(state,
|
|
327
|
+
execute(query, params) {
|
|
328
|
+
return executeOn(state, query, params)
|
|
274
329
|
},
|
|
275
|
-
|
|
276
|
-
return
|
|
277
|
-
nativeOperationWith(
|
|
278
|
-
"Snapshot.session",
|
|
279
|
-
(callback) => dbNative.runtimeSnapshotSession(handle, policyWire(work, "Snapshot.session"), callback),
|
|
280
|
-
dbNative.runtimeSessionTake,
|
|
281
|
-
(value) => makeSession(state, value)
|
|
282
|
-
),
|
|
283
|
-
(session) =>
|
|
284
|
-
Effect.suspend(() =>
|
|
285
|
-
releaseOwner("ExecutionSession.close", (callback) =>
|
|
286
|
-
dbNative.runtimeSessionClose(sessionHandles.get(session) ?? missingSession(), callback)
|
|
287
|
-
)
|
|
288
|
-
),
|
|
289
|
-
{ interruptible: true }
|
|
290
|
-
)
|
|
330
|
+
prepare(query) {
|
|
331
|
+
return prepareOn(state, query)
|
|
291
332
|
},
|
|
292
333
|
close() {
|
|
293
334
|
return drainClose("Snapshot.close", (callback) => dbNative.runtimeSnapshotClose(handle, callback))
|
|
@@ -298,12 +339,6 @@ function makeSnapshot<S extends AnySchema>(theory: S, handle: SnapshotHandle, wi
|
|
|
298
339
|
return snapshot
|
|
299
340
|
}
|
|
300
341
|
|
|
301
|
-
const sessionHandles = new WeakMap<object, SessionHandle>()
|
|
302
|
-
|
|
303
|
-
function missingSession(): never {
|
|
304
|
-
throw new DbError({ operation: "ExecutionSession.close", reason: { _tag: "Internal" } })
|
|
305
|
-
}
|
|
306
|
-
|
|
307
342
|
interface DbState {
|
|
308
343
|
readonly theory: AnySchema
|
|
309
344
|
readonly db: DbHandle
|
|
@@ -314,11 +349,19 @@ interface DbState {
|
|
|
314
349
|
function makeDb<S extends AnySchema>(theory: S, state: DbState): Db<S> {
|
|
315
350
|
const value: Db<S> = {
|
|
316
351
|
schemaId: state.schemaId,
|
|
317
|
-
|
|
352
|
+
clearCache() {
|
|
353
|
+
return nativeOperationWith(
|
|
354
|
+
"Db.clearCache",
|
|
355
|
+
(callback) => dbNative.runtimeDbClearCache(state.db, callback),
|
|
356
|
+
runtimeNative.runtimeTake,
|
|
357
|
+
() => undefined
|
|
358
|
+
)
|
|
359
|
+
},
|
|
360
|
+
snapshot() {
|
|
318
361
|
return Effect.acquireRelease(
|
|
319
362
|
nativeOperationWith(
|
|
320
363
|
"Db.snapshot",
|
|
321
|
-
(callback) => dbNative.runtimeDbSnapshot(state.db,
|
|
364
|
+
(callback) => dbNative.runtimeDbSnapshot(state.db, callback),
|
|
322
365
|
dbNative.runtimeSnapshotTake,
|
|
323
366
|
(wire) => makeSnapshot(theory, wire.snapshot, witnessOf(wire.witness))
|
|
324
367
|
),
|
|
@@ -348,33 +391,29 @@ function makeDb<S extends AnySchema>(theory: S, state: DbState): Db<S> {
|
|
|
348
391
|
: { kind: "exact", store: options.expected.at.store, generation: options.expected.at.generation }
|
|
349
392
|
return yield* nativeOperationWith(
|
|
350
393
|
"Db.apply",
|
|
351
|
-
(callback) =>
|
|
352
|
-
dbNative.runtimeDbApply(state.db, policyWire(options, "Db.apply"), internal.handle, expected, callback),
|
|
394
|
+
(callback) => dbNative.runtimeDbApply(state.db, internal.handle, expected, callback),
|
|
353
395
|
dbNative.runtimeApplyTake,
|
|
354
396
|
outcomeOf
|
|
355
397
|
)
|
|
356
398
|
})
|
|
357
399
|
},
|
|
358
|
-
inspect(
|
|
400
|
+
inspect() {
|
|
359
401
|
return nativeOperationWith(
|
|
360
402
|
"Db.inspect",
|
|
361
|
-
(callback) => dbNative.runtimeDbInspect(state.db,
|
|
403
|
+
(callback) => dbNative.runtimeDbInspect(state.db, callback),
|
|
362
404
|
dbNative.runtimeDbInspectTake,
|
|
363
405
|
(wire: DbInspectionWire): DbInspection =>
|
|
364
406
|
Object.freeze({
|
|
365
407
|
schemaId: state.schemaId,
|
|
366
408
|
generation: wire.generation,
|
|
367
|
-
|
|
368
|
-
populatedBytes: wire.populatedBytes,
|
|
369
|
-
diskBytes: wire.diskBytes,
|
|
370
|
-
residentEstimateBytes: wire.residentEstimateBytes,
|
|
409
|
+
storage: Object.freeze(wire.storage),
|
|
371
410
|
retainedOperations: wire.retainedOperations
|
|
372
411
|
})
|
|
373
412
|
)
|
|
374
413
|
},
|
|
375
414
|
close() {
|
|
376
415
|
// The one close authority: database child first, then the
|
|
377
|
-
// directory owner releases its kernel lock LAST
|
|
416
|
+
// directory owner releases its kernel lock LAST. Both
|
|
378
417
|
// joins are idempotent natively.
|
|
379
418
|
return drainClose("Db.close", (callback) => runtimeNative.runtimeManagedDbClose(state.db, callback)).pipe(
|
|
380
419
|
Effect.flatMap((report) =>
|
|
@@ -402,23 +441,18 @@ function openDatabase<S extends AnySchema>(
|
|
|
402
441
|
operation: "Db.create" | "Db.open",
|
|
403
442
|
path: string,
|
|
404
443
|
schema: S,
|
|
405
|
-
work: ExecutionPolicy,
|
|
406
444
|
create: boolean
|
|
407
445
|
): Effect.Effect<Db<S>, DbError, NativeRuntime | Scope.Scope> {
|
|
408
446
|
return Effect.gen(function* () {
|
|
409
447
|
const runtime = yield* runtimeHandle()
|
|
410
|
-
const compiled: CompiledSchema<S> = yield* CoreSchema.compile(schema
|
|
448
|
+
const compiled: CompiledSchema<S> = yield* CoreSchema.compile(schema)
|
|
411
449
|
const spec = lower(schema)
|
|
412
|
-
|
|
413
|
-
try: () => policyWire(work, operation),
|
|
414
|
-
catch: () => refusal(operation, "InvalidArgument")
|
|
415
|
-
})
|
|
416
|
-
// Compound acquisition (TS-003): register the directory owner and
|
|
450
|
+
// Compound acquisition: register the directory owner and
|
|
417
451
|
// its finalizer BEFORE any interruptible child-open step.
|
|
418
452
|
const directory = yield* Effect.acquireRelease(
|
|
419
453
|
nativeOperationWith(
|
|
420
454
|
operation,
|
|
421
|
-
(callback) => runtimeNative.runtimeDirectoryAcquire(runtime,
|
|
455
|
+
(callback) => runtimeNative.runtimeDirectoryAcquire(runtime, path, callback),
|
|
422
456
|
runtimeNative.runtimeDirectoryTake,
|
|
423
457
|
(value) => value
|
|
424
458
|
),
|
|
@@ -432,7 +466,7 @@ function openDatabase<S extends AnySchema>(
|
|
|
432
466
|
Effect.gen(function* () {
|
|
433
467
|
const outcome = yield* nativeOperationWith(
|
|
434
468
|
operation,
|
|
435
|
-
(callback) => runtimeNative.runtimeDirectoryDbOpen(directory,
|
|
469
|
+
(callback) => runtimeNative.runtimeDirectoryDbOpen(directory, CHILD, spec, create, callback),
|
|
436
470
|
runtimeNative.runtimeDbTake,
|
|
437
471
|
(value) => value
|
|
438
472
|
).pipe(
|
|
@@ -477,24 +511,24 @@ const dbStates = new WeakMap<object, DbState>()
|
|
|
477
511
|
/**
|
|
478
512
|
* `Db.create` is the explicit constructor and refuses existing authority;
|
|
479
513
|
* `Db.open` of a missing or unreadable database never creates an empty
|
|
480
|
-
* replacement
|
|
514
|
+
* replacement. Both compile the schema through the same
|
|
481
515
|
* implementation as `Schema.compile` — prior compilation is optional.
|
|
482
516
|
*/
|
|
483
517
|
const Db = Object.freeze({
|
|
484
|
-
create<S extends AnySchema>(path: string, schema: S
|
|
485
|
-
return openDatabase("Db.create", path, schema,
|
|
518
|
+
create<S extends AnySchema>(path: string, schema: S) {
|
|
519
|
+
return openDatabase("Db.create", path, schema, true)
|
|
486
520
|
},
|
|
487
|
-
open<S extends AnySchema>(path: string, schema: S
|
|
488
|
-
return openDatabase("Db.open", path, schema,
|
|
521
|
+
open<S extends AnySchema>(path: string, schema: S) {
|
|
522
|
+
return openDatabase("Db.open", path, schema, false)
|
|
489
523
|
}
|
|
490
524
|
})
|
|
491
525
|
|
|
492
526
|
/**
|
|
493
|
-
* Private log
|
|
527
|
+
* Private log integration: wraps a published core snapshot
|
|
494
528
|
* handle — minted by the internal log machine's native open/snapshot verbs
|
|
495
529
|
* — in the exact core `QueryReader` plus the scoped session acquisition
|
|
496
|
-
* (
|
|
497
|
-
*
|
|
530
|
+
* (the log adds identity, stamps and freshness around this capability,
|
|
531
|
+
* never a second reader).
|
|
498
532
|
* The argument is the log package's branded handle for the same native
|
|
499
533
|
* registry entry, so the one cast below is a cross-package respelling of
|
|
500
534
|
* one native capability — the native side re-judges kind/generation/owner
|
|
@@ -506,32 +540,18 @@ function internalPublishedReader<S extends AnySchema>(
|
|
|
506
540
|
): {
|
|
507
541
|
readonly get: QueryReader<S>["get"]
|
|
508
542
|
readonly execute: QueryReader<S>["execute"]
|
|
509
|
-
readonly
|
|
543
|
+
readonly prepare: QueryReader<S>["prepare"]
|
|
510
544
|
} {
|
|
511
545
|
const state: SnapshotState<S> = { theory, handle: core as SnapshotHandle }
|
|
512
546
|
return Object.freeze({
|
|
513
|
-
get<R extends Rel<S>>(relation: R, key: Key<R
|
|
514
|
-
return getOn(state, relation, key
|
|
547
|
+
get<R extends Rel<S>>(relation: R, key: Key<R>) {
|
|
548
|
+
return getOn(state, relation, key)
|
|
515
549
|
},
|
|
516
|
-
execute<P extends ParamsRecord, A>(queryValue: QueryTemplate<S, P, A>, params: P
|
|
517
|
-
return executeOn<S, A>(state,
|
|
550
|
+
execute<P extends ParamsRecord, A>(queryValue: QueryTemplate<S, P, A>, params: P) {
|
|
551
|
+
return executeOn<S, A>(state, queryValue as AnyQuery, params)
|
|
518
552
|
},
|
|
519
|
-
|
|
520
|
-
return
|
|
521
|
-
nativeOperationWith(
|
|
522
|
-
"Snapshot.session",
|
|
523
|
-
(callback) => dbNative.runtimeSnapshotSession(state.handle, policyWire(work, "Snapshot.session"), callback),
|
|
524
|
-
dbNative.runtimeSessionTake,
|
|
525
|
-
(value) => makeSession(state, value)
|
|
526
|
-
),
|
|
527
|
-
(session) =>
|
|
528
|
-
Effect.suspend(() =>
|
|
529
|
-
releaseOwner("ExecutionSession.close", (callback) =>
|
|
530
|
-
dbNative.runtimeSessionClose(sessionHandles.get(session) ?? missingSession(), callback)
|
|
531
|
-
)
|
|
532
|
-
),
|
|
533
|
-
{ interruptible: true }
|
|
534
|
-
)
|
|
553
|
+
prepare<P extends ParamsRecord, A>(queryValue: QueryTemplate<S, P, A>) {
|
|
554
|
+
return prepareOn(state, queryValue)
|
|
535
555
|
}
|
|
536
556
|
})
|
|
537
557
|
}
|
|
@@ -542,8 +562,9 @@ export type {
|
|
|
542
562
|
ApplyOutcome,
|
|
543
563
|
CoreWitness,
|
|
544
564
|
DbInspection,
|
|
545
|
-
|
|
565
|
+
PreparedQuery,
|
|
546
566
|
QueryReader,
|
|
547
|
-
Snapshot
|
|
567
|
+
Snapshot,
|
|
568
|
+
StorageInspection
|
|
548
569
|
}
|
|
549
570
|
export { Db, internalPublishedReader }
|
package/src/errors.ts
CHANGED
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
import { Data } from "effect"
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Pure authoring
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* outcome. Every operational failure of effectful work is the single
|
|
9
|
-
* `DbError` tagged-reason class in `#runtime-errors.ts` — the old
|
|
10
|
-
* per-surface `Err*` wrapper family is deleted (duplicate error wrappers
|
|
11
|
-
* are banned by C02/C10).
|
|
4
|
+
* Pure authoring failures, SDK-invariant defects and internal native-boundary
|
|
5
|
+
* diagnostics. AST misuse can throw synchronously without I/O. Runtime
|
|
6
|
+
* adapters translate operational failures into the public `DbError` class
|
|
7
|
+
* in `#runtime-errors.ts`; contradictions in SDK/native state remain defects.
|
|
12
8
|
*/
|
|
13
9
|
|
|
14
10
|
/** A pure schema, query, parameter, or value-authoring refusal. */
|
package/src/fields.ts
CHANGED
|
@@ -21,8 +21,8 @@ interface IntervalValue {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
|
-
* A half-open dense float interval `[start, end)` as a plain value object
|
|
25
|
-
*
|
|
24
|
+
* A half-open dense float interval `[start, end)` as a plain value object:
|
|
25
|
+
* two canonical binary64 bounds on the dense numeric line.
|
|
26
26
|
* NaN is never an endpoint, signed zero is normalized at the checked
|
|
27
27
|
* constructor and again by the native boundary, and strict `start < end`
|
|
28
28
|
* makes empty spans unrepresentable through {@link span}. Infinite bounds
|
|
@@ -35,8 +35,7 @@ interface FloatIntervalValue {
|
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
37
|
* Constructs a checked interval literal — the `start..end` spelling.
|
|
38
|
-
* Half-open and nonempty by construction.
|
|
39
|
-
* "checked small interval constructors": genuinely fallible pure parsing
|
|
38
|
+
* Half-open and nonempty by construction. Fallible pure parsing
|
|
40
39
|
* returns `Result` (use `Effect.fromResult(span(...))` inside a generator),
|
|
41
40
|
* never hidden I/O and never a thrown domain outcome.
|
|
42
41
|
*
|
|
@@ -109,7 +108,7 @@ interface F64Field {
|
|
|
109
108
|
}
|
|
110
109
|
|
|
111
110
|
/**
|
|
112
|
-
* The application-owned 128-bit identity scalar
|
|
111
|
+
* The application-owned 128-bit identity scalar: sixteen
|
|
113
112
|
* exact bytes, spelled as the canonical hyphenated UUID {@link Uuid}
|
|
114
113
|
* host value. There is no `fresh` mark anywhere: the database issues no
|
|
115
114
|
* identity, and key laws are declared statements.
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @bjornpagen/bumbledb — the Effect-native TypeScript SDK for the
|
|
3
|
-
* bumbledb embedded relational engine
|
|
3
|
+
* bumbledb embedded relational engine. Pure
|
|
4
4
|
* schema/query/scalar construction is synchronous metadata; all work is
|
|
5
5
|
* lazy, scoped and bounded on the one native runtime. No Promise, sync,
|
|
6
6
|
* or disposal twin. The raw native bridge is not exported from this barrel.
|
|
@@ -43,9 +43,10 @@ export type {
|
|
|
43
43
|
ApplyOutcome,
|
|
44
44
|
CoreWitness,
|
|
45
45
|
DbInspection,
|
|
46
|
-
|
|
46
|
+
PreparedQuery,
|
|
47
47
|
QueryReader,
|
|
48
|
-
Snapshot
|
|
48
|
+
Snapshot,
|
|
49
|
+
StorageInspection
|
|
49
50
|
} from "#db.ts"
|
|
50
51
|
export { Db } from "#db.ts"
|
|
51
52
|
export {
|
|
@@ -149,8 +150,8 @@ export type {
|
|
|
149
150
|
export { relation } from "#relation.ts"
|
|
150
151
|
export type { CompleteResult } from "#result.ts"
|
|
151
152
|
export type { CellValue } from "#rows.ts"
|
|
152
|
-
export {
|
|
153
|
-
export type {
|
|
153
|
+
export { cellOf, factOfCells, flatRowsOf, keyCellsOf } from "#rows.ts"
|
|
154
|
+
export type { NativeRuntimeOptions } from "#runtime.ts"
|
|
154
155
|
export { NativeRuntime } from "#runtime.ts"
|
|
155
156
|
export type { CloseReport, OutstandingWork } from "#runtime-errors.ts"
|
|
156
157
|
export { CloseFailure, DbError, dbError, runtimeErrorCodes } from "#runtime-errors.ts"
|
package/src/internal/log.ts
CHANGED
|
@@ -8,7 +8,7 @@ export type { ChangeDraft } from "#changes.ts"
|
|
|
8
8
|
export { ChangeSet, internalChanges } from "#changes.ts"
|
|
9
9
|
export type { CompiledSchema, SchemaId } from "#compile.ts"
|
|
10
10
|
export { Schema } from "#compile.ts"
|
|
11
|
-
export type {
|
|
11
|
+
export type { PreparedQuery, QueryReader } from "#db.ts"
|
|
12
12
|
export { Db, internalPublishedReader } from "#db.ts"
|
|
13
13
|
export type { SnapshotHandle } from "#db-native.ts"
|
|
14
14
|
export { lower } from "#lower.ts"
|
|
@@ -21,31 +21,26 @@ export {
|
|
|
21
21
|
nativeBindingIsLoaded
|
|
22
22
|
} from "#native.ts"
|
|
23
23
|
export type { CompleteResult } from "#result.ts"
|
|
24
|
-
export type {
|
|
24
|
+
export type { NativeRuntimeOptions, RepositoryLock } from "#runtime.ts"
|
|
25
25
|
export {
|
|
26
|
-
deliveryResultBytes,
|
|
27
26
|
finalizeClose,
|
|
28
27
|
hashChunk,
|
|
29
28
|
internalAcquireRepositoryLock,
|
|
30
29
|
NativeRuntime,
|
|
31
30
|
nativeOperation,
|
|
32
31
|
nativeOperationWith,
|
|
33
|
-
policyWire,
|
|
34
32
|
runtimeHandle
|
|
35
33
|
} from "#runtime.ts"
|
|
36
34
|
export type { CloseReport, OutstandingWork } from "#runtime-errors.ts"
|
|
37
35
|
export { CloseFailure, DbError, dbError, runtimeErrorCodes } from "#runtime-errors.ts"
|
|
38
36
|
export type {
|
|
39
37
|
Capability,
|
|
40
|
-
CloseDrain,
|
|
41
38
|
CloseWire,
|
|
42
39
|
DirectoryHandle,
|
|
43
40
|
InspectionWire,
|
|
44
41
|
NativeKind,
|
|
45
42
|
OperationHandle,
|
|
46
|
-
PolicyWire,
|
|
47
43
|
RepositoryLockHandle,
|
|
48
|
-
ResourceHeader,
|
|
49
44
|
RuntimeHandle
|
|
50
45
|
} from "#runtime-native.ts"
|
|
51
46
|
export { runtimeNative } from "#runtime-native.ts"
|
package/src/law.ts
CHANGED
|
@@ -50,7 +50,7 @@ import { AuthoringError } from "#errors.ts"
|
|
|
50
50
|
* widened type) — the runtime map stays complete and authoritative, and
|
|
51
51
|
* the wire lowering reads only the runtime map. Every loop below is
|
|
52
52
|
* tail-recursive with an accumulator, so the machinery rides TypeScript's
|
|
53
|
-
* tail-recursion elimination
|
|
53
|
+
* tail-recursion elimination for large schemas (~40 relations, ~200 slots,
|
|
54
54
|
* ~123 statements); should a schema ever exceed the compiler's limits, tsc
|
|
55
55
|
* fails LOUDLY with its own instantiation-depth error — the map is never
|
|
56
56
|
* silently widened.
|