@cloudbitmaps/core 0.10.0 → 0.11.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.
Files changed (53) hide show
  1. package/README.md +32 -36
  2. package/dist/{chunk-BUPDGZRR.js → chunk-5OMC5U7U.js} +87 -40
  3. package/dist/chunk-5OMC5U7U.js.map +7 -0
  4. package/dist/core/audit.d.ts +15 -14
  5. package/dist/core/budget.d.ts +5 -3
  6. package/dist/core/codec.d.ts +18 -10
  7. package/dist/core/consistency.d.ts +3 -3
  8. package/dist/core/cooperative.d.ts +9 -9
  9. package/dist/core/cost.d.ts +167 -15
  10. package/dist/core/crbm/format.d.ts +7 -9
  11. package/dist/core/crbm/reader.d.ts +18 -1
  12. package/dist/core/crbm/writer.d.ts +2 -2
  13. package/dist/core/crbm-storage-source.d.ts +150 -60
  14. package/dist/core/determinism.d.ts +1 -1
  15. package/dist/core/discover.d.ts +7 -5
  16. package/dist/core/due-index.d.ts +3 -5
  17. package/dist/core/engine.d.ts +55 -13
  18. package/dist/core/erase-id.d.ts +76 -41
  19. package/dist/core/erasure.d.ts +22 -16
  20. package/dist/core/errors.d.ts +13 -20
  21. package/dist/core/generation-gc.d.ts +9 -5
  22. package/dist/core/keys.d.ts +2 -2
  23. package/dist/core/load.d.ts +28 -9
  24. package/dist/core/metrics.d.ts +8 -4
  25. package/dist/core/name-codec.d.ts +21 -31
  26. package/dist/core/pinned-storage-source.d.ts +29 -8
  27. package/dist/core/ports.d.ts +142 -59
  28. package/dist/core/reader-defaults.d.ts +18 -0
  29. package/dist/core/registry-scan.d.ts +15 -6
  30. package/dist/core/retention-sweep.d.ts +26 -18
  31. package/dist/core/retry.d.ts +8 -4
  32. package/dist/core/rollback.d.ts +11 -7
  33. package/dist/core/validate.d.ts +27 -3
  34. package/dist/driver-kit.d.ts +2 -3
  35. package/dist/driver-kit.js +13 -52
  36. package/dist/driver-kit.js.map +3 -3
  37. package/dist/drivers/_shared/keys.d.ts +4 -5
  38. package/dist/drivers/_shared/object-registry.d.ts +10 -5
  39. package/dist/drivers/_shared/registry.d.ts +9 -5
  40. package/dist/drivers/backends.d.ts +10 -16
  41. package/dist/drivers/localfs/fs-util.d.ts +3 -2
  42. package/dist/drivers/localfs/registry.d.ts +4 -4
  43. package/dist/drivers/memory.d.ts +2 -10
  44. package/dist/drivers/retry/retrying-chunk-source.d.ts +59 -0
  45. package/dist/export/index.d.ts +7 -6
  46. package/dist/index.d.ts +15 -24
  47. package/dist/index.js +1014 -373
  48. package/dist/index.js.map +4 -4
  49. package/dist/testing/fuzz-core.d.ts +1 -1
  50. package/package.json +1 -1
  51. package/dist/chunk-BUPDGZRR.js.map +0 -7
  52. package/dist/drivers/_shared/aws-errors.d.ts +0 -18
  53. package/dist/drivers/retry/retrying-drivers.d.ts +0 -90
