@bjornpagen/bumbledb 1.3.0 → 2.0.0-rc.1
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 +224 -95
- package/README.md +114 -45
- package/dist/alternatives.d.ts +5 -6
- package/dist/alternatives.d.ts.map +1 -1
- package/dist/alternatives.js +5 -6
- package/dist/alternatives.js.map +1 -1
- package/dist/bin.d.ts +3 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +85 -0
- package/dist/bin.js.map +1 -0
- package/dist/capacity.d.ts +14 -17
- package/dist/capacity.d.ts.map +1 -1
- package/dist/capacity.js +7 -7
- package/dist/capacity.js.map +1 -1
- package/dist/changes.d.ts +32 -41
- package/dist/changes.d.ts.map +1 -1
- package/dist/changes.js +86 -110
- package/dist/changes.js.map +1 -1
- package/dist/closed.d.ts +2 -2
- package/dist/closed.d.ts.map +1 -1
- package/dist/closed.js +5 -5
- package/dist/closed.js.map +1 -1
- package/dist/codec.d.ts +20 -27
- package/dist/codec.d.ts.map +1 -1
- package/dist/codec.js +48 -22
- package/dist/codec.js.map +1 -1
- package/dist/compile.d.ts +26 -50
- package/dist/compile.d.ts.map +1 -1
- package/dist/compile.js +75 -64
- package/dist/compile.js.map +1 -1
- package/dist/database/database.d.ts +98 -0
- package/dist/database/database.d.ts.map +1 -0
- package/dist/database/database.js +249 -0
- package/dist/database/database.js.map +1 -0
- package/dist/database/driver.d.ts +40 -0
- package/dist/database/driver.d.ts.map +1 -0
- package/dist/database/driver.js +68 -0
- package/dist/database/driver.js.map +1 -0
- package/dist/database/fs.d.ts +12 -0
- package/dist/database/fs.d.ts.map +1 -0
- package/dist/database/fs.js +120 -0
- package/dist/database/fs.js.map +1 -0
- package/dist/database/generate.d.ts +26 -0
- package/dist/database/generate.d.ts.map +1 -0
- package/dist/database/generate.js +102 -0
- package/dist/database/generate.js.map +1 -0
- package/dist/database/hosted.d.ts +32 -0
- package/dist/database/hosted.d.ts.map +1 -0
- package/dist/database/hosted.js +44 -0
- package/dist/database/hosted.js.map +1 -0
- package/dist/database/io.d.ts +94 -0
- package/dist/database/io.d.ts.map +1 -0
- package/dist/database/io.js +35 -0
- package/dist/database/io.js.map +1 -0
- package/dist/database/mem.d.ts +26 -0
- package/dist/database/mem.d.ts.map +1 -0
- package/dist/database/mem.js +67 -0
- package/dist/database/mem.js.map +1 -0
- package/dist/database/migration.d.ts +55 -0
- package/dist/database/migration.d.ts.map +1 -0
- package/dist/database/migration.js +46 -0
- package/dist/database/migration.js.map +1 -0
- package/dist/database/s3.d.ts +36 -0
- package/dist/database/s3.d.ts.map +1 -0
- package/dist/database/s3.js +141 -0
- package/dist/database/s3.js.map +1 -0
- package/dist/db.d.ts +44 -128
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +163 -287
- package/dist/db.js.map +1 -1
- package/dist/engine.d.ts +7 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +2 -0
- package/dist/engine.js.map +1 -0
- package/dist/errors.d.ts +152 -46
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +107 -19
- package/dist/errors.js.map +1 -1
- package/dist/face.d.ts +5 -5
- package/dist/face.d.ts.map +1 -1
- package/dist/face.js +6 -6
- package/dist/face.js.map +1 -1
- package/dist/fields.d.ts +4 -5
- package/dist/fields.d.ts.map +1 -1
- package/dist/fields.js +3 -3
- package/dist/fields.js.map +1 -1
- package/dist/index.d.ts +60 -58
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +27 -29
- package/dist/index.js.map +1 -1
- package/dist/judgment.d.ts +1 -1
- package/dist/judgment.js +1 -1
- package/dist/law.d.ts +16 -68
- package/dist/law.d.ts.map +1 -1
- package/dist/law.js +3 -3
- package/dist/law.js.map +1 -1
- package/dist/lower.d.ts +3 -3
- package/dist/lower.d.ts.map +1 -1
- package/dist/lower.js +35 -39
- package/dist/lower.js.map +1 -1
- package/dist/native/addon.d.ts +23 -0
- package/dist/native/addon.d.ts.map +1 -0
- package/dist/native/addon.js +15 -0
- package/dist/native/addon.js.map +1 -0
- package/dist/native/binding.d.ts +996 -0
- package/dist/native/json.d.ts +14 -0
- package/dist/native/json.d.ts.map +1 -0
- package/dist/native/json.js +73 -0
- package/dist/native/json.js.map +1 -0
- package/dist/native/load.d.ts +9 -0
- package/dist/native/load.d.ts.map +1 -0
- package/dist/native/load.js +30 -0
- package/dist/native/load.js.map +1 -0
- package/dist/native/op.d.ts +29 -0
- package/dist/native/op.d.ts.map +1 -0
- package/dist/native/op.js +50 -0
- package/dist/native/op.js.map +1 -0
- package/dist/query/atom.d.ts +13 -14
- package/dist/query/atom.d.ts.map +1 -1
- package/dist/query/atom.js +2 -2
- package/dist/query/atom.js.map +1 -1
- package/dist/query/compute.d.ts +7 -7
- package/dist/query/compute.d.ts.map +1 -1
- package/dist/query/compute.js +7 -16
- package/dist/query/compute.js.map +1 -1
- package/dist/query/find.d.ts +8 -8
- package/dist/query/find.d.ts.map +1 -1
- package/dist/query/find.js +1 -1
- package/dist/query/lower.d.ts +31 -17
- package/dist/query/lower.d.ts.map +1 -1
- package/dist/query/lower.js +260 -368
- package/dist/query/lower.js.map +1 -1
- package/dist/query/run.d.ts +5 -5
- package/dist/query/run.d.ts.map +1 -1
- package/dist/query/run.js +32 -15
- package/dist/query/run.js.map +1 -1
- package/dist/query/scope.d.ts +20 -28
- package/dist/query/scope.d.ts.map +1 -1
- package/dist/query/scope.js +13 -8
- package/dist/query/scope.js.map +1 -1
- package/dist/query/segments.d.ts +2 -2
- package/dist/query/segments.d.ts.map +1 -1
- package/dist/query/segments.js +3 -3
- package/dist/query/segments.js.map +1 -1
- package/dist/relation.d.ts +1 -1
- package/dist/relation.d.ts.map +1 -1
- package/dist/relation.js +4 -4
- package/dist/relation.js.map +1 -1
- package/dist/result.d.ts +15 -22
- package/dist/result.d.ts.map +1 -1
- package/dist/result.js +30 -39
- package/dist/result.js.map +1 -1
- package/dist/rows.d.ts +9 -33
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +8 -12
- package/dist/rows.js.map +1 -1
- package/dist/runtime.d.ts +17 -43
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +41 -241
- package/dist/runtime.js.map +1 -1
- package/dist/scalar.d.ts +36 -106
- package/dist/scalar.d.ts.map +1 -1
- package/dist/scalar.js +36 -185
- package/dist/scalar.js.map +1 -1
- package/dist/schema.d.ts +7 -18
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +18 -228
- package/dist/schema.js.map +1 -1
- package/dist/selection.d.ts +4 -4
- package/dist/selection.d.ts.map +1 -1
- package/dist/selection.js +5 -5
- package/dist/selection.js.map +1 -1
- package/dist/shape.d.ts +5 -5
- package/dist/shape.d.ts.map +1 -1
- package/dist/spec.d.ts +7 -79
- package/dist/spec.d.ts.map +1 -1
- package/dist/spec.js.map +1 -1
- package/dist/statements.d.ts +3 -3
- package/dist/statements.d.ts.map +1 -1
- package/dist/statements.js +10 -10
- package/dist/statements.js.map +1 -1
- package/dist/uuid.d.ts +1 -1
- package/dist/uuid.d.ts.map +1 -1
- package/dist/uuid.js +1 -1
- package/dist/uuid.js.map +1 -1
- package/dist/values.d.ts +2 -2
- package/dist/values.d.ts.map +1 -1
- package/dist/values.js +2 -2
- package/dist/values.js.map +1 -1
- package/package.json +18 -18
- package/src/alternatives.ts +7 -8
- package/src/bin.ts +82 -0
- package/src/capacity.ts +20 -23
- package/src/changes.ts +134 -197
- package/src/closed.ts +5 -5
- package/src/codec.ts +77 -51
- package/src/compile.ts +91 -113
- package/src/database/database.ts +413 -0
- package/src/database/driver.ts +134 -0
- package/src/database/fs.ts +119 -0
- package/src/database/generate.ts +116 -0
- package/src/database/hosted.ts +102 -0
- package/src/database/io.ts +134 -0
- package/src/database/mem.ts +113 -0
- package/src/database/migration.ts +107 -0
- package/src/database/s3.ts +231 -0
- package/src/db.ts +290 -547
- package/src/engine.ts +14 -0
- package/src/errors.ts +118 -39
- package/src/face.ts +9 -9
- package/src/fields.ts +6 -7
- package/src/index.ts +102 -109
- package/src/judgment.ts +1 -1
- package/src/law.ts +18 -70
- package/src/lower.ts +61 -72
- package/src/native/addon.ts +54 -0
- package/src/native/binding.d.ts +996 -0
- package/src/native/json.ts +100 -0
- package/src/native/load.ts +31 -0
- package/src/native/op.ts +73 -0
- package/src/query/atom.ts +15 -16
- package/src/query/compute.ts +13 -22
- package/src/query/find.ts +8 -8
- package/src/query/lower.ts +323 -414
- package/src/query/run.ts +42 -21
- package/src/query/scope.ts +37 -38
- package/src/query/segments.ts +4 -4
- package/src/relation.ts +4 -4
- package/src/result.ts +53 -80
- package/src/rows.ts +18 -46
- package/src/runtime.ts +50 -346
- package/src/scalar.ts +76 -336
- package/src/schema.ts +23 -284
- package/src/selection.ts +6 -6
- package/src/shape.ts +5 -5
- package/src/spec.ts +7 -85
- package/src/statements.ts +11 -11
- package/src/uuid.ts +1 -1
- package/src/values.ts +4 -4
- package/dist/close.d.ts +0 -24
- package/dist/close.d.ts.map +0 -1
- package/dist/close.js +0 -34
- package/dist/close.js.map +0 -1
- package/dist/db-native.d.ts +0 -196
- package/dist/db-native.d.ts.map +0 -1
- package/dist/db-native.js +0 -13
- package/dist/db-native.js.map +0 -1
- package/dist/internal/log.d.ts +0 -26
- package/dist/internal/log.d.ts.map +0 -1
- package/dist/internal/log.js +0 -12
- package/dist/internal/log.js.map +0 -1
- package/dist/migration.d.ts +0 -31
- package/dist/migration.d.ts.map +0 -1
- package/dist/migration.js +0 -47
- package/dist/migration.js.map +0 -1
- package/dist/native.d.ts +0 -562
- package/dist/native.d.ts.map +0 -1
- package/dist/native.js +0 -123
- package/dist/native.js.map +0 -1
- package/dist/query/description.d.ts +0 -41
- package/dist/query/description.d.ts.map +0 -1
- package/dist/query/description.js +0 -311
- package/dist/query/description.js.map +0 -1
- package/dist/query/parse-ir.d.ts +0 -10
- package/dist/query/parse-ir.d.ts.map +0 -1
- package/dist/query/parse-ir.js +0 -280
- package/dist/query/parse-ir.js.map +0 -1
- package/dist/runtime-codes.d.ts +0 -2
- package/dist/runtime-codes.d.ts.map +0 -1
- package/dist/runtime-codes.js +0 -18
- package/dist/runtime-codes.js.map +0 -1
- package/dist/runtime-errors.d.ts +0 -118
- package/dist/runtime-errors.d.ts.map +0 -1
- package/dist/runtime-errors.js +0 -98
- package/dist/runtime-errors.js.map +0 -1
- package/dist/runtime-native.d.ts +0 -141
- package/dist/runtime-native.d.ts.map +0 -1
- package/dist/runtime-native.js +0 -5
- package/dist/runtime-native.js.map +0 -1
- package/pack-provenance.json +0 -7
- package/src/close.ts +0 -53
- package/src/db-native.ts +0 -243
- package/src/internal/log.ts +0 -48
- package/src/migration.ts +0 -61
- package/src/native.ts +0 -736
- package/src/query/description.ts +0 -424
- package/src/query/parse-ir.ts +0 -291
- package/src/runtime-codes.ts +0 -17
- package/src/runtime-errors.ts +0 -109
- package/src/runtime-native.ts +0 -189
package/src/runtime.ts
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
import { Context, Duration, Effect,
|
|
2
|
-
import type {
|
|
3
|
-
import {
|
|
4
|
-
import type {
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import { Context, Duration, Effect, Layer } from "effect"
|
|
2
|
+
import type { OutstandingWork } from "./errors.ts"
|
|
3
|
+
import { DbError, dbError } from "./errors.ts"
|
|
4
|
+
import type { RuntimeRef } from "./native/addon.ts"
|
|
5
|
+
import { addon } from "./native/addon.ts"
|
|
6
|
+
import type { RuntimeOptionsIn } from "./native/binding.d.ts"
|
|
7
|
+
import { call, scoped } from "./native/op.ts"
|
|
8
|
+
|
|
9
|
+
/** Sizing for the native runtime. The addon validates every count and picks the defaults. */
|
|
10
|
+
export interface BumbleOptions {
|
|
8
11
|
readonly workers?: number
|
|
9
12
|
readonly queueCapacity?: number
|
|
10
13
|
readonly cleanupCapacity?: number
|
|
@@ -13,359 +16,60 @@ export interface NativeRuntimeOptions {
|
|
|
13
16
|
readonly cleanupTimeout?: Duration.Input
|
|
14
17
|
}
|
|
15
18
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const owners = new WeakMap<RuntimeService, RuntimeHandle>()
|
|
22
|
-
|
|
23
|
-
function invalid(operation: string): DbError {
|
|
24
|
-
return new DbError({ operation, reason: { _tag: "InvalidArgument" } })
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function count(value: number, operation: string): number {
|
|
28
|
-
if (!Number.isSafeInteger(value) || value <= 0 || value > 0xffffffff) throw invalid(operation)
|
|
29
|
-
return value
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function millis(value: Duration.Input, operation: string): number {
|
|
33
|
-
const duration = Duration.toMillis(value)
|
|
34
|
-
if (!Number.isFinite(duration) || duration < 0 || duration > 0xffffffff) throw invalid(operation)
|
|
35
|
-
return Math.ceil(duration)
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function options(value: NativeRuntimeOptions): OptionsWire {
|
|
39
|
-
const operation = "NativeRuntime.acquire"
|
|
40
|
-
return {
|
|
41
|
-
workers: value.workers === undefined ? undefined : count(value.workers, operation),
|
|
42
|
-
queueCapacity: value.queueCapacity === undefined ? undefined : count(value.queueCapacity, operation),
|
|
43
|
-
cleanupCapacity: value.cleanupCapacity === undefined ? undefined : count(value.cleanupCapacity, operation),
|
|
44
|
-
ownerCapacity: value.ownerCapacity === undefined ? undefined : count(value.ownerCapacity, operation),
|
|
45
|
-
nativeHandleCapacity:
|
|
46
|
-
value.nativeHandleCapacity === undefined ? undefined : count(value.nativeHandleCapacity, operation),
|
|
47
|
-
cleanupTimeoutMs:
|
|
48
|
-
value.cleanupTimeout === undefined ? undefined : count(millis(value.cleanupTimeout, operation), operation)
|
|
19
|
+
function wire(options: BumbleOptions): string {
|
|
20
|
+
const timeout = options.cleanupTimeout === undefined ? undefined : Duration.toMillis(options.cleanupTimeout)
|
|
21
|
+
if (timeout !== undefined && !Number.isFinite(timeout)) {
|
|
22
|
+
throw new DbError({ operation: "Bumble.layer", reason: { _tag: "InvalidArgument" } })
|
|
49
23
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
// A payload-less native "failed" drain (cleanup capacity exhausted, or
|
|
58
|
-
// owner teardown failed) decodes as the core `Internal` reason — the
|
|
59
|
-
// same mapping the log bridge applies, so one wire arm has one meaning.
|
|
60
|
-
// It is deliberately NOT `QueueFull`: a failed drain is never retryable
|
|
61
|
-
// submit backpressure.
|
|
62
|
-
return report.kind === "failed" ? { kind: "failed", error: dbError(operation, { _tag: "Internal" }) } : report
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function drain(operation: string, start: (callback: (report: CloseWire) => void) => void): Effect.Effect<CloseReport> {
|
|
66
|
-
return Effect.callback<CloseReport>((resume) => {
|
|
67
|
-
try {
|
|
68
|
-
start((report) => resume(Effect.succeed(closeReport(operation, report))))
|
|
69
|
-
} catch (cause) {
|
|
70
|
-
resume(Effect.succeed({ kind: "failed", error: failure(operation, cause) }))
|
|
71
|
-
}
|
|
72
|
-
}).pipe(Effect.uninterruptible)
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export function finalizeClose(operation: string, report: CloseReport): Effect.Effect<void> {
|
|
76
|
-
return report.kind === "closed" ? Effect.void : Effect.die(new CloseFailure({ operation, report }))
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Effect.callback's returned finalizer is interruption cleanup only
|
|
81
|
-
* (`asyncFinalizer` runs solely on interrupt Cause). If that finalizer
|
|
82
|
-
* dies, the original interrupt is dropped. Join the native drain here and
|
|
83
|
-
* always succeed so the interrupt Cause is kept; attach CloseFailure via
|
|
84
|
-
* `onExit` so both appear in the final Cause.
|
|
85
|
-
*/
|
|
86
|
-
function joinInterruptDrain(
|
|
87
|
-
operation: string,
|
|
88
|
-
start: (callback: (report: CloseWire) => void) => void,
|
|
89
|
-
stash: { report?: CloseReport }
|
|
90
|
-
): Effect.Effect<void> {
|
|
91
|
-
return drain(operation, start).pipe(
|
|
92
|
-
Effect.tap((report) => {
|
|
93
|
-
stash.report = report
|
|
94
|
-
return Effect.void
|
|
95
|
-
}),
|
|
96
|
-
Effect.asVoid
|
|
97
|
-
)
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
function attachInterruptClose(
|
|
101
|
-
operation: string,
|
|
102
|
-
stash: { report?: CloseReport }
|
|
103
|
-
): <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R> {
|
|
104
|
-
return (effect) =>
|
|
105
|
-
effect.pipe(
|
|
106
|
-
Effect.onExit((exit) => {
|
|
107
|
-
if (!Exit.hasInterrupts(exit)) {
|
|
108
|
-
return Effect.void
|
|
109
|
-
}
|
|
110
|
-
const report = stash.report
|
|
111
|
-
if (report === undefined || report.kind === "closed") {
|
|
112
|
-
return Effect.void
|
|
113
|
-
}
|
|
114
|
-
return Effect.die(new CloseFailure({ operation, report }))
|
|
115
|
-
})
|
|
116
|
-
)
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
function afterClose<A, E, R>(
|
|
120
|
-
operation: string,
|
|
121
|
-
report: CloseReport,
|
|
122
|
-
effect: Effect.Effect<A, E, R>
|
|
123
|
-
): Effect.Effect<A, E, R> {
|
|
124
|
-
if (report.kind === "closed") {
|
|
125
|
-
return effect
|
|
24
|
+
const input: RuntimeOptionsIn = {
|
|
25
|
+
...(options.workers === undefined ? {} : { workers: options.workers }),
|
|
26
|
+
...(options.queueCapacity === undefined ? {} : { queueCapacity: options.queueCapacity }),
|
|
27
|
+
...(options.cleanupCapacity === undefined ? {} : { cleanupCapacity: options.cleanupCapacity }),
|
|
28
|
+
...(options.ownerCapacity === undefined ? {} : { ownerCapacity: options.ownerCapacity }),
|
|
29
|
+
...(options.nativeHandleCapacity === undefined ? {} : { nativeHandleCapacity: options.nativeHandleCapacity }),
|
|
30
|
+
...(timeout === undefined ? {} : { cleanupTimeoutMs: Math.ceil(timeout) })
|
|
126
31
|
}
|
|
127
|
-
return
|
|
32
|
+
return JSON.stringify(input)
|
|
128
33
|
}
|
|
129
34
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
35
|
+
/** The live native runtime: one worker pool and handle registry per process. */
|
|
36
|
+
export class Runtime {
|
|
37
|
+
readonly #handle: RuntimeRef
|
|
38
|
+
/** The runtime's outstanding native work, after every operation queued before it settles. */
|
|
39
|
+
readonly inspect: () => Effect.Effect<OutstandingWork, DbError>
|
|
133
40
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
function startCancelDrain(operation: string, lease: OperationHandle, stash: { report?: CloseReport }): void {
|
|
140
|
-
try {
|
|
141
|
-
runtimeNative.runtimeCancel(lease, (report) => {
|
|
142
|
-
stash.report = closeReport(operation, report)
|
|
41
|
+
constructor(handle: RuntimeRef) {
|
|
42
|
+
this.#handle = handle
|
|
43
|
+
this.inspect = Effect.fn("Bumble.inspect")(function* () {
|
|
44
|
+
yield* call("Bumble.inspect", (done) => addon.runtimeReady(handle, done), addon.runtimeTake)
|
|
45
|
+
return addon.runtimeInspect(handle) as OutstandingWork
|
|
143
46
|
})
|
|
144
|
-
} catch (cause) {
|
|
145
|
-
stash.report = { kind: "failed", error: failure(operation, cause) }
|
|
146
47
|
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/** Registration returns the native lease before any completion can run in JS.
|
|
150
|
-
* Interruption cancels and joins that lease, including a late successful result.
|
|
151
|
-
* No Promise or libuv job is created for ordinary native work.
|
|
152
|
-
*/
|
|
153
|
-
export function nativeOperation<A>(
|
|
154
|
-
operation: string,
|
|
155
|
-
start: (callback: () => void) => OperationHandle,
|
|
156
|
-
accept: (value: Uint8Array | null) => A
|
|
157
|
-
): Effect.Effect<A, DbError> {
|
|
158
|
-
return nativeOperationWith(operation, start, runtimeNative.runtimeTake, accept)
|
|
159
|
-
}
|
|
160
48
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
take: (operation: OperationHandle) => Value,
|
|
165
|
-
accept: (value: Value) => A
|
|
166
|
-
): Effect.Effect<A, DbError> {
|
|
167
|
-
const stash: { report?: CloseReport } = {}
|
|
168
|
-
const cancelOp = `${operation}.cancel`
|
|
169
|
-
return attachInterruptClose(
|
|
170
|
-
cancelOp,
|
|
171
|
-
stash
|
|
172
|
-
)(
|
|
173
|
-
Effect.callback((resume, signal) => {
|
|
174
|
-
let lease: OperationHandle
|
|
175
|
-
try {
|
|
176
|
-
lease = start(() => {
|
|
177
|
-
if (signal.aborted) {
|
|
178
|
-
startCancelDrain(cancelOp, lease, stash)
|
|
179
|
-
return
|
|
180
|
-
}
|
|
181
|
-
try {
|
|
182
|
-
resume(Effect.succeed(accept(take(lease))))
|
|
183
|
-
} catch (cause) {
|
|
184
|
-
resume(Effect.fail(failure(operation, cause)))
|
|
185
|
-
}
|
|
186
|
-
})
|
|
187
|
-
} catch (cause) {
|
|
188
|
-
resume(Effect.fail(failure(operation, cause)))
|
|
189
|
-
return
|
|
190
|
-
}
|
|
191
|
-
return joinInterruptDrain(cancelOp, (callback) => runtimeNative.runtimeCancel(lease, callback), stash)
|
|
192
|
-
})
|
|
193
|
-
)
|
|
49
|
+
static handle(runtime: Runtime): RuntimeRef {
|
|
50
|
+
return runtime.#handle
|
|
51
|
+
}
|
|
194
52
|
}
|
|
195
53
|
|
|
196
|
-
const acquire = Effect.fn("
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
stash
|
|
203
|
-
)(
|
|
204
|
-
Effect.callback<RuntimeService, DbError>((resume, signal) => {
|
|
205
|
-
let handle: RuntimeHandle | undefined
|
|
206
|
-
try {
|
|
207
|
-
const wire = options(configuration)
|
|
208
|
-
handle = runtimeNative.runtimeOpen(wire)
|
|
209
|
-
const owner = handle
|
|
210
|
-
const lease = runtimeNative.runtimeReady(owner, () => {
|
|
211
|
-
if (signal.aborted) {
|
|
212
|
-
try {
|
|
213
|
-
runtimeNative.runtimeClose(owner, (report) => {
|
|
214
|
-
stash.report = closeReport("NativeRuntime.acquire.cancel", report)
|
|
215
|
-
})
|
|
216
|
-
} catch (cause) {
|
|
217
|
-
stash.report = { kind: "failed", error: failure("NativeRuntime.acquire.cancel", cause) }
|
|
218
|
-
}
|
|
219
|
-
return
|
|
220
|
-
}
|
|
221
|
-
try {
|
|
222
|
-
runtimeNative.runtimeTake(lease)
|
|
223
|
-
const service: RuntimeService = {
|
|
224
|
-
close: () => close(owner),
|
|
225
|
-
inspect: Effect.fn("NativeRuntime.inspect")(function* () {
|
|
226
|
-
yield* nativeOperation(
|
|
227
|
-
"NativeRuntime.inspect",
|
|
228
|
-
(callback) => runtimeNative.runtimeReady(owner, callback),
|
|
229
|
-
() => undefined
|
|
230
|
-
)
|
|
231
|
-
return runtimeNative.runtimeInspect(owner)
|
|
232
|
-
})
|
|
233
|
-
}
|
|
234
|
-
owners.set(service, owner)
|
|
235
|
-
resume(Effect.succeed(service))
|
|
236
|
-
} catch (cause) {
|
|
237
|
-
const error = failure("NativeRuntime.acquire", cause)
|
|
238
|
-
resume(
|
|
239
|
-
close(owner).pipe(
|
|
240
|
-
Effect.flatMap((report) => afterClose("NativeRuntime.acquire", report, Effect.fail(error)))
|
|
241
|
-
)
|
|
242
|
-
)
|
|
243
|
-
}
|
|
244
|
-
})
|
|
245
|
-
} catch (cause) {
|
|
246
|
-
const error = failure("NativeRuntime.acquire", cause)
|
|
247
|
-
resume(
|
|
248
|
-
handle === undefined
|
|
249
|
-
? Effect.fail(error)
|
|
250
|
-
: close(handle).pipe(
|
|
251
|
-
Effect.flatMap((report) => afterClose("NativeRuntime.acquire", report, Effect.fail(error)))
|
|
252
|
-
)
|
|
253
|
-
)
|
|
254
|
-
}
|
|
255
|
-
return handle === undefined
|
|
256
|
-
? Effect.void
|
|
257
|
-
: joinInterruptDrain(
|
|
258
|
-
"NativeRuntime.acquire.cancel",
|
|
259
|
-
(callback) => runtimeNative.runtimeClose(handle, callback),
|
|
260
|
-
stash
|
|
261
|
-
)
|
|
262
|
-
})
|
|
263
|
-
)
|
|
264
|
-
}),
|
|
265
|
-
(service) => service.close().pipe(Effect.flatMap((report) => finalizeClose("NativeRuntime.release", report))),
|
|
266
|
-
{ interruptible: true }
|
|
54
|
+
const acquire = Effect.fn("Bumble.layer")(function* (options: BumbleOptions) {
|
|
55
|
+
const input = yield* Effect.try({ try: () => wire(options), catch: (cause) => dbError("Bumble.layer", cause) })
|
|
56
|
+
const handle = yield* scoped(
|
|
57
|
+
"Bumble.release",
|
|
58
|
+
Effect.try({ try: () => addon.runtimeOpen(input), catch: (cause) => dbError("Bumble.layer", cause) }),
|
|
59
|
+
(owner) => (done) => addon.runtimeClose(owner, done)
|
|
267
60
|
)
|
|
61
|
+
yield* call("Bumble.layer", (done) => addon.runtimeReady(handle, done), addon.runtimeTake)
|
|
62
|
+
return new Runtime(handle)
|
|
268
63
|
})
|
|
269
64
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
) {
|
|
273
|
-
|
|
274
|
-
return Layer.effect(NativeRuntime, acquire(options))
|
|
65
|
+
/** The native runtime as an Effect service. Provide `Bumble.layer()` once in the application graph. */
|
|
66
|
+
export class Bumble extends Context.Service<Bumble, Runtime>()("@bjornpagen/bumbledb/Bumble") {
|
|
67
|
+
static layer(options: BumbleOptions = {}): Layer.Layer<Bumble, DbError> {
|
|
68
|
+
return Layer.effect(Bumble, acquire(options))
|
|
275
69
|
}
|
|
276
70
|
}
|
|
277
71
|
|
|
278
|
-
/**
|
|
279
|
-
export const runtimeHandle = Effect.
|
|
280
|
-
|
|
281
|
-
const handle = owners.get(runtime)
|
|
282
|
-
if (handle === undefined) return yield* Effect.fail(invalid("NativeRuntime.handle"))
|
|
283
|
-
return handle
|
|
284
|
-
})
|
|
285
|
-
|
|
286
|
-
/**
|
|
287
|
-
* Opaque kernel fence (C8). Backed by L14 `log_repository_lock_*` and
|
|
288
|
-
* L12 `mint_repository_lock` (`NativeKind::RepositoryLock`). Native
|
|
289
|
-
* exclusion is the owner — there is no JS occupancy table. `release`
|
|
290
|
-
* is the one close: it joins `logRepositoryLockRelease` then clears
|
|
291
|
-
* `slot.owner` so the Scope finalizer is a no-op. Callers join host
|
|
292
|
-
* I/O first (`joinPendingIo.pipe(Effect.andThen(lock.release))`).
|
|
293
|
-
*/
|
|
294
|
-
export interface RepositoryLock {
|
|
295
|
-
readonly directory: string
|
|
296
|
-
readonly release: Effect.Effect<void>
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
function joinLockRelease(operation: string, owner: RepositoryLockHandle): Effect.Effect<void> {
|
|
300
|
-
return drain(operation, (callback) => runtimeNative.logRepositoryLockRelease(owner, callback)).pipe(
|
|
301
|
-
Effect.flatMap((report) => finalizeClose(operation, report))
|
|
302
|
-
)
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
/**
|
|
306
|
-
* Internal log seam: stamped mint only. Cleanup is registered before
|
|
307
|
-
* the interruptible acquire: `acquireRelease({ interruptible })`
|
|
308
|
-
* installs the finalizer only after acquire succeeds. Interrupt, defect,
|
|
309
|
-
* and acquire failure all run the same slot finalizer — empty slot is
|
|
310
|
-
* a no-op. No `runtimeDirectoryAcquire`, no core `Db`, no JS bookkeeping.
|
|
311
|
-
*/
|
|
312
|
-
export const internalAcquireRepositoryLock = Effect.fn("internalAcquireRepositoryLock")(function* (
|
|
313
|
-
operation: string,
|
|
314
|
-
directory: string
|
|
315
|
-
) {
|
|
316
|
-
if (directory.length === 0) {
|
|
317
|
-
return yield* Effect.fail(invalid(operation))
|
|
318
|
-
}
|
|
319
|
-
const runtime = yield* runtimeHandle()
|
|
320
|
-
const closeOp = `${operation}.repositoryLock`
|
|
321
|
-
return yield* Effect.uninterruptibleMask((restore) =>
|
|
322
|
-
Effect.gen(function* () {
|
|
323
|
-
const slot: { owner: RepositoryLockHandle | undefined } = { owner: undefined }
|
|
324
|
-
const release = Effect.suspend(() => {
|
|
325
|
-
const held = slot.owner
|
|
326
|
-
if (held === undefined) {
|
|
327
|
-
return Effect.void
|
|
328
|
-
}
|
|
329
|
-
return joinLockRelease(closeOp, held).pipe(
|
|
330
|
-
Effect.ensuring(
|
|
331
|
-
Effect.sync(() => {
|
|
332
|
-
slot.owner = undefined
|
|
333
|
-
})
|
|
334
|
-
)
|
|
335
|
-
)
|
|
336
|
-
})
|
|
337
|
-
yield* Effect.addFinalizer(() => release)
|
|
338
|
-
const owner = yield* restore(
|
|
339
|
-
nativeOperationWith(
|
|
340
|
-
operation,
|
|
341
|
-
(callback) => runtimeNative.logRepositoryLockAcquire(runtime, directory, callback),
|
|
342
|
-
runtimeNative.logRepositoryLockTake,
|
|
343
|
-
(value) => value
|
|
344
|
-
)
|
|
345
|
-
)
|
|
346
|
-
slot.owner = owner
|
|
347
|
-
return Object.freeze({
|
|
348
|
-
directory,
|
|
349
|
-
release
|
|
350
|
-
})
|
|
351
|
-
})
|
|
352
|
-
)
|
|
353
|
-
})
|
|
354
|
-
|
|
355
|
-
/** Internal first executor consumer; not a replacement row codec or public hash API. */
|
|
356
|
-
export const hashChunk = Effect.fn("bumbledb.hashChunk")(function* (input: Uint8Array) {
|
|
357
|
-
const runtime = yield* NativeRuntime
|
|
358
|
-
const handle = owners.get(runtime)
|
|
359
|
-
if (handle === undefined) return yield* Effect.fail(invalid("hashChunk"))
|
|
360
|
-
return yield* nativeOperation(
|
|
361
|
-
"hashChunk",
|
|
362
|
-
(callback) => {
|
|
363
|
-
if (!(input instanceof Uint8Array) || !(input.buffer instanceof ArrayBuffer)) throw invalid("hashChunk")
|
|
364
|
-
return runtimeNative.runtimeHash(handle, input, callback)
|
|
365
|
-
},
|
|
366
|
-
(value) => {
|
|
367
|
-
if (value === null) throw dbError("hashChunk", { _tag: "Internal" })
|
|
368
|
-
return value
|
|
369
|
-
}
|
|
370
|
-
)
|
|
72
|
+
/** The provided runtime's native handle. */
|
|
73
|
+
export const runtimeHandle: Effect.Effect<RuntimeRef, never, Bumble> = Effect.gen(function* () {
|
|
74
|
+
return Runtime.handle(yield* Bumble)
|
|
371
75
|
})
|