@cloudbitmaps/core 0.16.0 → 0.17.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/dist/{chunk-LFUNPMXZ.js → chunk-CV7GJO3B.js} +363 -23
- package/dist/chunk-CV7GJO3B.js.map +7 -0
- package/dist/core/cost.d.ts +3 -3
- package/dist/core/crbm-storage-source.d.ts +73 -65
- package/dist/core/engine.d.ts +23 -0
- package/dist/core/erasure.d.ts +2 -1
- package/dist/core/errors.d.ts +23 -0
- package/dist/core/generation-gc.d.ts +69 -45
- package/dist/core/kept-generations.d.ts +40 -0
- package/dist/core/leases.d.ts +119 -0
- package/dist/core/load-input.d.ts +12 -0
- package/dist/core/load.d.ts +13 -11
- package/dist/core/metrics.d.ts +24 -0
- package/dist/core/ports.d.ts +99 -2
- package/dist/core/registry-reap.d.ts +22 -0
- package/dist/core/retention.d.ts +2 -1
- package/dist/core/rollback.d.ts +2 -1
- package/dist/driver-kit.d.ts +1 -0
- package/dist/driver-kit.js +100 -1
- package/dist/driver-kit.js.map +2 -2
- package/dist/drivers/_shared/object-registry.d.ts +19 -1
- package/dist/drivers/_shared/registry.d.ts +7 -9
- package/dist/export/index.d.ts +20 -8
- package/dist/index.d.ts +9 -3
- package/dist/index.js +527 -86
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
- package/dist/chunk-LFUNPMXZ.js.map +0 -7
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { IRegistryDriver, NewRegistryRecord, RegCaps, RegistryPatch, RegistryRecord, RegistryWriteOptions, SegmentRef, Token } from '../../core/ports.js';
|
|
1
|
+
import type { IRegistryDriver, NewRegistryRecord, ReapLegacyTombstonesOptions, ReapLegacyTombstonesResult, RegCaps, RegistryPatch, RegistryRecord, RegistryWriteOptions, SegmentRef, Token } from '../../core/ports.js';
|
|
2
2
|
import type { Entropy } from '../../core/determinism.js';
|
|
3
3
|
/** Defensive cap on a single registry object read from storage, before allocation (rows are tiny; ~1 KB). */
|
|
4
4
|
export declare const MAX_ROW_BYTES: number;
|
|
@@ -79,6 +79,11 @@ export interface ObjectRegistryStore {
|
|
|
79
79
|
* a live one included. Absent or `false`, the registry never calls `delete` and tombstones every row instead.
|
|
80
80
|
*/
|
|
81
81
|
readonly conditionalDelete?: boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Optional: settle {@link conditionalDelete} without a request to the backend, for a store that learns it from its
|
|
84
|
+
* client rather than knowing it at construction. A caller that must refuse before its first request awaits it first.
|
|
85
|
+
*/
|
|
86
|
+
resolveCapabilities?(): Promise<void>;
|
|
82
87
|
}
|
|
83
88
|
export declare class ObjectStoreRegistry implements IRegistryDriver {
|
|
84
89
|
private readonly store;
|
|
@@ -114,6 +119,19 @@ export declare class ObjectStoreRegistry implements IRegistryDriver {
|
|
|
114
119
|
private observedRow;
|
|
115
120
|
list(namespace?: string): AsyncIterable<RegistryRecord>;
|
|
116
121
|
delete(ref: SegmentRef, expected?: Token): Promise<void>;
|
|
122
|
+
/**
|
|
123
|
+
* Remove the `deleted: true` rows with no incarnation id (the envelopes a release before 0.12 left), or count them.
|
|
124
|
+
* One listing, a read per key and a conditional delete per envelope, so a row that a create wrote over since it was
|
|
125
|
+
* read keeps its new version and the delete is refused. Refuses with {@link CapabilityError}, before any request,
|
|
126
|
+
* where the store's delete is not known to apply its precondition.
|
|
127
|
+
*
|
|
128
|
+
* An object that cannot be read or parsed stops the run with the error that names its key, and removes nothing
|
|
129
|
+
* more: it may be a newer release's row. Rows removed before the stop stay removed, and a re-run is safe.
|
|
130
|
+
*
|
|
131
|
+
* Not resumable: it lists and reads from the start on every call. A delete refused as a conflict, including one for a
|
|
132
|
+
* row already gone, is counted as `raced`.
|
|
133
|
+
*/
|
|
134
|
+
reapLegacyTombstones(options: ReapLegacyTombstonesOptions): Promise<ReapLegacyTombstonesResult>;
|
|
117
135
|
/**
|
|
118
136
|
* Read + parse a registry object, returning its envelope and version fence, or null if absent.
|
|
119
137
|
*
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import type { Entropy } from '../../core/determinism.js';
|
|
2
2
|
import { incarnationOf } from '../../core/token.js';
|
|
3
|
+
import { usableKeptGens } from '../../core/kept-generations.js';
|
|
3
4
|
import type { NewRegistryRecord, RegistryPatch, RegistryRecord, SegmentRef, Token } from '../../core/ports.js';
|
|
4
|
-
|
|
5
|
-
* The fields a stored record may carry: {@link RegistryRecord}'s, and nothing else. A field no reader resolves
|
|
6
|
-
* through is refused on read-back like any other corruption (invariant 5), rather than ignored.
|
|
7
|
-
*/
|
|
8
|
-
export declare const RECORD_FIELDS: readonly ["namespace", "segment", "currentGen", "wrappedDeks", "keyId", "status", "retention", "residency", "summary", "createdAt", "updatedAt", "token"];
|
|
5
|
+
export declare const RECORD_FIELDS: readonly ["namespace", "segment", "currentGen", "wrappedDeks", "keyId", "status", "retention", "residency", "summary", "createdAt", "updatedAt", "token", "keptGens", "leases"];
|
|
9
6
|
/**
|
|
10
7
|
* Validate the caller-settable fields at `create`, and return the record to store: the caller's, with its summary
|
|
11
8
|
* replaced by the checked, frozen copy {@link validateSummary} builds.
|
|
@@ -38,11 +35,11 @@ export interface RegistryEnvelope {
|
|
|
38
35
|
* on a backward-incompatible change. Policy: a **higher** stamp than this build knows → `UnsupportedError`
|
|
39
36
|
* (fail-closed); an **absent** or malformed stamp → `IntegrityError`, since every row this build writes has one.
|
|
40
37
|
*
|
|
41
|
-
* Schema 2
|
|
42
|
-
* whatever it holds, and a build that reads only schema
|
|
43
|
-
* written.
|
|
38
|
+
* Schema 2 added the record's `summary` and the incarnation-form token; schema 3 adds `keptGens`. Every row this
|
|
39
|
+
* build writes is stamped 3, whatever it holds, and a build that reads only schema 2 refuses it, so a fleet cannot go
|
|
40
|
+
* back once one has been written.
|
|
44
41
|
*/
|
|
45
|
-
export declare const REGISTRY_SCHEMA_VERSION =
|
|
42
|
+
export declare const REGISTRY_SCHEMA_VERSION = 3;
|
|
46
43
|
/**
|
|
47
44
|
* Validate a persisted registry row's `schemaVersion` (untrusted bytes, invariant 5) and return it: an absent or
|
|
48
45
|
* malformed value → `IntegrityError`; a version newer than this build → `UnsupportedError` (fail-closed rather than
|
|
@@ -51,6 +48,7 @@ export declare const REGISTRY_SCHEMA_VERSION = 2;
|
|
|
51
48
|
export declare function assertRegistrySchemaVersion(raw: unknown, ctx: string): number;
|
|
52
49
|
/** Serialize a registry envelope for persistence, stamping the current {@link REGISTRY_SCHEMA_VERSION}. */
|
|
53
50
|
export declare function serializeRegistryEnvelope(env: RegistryEnvelope): string;
|
|
51
|
+
export { usableKeptGens };
|
|
54
52
|
export { incarnationOf };
|
|
55
53
|
/** A fresh incarnation id from `entropy`: 128 bits as 32 lowercase hex digits. */
|
|
56
54
|
export declare function drawIncarnation(entropy: Entropy): string;
|
package/dist/export/index.d.ts
CHANGED
|
@@ -64,12 +64,18 @@ export interface ExportManifest {
|
|
|
64
64
|
*/
|
|
65
65
|
readonly failed: readonly ExportFailure[];
|
|
66
66
|
}
|
|
67
|
-
/**
|
|
67
|
+
/**
|
|
68
|
+
* The minimal read surface the export needs from a store — a `CloudRoaring` satisfies this structurally: `segment(name,
|
|
69
|
+
* { namespace? })` returns a handle whose `pin()` resolves to something that iterates the ids. A segment's
|
|
70
|
+
* `pin()` resolves its generation once and reads only that generation's object, so one segment's export is one instant.
|
|
71
|
+
*/
|
|
68
72
|
export interface SegmentReader {
|
|
69
73
|
segment(name: string, options?: {
|
|
70
74
|
namespace?: string;
|
|
71
75
|
}): {
|
|
72
|
-
|
|
76
|
+
pin(): Promise<{
|
|
77
|
+
iterate(): AsyncIterable<number>;
|
|
78
|
+
}>;
|
|
73
79
|
};
|
|
74
80
|
}
|
|
75
81
|
/**
|
|
@@ -83,11 +89,17 @@ export interface SegmentReader {
|
|
|
83
89
|
* `close()` fault is likewise recorded (never triggering `abort()` — they're mutually exclusive).
|
|
84
90
|
*
|
|
85
91
|
* Re-running overwrites the segments it re-exports but does **not** prune files for segments that have since
|
|
86
|
-
* disappeared — export to a fresh directory for a clean dump.
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
+
* disappeared — export to a fresh directory for a clean dump.
|
|
93
|
+
*
|
|
94
|
+
* Each segment is pinned for its export: its generation is read from the registry when its export begins, on a warm
|
|
95
|
+
* store as on a cold one, and only that generation's object is read for the whole segment, so a publish during a long
|
|
96
|
+
* segment's export cannot put two generations in one file. A cold store makes one registry read and one tail read
|
|
97
|
+
* per segment; a warm store makes one registry read per segment. A pin holds nothing: if a collection or an erasure
|
|
98
|
+
* removes the pinned generation mid-export, that segment's export fails, recorded in `failed`, and never reads the
|
|
99
|
+
* newer generation. Different segments are different instants.
|
|
100
|
+
*
|
|
101
|
+
* `reader` is any object with `segment(name, { namespace? })` returning a handle with `pin()`, which resolves to
|
|
102
|
+
* `{ iterate(): AsyncIterable<number> }` (see {@link SegmentReader}). A reader without that shape throws a
|
|
103
|
+
* `ValidationError` before any file is opened.
|
|
92
104
|
*/
|
|
93
105
|
export declare function runExport(reader: SegmentReader, registry: IRegistryDriver, sink: ExportSink, options?: ExportOptions): Promise<ExportManifest>;
|
package/dist/index.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ export { BoundedLru } from './core/lru.js';
|
|
|
21
21
|
export { safeMetrics } from './core/metrics.js';
|
|
22
22
|
export { groundedReport } from './core/cost.js';
|
|
23
23
|
export { runExport } from './export/index.js';
|
|
24
|
+
export type { SegmentReader } from './export/index.js';
|
|
24
25
|
export { splitId } from './core/bit-route.js';
|
|
25
26
|
export { mapWithConcurrency } from './core/concurrency.js';
|
|
26
27
|
export { resolveBudget, resolvePerOpBudget, checkBudget, collectWithinBudget } from './core/budget.js';
|
|
@@ -32,20 +33,23 @@ export { isStorageBackend } from './core/ports.js';
|
|
|
32
33
|
export { LocalFsStorage, MemoryStorage } from './drivers/backends.js';
|
|
33
34
|
export type { LocalFsStorageOptions, MemoryStorageOptions } from './drivers/backends.js';
|
|
34
35
|
export { CrbmStorageChunkSource } from './core/crbm-storage-source.js';
|
|
35
|
-
export type { CrbmStorageChunkSourceOptions, PinnedObject } from './core/crbm-storage-source.js';
|
|
36
|
+
export type { CrbmStorageChunkSourceOptions, PinLease, PinnedObject, } from './core/crbm-storage-source.js';
|
|
37
|
+
export { LEASE_SKEW_MS, MAX_LEASE_MS, MAX_LEASES_PER_SEGMENT, releaseLease, takeLease, } from './core/leases.js';
|
|
38
|
+
export type { LeaseDeps, LeaseTake, TakenLease } from './core/leases.js';
|
|
36
39
|
export { PinnedStorageChunkSource } from './core/pinned-storage-source.js';
|
|
37
40
|
export type { PinnedAt } from './core/pinned-storage-source.js';
|
|
38
41
|
export { loadSegment, loadSegmentChunks } from './core/load.js';
|
|
39
42
|
export type { LoadDeps, LoadOptions, LoadGuard, LoadResult, LoadRefusal } from './core/load.js';
|
|
40
43
|
export type { LoadInput, PortableBitmap } from './core/load-input.js';
|
|
44
|
+
export { decodeSerialized } from './core/load-input.js';
|
|
41
45
|
export { listGenerations, rollbackSegment } from './core/rollback.js';
|
|
42
46
|
export type { GenerationListDeps, GenerationEntry, RollbackResult } from './core/rollback.js';
|
|
43
47
|
export { eraseIdFromSegment } from './core/erase-id.js';
|
|
44
48
|
export type { EraseIdDeps, EraseIdResult } from './core/erase-id.js';
|
|
45
49
|
export type { CodecInterface, CodecBitmap, EncodedChunk } from './core/codec.js';
|
|
46
50
|
export type { Clock, Entropy, Rng } from './core/determinism.js';
|
|
47
|
-
export type { StorageChunkSource, IStorageDriver, StorageCaps, ChunkRef, ChunkRead, ReadChunksOptions, SegmentRef, GenKey, IRegistryDriver, StorageBackend, RegistryRecord, NewRegistryRecord, RegistryPatch, RegistryStatus, RegistrySummary, RegistryWriteOptions, ClearRegistrySummary, SealedRegistrySummary, GenerationMetadata, GenerationSummary, RegCaps, GovernanceMeta, SegmentSize, } from './core/ports.js';
|
|
48
|
-
export { CloudRoaringError, ValidationError, WriteConflictError, IntegrityError, NotFoundError, UnsupportedError, CapabilityError, TransientError, KeyUnavailableError, BudgetExceededError, isCloudRoaringError, isWriteConflictError, isTransientError, isNotFoundError, isIntegrityError, isValidationError, } from './core/errors.js';
|
|
51
|
+
export type { StorageChunkSource, IStorageDriver, StorageCaps, ChunkRef, ChunkRead, ReadChunksOptions, SegmentRef, GenKey, IRegistryDriver, StorageBackend, RegistryRecord, NewRegistryRecord, RegistryPatch, RegistryStatus, RegistrySummary, RegistryWriteOptions, LeaseEntry, ReapLegacyTombstonesOptions, ReapLegacyTombstonesResult, ClearRegistrySummary, SealedRegistrySummary, GenerationMetadata, GenerationSummary, RegCaps, GovernanceMeta, SegmentSize, } from './core/ports.js';
|
|
52
|
+
export { CloudRoaringError, ValidationError, WriteConflictError, IntegrityError, NotFoundError, UnsupportedError, CapabilityError, TransientError, KeyUnavailableError, BudgetExceededError, LeaseExpiredError, LeaseLimitError, isCloudRoaringError, isWriteConflictError, isTransientError, isNotFoundError, isIntegrityError, isValidationError, isLeaseExpiredError, isLeaseLimitError, } from './core/errors.js';
|
|
49
53
|
export type { Aead, AeadSealed, IKeystore, WrappedDek, CrbmCrypto } from './core/crypto.js';
|
|
50
54
|
export { aadFor } from './core/crypto.js';
|
|
51
55
|
export { NodeAead, InProcessKeystore } from './drivers/crypto.js';
|
|
@@ -55,6 +59,8 @@ export type { DropDeps, DropResult, EraseDeps, DestroyResult } from './core/eras
|
|
|
55
59
|
export { setSegmentRetention, clearSegmentRetention, getSegmentRetention, readRetentionPolicy, MIN_EXPIRES_AT_MS, } from './core/retention.js';
|
|
56
60
|
export type { RetentionPolicy, RetentionDeps, SetRetentionResult } from './core/retention.js';
|
|
57
61
|
export { retireExpired } from './core/retention-sweep.js';
|
|
62
|
+
export { reapRegistryTombstones } from './core/registry-reap.js';
|
|
63
|
+
export type { ReapRegistryTombstonesOptions, ReapRegistryTombstonesResult, } from './core/registry-reap.js';
|
|
58
64
|
export { excludingReservedRows } from './core/registry-scan.js';
|
|
59
65
|
export type { RetireExpiredOptions, RetireExpiredResult, RetireEntry, } from './core/retention-sweep.js';
|
|
60
66
|
export { DEFAULT_BUDGET } from './core/budget.js';
|