@@ -0,0 +1,59 @@
1
+ /**
2
+ * The store's read retry.
3
+ *
4
+ * {@link RetryingStorageChunkSource} wraps a {@link StorageChunkSource} so every read it serves retries
5
+ * **transient** faults with bounded, jittered backoff, through the one shared `core/retry` primitive, so every
6
+ * backend (S3, GCS, Azure Blob, LocalFS, …) inherits the same policy instead of each rolling its own. `CloudRoaring`
7
+ * wraps the source it reads segment data through in one — a `StorageChunkSource` passed as `storage` included, so
8
+ * wrapping that one first multiplies each read's attempts — and a pinned handle's source too, unless it is built
9
+ * with `retry: false`.
10
+ * Pure composition over the port (no SDK, no I/O of its own); the driver under the source is responsible for
11
+ * *classifying* its transient faults (raising {@link TransientError}), and this wrapper decides *whether and when*
12
+ * to retry.
13
+ *
14
+ * **Reads only, on purpose.** A read changes nothing, so running it again is safe. A write is not: a conditional put
15
+ * or compare-and-swap that lands and then loses its response would, replayed, find its own write already there and
16
+ * report it as a conflict. So nothing here wraps a write, and the store's writes and admin calls report a transient
17
+ * fault to their caller, who re-runs the call or checks what landed.
18
+ *
19
+ * What is **not** retried: every deterministic error (`ValidationError`/`IntegrityError`/`NotFoundError`/…).
20
+ * Default classifier: {@link isTransientError}.
21
+ */
22
+ import type { Clock, Rng } from '../../core/determinism.js';
23
+ import type { RetryPolicy } from '../../core/retry.js';
24
+ import type { ChunkRef, StorageChunkSource, SegmentRef, SegmentSize } from '../../core/ports.js';
25
+ export interface RetryingOptions {
26
+ readonly clock: Clock;
27
+ readonly rng: Rng;
28
+ /** Defaults to {@link DEFAULT_RETRY_POLICY}. */
29
+ readonly policy?: RetryPolicy;
30
+ /** Override which errors are retryable. Default: {@link isTransientError} (any `TransientError`). */
31
+ readonly isRetryable?: (err: unknown) => boolean;
32
+ /** Observability hook fired before each backoff wait. */
33
+ readonly onRetry?: (info: {
34
+ attempt: number;
35
+ delayMs: number;
36
+ err: unknown;
37
+ }) => void;
38
+ }
39
+ /** Wrap a storage chunk source so its reads retry transient faults. */
40
+ export declare class RetryingStorageChunkSource implements StorageChunkSource {
41
+ private readonly inner;
42
+ private readonly policy;
43
+ private readonly deps;
44
+ /** Present only when the inner source supports it — so capability detection stays honest. */
45
+ readonly sizeOf?: (ref: SegmentRef) => Promise<SegmentSize | null>;
46
+ readonly cardinalities?: (ref: SegmentRef) => Promise<ReadonlyMap<number, number> | null>;
47
+ readonly currentGeneration?: (ref: SegmentRef) => Promise<number | null>;
48
+ readonly invalidate?: (ref: SegmentRef) => void;
49
+ readonly exists?: (ref: SegmentRef) => Promise<boolean>;
50
+ readonly currentVersion?: (ref: SegmentRef) => Promise<string | null>;
51
+ /**
52
+ * Forwarded, not retried: a property, with no request behind it. Without it the grounded cost report priced a
53
+ * retrying store's refresh at the default TTL whatever the store was configured with.
54
+ */
55
+ get pointerRefreshMs(): number | undefined;
56
+ constructor(inner: StorageChunkSource, opts: RetryingOptions);
57
+ getChunk(ref: ChunkRef): Promise<Uint8Array | null>;
58
+ listChunkKeys(ref: SegmentRef): Promise<number[]>;
59
+ }
@@ -22,9 +22,8 @@ export interface ExportOptions {
22
22
  /** Output format; defaults to `'roaring'`. */
23
23
  readonly format?: ExportFormat;
24
24
  /**
25
- * Bitmap codec used to build the exported bitmap for the `'roaring'` format. Optional in the
26
- * type so this stays call-compatible public API; a **flavor** package binds it (see `requireCodec`). Not needed
27
- * for `'ndjson'`, which streams plain ids.
25
+ * Bitmap codec that builds the exported bitmap for the `'roaring'` format. Optional in the type; a **flavor**'s
26
+ * store passes its own (see `requireCodec`). Not needed for `'ndjson'`, which streams plain ids.
28
27
  */
29
28
  readonly codec?: CodecInterface;
30
29
  /** Scope the export to one namespace; omit to export every registered segment. */
@@ -85,8 +84,10 @@ export interface SegmentReader {
85
84
  *
86
85
  * Re-running overwrites the segments it re-exports but does **not** prune files for segments that have since
87
86
  * disappeared — export to a fresh directory for a clean dump. For a *current* image, run against a
88
- * freshly-constructed store: a store's storage source re-resolves each segment's generation on a short TTL (or pins
89
- * it for its lifetime when built without a clock or registry), so a long-lived store may export a view one load
90
- * behind.
87
+ * freshly-constructed store: a store's storage source re-resolves each segment's generation on a short TTL, or, with
88
+ * no registry, with `cache.genTtlMs: 0`, or built without a clock, only when an eviction, a sweep or an invalidation
89
+ * makes it, so a long-lived store may export a view one load behind, or more. Each segment is read live, not pinned:
90
+ * a publish while a long segment exports can re-resolve it part-way, and its file then holds chunks of two
91
+ * generations, each whole and verified. For one generation per file, export from a quiet window.
91
92
  */
92
93
  export declare function runExport(reader: SegmentReader, registry: IRegistryDriver, sink: ExportSink, options?: ExportOptions): Promise<ExportManifest>;
package/dist/index.d.ts CHANGED
@@ -1,21 +1,22 @@
1
1
  /**
2
2
  * `@cloudbitmaps/core` — the codec-agnostic cloud engine behind the @cloudbitmaps family.
3
3
  *
4
- * Everything here is **independent of any bitmap codec**: the read engine, every storage driver, the `.crbm`
5
- * format, the loaded store's write path (bulk load + forward-only publish), encryption/crypto-shred, the registry,
4
+ * Everything here is **independent of any bitmap codec**: the read engine, the SDK-free storage backends, the `.crbm`
5
+ * format, the loaded store's write path (`loadSegment`: write, guard, publish, collect), encryption/crypto-shred, the registry,
6
6
  * the budget/consistency/eject machinery. Bitmaps are only ever constructed and combined through the
7
7
  * {@link CodecInterface} seam, so a *flavor* package (`@cloudbitmaps/roaring` today) supplies the codec and a
8
8
  * facade on top.
9
9
  *
10
10
  * **You normally install a flavor, not this package** — `pnpm add @cloudbitmaps/roaring` pulls this in
11
- * transitively and re-exports it, so `@cloudbitmaps/roaring` is the one name to know. Depend on `core`
12
- * directly only when authoring a new flavor or a driver.
11
+ * transitively and re-exports, by name, what an application uses, so `@cloudbitmaps/roaring` is the one name to
12
+ * know. The engine, the standalone forms of the store's methods and the retry and budget internals stay here:
13
+ * depend on `core` directly only when authoring a new flavor or a driver.
13
14
  *
14
15
  * Nothing in here may import a flavor package — the dependency arrow is one-way (flavor → core), so core stays
15
16
  * publishable on its own and every codec reuses one driver set with zero duplication.
16
17
  */
17
18
  export { SegmentEngine } from './core/engine.js';
18
- export type { EngineDeps, CombineOptions as EngineCombineOptions } from './core/engine.js';
19
+ export type { EngineDeps, CombineOptions as EngineCombineOptions, IdRange } from './core/engine.js';
19
20
  export { BoundedLru } from './core/lru.js';
20
21
  export { safeMetrics } from './core/metrics.js';
21
22
  export { groundedReport } from './core/cost.js';
@@ -23,27 +24,17 @@ export { runExport } from './export/index.js';
23
24
  export { splitId } from './core/bit-route.js';
24
25
  export { mapWithConcurrency } from './core/concurrency.js';
25
26
  export { resolveBudget, resolvePerOpBudget, checkBudget, collectWithinBudget } from './core/budget.js';
26
- export { validateSegmentRef } from './core/validate.js';
27
27
  export { segmentExists, listSegments } from './core/discover.js';
28
28
  export type { SegmentInfo } from './core/discover.js';
29
- export { encodeNameForPath } from './core/name-codec.js';
30
- export { namespacePathPart } from './drivers/_shared/keys.js';
31
29
  export type { Token } from './core/ports.js';
32
30
  export { segmentKey } from './core/keys.js';
33
- export { createBackend, isStorageBackend } from './core/ports.js';
34
- export { MemoryStorageChunkSource, MemoryStorageDriver, MemoryRegistryDriver, } from './drivers/memory.js';
35
- export type { MemoryRegistryDriverOptions } from './drivers/memory.js';
36
- export { LocalFsStorageDriver } from './drivers/localfs/storage.js';
37
- export { LocalFsRegistryDriver } from './drivers/localfs/registry.js';
31
+ export { isStorageBackend } from './core/ports.js';
38
32
  export { LocalFsStorage, MemoryStorage } from './drivers/backends.js';
39
33
  export type { LocalFsStorageOptions, MemoryStorageOptions } from './drivers/backends.js';
40
- export type { LocalFsRegistryDriverOptions } from './drivers/localfs/registry.js';
41
- export { CrbmStorageChunkSource, writeCrbmGeneration, bulkLoadCrbmGeneration, publishGeneration, } from './core/crbm-storage-source.js';
42
- export type { BulkLoadResult, CrbmStorageChunkSourceOptions } from './core/crbm-storage-source.js';
34
+ export { CrbmStorageChunkSource } from './core/crbm-storage-source.js';
35
+ export type { CrbmStorageChunkSourceOptions, PinnedObject } from './core/crbm-storage-source.js';
43
36
  export { PinnedStorageChunkSource } from './core/pinned-storage-source.js';
44
37
  export type { PinnedAt } from './core/pinned-storage-source.js';
45
- export { gcOrphanGenerations, nextGeneration } from './core/generation-gc.js';
46
- export type { GenerationDeps } from './core/generation-gc.js';
47
38
  export { loadSegment } from './core/load.js';
48
39
  export type { LoadDeps, LoadOptions, LoadGuard, LoadResult, LoadRefusal } from './core/load.js';
49
40
  export { listGenerations, rollbackSegment } from './core/rollback.js';
@@ -53,7 +44,7 @@ export type { EraseIdDeps, EraseIdResult } from './core/erase-id.js';
53
44
  export type { CodecInterface, CodecBitmap } from './core/codec.js';
54
45
  export type { Clock, Rng } from './core/determinism.js';
55
46
  export type { StorageChunkSource, IStorageDriver, StorageCaps, ChunkRef, SegmentRef, GenKey, IRegistryDriver, StorageBackend, RegistryRecord, NewRegistryRecord, RegistryPatch, RegistryStatus, RegCaps, GovernanceMeta, SegmentSize, } from './core/ports.js';
56
- export { CloudRoaringError, ValidationError, WriteConflictError, IntegrityError, NotFoundError, UnsupportedError, CapabilityError, TransientError, TimeoutError, KeyUnavailableError, BudgetExceededError, isCloudRoaringError, isWriteConflictError, isTransientError, isNotFoundError, isIntegrityError, isValidationError, } from './core/errors.js';
47
+ export { CloudRoaringError, ValidationError, WriteConflictError, IntegrityError, NotFoundError, UnsupportedError, CapabilityError, TransientError, KeyUnavailableError, BudgetExceededError, isCloudRoaringError, isWriteConflictError, isTransientError, isNotFoundError, isIntegrityError, isValidationError, } from './core/errors.js';
57
48
  export type { Aead, AeadSealed, IKeystore, WrappedDek, CrbmCrypto } from './core/crypto.js';
58
49
  export { aadFor } from './core/crypto.js';
59
50
  export { NodeAead, InProcessKeystore } from './drivers/crypto.js';
@@ -72,15 +63,15 @@ export type { ConsistencyReport, ConsistencyIssue, ConsistencyErrorEntry, } from
72
63
  export type { ExportFormat, ExportSink, ExportWriter, ExportOptions, ExportedSegment, ExportFailure, ExportManifest, } from './export/index.js';
73
64
  export { withRetry, DEFAULT_RETRY_POLICY } from './core/retry.js';
74
65
  export type { RetryPolicy, RetryDeps } from './core/retry.js';
75
- export { RetryingStorageChunkSource, RetryingStorageDriver, RetryingRegistryDriver, } from './drivers/retry/retrying-drivers.js';
76
- export type { RetryingOptions } from './drivers/retry/retrying-drivers.js';
66
+ export { RetryingStorageChunkSource } from './drivers/retry/retrying-chunk-source.js';
67
+ export type { RetryingOptions } from './drivers/retry/retrying-chunk-source.js';
77
68
  export { CrbmReader } from './core/crbm/reader.js';
78
69
  export type { CrbmReaderOptions } from './core/crbm/reader.js';
79
70
  export { BufferReader } from './core/blob.js';
80
71
  export type { BlobReader, BlobSink } from './core/blob.js';
81
72
  export { NOOP_METRICS, CountingMetricsSink } from './core/metrics.js';
82
73
  export type { IMetricsSink, MetricEvent, MetricOpName, MetricsSnapshot } from './core/metrics.js';
83
- export { estimateCost, DEFAULT_PRICING, AWS_US_EAST_1_ONDEMAND } from './core/cost.js';
84
- export type { PricingProfile, CostReport, Workload, SegmentSizing, EstimateInput, } from './core/cost.js';
74
+ export { estimateCost, AWS_US_EAST_1_ONDEMAND, ELASTICACHE_REDIS_US_EAST_1_ONDEMAND, ONE_REDIS_HA_CLUSTER, } from './core/cost.js';
75
+ export type { PricingProfile, RedisNodeType, RedisSizing, CostReport, Workload, SegmentSizing, EstimateInput, } from './core/cost.js';
85
76
  export { RecordingAuditSink } from './core/audit.js';
86
- export type { IAuditSink, AuditEvent, AuditEventKind } from './core/audit.js';
77
+ export type { IAuditSink, AuditEvent } from './core/audit.js';