keri-ts 2.0.0 → 2.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/esm/keri/npm/src/acdc/chaining.js +223 -89
- package/esm/keri/npm/src/acdc/observing.js +2 -2
- package/esm/keri/npm/src/acdc/regbasing.js +20 -29
- package/esm/keri/npm/src/acdc/regengine.js +4 -6
- package/esm/keri/npm/src/acdc/registering.js +13 -10
- package/esm/keri/npm/src/acdc/registraring.js +4 -9
- package/esm/keri/npm/src/acdc/salting.js +127 -25
- package/esm/keri/npm/src/acdc/unblinding.js +2 -4
- package/esm/keri/npm/src/app/bootstrap/oobiery.js +1 -1
- package/esm/keri/npm/src/app/credentials/root-replicating.js +123 -0
- package/esm/keri/npm/src/app/credentials/verifying.js +21 -3
- package/esm/keri/npm/src/app/delivery/forwarding.js +49 -7
- package/esm/keri/npm/src/app/exchanges/exchanging.js +11 -12
- package/esm/keri/npm/src/app/identity/configing.js +17 -43
- package/esm/keri/npm/src/app/identity/habbing.js +54 -35
- package/esm/keri/npm/src/app/identity/keeping.js +1 -1
- package/esm/keri/npm/src/app/identity/lmdb-habery.js +12 -0
- package/esm/keri/npm/src/app/ipex/ipex-graph.js +7 -70
- package/esm/keri/npm/src/app/ipex/ipex-grouping.js +8 -5
- package/esm/keri/npm/src/app/ipex/ipex-v2.js +21 -5
- package/esm/keri/npm/src/app/ipex/ipexing.js +1 -1
- package/esm/keri/npm/src/app/mailbox/mailboxing.js +5 -9
- package/esm/keri/npm/src/app/multisig/group-members.js +14 -0
- package/esm/keri/npm/src/app/multisig/grouping.js +4 -3
- package/esm/keri/npm/src/app/multisig/multisig-workflows.js +7 -2
- package/esm/keri/npm/src/app/notifications/notifying.js +5 -9
- package/esm/keri/npm/src/app/protocol/protocol-processing.js +35 -3
- package/esm/keri/npm/src/app/queries/witness-inquisitor.js +2 -2
- package/esm/keri/npm/src/app/runtime/agent-runtime.js +7 -10
- package/esm/keri/npm/src/app/transport/byte-source.js +6 -42
- package/esm/keri/npm/src/app/transport/cesr-egress.js +77 -13
- package/esm/keri/npm/src/app/transport/file-bytes.js +41 -0
- package/esm/keri/npm/src/app/transport/http-messenger.js +14 -9
- package/esm/keri/npm/src/app/transport/message-source.js +1 -1
- package/esm/keri/npm/src/app/transport/messengering.js +3 -4
- package/esm/keri/npm/src/app/transport/node-http-client.js +21 -0
- package/esm/keri/npm/src/app/transport/tcp-dialer.js +14 -0
- package/esm/keri/npm/src/app/witness/receipt-client.js +2 -2
- package/esm/keri/npm/src/cli/common/context.js +2 -2
- package/esm/keri/npm/src/cli/common/existing.js +3 -5
- package/esm/keri/npm/src/cli/credentials/ipex.js +2 -1
- package/esm/keri/npm/src/cli/endpoints/oobi-clean.js +4 -3
- package/esm/keri/npm/src/cli/endpoints/oobi.js +2 -2
- package/esm/keri/npm/src/cli/identity/challenge.js +2 -2
- package/esm/keri/npm/src/cli/identity/incept.js +2 -2
- package/esm/keri/npm/src/cli/identity/init.js +4 -3
- package/esm/keri/npm/src/cli/identity/interact.js +2 -2
- package/esm/keri/npm/src/cli/identity/rotate.js +2 -2
- package/esm/keri/npm/src/cli/messaging/exchange.js +2 -2
- package/esm/keri/npm/src/cli/messaging/multisig.js +61 -3
- package/esm/keri/npm/src/cli/tools/annotate.js +2 -1
- package/esm/keri/npm/src/cli/tools/benchmark.js +2 -1
- package/esm/keri/npm/src/cli/tools/db-dump.js +1 -4
- package/esm/keri/npm/src/core/bytes.js +9 -0
- package/esm/keri/npm/src/core/kel/delegation-ancestry.js +92 -0
- package/esm/keri/npm/src/core/kel/eventing.js +1 -2
- package/esm/keri/npm/src/core/kel/kever.js +11 -9
- package/esm/keri/npm/src/core/mailbox/kram-policy.js +2 -3
- package/esm/keri/npm/src/core/mailbox/kram-pruning.js +15 -22
- package/esm/keri/npm/src/core/mailbox/kram-staging.js +2 -2
- package/esm/keri/npm/src/core/routing.js +2 -2
- package/esm/keri/npm/src/db/basing.js +149 -203
- package/esm/keri/npm/src/db/core/dber.js +1062 -0
- package/esm/keri/npm/src/db/core/index.js +4 -2
- package/esm/keri/npm/src/db/core/lmdb-opener.js +30 -0
- package/esm/keri/npm/src/db/core/lmdber.js +199 -1067
- package/esm/keri/npm/src/db/core/memstore.js +532 -0
- package/esm/keri/npm/src/db/core/path-manager.js +109 -223
- package/esm/keri/npm/src/db/core/store-owner.js +104 -0
- package/esm/keri/npm/src/db/core/webdber.js +252 -0
- package/esm/keri/npm/src/db/escrowing.js +2 -2
- package/esm/keri/npm/src/db/exchange/exchange-nests.js +3 -2
- package/esm/keri/npm/src/db/keeping.js +27 -121
- package/esm/keri/npm/src/db/koming.js +1 -1
- package/esm/keri/npm/src/db/lmdb-stores.js +68 -0
- package/esm/keri/npm/src/db/lmdb.js +6 -0
- package/esm/keri/npm/src/db/mailbox/mailboxing.js +12 -65
- package/esm/keri/npm/src/db/noting.js +11 -55
- package/esm/keri/npm/src/db/reger.js +43 -105
- package/esm/keri/npm/src/db/replay/witness-replay.js +2 -20
- package/esm/keri/npm/src/db/subing.js +1 -1
- package/esm/keri/npm/src/npm/db-lmdb.js +3 -0
- package/esm/keri/npm/src/npm/runtime-node.js +3 -0
- package/esm/keri/npm/src/runtime/index.js +9 -10
- package/esm/keri/npm/src/runtime/node.js +14 -0
- package/esm/keri/npm/src/vdr/eventing.js +1 -1
- package/esm/keri/npm/src/vdr/tel-publication.js +3 -3
- package/esm/keri/npm/src/version.js +2 -2
- package/package.json +11 -4
- package/types/acdc/chaining.d.ts +56 -6
- package/types/acdc/chaining.d.ts.map +1 -1
- package/types/acdc/regbasing.d.ts +7 -6
- package/types/acdc/regbasing.d.ts.map +1 -1
- package/types/acdc/regengine.d.ts.map +1 -1
- package/types/acdc/registering.d.ts +8 -4
- package/types/acdc/registering.d.ts.map +1 -1
- package/types/acdc/registraring.d.ts.map +1 -1
- package/types/acdc/salting.d.ts +53 -6
- package/types/acdc/salting.d.ts.map +1 -1
- package/types/acdc/unblinding.d.ts.map +1 -1
- package/types/app/credentials/root-replicating.d.ts +85 -0
- package/types/app/credentials/root-replicating.d.ts.map +1 -0
- package/types/app/credentials/verifying.d.ts +2 -1
- package/types/app/credentials/verifying.d.ts.map +1 -1
- package/types/app/delivery/forwarding.d.ts +10 -0
- package/types/app/delivery/forwarding.d.ts.map +1 -1
- package/types/app/exchanges/exchanging.d.ts +2 -0
- package/types/app/exchanges/exchanging.d.ts.map +1 -1
- package/types/app/identity/configing.d.ts +7 -5
- package/types/app/identity/configing.d.ts.map +1 -1
- package/types/app/identity/habbing.d.ts +23 -5
- package/types/app/identity/habbing.d.ts.map +1 -1
- package/types/app/identity/keeping.d.ts +1 -1
- package/types/app/identity/lmdb-habery.d.ts +6 -0
- package/types/app/identity/lmdb-habery.d.ts.map +1 -0
- package/types/app/ipex/ipex-graph.d.ts +4 -4
- package/types/app/ipex/ipex-graph.d.ts.map +1 -1
- package/types/app/ipex/ipex-grouping.d.ts.map +1 -1
- package/types/app/ipex/ipex-v2.d.ts +11 -2
- package/types/app/ipex/ipex-v2.d.ts.map +1 -1
- package/types/app/ipex/ipexing.d.ts +3 -0
- package/types/app/ipex/ipexing.d.ts.map +1 -1
- package/types/app/mailbox/mailboxing.d.ts +1 -1
- package/types/app/mailbox/mailboxing.d.ts.map +1 -1
- package/types/app/multisig/group-members.d.ts +9 -0
- package/types/app/multisig/group-members.d.ts.map +1 -1
- package/types/app/multisig/grouping.d.ts.map +1 -1
- package/types/app/multisig/multisig-workflows.d.ts +2 -1
- package/types/app/multisig/multisig-workflows.d.ts.map +1 -1
- package/types/app/notifications/notifying.d.ts +1 -1
- package/types/app/notifications/notifying.d.ts.map +1 -1
- package/types/app/protocol/parsering.d.ts +3 -1
- package/types/app/protocol/parsering.d.ts.map +1 -1
- package/types/app/protocol/protocol-processing.d.ts +2 -0
- package/types/app/protocol/protocol-processing.d.ts.map +1 -1
- package/types/app/runtime/agent-runtime.d.ts +7 -0
- package/types/app/runtime/agent-runtime.d.ts.map +1 -1
- package/types/app/transport/byte-source.d.ts +13 -10
- package/types/app/transport/byte-source.d.ts.map +1 -1
- package/types/app/transport/cesr-egress.d.ts +21 -7
- package/types/app/transport/cesr-egress.d.ts.map +1 -1
- package/types/app/transport/file-bytes.d.ts +11 -0
- package/types/app/transport/file-bytes.d.ts.map +1 -0
- package/types/app/transport/http-client.d.ts +3 -0
- package/types/app/transport/http-client.d.ts.map +1 -1
- package/types/app/transport/http-messenger.d.ts +15 -10
- package/types/app/transport/http-messenger.d.ts.map +1 -1
- package/types/app/transport/message-source.d.ts +1 -1
- package/types/app/transport/messengering.d.ts +2 -2
- package/types/app/transport/messengering.d.ts.map +1 -1
- package/types/app/transport/node-http-client.d.ts +10 -0
- package/types/app/transport/node-http-client.d.ts.map +1 -0
- package/types/app/transport/tcp-dialer.d.ts +21 -0
- package/types/app/transport/tcp-dialer.d.ts.map +1 -0
- package/types/cli/common/existing.d.ts.map +1 -1
- package/types/cli/credentials/ipex.d.ts.map +1 -1
- package/types/cli/endpoints/oobi-clean.d.ts.map +1 -1
- package/types/cli/identity/init.d.ts.map +1 -1
- package/types/cli/index.d.ts +1 -1
- package/types/cli/index.d.ts.map +1 -1
- package/types/cli/messaging/multisig.d.ts +10 -1
- package/types/cli/messaging/multisig.d.ts.map +1 -1
- package/types/cli/tools/annotate.d.ts.map +1 -1
- package/types/cli/tools/benchmark.d.ts.map +1 -1
- package/types/cli/tools/db-dump.d.ts.map +1 -1
- package/types/core/bytes.d.ts +2 -0
- package/types/core/bytes.d.ts.map +1 -1
- package/types/core/kel/delegation-ancestry.d.ts +41 -0
- package/types/core/kel/delegation-ancestry.d.ts.map +1 -0
- package/types/core/kel/eventing.d.ts.map +1 -1
- package/types/core/kel/kever.d.ts +5 -4
- package/types/core/kel/kever.d.ts.map +1 -1
- package/types/core/mailbox/kram-policy.d.ts.map +1 -1
- package/types/core/mailbox/kram-pruning.d.ts +1 -3
- package/types/core/mailbox/kram-pruning.d.ts.map +1 -1
- package/types/db/basing.d.ts +14 -23
- package/types/db/basing.d.ts.map +1 -1
- package/types/db/core/dber.d.ts +505 -0
- package/types/db/core/dber.d.ts.map +1 -0
- package/types/db/core/index.d.ts +4 -2
- package/types/db/core/index.d.ts.map +1 -1
- package/types/db/core/lmdb-opener.d.ts +17 -0
- package/types/db/core/lmdb-opener.d.ts.map +1 -0
- package/types/db/core/lmdber.d.ts +60 -383
- package/types/db/core/lmdber.d.ts.map +1 -1
- package/types/db/core/memstore.d.ts +129 -0
- package/types/db/core/memstore.d.ts.map +1 -0
- package/types/db/core/path-manager.d.ts +22 -45
- package/types/db/core/path-manager.d.ts.map +1 -1
- package/types/db/core/store-owner.d.ts +59 -0
- package/types/db/core/store-owner.d.ts.map +1 -0
- package/types/db/core/webdber.d.ts +127 -0
- package/types/db/core/webdber.d.ts.map +1 -0
- package/types/db/escrowing.d.ts +3 -3
- package/types/db/escrowing.d.ts.map +1 -1
- package/types/db/exchange/exchange-nests.d.ts.map +1 -1
- package/types/db/keeping.d.ts +9 -23
- package/types/db/keeping.d.ts.map +1 -1
- package/types/db/koming.d.ts +7 -8
- package/types/db/koming.d.ts.map +1 -1
- package/types/db/lmdb-stores.d.ts +45 -0
- package/types/db/lmdb-stores.d.ts.map +1 -0
- package/types/db/lmdb.d.ts +7 -0
- package/types/db/lmdb.d.ts.map +1 -0
- package/types/db/mailbox/mailboxing.d.ts +7 -21
- package/types/db/mailbox/mailboxing.d.ts.map +1 -1
- package/types/db/noting.d.ts +7 -12
- package/types/db/noting.d.ts.map +1 -1
- package/types/db/reger.d.ts +7 -11
- package/types/db/reger.d.ts.map +1 -1
- package/types/db/replay/witness-replay.d.ts +0 -2
- package/types/db/replay/witness-replay.d.ts.map +1 -1
- package/types/db/subing.d.ts +24 -25
- package/types/db/subing.d.ts.map +1 -1
- package/types/npm/db-lmdb.d.ts +4 -0
- package/types/npm/db-lmdb.d.ts.map +1 -0
- package/types/npm/runtime-node.d.ts +4 -0
- package/types/npm/runtime-node.d.ts.map +1 -0
- package/types/runtime/index.d.ts +9 -10
- package/types/runtime/index.d.ts.map +1 -1
- package/types/runtime/node.d.ts +15 -0
- package/types/runtime/node.d.ts.map +1 -0
- package/types/version.d.ts +2 -2
- package/esm/keri/npm/src/acdc/relating.js +0 -59
- package/esm/keri/npm/src/db/baser-defaults.js +0 -11
- package/types/acdc/relating.d.ts +0 -21
- package/types/acdc/relating.d.ts.map +0 -1
- package/types/db/baser-defaults.d.ts +0 -5
- package/types/db/baser-defaults.d.ts.map +0 -1
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser-capable `DBer`: a `MemStore` mirror with write-behind persistence.
|
|
3
|
+
*
|
|
4
|
+
* ADR-0015 owns the durability model. Reads and writes are synchronous against
|
|
5
|
+
* the mirror; each outermost commit enqueues one batch holding its net effect,
|
|
6
|
+
* and a queue shared by a composition applies batches one at a time in global
|
|
7
|
+
* commit order. Nothing here may reach `lmdb`, `node:` or the `Deno` global.
|
|
8
|
+
*
|
|
9
|
+
* Invariant: once the queue is joined with no failure, the mirror and the
|
|
10
|
+
* persisted rows are byte-identical, which is why `reopen` joins before it loads.
|
|
11
|
+
*/
|
|
12
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
13
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
14
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
15
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
16
|
+
};
|
|
17
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
18
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
19
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
20
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
21
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
22
|
+
};
|
|
23
|
+
var _PersistenceQueue_instances, _PersistenceQueue_tail, _PersistenceQueue_failure, _PersistenceQueue_append, _PersistenceQueue_settled, _WebDBer_instances, _WebDBer_persistence, _WebDBer_queue, _WebDBer_pendingTables, _WebDBer_connected, _WebDBer_enqueue, _WebDBer_takePendingTables, _WebDBer_carryPendingTables;
|
|
24
|
+
import { bytesEqual, bytesHex } from "cesr-ts";
|
|
25
|
+
import { call, ensure } from "effection";
|
|
26
|
+
import { DatabaseOperationError } from "../../core/errors.js";
|
|
27
|
+
import { MemStore } from "./memstore.js";
|
|
28
|
+
/**
|
|
29
|
+
* The persistence order of one composition. Tasks run strictly one at a time,
|
|
30
|
+
* outside any Effection scope, so cancelling a waiter never cancels a write.
|
|
31
|
+
*
|
|
32
|
+
* The first failure latches: every later task is skipped, because applying a
|
|
33
|
+
* later batch over a lost earlier one would break prefix durability.
|
|
34
|
+
*/
|
|
35
|
+
export class PersistenceQueue {
|
|
36
|
+
constructor() {
|
|
37
|
+
_PersistenceQueue_instances.add(this);
|
|
38
|
+
_PersistenceQueue_tail.set(this, Promise.resolve());
|
|
39
|
+
_PersistenceQueue_failure.set(this, null);
|
|
40
|
+
}
|
|
41
|
+
/** Append a task, which is skipped if an earlier one failed. */
|
|
42
|
+
enqueue(task) {
|
|
43
|
+
__classPrivateFieldGet(this, _PersistenceQueue_instances, "m", _PersistenceQueue_append).call(this, task, false);
|
|
44
|
+
}
|
|
45
|
+
/** Append connection teardown, which still runs after a failure so a handle is not left open. */
|
|
46
|
+
release(task) {
|
|
47
|
+
__classPrivateFieldGet(this, _PersistenceQueue_instances, "m", _PersistenceQueue_append).call(this, task, true);
|
|
48
|
+
}
|
|
49
|
+
/** Refuse new work once latched. The original failure is the cause. */
|
|
50
|
+
assertHealthy() {
|
|
51
|
+
if (__classPrivateFieldGet(this, _PersistenceQueue_failure, "f")) {
|
|
52
|
+
throw new DatabaseOperationError("Persistence failed; this composition accepts no more commits", {
|
|
53
|
+
cause: __classPrivateFieldGet(this, _PersistenceQueue_failure, "f").error,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/** Wait until everything enqueued before this call is durable. Halting cancels only the wait. */
|
|
58
|
+
*flushed() {
|
|
59
|
+
const settled = __classPrivateFieldGet(this, _PersistenceQueue_instances, "m", _PersistenceQueue_settled).call(this);
|
|
60
|
+
yield* call(() => settled);
|
|
61
|
+
}
|
|
62
|
+
/** Like `flushed`, but a halted caller still waits for the queue and still reports its failure. */
|
|
63
|
+
*joined() {
|
|
64
|
+
const settled = __classPrivateFieldGet(this, _PersistenceQueue_instances, "m", _PersistenceQueue_settled).call(this);
|
|
65
|
+
yield* call(function* () {
|
|
66
|
+
yield* ensure(() => call(() => settled));
|
|
67
|
+
yield* call(() => settled);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
_PersistenceQueue_tail = new WeakMap(), _PersistenceQueue_failure = new WeakMap(), _PersistenceQueue_instances = new WeakSet(), _PersistenceQueue_append = function _PersistenceQueue_append(task, always) {
|
|
72
|
+
__classPrivateFieldSet(this, _PersistenceQueue_tail, __classPrivateFieldGet(this, _PersistenceQueue_tail, "f").then(async () => {
|
|
73
|
+
if (__classPrivateFieldGet(this, _PersistenceQueue_failure, "f") && !always)
|
|
74
|
+
return;
|
|
75
|
+
try {
|
|
76
|
+
await task();
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
__classPrivateFieldSet(this, _PersistenceQueue_failure, __classPrivateFieldGet(this, _PersistenceQueue_failure, "f") ?? { error }, "f");
|
|
80
|
+
}
|
|
81
|
+
}), "f");
|
|
82
|
+
}, _PersistenceQueue_settled = function _PersistenceQueue_settled() {
|
|
83
|
+
return __classPrivateFieldGet(this, _PersistenceQueue_tail, "f").then(() => {
|
|
84
|
+
if (__classPrivateFieldGet(this, _PersistenceQueue_failure, "f"))
|
|
85
|
+
throw __classPrivateFieldGet(this, _PersistenceQueue_failure, "f").error;
|
|
86
|
+
});
|
|
87
|
+
};
|
|
88
|
+
function sameValue(a, c) {
|
|
89
|
+
return a === null || c === null ? a === c : bytesEqual(a, c);
|
|
90
|
+
}
|
|
91
|
+
/** Collapse a commit's writes to the first prior and latest state of each row identity. */
|
|
92
|
+
function netRows(changes) {
|
|
93
|
+
const net = new Map();
|
|
94
|
+
for (const change of changes) {
|
|
95
|
+
if (change.kind !== "row")
|
|
96
|
+
continue;
|
|
97
|
+
const duplicate = change.dupsort ? bytesHex((change.before ?? change.after)) : "";
|
|
98
|
+
const identity = `${bytesHex(change.key)}/${duplicate}/${change.table}`;
|
|
99
|
+
const seen = net.get(identity);
|
|
100
|
+
if (seen) {
|
|
101
|
+
seen.after = change.after;
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
net.set(identity, { ...change });
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return [...net.values()].filter((row) => !sameValue(row.before, row.after));
|
|
108
|
+
}
|
|
109
|
+
/** The version a commit leaves behind, or `undefined` when it ends where it began. */
|
|
110
|
+
function netVersion(changes) {
|
|
111
|
+
const versions = changes.filter((change) => change.kind === "version");
|
|
112
|
+
const first = versions.at(0);
|
|
113
|
+
const last = versions.at(-1);
|
|
114
|
+
return first && last && first.before !== last.after ? last.after : undefined;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* `MemStore` mirror whose commits persist through a `Persistence` adapter.
|
|
118
|
+
*
|
|
119
|
+
* After the queue latches, a commit already in the mirror stays there and stays
|
|
120
|
+
* readable even though it was never persisted, and every later transaction
|
|
121
|
+
* throws before touching the mirror, so the mirror stops changing. The durable
|
|
122
|
+
* state is a prefix of the commit sequence. Recovery is a new composition, with
|
|
123
|
+
* a new queue, loading that prefix; there is no retry.
|
|
124
|
+
*/
|
|
125
|
+
export class WebDBer extends MemStore {
|
|
126
|
+
constructor(options, persistence, queue) {
|
|
127
|
+
super(options);
|
|
128
|
+
_WebDBer_instances.add(this);
|
|
129
|
+
_WebDBer_persistence.set(this, void 0);
|
|
130
|
+
_WebDBer_queue.set(this, void 0);
|
|
131
|
+
/** Tables not yet carried by a batch, so an unwritten table still persists its dupsort flag. */
|
|
132
|
+
_WebDBer_pendingTables.set(this, new Map());
|
|
133
|
+
_WebDBer_connected.set(this, false);
|
|
134
|
+
__classPrivateFieldSet(this, _WebDBer_persistence, persistence, "f");
|
|
135
|
+
__classPrivateFieldSet(this, _WebDBer_queue, queue, "f");
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Join the queue, then bulk-load every persisted table before returning, so
|
|
139
|
+
* reads never suspend. A latched queue refuses, reporting its failure.
|
|
140
|
+
*/
|
|
141
|
+
*reopen(options = {}) {
|
|
142
|
+
yield* this.close(options.clear ?? false);
|
|
143
|
+
const persistence = __classPrivateFieldGet(this, _WebDBer_persistence, "f");
|
|
144
|
+
__classPrivateFieldSet(this, _WebDBer_connected, true, "f");
|
|
145
|
+
const meta = yield* call(() => persistence.meta());
|
|
146
|
+
const tables = [];
|
|
147
|
+
for (const { name, dupsort } of meta.tables) {
|
|
148
|
+
tables.push({ name, dupsort, rows: yield* call(() => persistence.load(name)) });
|
|
149
|
+
}
|
|
150
|
+
this.loadContents(tables, meta.version);
|
|
151
|
+
return yield* super.reopen(options);
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Stop accepting work, drain and join the queue even when cancelled, and
|
|
155
|
+
* report any failure. A latched store is neither cleared nor reusable, and
|
|
156
|
+
* every later close reports the same failure.
|
|
157
|
+
*/
|
|
158
|
+
*close(clear = false) {
|
|
159
|
+
if (clear) {
|
|
160
|
+
__classPrivateFieldGet(this, _WebDBer_pendingTables, "f").clear();
|
|
161
|
+
}
|
|
162
|
+
else if (this.opened && !this.readonly) {
|
|
163
|
+
__classPrivateFieldGet(this, _WebDBer_instances, "m", _WebDBer_carryPendingTables).call(this);
|
|
164
|
+
}
|
|
165
|
+
yield* super.close();
|
|
166
|
+
const persistence = __classPrivateFieldGet(this, _WebDBer_persistence, "f");
|
|
167
|
+
if (__classPrivateFieldGet(this, _WebDBer_connected, "f")) {
|
|
168
|
+
__classPrivateFieldSet(this, _WebDBer_connected, false, "f");
|
|
169
|
+
__classPrivateFieldGet(this, _WebDBer_queue, "f").release(() => persistence.close());
|
|
170
|
+
}
|
|
171
|
+
if (clear)
|
|
172
|
+
__classPrivateFieldGet(this, _WebDBer_queue, "f").enqueue(() => persistence.clear());
|
|
173
|
+
yield* __classPrivateFieldGet(this, _WebDBer_queue, "f").joined();
|
|
174
|
+
if (clear)
|
|
175
|
+
yield* super.close(true);
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
/** Bind a table; a new one is physically created by the batch that first carries it. */
|
|
179
|
+
openTable(name, options = {}) {
|
|
180
|
+
if (this.readonly || !this.opened || !name || this.hasTable(name))
|
|
181
|
+
return super.openTable(name, options);
|
|
182
|
+
__classPrivateFieldGet(this, _WebDBer_queue, "f").assertHealthy();
|
|
183
|
+
const table = super.openTable(name, options);
|
|
184
|
+
__classPrivateFieldGet(this, _WebDBer_pendingTables, "f").set(name, options.dupsort ?? false);
|
|
185
|
+
return table;
|
|
186
|
+
}
|
|
187
|
+
transaction(fn) {
|
|
188
|
+
this.assertOpen();
|
|
189
|
+
__classPrivateFieldGet(this, _WebDBer_queue, "f").assertHealthy();
|
|
190
|
+
return super.transaction(fn);
|
|
191
|
+
}
|
|
192
|
+
/** Completes when every earlier commit in this composition is durable, or fails with its recorded failure. */
|
|
193
|
+
*flushed() {
|
|
194
|
+
this.assertOpen();
|
|
195
|
+
if (!this.readonly)
|
|
196
|
+
__classPrivateFieldGet(this, _WebDBer_instances, "m", _WebDBer_carryPendingTables).call(this);
|
|
197
|
+
yield* __classPrivateFieldGet(this, _WebDBer_queue, "f").flushed();
|
|
198
|
+
}
|
|
199
|
+
committed(changes) {
|
|
200
|
+
const rows = netRows(changes);
|
|
201
|
+
const version = netVersion(changes);
|
|
202
|
+
if (rows.length === 0 && version === undefined)
|
|
203
|
+
return;
|
|
204
|
+
const copy = (bytes) => new Uint8Array(bytes);
|
|
205
|
+
__classPrivateFieldGet(this, _WebDBer_instances, "m", _WebDBer_enqueue).call(this, {
|
|
206
|
+
tables: __classPrivateFieldGet(this, _WebDBer_instances, "m", _WebDBer_takePendingTables).call(this),
|
|
207
|
+
...(version === undefined ? {} : { version }),
|
|
208
|
+
puts: rows.filter(({ after }) => after !== null).map(({ table, key, after }) => ({
|
|
209
|
+
table,
|
|
210
|
+
key: copy(key),
|
|
211
|
+
value: copy(after),
|
|
212
|
+
})),
|
|
213
|
+
deletes: rows.filter(({ after }) => after === null).map(({ table, dupsort, key, before }) => ({
|
|
214
|
+
table,
|
|
215
|
+
key: copy(key),
|
|
216
|
+
...(dupsort ? { value: copy(before) } : {}),
|
|
217
|
+
})),
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
_WebDBer_persistence = new WeakMap(), _WebDBer_queue = new WeakMap(), _WebDBer_pendingTables = new WeakMap(), _WebDBer_connected = new WeakMap(), _WebDBer_instances = new WeakSet(), _WebDBer_enqueue = function _WebDBer_enqueue(batch) {
|
|
222
|
+
const persistence = __classPrivateFieldGet(this, _WebDBer_persistence, "f");
|
|
223
|
+
__classPrivateFieldGet(this, _WebDBer_queue, "f").enqueue(() => persistence.write(batch));
|
|
224
|
+
}, _WebDBer_takePendingTables = function _WebDBer_takePendingTables() {
|
|
225
|
+
const tables = [...__classPrivateFieldGet(this, _WebDBer_pendingTables, "f")].filter(([name]) => this.hasTable(name));
|
|
226
|
+
__classPrivateFieldGet(this, _WebDBer_pendingTables, "f").clear();
|
|
227
|
+
return tables.map(([name, dupsort]) => ({ name, dupsort }));
|
|
228
|
+
}, _WebDBer_carryPendingTables = function _WebDBer_carryPendingTables() {
|
|
229
|
+
const tables = __classPrivateFieldGet(this, _WebDBer_instances, "m", _WebDBer_takePendingTables).call(this);
|
|
230
|
+
if (tables.length > 0)
|
|
231
|
+
__classPrivateFieldGet(this, _WebDBer_instances, "m", _WebDBer_enqueue).call(this, { tables, puts: [], deletes: [] });
|
|
232
|
+
};
|
|
233
|
+
/** A `StoreOpener` of `WebDBer`s bound to one queue, which is what makes a composition one commit order. */
|
|
234
|
+
export class WebStoreOpener {
|
|
235
|
+
constructor(persistenceFor) {
|
|
236
|
+
Object.defineProperty(this, "persistenceFor", {
|
|
237
|
+
enumerable: true,
|
|
238
|
+
configurable: true,
|
|
239
|
+
writable: true,
|
|
240
|
+
value: persistenceFor
|
|
241
|
+
});
|
|
242
|
+
Object.defineProperty(this, "queue", {
|
|
243
|
+
enumerable: true,
|
|
244
|
+
configurable: true,
|
|
245
|
+
writable: true,
|
|
246
|
+
value: new PersistenceQueue()
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
create(family, identity) {
|
|
250
|
+
return new WebDBer(identity, this.persistenceFor(family, identity), this.queue);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
@@ -155,7 +155,7 @@ export class Broker {
|
|
|
155
155
|
if (!scan) {
|
|
156
156
|
const start = encode(`${typ}.`), ceiling = encode(`${typ}/`);
|
|
157
157
|
let tail;
|
|
158
|
-
for (const key of this.escrowdb.sdb
|
|
158
|
+
for (const key of this.db.scanKeys(this.escrowdb.sdb, { start: ceiling, end: start, reverse: true, limit: 1 })) {
|
|
159
159
|
tail = key.slice();
|
|
160
160
|
}
|
|
161
161
|
if (!tail)
|
|
@@ -164,7 +164,7 @@ export class Broker {
|
|
|
164
164
|
this.retryScans.set(typ, scan);
|
|
165
165
|
}
|
|
166
166
|
const rows = [];
|
|
167
|
-
for (const key of this.escrowdb.sdb
|
|
167
|
+
for (const key of this.db.scanKeys(this.escrowdb.sdb, { start: scan.start, end: scan.end, limit: maxRows })) {
|
|
168
168
|
rows.push(key.slice());
|
|
169
169
|
}
|
|
170
170
|
for (const key of rows) {
|
|
@@ -3,7 +3,7 @@ import { b, collectPayload, concatBytes, Counter, nestedPayload, parseBytes, t,
|
|
|
3
3
|
import { suffix, unsuffix } from "../core/keys.js";
|
|
4
4
|
/** Read one physical row and close the LMDB key cursor before any caller suspension. */
|
|
5
5
|
function nextRow(db, table, said, ordinal) {
|
|
6
|
-
for (const key of table.sdb
|
|
6
|
+
for (const key of db.scanKeys(table.sdb, { start: suffix(b(said), ordinal) })) {
|
|
7
7
|
const [owner, index] = unsuffix(key);
|
|
8
8
|
if (t(owner) !== said)
|
|
9
9
|
return null;
|
|
@@ -16,8 +16,9 @@ function nextRow(db, table, said, ordinal) {
|
|
|
16
16
|
}
|
|
17
17
|
/** Test row presence without hydrating a potentially large wire value. */
|
|
18
18
|
export function hasNests(db, said, ordinal = 0) {
|
|
19
|
-
for (const key of db.enst.sdb
|
|
19
|
+
for (const key of db.scanKeys(db.enst.sdb, { start: suffix(b(said), ordinal) })) {
|
|
20
20
|
return t(unsuffix(key)[0]) === said;
|
|
21
|
+
}
|
|
21
22
|
return false;
|
|
22
23
|
}
|
|
23
24
|
/** Serialize resident children before the caller enters its synchronous evidence writer. */
|
|
@@ -2,7 +2,7 @@ import { Cipher, MtrDex, NumberPrimitive, Prefixer, Salter, Signer, Verfer, } fr
|
|
|
2
2
|
import { DatabaseNotOpenError, DatabaseOperationError } from "../core/errors.js";
|
|
3
3
|
import { consoleLogger } from "../core/logger.js";
|
|
4
4
|
import { RawRecord } from "../core/records.js";
|
|
5
|
-
import {
|
|
5
|
+
import { StoreOwner } from "./core/store-owner.js";
|
|
6
6
|
import { Komer } from "./koming.js";
|
|
7
7
|
import { CatCesrIoSetSuber, CesrSuber, CryptSignerSuber, Suber } from "./subing.js";
|
|
8
8
|
/**
|
|
@@ -101,14 +101,9 @@ function reencryptSalt(salt, encrypter, decrypter) {
|
|
|
101
101
|
* named handles
|
|
102
102
|
* - compatibility mode supports KERIpy `.keri/ks` layout visibility
|
|
103
103
|
*/
|
|
104
|
-
export class Keeper {
|
|
105
|
-
constructor(
|
|
106
|
-
|
|
107
|
-
enumerable: true,
|
|
108
|
-
configurable: true,
|
|
109
|
-
writable: true,
|
|
110
|
-
value: void 0
|
|
111
|
-
});
|
|
104
|
+
export class Keeper extends StoreOwner {
|
|
105
|
+
constructor(store, logger = consoleLogger) {
|
|
106
|
+
super(store);
|
|
112
107
|
Object.defineProperty(this, "logger", {
|
|
113
108
|
enumerable: true,
|
|
114
109
|
configurable: true,
|
|
@@ -192,42 +187,7 @@ export class Keeper {
|
|
|
192
187
|
writable: true,
|
|
193
188
|
value: void 0
|
|
194
189
|
});
|
|
195
|
-
this.logger =
|
|
196
|
-
const compat = options.compat ?? false;
|
|
197
|
-
this.lmdber = new LMDBer(options, {
|
|
198
|
-
tailDirPath: Keeper.TailDirPath,
|
|
199
|
-
cleanTailDirPath: "keri/clean/ks",
|
|
200
|
-
altTailDirPath: compat
|
|
201
|
-
? Keeper.CompatAltTailDirPath
|
|
202
|
-
: Keeper.AltTailDirPath,
|
|
203
|
-
altCleanTailDirPath: compat ? ".keri/clean/ks" : ".tufa/clean/ks",
|
|
204
|
-
tempPrefix: Keeper.TempPrefix,
|
|
205
|
-
maxNamedDBs: Keeper.MaxNamedDBs,
|
|
206
|
-
});
|
|
207
|
-
}
|
|
208
|
-
/** Expose the resolved keeper database name delegated from the root LMDBer. */
|
|
209
|
-
get name() {
|
|
210
|
-
return this.lmdber.name;
|
|
211
|
-
}
|
|
212
|
-
/** Expose the resolved keeper base prefix delegated from the root LMDBer. */
|
|
213
|
-
get base() {
|
|
214
|
-
return this.lmdber.base;
|
|
215
|
-
}
|
|
216
|
-
/** Report whether the keeper LMDB environment and named subdb surface are open. */
|
|
217
|
-
get opened() {
|
|
218
|
-
return this.lmdber.opened;
|
|
219
|
-
}
|
|
220
|
-
/** Report whether the keeper environment is opened in read-only mode. */
|
|
221
|
-
get readonly() {
|
|
222
|
-
return this.lmdber.readonly;
|
|
223
|
-
}
|
|
224
|
-
/** Report whether this keeper uses a temporary backing directory. */
|
|
225
|
-
get temp() {
|
|
226
|
-
return this.lmdber.temp;
|
|
227
|
-
}
|
|
228
|
-
/** Expose the resolved filesystem path for the keeper environment, when open. */
|
|
229
|
-
get path() {
|
|
230
|
-
return this.lmdber.path;
|
|
190
|
+
this.logger = logger;
|
|
231
191
|
}
|
|
232
192
|
/**
|
|
233
193
|
* Reopen the keeper environment and bind the KERIpy-style named subdbs.
|
|
@@ -238,7 +198,7 @@ export class Keeper {
|
|
|
238
198
|
* flows have not yet exercised it deeply.
|
|
239
199
|
*/
|
|
240
200
|
*reopen(options = {}) {
|
|
241
|
-
const opened = yield* this.
|
|
201
|
+
const opened = yield* this.store.reopen(options);
|
|
242
202
|
if (!opened)
|
|
243
203
|
return false;
|
|
244
204
|
try {
|
|
@@ -246,62 +206,62 @@ export class Keeper {
|
|
|
246
206
|
// `aeid` anchors the encrypter/decrypter used to protect salts and
|
|
247
207
|
// private keys, while `pidx`, `algo`, `salt`, and `tier` capture the
|
|
248
208
|
// default root key-management settings.
|
|
249
|
-
this.gbls = new Suber(this.
|
|
209
|
+
this.gbls = new Suber(this.store, { subkey: "gbls." });
|
|
250
210
|
// Public-key to private-key secret material store.
|
|
251
211
|
// Keys are fully qualified public keys and values are the corresponding
|
|
252
212
|
// fully qualified private keys.
|
|
253
|
-
this.pris = new CryptSignerSuber(this.
|
|
213
|
+
this.pris = new CryptSignerSuber(this.store, { subkey: "pris." });
|
|
254
214
|
// Group signing member tuples for one multisig prefix.
|
|
255
215
|
// The stored tuple shape mirrors KERIpy's `(Prefixer, Number)` member
|
|
256
216
|
// identifier set used by GroupSignifyHab flows.
|
|
257
|
-
this.smids = new CatCesrIoSetSuber(this.
|
|
217
|
+
this.smids = new CatCesrIoSetSuber(this.store, {
|
|
258
218
|
subkey: "smids.",
|
|
259
219
|
ctor: [Prefixer, NumberPrimitive],
|
|
260
220
|
});
|
|
261
221
|
// Group rotating member tuples for one multisig prefix.
|
|
262
222
|
// The stored tuple shape mirrors KERIpy's `(Prefixer, Number)` member
|
|
263
223
|
// identifier set used by GroupSignifyHab flows.
|
|
264
|
-
this.rmids = new CatCesrIoSetSuber(this.
|
|
224
|
+
this.rmids = new CatCesrIoSetSuber(this.store, {
|
|
265
225
|
subkey: "rmids.",
|
|
266
226
|
ctor: [Prefixer, NumberPrimitive],
|
|
267
227
|
});
|
|
268
228
|
// Prefix index keyed by the first public key in a key sequence.
|
|
269
229
|
// Values are the identifier prefix, or the first public key for
|
|
270
230
|
// temporary prefixes, matching the KERIpy keeper index contract.
|
|
271
|
-
this.pres = new CesrSuber(this.
|
|
231
|
+
this.pres = new CesrSuber(this.store, {
|
|
272
232
|
subkey: "pres.",
|
|
273
233
|
ctor: Prefixer,
|
|
274
234
|
});
|
|
275
235
|
// Root derivation parameters for one managed identifier prefix.
|
|
276
|
-
this.prms = new Komer(this.
|
|
236
|
+
this.prms = new Komer(this.store, {
|
|
277
237
|
subkey: "prms.",
|
|
278
238
|
recordClass: PrePrm,
|
|
279
239
|
});
|
|
280
240
|
// Old/current/next key situation for one managed identifier prefix.
|
|
281
|
-
this.sits = new Komer(this.
|
|
241
|
+
this.sits = new Komer(this.store, {
|
|
282
242
|
subkey: "sits.",
|
|
283
243
|
recordClass: PreSit,
|
|
284
244
|
});
|
|
285
245
|
// Replayable public-key sets keyed by `(prefix, ridx)`.
|
|
286
246
|
// This enables lookup of the current signing keys after each rotation so
|
|
287
247
|
// establishment events can be replayed in order.
|
|
288
|
-
this.pubs = new Komer(this.
|
|
248
|
+
this.pubs = new Komer(this.store, {
|
|
289
249
|
subkey: "pubs.",
|
|
290
250
|
recordClass: PubSet,
|
|
291
251
|
});
|
|
292
252
|
// Encrypted next private keys used by group-signify keeper flows.
|
|
293
253
|
// KERIpy notes these are not yet broadly exercised outside that path.
|
|
294
|
-
this.prxs = new CesrSuber(this.
|
|
254
|
+
this.prxs = new CesrSuber(this.store, {
|
|
295
255
|
subkey: "prxs.",
|
|
296
256
|
ctor: Cipher,
|
|
297
257
|
});
|
|
298
258
|
// Encrypted next-key commitments used by group-signify keeper flows.
|
|
299
259
|
// KERIpy notes these are not yet broadly exercised outside that path.
|
|
300
|
-
this.nxts = new CesrSuber(this.
|
|
260
|
+
this.nxts = new CesrSuber(this.store, {
|
|
301
261
|
subkey: "nxts.",
|
|
302
262
|
ctor: Cipher,
|
|
303
263
|
});
|
|
304
|
-
this.rroots = new CesrSuber(this.
|
|
264
|
+
this.rroots = new CesrSuber(this.store, { subkey: "rroots.", ctor: Cipher });
|
|
305
265
|
return true;
|
|
306
266
|
}
|
|
307
267
|
catch (error) {
|
|
@@ -311,7 +271,7 @@ export class Keeper {
|
|
|
311
271
|
}
|
|
312
272
|
/** Close the underlying keeper LMDB environment. */
|
|
313
273
|
*close(clear = false) {
|
|
314
|
-
return yield* this.
|
|
274
|
+
return yield* this.store.close(clear);
|
|
315
275
|
}
|
|
316
276
|
/**
|
|
317
277
|
* Read one keeper-global string value from `gbls.`.
|
|
@@ -337,13 +297,12 @@ export class Keeper {
|
|
|
337
297
|
changeEncryption({ currentAeid, aeid, encrypter, decrypter }) {
|
|
338
298
|
if (this.readonly)
|
|
339
299
|
throw new DatabaseOperationError("Cannot change encryption in a read-only keeper");
|
|
340
|
-
|
|
341
|
-
if (!env)
|
|
300
|
+
if (!this.store.opened)
|
|
342
301
|
throw new DatabaseNotOpenError("Keeper environment is not open");
|
|
343
|
-
if (this.
|
|
302
|
+
if (this.store.inWriteTransaction) {
|
|
344
303
|
throw new DatabaseOperationError("Keeper encryption change must own its write transaction");
|
|
345
304
|
}
|
|
346
|
-
|
|
305
|
+
this.store.transaction(() => {
|
|
347
306
|
const storedAeid = this.getGbls("aeid");
|
|
348
307
|
if ((storedAeid ?? "") !== currentAeid) {
|
|
349
308
|
throw new DatabaseOperationError("Keeper AEID changed before encryption migration; reopen the manager");
|
|
@@ -388,13 +347,12 @@ export class Keeper {
|
|
|
388
347
|
retainRegistryRoot(keys, root, currentAeid, encrypter, decrypter) {
|
|
389
348
|
if (this.readonly)
|
|
390
349
|
throw new DatabaseOperationError("Cannot retain registry roots in a read-only keeper");
|
|
391
|
-
|
|
392
|
-
if (!env)
|
|
350
|
+
if (!this.store.opened)
|
|
393
351
|
throw new DatabaseNotOpenError("Keeper environment is not open");
|
|
394
|
-
if (this.
|
|
352
|
+
if (this.store.inWriteTransaction) {
|
|
395
353
|
throw new DatabaseOperationError("Registry root retention must own its write transaction");
|
|
396
354
|
}
|
|
397
|
-
return
|
|
355
|
+
return this.store.transaction(() => {
|
|
398
356
|
if (this.getGbls("aeid") !== currentAeid) {
|
|
399
357
|
throw new DatabaseOperationError("Keeper AEID changed before registry root retention; reopen the manager");
|
|
400
358
|
}
|
|
@@ -520,29 +478,12 @@ export class Keeper {
|
|
|
520
478
|
return this.rmids.get(pre);
|
|
521
479
|
}
|
|
522
480
|
}
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
configurable: true,
|
|
526
|
-
writable: true,
|
|
527
|
-
value: "keri/ks"
|
|
528
|
-
});
|
|
529
|
-
Object.defineProperty(Keeper, "AltTailDirPath", {
|
|
481
|
+
/** Placement of this store kind. */
|
|
482
|
+
Object.defineProperty(Keeper, "Family", {
|
|
530
483
|
enumerable: true,
|
|
531
484
|
configurable: true,
|
|
532
485
|
writable: true,
|
|
533
|
-
value: "
|
|
534
|
-
});
|
|
535
|
-
Object.defineProperty(Keeper, "CompatAltTailDirPath", {
|
|
536
|
-
enumerable: true,
|
|
537
|
-
configurable: true,
|
|
538
|
-
writable: true,
|
|
539
|
-
value: ".keri/ks"
|
|
540
|
-
});
|
|
541
|
-
Object.defineProperty(Keeper, "TempPrefix", {
|
|
542
|
-
enumerable: true,
|
|
543
|
-
configurable: true,
|
|
544
|
-
writable: true,
|
|
545
|
-
value: "keri_ks_"
|
|
486
|
+
value: { tail: "ks", maxTables: 24 }
|
|
546
487
|
});
|
|
547
488
|
Object.defineProperty(Keeper, "MaxNamedDBs", {
|
|
548
489
|
enumerable: true,
|
|
@@ -550,38 +491,3 @@ Object.defineProperty(Keeper, "MaxNamedDBs", {
|
|
|
550
491
|
writable: true,
|
|
551
492
|
value: 24
|
|
552
493
|
});
|
|
553
|
-
/** Constructor-safe async factory for a fully reopened `Keeper`. */
|
|
554
|
-
export function* createKeeper(options = {}) {
|
|
555
|
-
const keeper = new Keeper(options);
|
|
556
|
-
let delivered = false;
|
|
557
|
-
let failure;
|
|
558
|
-
try {
|
|
559
|
-
const opened = yield* keeper.reopen(options);
|
|
560
|
-
if (!opened) {
|
|
561
|
-
throw new DatabaseNotOpenError("Failed to open Keeper");
|
|
562
|
-
}
|
|
563
|
-
delivered = true;
|
|
564
|
-
return keeper;
|
|
565
|
-
}
|
|
566
|
-
catch (error) {
|
|
567
|
-
failure = { error };
|
|
568
|
-
throw error;
|
|
569
|
-
}
|
|
570
|
-
finally {
|
|
571
|
-
if (!delivered) {
|
|
572
|
-
try {
|
|
573
|
-
yield* keeper.close();
|
|
574
|
-
}
|
|
575
|
-
catch (error) {
|
|
576
|
-
if (failure) {
|
|
577
|
-
// deno-lint-ignore no-unsafe-finally -- Preserve the operation failure alongside shutdown failure.
|
|
578
|
-
throw new AggregateError([failure.error, error], "Database acquisition and close failed", {
|
|
579
|
-
cause: failure.error,
|
|
580
|
-
});
|
|
581
|
-
}
|
|
582
|
-
// deno-lint-ignore no-unsafe-finally -- A shutdown failure must propagate.
|
|
583
|
-
throw error;
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LMDB-backed construction of the domain stores.
|
|
3
|
+
*
|
|
4
|
+
* These helpers bind each `StoreOwner` to an `LMDBer` at its established paths.
|
|
5
|
+
* Everything here reaches the native addon; backend-neutral callers use the
|
|
6
|
+
* store classes with an injected `DBer` instead.
|
|
7
|
+
*/
|
|
8
|
+
import { RegBaser } from "../acdc/regbasing.js";
|
|
9
|
+
import { adoptRegistry } from "../acdc/registering.js";
|
|
10
|
+
import { ValidationError } from "../core/errors.js";
|
|
11
|
+
import { Baser } from "./basing.js";
|
|
12
|
+
import { lmdbDefaultsFor } from "./core/lmdb-opener.js";
|
|
13
|
+
import { LMDBer } from "./core/lmdber.js";
|
|
14
|
+
import { openOwner } from "./core/store-owner.js";
|
|
15
|
+
import { Keeper } from "./keeping.js";
|
|
16
|
+
import { Mailboxer } from "./mailbox/mailboxing.js";
|
|
17
|
+
import { Noter } from "./noting.js";
|
|
18
|
+
import { Reger } from "./reger.js";
|
|
19
|
+
/** Construct a closed LMDB-backed `Baser` at its established paths. */
|
|
20
|
+
export function lmdbBaser({ compat, ...options } = {}) {
|
|
21
|
+
return new Baser(new LMDBer(options, lmdbDefaultsFor(Baser.Family, compat)), options.logger);
|
|
22
|
+
}
|
|
23
|
+
/** Constructor-safe async factory for a fully reopened `Baser`. */
|
|
24
|
+
export function* createBaser(options = {}) {
|
|
25
|
+
return yield* openOwner(lmdbBaser(options), "Baser", options);
|
|
26
|
+
}
|
|
27
|
+
/** Construct a closed LMDB-backed `Keeper` at its established paths. */
|
|
28
|
+
export function lmdbKeeper({ compat, ...options } = {}) {
|
|
29
|
+
return new Keeper(new LMDBer(options, lmdbDefaultsFor(Keeper.Family, compat)), options.logger);
|
|
30
|
+
}
|
|
31
|
+
/** Constructor-safe async factory for a fully reopened `Keeper`. */
|
|
32
|
+
export function* createKeeper(options = {}) {
|
|
33
|
+
return yield* openOwner(lmdbKeeper(options), "Keeper", options);
|
|
34
|
+
}
|
|
35
|
+
/** Construct a closed LMDB-backed `Noter` at its established paths. */
|
|
36
|
+
export function lmdbNoter({ compat, ...options } = {}) {
|
|
37
|
+
return new Noter(new LMDBer(options, lmdbDefaultsFor(Noter.Family, compat)));
|
|
38
|
+
}
|
|
39
|
+
/** Open a notification sidecar and return the ready-to-use databaser. */
|
|
40
|
+
export function* createNoter(options = {}) {
|
|
41
|
+
return yield* openOwner(lmdbNoter(options), "Noter", options);
|
|
42
|
+
}
|
|
43
|
+
/** Construct a closed LMDB-backed `Mailboxer` at its established paths. */
|
|
44
|
+
export function lmdbMailboxer({ compat, ...options } = {}) {
|
|
45
|
+
return new Mailboxer(new LMDBer(options, lmdbDefaultsFor(Mailboxer.Family, compat)));
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Open a mailbox environment and return the ready-to-use databaser.
|
|
49
|
+
*
|
|
50
|
+
* Compatibility rule:
|
|
51
|
+
* - explicit mailbox opens stay strict
|
|
52
|
+
* - missing additive sidecars are tolerated only by higher-level habery open
|
|
53
|
+
* flows that are inspecting compat stores readonly
|
|
54
|
+
*/
|
|
55
|
+
export function* createMailboxer(options = {}) {
|
|
56
|
+
return yield* openOwner(lmdbMailboxer(options), "Mailboxer", options);
|
|
57
|
+
}
|
|
58
|
+
/** Transfer a ready `Reger` to its caller, closing unreturned acquisitions on failure or cancellation. */
|
|
59
|
+
export function* createReger({ compat, ...options } = {}) {
|
|
60
|
+
const store = new LMDBer(options, lmdbDefaultsFor(Reger.Family, compat));
|
|
61
|
+
return yield* openOwner(new Reger(store), "Reger", options);
|
|
62
|
+
}
|
|
63
|
+
/** Open a registry store on LMDB at its established paths; the reference web backend remains unsupported. */
|
|
64
|
+
export function* openLmdbRegistry({ web = false, reopen = true, compat, opener: _opener, ...options } = {}) {
|
|
65
|
+
if (web)
|
|
66
|
+
throw new ValidationError("web registry backend is not yet supported by V2 Regery");
|
|
67
|
+
return yield* adoptRegistry(new RegBaser(new LMDBer(options, lmdbDefaultsFor(RegBaser.Family, compat))), reopen);
|
|
68
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** LMDB backend surface: native stores, paths and the default opener. */
|
|
2
|
+
export { createHabery } from "../app/identity/lmdb-habery.js";
|
|
3
|
+
export * from "./core/lmdb-opener.js";
|
|
4
|
+
export * from "./core/lmdber.js";
|
|
5
|
+
export * from "./core/path-manager.js";
|
|
6
|
+
export * from "./lmdb-stores.js";
|