@cloudbitmaps/roaring 0.20.0 → 0.21.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/PRIVACY.md +27 -11
- package/README.md +1 -1
- package/dist/bin/export-segments.d.ts +5 -1
- package/dist/bin/export-segments.js +497 -448
- package/dist/bin/export-segments.js.map +4 -4
- package/dist/index.d.ts +119 -47
- package/dist/index.js +474 -442
- package/dist/index.js.map +4 -4
- package/dist/lease-guards.d.ts +25 -13
- package/dist/open-charging-storage.d.ts +4 -2
- package/dist/options.d.ts +30 -0
- package/dist/portable/decode.d.ts +2 -1
- package/dist/portable/layout.d.ts +3 -2
- package/dist/testing/conformance.d.ts +2 -2
- package/dist/wire-store.d.ts +38 -0
- package/package.json +2 -2
package/dist/lease-guards.d.ts
CHANGED
|
@@ -2,17 +2,31 @@
|
|
|
2
2
|
* The checks a stream makes of a lease: before its first pull, and each time it reads a chunk. Kept apart from the store
|
|
3
3
|
* so each can be held on its own, and so a stream of another shape (a rank read, a plain iterable of ids) is wrapped by
|
|
4
4
|
* the same function.
|
|
5
|
+
*
|
|
6
|
+
* ```
|
|
7
|
+
* caller ── next() ──> guarded stream ── next() ──> engine's stream
|
|
8
|
+
* │ check before the first pull
|
|
9
|
+
* │ check again at each chunk (or each item)
|
|
10
|
+
* └─ a throwing check ends the engine's stream, then rejects
|
|
11
|
+
* return() / throw() ─────────────────────────────> engine's stream (ended / thrown into)
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* A guarded stream is its own iterator and single-use, as the engine's generator it wraps is: it answers `next`,
|
|
15
|
+
* `return` and `throw`, and iterating it gives it back.
|
|
5
16
|
*/
|
|
6
|
-
|
|
17
|
+
/** An async iterator that is also its own iterable, with `return` and `throw` always present, as a generator's are. */
|
|
18
|
+
interface GuardedStream<T> extends AsyncIterableIterator<T> {
|
|
19
|
+
return(value?: unknown): Promise<IteratorResult<T, unknown>>;
|
|
20
|
+
throw(err: unknown): Promise<IteratorResult<T, unknown>>;
|
|
21
|
+
}
|
|
7
22
|
/** What an id stream is, as far as a guard is concerned: ids, and the same ids a chunk at a time. */
|
|
8
23
|
interface IdStream extends AsyncIterable<number> {
|
|
9
24
|
batches(): AsyncIterable<Uint32Array>;
|
|
10
25
|
}
|
|
11
|
-
/**
|
|
12
|
-
type
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}>;
|
|
26
|
+
/** An id stream that is guarded: the per-id stream is an iterator of its own, and `batches()` is guarded too. */
|
|
27
|
+
type GuardedIds = GuardedStream<number> & {
|
|
28
|
+
batches(): GuardedStream<Uint32Array>;
|
|
29
|
+
};
|
|
16
30
|
/**
|
|
17
31
|
* A stream of ascending ids that checks a lease before it first pulls, and each time it reads a chunk after that: once
|
|
18
32
|
* the engine has the next chunk and before an id of it is yielded, so nothing of a chunk fetched past the lease is
|
|
@@ -21,14 +35,12 @@ type ChunkStream = AsyncIterable<{
|
|
|
21
35
|
* engine's reads. Used only when a handle in the call holds a lease: a call with none returns the engine's stream
|
|
22
36
|
* untouched. It takes any async iterable of ids, so a stream with no `.batches()` (a rank read) is wrapped the same way.
|
|
23
37
|
*/
|
|
24
|
-
export declare const guardIdIterable: (inner: AsyncIterable<number>, check: () => void) =>
|
|
38
|
+
export declare const guardIdIterable: (inner: AsyncIterable<number>, check: () => void) => GuardedStream<number>;
|
|
25
39
|
/** {@link guardIdIterable} for an `IdStream`, whose `.batches()` is guarded too. */
|
|
26
|
-
export declare const guardIds: (inner: IdStream, check: () => void) =>
|
|
40
|
+
export declare const guardIds: (inner: IdStream, check: () => void) => GuardedIds;
|
|
27
41
|
/**
|
|
28
|
-
* A stream of chunks
|
|
29
|
-
*
|
|
42
|
+
* A stream of chunks that checks a lease before the first pull and before each item is handed on: an item is one
|
|
43
|
+
* chunk (a batch of ids, or a chunk an `*Into` writes).
|
|
30
44
|
*/
|
|
31
|
-
export declare const guardItems: <T>(inner: AsyncIterable<T>, check: () => void) =>
|
|
32
|
-
/** A chunk stream (what an `*Into` writes) that checks a lease before the first pull and before each chunk. */
|
|
33
|
-
export declare const guardChunks: (inner: ChunkStream, check: () => void) => ChunkStream;
|
|
45
|
+
export declare const guardItems: <T>(inner: AsyncIterable<T>, check: () => void) => GuardedStream<T>;
|
|
34
46
|
export {};
|
|
@@ -10,8 +10,10 @@
|
|
|
10
10
|
*
|
|
11
11
|
* Two opens are never charged, because the segment's unit already pays for them: the generation the row named when
|
|
12
12
|
* the scan listed it, which every erasure must read to decide membership, and an object this call wrote itself,
|
|
13
|
-
* which it reads back to verify. A refusal here comes from a read
|
|
14
|
-
* come
|
|
13
|
+
* which it reads back to verify. A refusal here comes from a read. Most of an erasure's reads that can be refused come
|
|
14
|
+
* before its deletes; two kinds come after one: the look for a holder left once the call has deleted, and the zero-byte
|
|
15
|
+
* read of a generation the call deleted that the row then names. A refusal of either is thrown in place of the call's
|
|
16
|
+
* answer, so the call reports the budget, not what it deleted.
|
|
15
17
|
*/
|
|
16
18
|
import type { GenKey, IStorageDriver, SegmentRef, StorageDeleteOptions } from '@cloudbitmaps/core';
|
|
17
19
|
export declare class OpenChargingStorage implements IStorageDriver {
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The shape checks every call that takes an options bag makes before it reads or writes anything: the bag is an
|
|
3
|
+
* object, it names only keys the call takes, and each switch is a boolean. The per-call key tables stay with the
|
|
4
|
+
* facade, because each is held to the options type it describes.
|
|
5
|
+
*/
|
|
6
|
+
import { ValidationError } from '@cloudbitmaps/core';
|
|
7
|
+
/** A key of `T` that `K` does not list: a key table missing one fails to compile. */
|
|
8
|
+
type Unlisted<T, K extends readonly PropertyKey[]> = Exclude<keyof T, K[number]>;
|
|
9
|
+
/** The keys of `T`, every one of them, as a table the options check below reads. */
|
|
10
|
+
export declare const keysOf: <T>() => <const K extends readonly (keyof T & string)[]>(keys: K & ([Unlisted<T, K>] extends [never] ? unknown : never)) => readonly string[];
|
|
11
|
+
/** How a value of the wrong kind is named in a message: by its kind, never by its content. */
|
|
12
|
+
export declare const kindOf: (v: unknown) => string;
|
|
13
|
+
/**
|
|
14
|
+
* Why `options` cannot be a call's options, or `undefined` when it can. `undefined` and `null` read as none; anything
|
|
15
|
+
* but an object is refused, and so is a key `known` does not list, unless its value is `undefined`, so a spread of
|
|
16
|
+
* options keeps working; and each of `booleans` present must be a boolean, `null` included. A bag of the wrong shape, a misspelt key or
|
|
17
|
+
* a switch given as a string would otherwise read as no option at all, and silently widen what the call does: a scope
|
|
18
|
+
* passed as a string swept every namespace, and `dryRun: 'true'` deleted.
|
|
19
|
+
*/
|
|
20
|
+
export declare function optionsError(options: unknown, op: string, known: readonly string[], booleans?: readonly string[]): ValidationError | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* The keys of `options` a call takes, each read by name. A spread copies only own enumerable properties, so an option
|
|
23
|
+
* held in a getter or inherited from a prototype, which TypeScript accepts and {@link optionsError} reads, would pass
|
|
24
|
+
* the checks and then be dropped: a `dryRun` so held ran a real sweep, and a `namespace` exported every tenant. The
|
|
25
|
+
* call then reads the copy only, so it runs with exactly what was checked.
|
|
26
|
+
*/
|
|
27
|
+
export declare function picked<T extends object>(options: T | null | undefined, keys: readonly string[]): Partial<T>;
|
|
28
|
+
/** {@link optionsError}, thrown: for a call that rejects, rather than one that returns a stream. */
|
|
29
|
+
export declare function checkOptions(options: unknown, op: string, known: readonly string[], booleans?: readonly string[]): void;
|
|
30
|
+
export {};
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Construction checks every container once, in {@link parsePortableLayout}, which is the same check the native
|
|
5
5
|
* path runs; after that a membership test reads one container rather than materializing the set.
|
|
6
6
|
*/
|
|
7
|
-
|
|
7
|
+
declare class PortableRoaringReader {
|
|
8
8
|
private readonly view;
|
|
9
9
|
private readonly containers;
|
|
10
10
|
private constructor();
|
|
@@ -51,3 +51,4 @@ export declare class PortableRoaringReader {
|
|
|
51
51
|
}
|
|
52
52
|
/** Convenience wrapper over {@link PortableRoaringReader.decode}. */
|
|
53
53
|
export declare function decodePortableRoaring(bytes: Uint8Array): PortableRoaringReader;
|
|
54
|
+
export {};
|
|
@@ -4,8 +4,8 @@ export declare const ARRAY = 0;
|
|
|
4
4
|
/** A container of 65,536 bits. */
|
|
5
5
|
export declare const BITMAP = 1;
|
|
6
6
|
/** A container of `(start, length)` runs. */
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
declare const RUN = 2;
|
|
8
|
+
type ContainerKind = typeof ARRAY | typeof BITMAP | typeof RUN;
|
|
9
9
|
export interface PortableContainer {
|
|
10
10
|
/** High 16 bits of every value in this container. */
|
|
11
11
|
readonly key: number;
|
|
@@ -49,3 +49,4 @@ export declare function checkPortableLayout(bytes: Uint8Array): number;
|
|
|
49
49
|
* @throws {IntegrityError} at the first container that runs past the buffer or does not hold what its header says.
|
|
50
50
|
*/
|
|
51
51
|
export declare function containerPayloads(bytes: Uint8Array): Generator<EncodedChunk>;
|
|
52
|
+
export {};
|
|
@@ -19,8 +19,8 @@ export type StorageDriverCase = 'write-once round trip' | 'collision' | 'collisi
|
|
|
19
19
|
/**
|
|
20
20
|
* Contract tests for an {@link IStorageDriver} — the contract its doc comment lists: write-once with
|
|
21
21
|
* `WriteConflictError` on a collision, `NotFoundError` for a missing object, `ValidationError` for an out-of-range
|
|
22
|
-
* read, `getTail`'s true total size, idempotent `delete` (of an absent key too, with neighbours present)
|
|
23
|
-
* that is read-after-delete, and a `delete` given `ifVersion` that does what `conditionalDelete` says. `makeDriver`
|
|
22
|
+
* read, `getTail`'s true total size, idempotent `delete` (of an absent key too, with neighbours present) after which a
|
|
23
|
+
* read of the key is `NotFoundError` at once, a `list` that is read-after-delete, and a `delete` given `ifVersion` that does what `conditionalDelete` says. `makeDriver`
|
|
24
24
|
* MUST return a driver over an empty, isolated keyspace on each call.
|
|
25
25
|
*
|
|
26
26
|
* `skip` names the cases a backend cannot exercise (a local emulator that does not model a contract), so each
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Clock, IMetricsSink, IKeystore, IRegistryDriver, IStorageDriver, RetryPolicy, RetryingOptions, Rng, StorageChunkSource } from '@cloudbitmaps/core';
|
|
2
|
+
/** The slice of a store's options the wiring reads; `CloudRoaringOptions` satisfies it. */
|
|
3
|
+
interface StoreWiring {
|
|
4
|
+
readonly storage: unknown;
|
|
5
|
+
readonly encryption?: {
|
|
6
|
+
readonly keystore?: IKeystore;
|
|
7
|
+
readonly required?: boolean;
|
|
8
|
+
};
|
|
9
|
+
readonly cache?: {
|
|
10
|
+
readonly genTtlMs?: number;
|
|
11
|
+
readonly readerMax?: number;
|
|
12
|
+
readonly readerMaxBytes?: number;
|
|
13
|
+
};
|
|
14
|
+
readonly retry?: (Partial<RetryPolicy> & {
|
|
15
|
+
readonly onRetry?: (info: {
|
|
16
|
+
attempt: number;
|
|
17
|
+
delayMs: number;
|
|
18
|
+
err: unknown;
|
|
19
|
+
}) => void;
|
|
20
|
+
}) | false;
|
|
21
|
+
}
|
|
22
|
+
/** What {@link wireStore} builds for the constructor. */
|
|
23
|
+
interface WiredStore {
|
|
24
|
+
/** What the engine reads through: the source, wrapped in the read retry unless it is off. */
|
|
25
|
+
readonly storage: StorageChunkSource;
|
|
26
|
+
/** The resolved source before the retry wrapper. */
|
|
27
|
+
readonly source: StorageChunkSource;
|
|
28
|
+
readonly driver: IStorageDriver | undefined;
|
|
29
|
+
readonly registry: IRegistryDriver | undefined;
|
|
30
|
+
/** The read retry the store shares with its lifecycle reads; `undefined` when retry is off. */
|
|
31
|
+
readonly retryOptions: RetryingOptions | undefined;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Resolve the storage seam, hand a backend the metrics sink, and wrap the source in the read retry. Refusals come in
|
|
35
|
+
* that order: a bad `storage` first, then a bad `retry`.
|
|
36
|
+
*/
|
|
37
|
+
export declare function wireStore(options: StoreWiring, clock: Clock, rng: Rng, metrics: IMetricsSink): WiredStore;
|
|
38
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloudbitmaps/roaring",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
4
4
|
"description": "Distributed, cloud-native Roaring Bitmaps — query and intersect billion-scale integer sets straight out of object storage, from a bounded RAM cache over immutable objects in your own bucket, at a fraction of an always-on cache.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"roaring",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
},
|
|
66
66
|
"dependencies": {
|
|
67
67
|
"roaring": "2.7.0",
|
|
68
|
-
"@cloudbitmaps/core": "^0.
|
|
68
|
+
"@cloudbitmaps/core": "^0.21.0"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
71
|
"@types/node": "^22.0.0",
|