@klum-db/lobby 0.2.0-pre.29 → 0.2.0-pre.31
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/README.md +55 -28
- package/dist/bin/klum.d.cts +1 -1
- package/dist/bin/klum.d.ts +1 -1
- package/dist/index.cjs +108 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +108 -10
- package/dist/index.js.map +1 -1
- package/dist/{vault-group-BXjO5kHB.d.cts → vault-group-DqEyXbN1.d.cts} +49 -3
- package/dist/{vault-group-BXjO5kHB.d.ts → vault-group-DqEyXbN1.d.ts} +49 -3
- package/package.json +9 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Vault, SealingKeyProvider, PublicEnvelope, Noydb } from '@noy-db/hub';
|
|
2
2
|
export { CustodyApi, DeedMarker, GrantCustodianOptions, LiberateOptions, LiberateResult, createDeedOwner, isDeedVault, liberateVault, loadDeedMarker } from '@noy-db/hub';
|
|
3
|
-
import { a as VaultTemplate, S as StateManagementVault, V as VaultGroup, b as SkippedVault, M as MergeCompartmentOptions, c as MergeReport, d as SurfaceDirection, e as SurfaceConflictPolicy, f as SurfaceRow, g as VaultGroupOptions } from './vault-group-
|
|
4
|
-
export { C as CapturedBlueprint, h as CrossVaultAggregation, i as CrossVaultDerivationContext, j as CrossVaultDerivationSpec, k as CrossVaultGroupedAggregation, G as CrossVaultGroupedRow, l as CrossVaultLiveAggregation, m as CrossVaultLiveQuery, D as DecryptedMergeOptions, n as DeploymentEvent, F as FanoutQueryOptions, o as FanoutResult, p as FieldAuthorityInputs, q as FieldAuthorityPolicy, r as FieldAuthorityPolicyMissingError, s as FieldAuthorityRule, t as FieldLevelDeferredError, L as LiveQueryOptions, u as MergeConflict, v as MergeStrategy, w as MigrationStatusRow, R as RefreshInsightsResult, x as SchemaManifestRow, y as SchemaRolloutResult, z as ShardedCollection, A as ShardedGroupedQuery, B as ShardedQuery, E as ShardingConfig, H as SurfaceStatus, I as VaultRegistryRow, J as mergeCompartment, K as mergeDecryptedRecords, N as resolveFieldAuthority, O as resolveRecordByFieldAuthority } from './vault-group-
|
|
3
|
+
import { a as VaultTemplate, S as StateManagementVault, V as VaultGroup, b as SkippedVault, M as MergeCompartmentOptions, c as MergeReport, d as SurfaceDirection, e as SurfaceConflictPolicy, f as SurfaceRow, g as VaultGroupOptions } from './vault-group-DqEyXbN1.cjs';
|
|
4
|
+
export { C as CapturedBlueprint, h as CrossVaultAggregation, i as CrossVaultDerivationContext, j as CrossVaultDerivationSpec, k as CrossVaultGroupedAggregation, G as CrossVaultGroupedRow, l as CrossVaultLiveAggregation, m as CrossVaultLiveQuery, D as DecryptedMergeOptions, n as DeploymentEvent, F as FanoutQueryOptions, o as FanoutResult, p as FieldAuthorityInputs, q as FieldAuthorityPolicy, r as FieldAuthorityPolicyMissingError, s as FieldAuthorityRule, t as FieldLevelDeferredError, L as LiveQueryOptions, u as MergeConflict, v as MergeStrategy, w as MigrationStatusRow, R as RefreshInsightsResult, x as SchemaManifestRow, y as SchemaRolloutResult, z as ShardedCollection, A as ShardedGroupedQuery, B as ShardedQuery, E as ShardingConfig, H as SurfaceStatus, I as VaultRegistryRow, J as mergeCompartment, K as mergeDecryptedRecords, N as resolveFieldAuthority, O as resolveRecordByFieldAuthority } from './vault-group-DqEyXbN1.cjs';
|
|
5
5
|
import { AsXlsxSheetOptions } from '@noy-db/as-xlsx';
|
|
6
6
|
export { MultiVaultDenormColumn, MultiVaultXlsxEntry, MultiVaultXlsxOptions } from '@noy-db/as-xlsx';
|
|
7
7
|
import { ExtractionPreview, WriteNoydbBundleOptions } from '@noy-db/hub/bundle';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Vault, SealingKeyProvider, PublicEnvelope, Noydb } from '@noy-db/hub';
|
|
2
2
|
export { CustodyApi, DeedMarker, GrantCustodianOptions, LiberateOptions, LiberateResult, createDeedOwner, isDeedVault, liberateVault, loadDeedMarker } from '@noy-db/hub';
|
|
3
|
-
import { a as VaultTemplate, S as StateManagementVault, V as VaultGroup, b as SkippedVault, M as MergeCompartmentOptions, c as MergeReport, d as SurfaceDirection, e as SurfaceConflictPolicy, f as SurfaceRow, g as VaultGroupOptions } from './vault-group-
|
|
4
|
-
export { C as CapturedBlueprint, h as CrossVaultAggregation, i as CrossVaultDerivationContext, j as CrossVaultDerivationSpec, k as CrossVaultGroupedAggregation, G as CrossVaultGroupedRow, l as CrossVaultLiveAggregation, m as CrossVaultLiveQuery, D as DecryptedMergeOptions, n as DeploymentEvent, F as FanoutQueryOptions, o as FanoutResult, p as FieldAuthorityInputs, q as FieldAuthorityPolicy, r as FieldAuthorityPolicyMissingError, s as FieldAuthorityRule, t as FieldLevelDeferredError, L as LiveQueryOptions, u as MergeConflict, v as MergeStrategy, w as MigrationStatusRow, R as RefreshInsightsResult, x as SchemaManifestRow, y as SchemaRolloutResult, z as ShardedCollection, A as ShardedGroupedQuery, B as ShardedQuery, E as ShardingConfig, H as SurfaceStatus, I as VaultRegistryRow, J as mergeCompartment, K as mergeDecryptedRecords, N as resolveFieldAuthority, O as resolveRecordByFieldAuthority } from './vault-group-
|
|
3
|
+
import { a as VaultTemplate, S as StateManagementVault, V as VaultGroup, b as SkippedVault, M as MergeCompartmentOptions, c as MergeReport, d as SurfaceDirection, e as SurfaceConflictPolicy, f as SurfaceRow, g as VaultGroupOptions } from './vault-group-DqEyXbN1.js';
|
|
4
|
+
export { C as CapturedBlueprint, h as CrossVaultAggregation, i as CrossVaultDerivationContext, j as CrossVaultDerivationSpec, k as CrossVaultGroupedAggregation, G as CrossVaultGroupedRow, l as CrossVaultLiveAggregation, m as CrossVaultLiveQuery, D as DecryptedMergeOptions, n as DeploymentEvent, F as FanoutQueryOptions, o as FanoutResult, p as FieldAuthorityInputs, q as FieldAuthorityPolicy, r as FieldAuthorityPolicyMissingError, s as FieldAuthorityRule, t as FieldLevelDeferredError, L as LiveQueryOptions, u as MergeConflict, v as MergeStrategy, w as MigrationStatusRow, R as RefreshInsightsResult, x as SchemaManifestRow, y as SchemaRolloutResult, z as ShardedCollection, A as ShardedGroupedQuery, B as ShardedQuery, E as ShardingConfig, H as SurfaceStatus, I as VaultRegistryRow, J as mergeCompartment, K as mergeDecryptedRecords, N as resolveFieldAuthority, O as resolveRecordByFieldAuthority } from './vault-group-DqEyXbN1.js';
|
|
5
5
|
import { AsXlsxSheetOptions } from '@noy-db/as-xlsx';
|
|
6
6
|
export { MultiVaultDenormColumn, MultiVaultXlsxEntry, MultiVaultXlsxOptions } from '@noy-db/as-xlsx';
|
|
7
7
|
import { ExtractionPreview, WriteNoydbBundleOptions } from '@noy-db/hub/bundle';
|
package/dist/index.js
CHANGED
|
@@ -1254,6 +1254,43 @@ var init_insight_auto_push = __esm({
|
|
|
1254
1254
|
}
|
|
1255
1255
|
});
|
|
1256
1256
|
|
|
1257
|
+
// src/federation/partial-reduce.ts
|
|
1258
|
+
function canPartialReduce(spec) {
|
|
1259
|
+
return Object.values(spec).every((r) => typeof r.merge === "function");
|
|
1260
|
+
}
|
|
1261
|
+
function reduceToPartial(records, spec) {
|
|
1262
|
+
const out = {};
|
|
1263
|
+
for (const [key, reducer] of Object.entries(spec)) {
|
|
1264
|
+
const r = reducer;
|
|
1265
|
+
let state = r.init();
|
|
1266
|
+
for (const rec of records) state = r.step(state, rec);
|
|
1267
|
+
out[key] = state;
|
|
1268
|
+
}
|
|
1269
|
+
return out;
|
|
1270
|
+
}
|
|
1271
|
+
function mergePartials(spec, partials) {
|
|
1272
|
+
const out = {};
|
|
1273
|
+
for (const [key, reducer] of Object.entries(spec)) {
|
|
1274
|
+
const r = reducer;
|
|
1275
|
+
let acc = r.init();
|
|
1276
|
+
for (const p of partials) acc = r.merge(acc, p[key]);
|
|
1277
|
+
out[key] = acc;
|
|
1278
|
+
}
|
|
1279
|
+
return out;
|
|
1280
|
+
}
|
|
1281
|
+
function finalizePartial(spec, merged) {
|
|
1282
|
+
const out = {};
|
|
1283
|
+
for (const [key, reducer] of Object.entries(spec)) {
|
|
1284
|
+
out[key] = reducer.finalize(merged[key]);
|
|
1285
|
+
}
|
|
1286
|
+
return out;
|
|
1287
|
+
}
|
|
1288
|
+
var init_partial_reduce = __esm({
|
|
1289
|
+
"src/federation/partial-reduce.ts"() {
|
|
1290
|
+
"use strict";
|
|
1291
|
+
}
|
|
1292
|
+
});
|
|
1293
|
+
|
|
1257
1294
|
// src/federation/aggregate-across.ts
|
|
1258
1295
|
import { reduceRecords } from "@noy-db/hub/kernel";
|
|
1259
1296
|
import { groupAndReduce } from "@noy-db/hub/kernel";
|
|
@@ -1262,6 +1299,7 @@ var init_aggregate_across = __esm({
|
|
|
1262
1299
|
"src/federation/aggregate-across.ts"() {
|
|
1263
1300
|
"use strict";
|
|
1264
1301
|
init_cross_vault_live();
|
|
1302
|
+
init_partial_reduce();
|
|
1265
1303
|
CrossVaultAggregation = class {
|
|
1266
1304
|
constructor(src, spec, bind) {
|
|
1267
1305
|
this.src = src;
|
|
@@ -1272,6 +1310,10 @@ var init_aggregate_across = __esm({
|
|
|
1272
1310
|
spec;
|
|
1273
1311
|
bind;
|
|
1274
1312
|
async run(options = {}) {
|
|
1313
|
+
if (this.src.fanoutReduce && canPartialReduce(this.spec)) {
|
|
1314
|
+
const { partials, skippedVaults: skippedVaults2 } = await this.src.fanoutReduce(this.spec, options);
|
|
1315
|
+
return { result: finalizePartial(this.spec, mergePartials(this.spec, partials)), skippedVaults: skippedVaults2 };
|
|
1316
|
+
}
|
|
1275
1317
|
const { records, skippedVaults } = await this.src.fanoutRecords(options);
|
|
1276
1318
|
return { result: reduceRecords(records, this.spec), skippedVaults };
|
|
1277
1319
|
}
|
|
@@ -1398,6 +1440,7 @@ var init_vault_group = __esm({
|
|
|
1398
1440
|
init_cross_vault_live();
|
|
1399
1441
|
init_insight_auto_push();
|
|
1400
1442
|
init_aggregate_across();
|
|
1443
|
+
init_partial_reduce();
|
|
1401
1444
|
SHARD_SEPARATOR = "--";
|
|
1402
1445
|
SAFE_PARTITION_KEY = /^[A-Za-z0-9._-]+$/;
|
|
1403
1446
|
VaultGroup = class {
|
|
@@ -1536,22 +1579,33 @@ var init_vault_group = __esm({
|
|
|
1536
1579
|
collection(collectionName) {
|
|
1537
1580
|
return new ShardedCollection(this, collectionName);
|
|
1538
1581
|
}
|
|
1539
|
-
/** @internal — eligible (openable-candidate) rows + drift/divergence skips. */
|
|
1582
|
+
/** @internal — eligible (openable-candidate) rows + drift/divergence/unreachable skips. */
|
|
1540
1583
|
async resolveEligible(options = {}) {
|
|
1541
1584
|
const rows = await this.allRows();
|
|
1585
|
+
const candidates = options.only ? rows.filter((r) => options.only.includes(r.partitionKey)) : rows;
|
|
1542
1586
|
const skipped = [];
|
|
1543
1587
|
const versionOk = [];
|
|
1544
|
-
for (const row of
|
|
1588
|
+
for (const row of candidates) {
|
|
1545
1589
|
if (options.minVersion !== void 0 && row.schemaVersion < options.minVersion) {
|
|
1546
1590
|
skipped.push({ vaultId: row.vaultId, reason: "schema-drift" });
|
|
1547
1591
|
} else versionOk.push(row);
|
|
1548
1592
|
}
|
|
1549
|
-
const
|
|
1593
|
+
const probes = await Promise.all(
|
|
1594
|
+
versionOk.map(async (row) => {
|
|
1595
|
+
try {
|
|
1596
|
+
return { row, provisioned: await this.db._shardVaultProvisioned(row.vaultId) };
|
|
1597
|
+
} catch (err) {
|
|
1598
|
+
if (options.failFast) throw err;
|
|
1599
|
+
return { row, error: err };
|
|
1600
|
+
}
|
|
1601
|
+
})
|
|
1602
|
+
);
|
|
1550
1603
|
const eligible = [];
|
|
1551
|
-
|
|
1552
|
-
if (
|
|
1553
|
-
else
|
|
1554
|
-
|
|
1604
|
+
for (const p of probes) {
|
|
1605
|
+
if ("error" in p) skipped.push({ vaultId: p.row.vaultId, reason: "error", error: p.error });
|
|
1606
|
+
else if (p.provisioned) eligible.push(p.row);
|
|
1607
|
+
else skipped.push({ vaultId: p.row.vaultId, reason: "error", error: new ShardProvisioningError(p.row.vaultId, p.row.partitionKey) });
|
|
1608
|
+
}
|
|
1555
1609
|
return { eligible, skipped };
|
|
1556
1610
|
}
|
|
1557
1611
|
/** @internal — registered push-model cross-vault derivations (#271 Insight Vault). */
|
|
@@ -1611,12 +1665,19 @@ var init_vault_group = __esm({
|
|
|
1611
1665
|
* Insight Vault keyed by partition key. Shards behind `minVersion`,
|
|
1612
1666
|
* unprovisioned, or whose read errors are reported in `skippedVaults` and
|
|
1613
1667
|
* are not written (a stale summary is never left behind for a failed shard).
|
|
1668
|
+
* A shard whose backend is unreachable (provisioning probe or read throws) is
|
|
1669
|
+
* **skipped** (`reason: 'error'`) and the pass continues for the others — its
|
|
1670
|
+
* prior summary is left intact. Pass `failFast: true` for the legacy
|
|
1671
|
+
* all-or-nothing throw. Reconcile a lagging shard later with
|
|
1672
|
+
* `refreshInsights({ only: [pk] })` or `refreshDerivation(pk)`.
|
|
1614
1673
|
*/
|
|
1615
1674
|
async refreshInsights(options = {}) {
|
|
1616
1675
|
if (this.crossVaultDerivations.length === 0) return { written: 0, skippedVaults: [] };
|
|
1617
|
-
const { eligible, skipped } = await this.resolveEligible(
|
|
1618
|
-
options.minVersion !== void 0 ? { minVersion: options.minVersion } : {}
|
|
1619
|
-
|
|
1676
|
+
const { eligible, skipped } = await this.resolveEligible({
|
|
1677
|
+
...options.minVersion !== void 0 ? { minVersion: options.minVersion } : {},
|
|
1678
|
+
...options.only !== void 0 ? { only: options.only } : {},
|
|
1679
|
+
...options.failFast !== void 0 ? { failFast: options.failFast } : {}
|
|
1680
|
+
});
|
|
1620
1681
|
let written = 0;
|
|
1621
1682
|
for (const spec of this.crossVaultDerivations) {
|
|
1622
1683
|
const results = await this.db.queryAcross(
|
|
@@ -1633,6 +1694,7 @@ var init_vault_group = __esm({
|
|
|
1633
1694
|
const row = eligible[i];
|
|
1634
1695
|
const res = results[i];
|
|
1635
1696
|
if (!res || res.result === void 0) {
|
|
1697
|
+
if (options.failFast && res?.error) throw res.error;
|
|
1636
1698
|
skipped.push({ vaultId: row.vaultId, reason: "error", ...res?.error ? { error: res.error } : {} });
|
|
1637
1699
|
continue;
|
|
1638
1700
|
}
|
|
@@ -1648,6 +1710,14 @@ var init_vault_group = __esm({
|
|
|
1648
1710
|
}
|
|
1649
1711
|
return { written, skippedVaults: skipped };
|
|
1650
1712
|
}
|
|
1713
|
+
/**
|
|
1714
|
+
* Reconcile one shard's Insight summaries after its backend was unreachable.
|
|
1715
|
+
* Equivalent to `refreshInsights({ only: [partitionKey] })` — runs every
|
|
1716
|
+
* registered derivation (autoPush or not) for just this shard.
|
|
1717
|
+
*/
|
|
1718
|
+
async refreshDerivation(partitionKey) {
|
|
1719
|
+
return this.refreshInsights({ only: [partitionKey] });
|
|
1720
|
+
}
|
|
1651
1721
|
/** @internal — re-derive + push every autoPush derivation's summary for one shard. */
|
|
1652
1722
|
async _recomputeShardInsights(partitionKey) {
|
|
1653
1723
|
const row = await this.registry.get(this.registryId(partitionKey));
|
|
@@ -1883,6 +1953,34 @@ var init_vault_group = __esm({
|
|
|
1883
1953
|
}
|
|
1884
1954
|
return { records: results, skippedVaults: skipped };
|
|
1885
1955
|
}
|
|
1956
|
+
/**
|
|
1957
|
+
* @internal — distributed partial-reduce (#8). Fan out across eligible shards,
|
|
1958
|
+
* but fold each shard's where-filtered records to a partial reducer STATE
|
|
1959
|
+
* inside the per-shard callback (never returning the rows). Only the scalar
|
|
1960
|
+
* `.aggregate()` path calls this, and that path rejects join legs upstream.
|
|
1961
|
+
*/
|
|
1962
|
+
async fanoutReduce(spec, options = {}) {
|
|
1963
|
+
const { eligible, skipped } = await this.group.resolveEligible(options);
|
|
1964
|
+
const across = await this.group.db.queryAcross(
|
|
1965
|
+
eligible.map((r) => r.vaultId),
|
|
1966
|
+
async (vault) => {
|
|
1967
|
+
this.group.template.configure(vault);
|
|
1968
|
+
const coll = vault.collection(this.collectionName);
|
|
1969
|
+
await coll.list();
|
|
1970
|
+
let q = coll.query();
|
|
1971
|
+
for (const c of this.clauses) q = q.where(c.field, c.op, c.value);
|
|
1972
|
+
const rows = q.toArray();
|
|
1973
|
+
return reduceToPartial(rows, spec);
|
|
1974
|
+
},
|
|
1975
|
+
{ concurrency: options.concurrency ?? 1, create: false }
|
|
1976
|
+
);
|
|
1977
|
+
const partials = [];
|
|
1978
|
+
for (const r of across) {
|
|
1979
|
+
if (r.error) skipped.push({ vaultId: r.vault, reason: classifyShardSkip(r.error), error: r.error });
|
|
1980
|
+
else partials.push(r.result);
|
|
1981
|
+
}
|
|
1982
|
+
return { partials, skippedVaults: skipped };
|
|
1983
|
+
}
|
|
1886
1984
|
/** Fan out across eligible shards, merge, then apply any broadcast dimension legs. */
|
|
1887
1985
|
async toArray(options = {}) {
|
|
1888
1986
|
const { records, skippedVaults } = await this.fanoutRecords(options);
|