@cloudbitmaps/core 0.23.0 → 0.25.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/README.md +0 -9
- package/dist/{chunk-MVUD4R72.js → chunk-2B2QF4FU.js} +6 -1
- package/dist/chunk-2B2QF4FU.js.map +7 -0
- package/dist/{chunk-7GT632UF.js → chunk-45ML6YU4.js} +2 -2
- package/dist/{chunk-CGILDXGP.js → chunk-BUDAVGBI.js} +2 -2
- package/dist/{chunk-GKHERVVQ.js → chunk-WPER7R2R.js} +2 -2
- package/dist/core/check.d.ts +2 -1
- package/dist/core/codec.d.ts +16 -6
- package/dist/core/cooperative.d.ts +9 -6
- package/dist/core/crbm/reader.d.ts +1 -1
- package/dist/core/engine.d.ts +1 -1
- package/dist/core/erase-id.d.ts +1 -1
- package/dist/core/load-input.d.ts +10 -4
- package/dist/core/load.d.ts +2 -2
- package/dist/driver-kit.js +3 -3
- package/dist/index.d.ts +2 -2
- package/dist/index.js +135 -82
- package/dist/index.js.map +2 -2
- package/dist/node.js +3 -3
- package/dist/node.js.map +1 -1
- package/package.json +1 -2
- package/dist/chunk-MVUD4R72.js.map +0 -7
- /package/dist/{chunk-7GT632UF.js.map → chunk-45ML6YU4.js.map} +0 -0
- /package/dist/{chunk-CGILDXGP.js.map → chunk-BUDAVGBI.js.map} +0 -0
- /package/dist/{chunk-GKHERVVQ.js.map → chunk-WPER7R2R.js.map} +0 -0
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
requirePositiveInteger,
|
|
20
20
|
shown,
|
|
21
21
|
tailBytesFit
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-2B2QF4FU.js";
|
|
23
23
|
|
|
24
24
|
// src/drivers/_shared/options.ts
|
|
25
25
|
function checkNow(name, now) {
|
|
@@ -638,4 +638,4 @@ export {
|
|
|
638
638
|
namespaceKeyPart,
|
|
639
639
|
namespacePathPart
|
|
640
640
|
};
|
|
641
|
-
//# sourceMappingURL=chunk-
|
|
641
|
+
//# sourceMappingURL=chunk-45ML6YU4.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
requirePositiveInteger
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-2B2QF4FU.js";
|
|
4
4
|
|
|
5
5
|
// src/core/concurrency.ts
|
|
6
6
|
async function mapWithConcurrency(items, limit, fn) {
|
|
@@ -70,4 +70,4 @@ export {
|
|
|
70
70
|
mapWithConcurrency,
|
|
71
71
|
boundedAll
|
|
72
72
|
};
|
|
73
|
-
//# sourceMappingURL=chunk-
|
|
73
|
+
//# sourceMappingURL=chunk-BUDAVGBI.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ValidationError,
|
|
3
3
|
encodeNameForKey
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-2B2QF4FU.js";
|
|
5
5
|
|
|
6
6
|
// src/core/keys.ts
|
|
7
7
|
var FIELD = " ";
|
|
@@ -118,4 +118,4 @@ export {
|
|
|
118
118
|
BufferSink,
|
|
119
119
|
BufferReader
|
|
120
120
|
};
|
|
121
|
-
//# sourceMappingURL=chunk-
|
|
121
|
+
//# sourceMappingURL=chunk-WPER7R2R.js.map
|
package/dist/core/check.d.ts
CHANGED
|
@@ -33,7 +33,8 @@ export declare function requireFiniteNumber(value: unknown, bounds: {
|
|
|
33
33
|
/**
|
|
34
34
|
* Refuse an options bag that is not an object, or that holds a key not in `keys`, naming each such key and the keys it
|
|
35
35
|
* takes. `hint`, when given, ends the message, to point at where a likely mistake belongs (`an S3 client goes in
|
|
36
|
-
* \`client\``). Only the bag's own enumerable string keys are read
|
|
36
|
+
* \`client\``). Only the bag's own enumerable string keys are read, so a key inherited through a prototype is not
|
|
37
|
+
* checked.
|
|
37
38
|
*/
|
|
38
39
|
export declare function refuseUnknownOptions(name: string, options: unknown, keys: readonly string[], hint?: string): void;
|
|
39
40
|
/**
|
package/dist/core/codec.d.ts
CHANGED
|
@@ -16,9 +16,9 @@
|
|
|
16
16
|
* different codecs, or a cached bitmap from codec A could reach codec B's in-place op. The `CloudRoaring` facade
|
|
17
17
|
* mints the cache per store, so this cannot arise in normal use.)
|
|
18
18
|
*
|
|
19
|
-
* **Interface surface = exactly what the engine needs**,
|
|
20
|
-
* (positional/
|
|
21
|
-
*
|
|
19
|
+
* **Interface surface = exactly what the engine needs**, and nothing a codec might one day offer: an operation the
|
|
20
|
+
* engine never calls (positional or rank/select access, say) is not on {@link CodecBitmap}, and a second codec that
|
|
21
|
+
* has such operations would carry them on its own value type. The one codec-linked concern
|
|
22
22
|
* this seam intentionally leaves in the format layer is the `.crbm` **payload codec id**
|
|
23
23
|
* (`PAYLOAD_CODEC_ROARING_PORTABLE` / `KNOWN_PAYLOAD_CODEC_IDS` in `crbm/format.ts`): it is stamped in the footer
|
|
24
24
|
* and validated on read, as membership of a registry rather than equality with one constant, so a codec-specific
|
|
@@ -54,7 +54,7 @@ export interface CodecBitmap {
|
|
|
54
54
|
toArray(): number[];
|
|
55
55
|
/**
|
|
56
56
|
* The set's values as one ascending `Uint32Array` the caller owns: what a batch read converts a chunk with, in one
|
|
57
|
-
*
|
|
57
|
+
* step instead of one iterator step per value.
|
|
58
58
|
*
|
|
59
59
|
* **Optional.** A codec without it is read through its iterator, which is correct and slower.
|
|
60
60
|
*
|
|
@@ -125,7 +125,7 @@ export interface EncodedChunk {
|
|
|
125
125
|
}
|
|
126
126
|
/**
|
|
127
127
|
* A pluggable bitmap codec — the factory the codec-agnostic engine constructs {@link CodecBitmap}s through.
|
|
128
|
-
* Implementations **must** size-cap before handing untrusted bytes to
|
|
128
|
+
* Implementations **must** size-cap before handing untrusted bytes to a decoder and use a safe
|
|
129
129
|
* (never a trusting/frozen) deserializer — hard invariant 5.
|
|
130
130
|
*/
|
|
131
131
|
export interface CodecInterface {
|
|
@@ -135,7 +135,7 @@ export interface CodecInterface {
|
|
|
135
135
|
fromValues(values: Iterable<number>): CodecBitmap;
|
|
136
136
|
/**
|
|
137
137
|
* Size-cap (`bytes.length <= maxBytes`) then portable-deserialize. Throws `IntegrityError` when the input
|
|
138
|
-
* exceeds the cap or fails to decode — the
|
|
138
|
+
* exceeds the cap or fails to decode — the decoder is never handed unbounded or unsafe-format input.
|
|
139
139
|
*
|
|
140
140
|
* "Fails to decode" includes bytes that are the right length and the wrong shape. A bitmap this returns must
|
|
141
141
|
* satisfy every invariant its own operations assume (for roaring: containers and values in order, runs
|
|
@@ -161,6 +161,16 @@ export interface CodecInterface {
|
|
|
161
161
|
* The answer is the whole check: an `owns` that answers `true` for anything lets any object through as a bitmap.
|
|
162
162
|
*/
|
|
163
163
|
owns?(bitmap: unknown): boolean;
|
|
164
|
+
/**
|
|
165
|
+
* Whether an intersect of three or more operands should meet each chunk's operands smallest-first (by `size`).
|
|
166
|
+
*
|
|
167
|
+
* **Optional, and off by default.** A codec whose combine cost depends on the order, because an early operand that is
|
|
168
|
+
* large and of one container kind makes the running result expensive, sets it; the engine then pays one `size` read per
|
|
169
|
+
* operand per chunk to put the sparsest first. A codec whose combines cost about the same in any order, or whose
|
|
170
|
+
* `size` is expensive to read, leaves it out and keeps the operand order it was given. The answer is the
|
|
171
|
+
* same either way.
|
|
172
|
+
*/
|
|
173
|
+
readonly intersectSmallestFirst?: boolean;
|
|
164
174
|
}
|
|
165
175
|
/**
|
|
166
176
|
* Resolve a codec that a **public core entry point** was given, failing fast when it is missing.
|
|
@@ -3,13 +3,16 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Everything this library does on the hot read path is small. Bulk-load is the exception: it is the one place
|
|
5
5
|
* where a single call legitimately occupies the CPU for hundreds of milliseconds, and Node has exactly one thread
|
|
6
|
-
* to occupy. Measured on
|
|
7
|
-
*
|
|
6
|
+
* to occupy. Measured on the native codec of 0.23.0 (every figure in this header is the native codec's, to be
|
|
7
|
+
* re-measured on the TypeScript codec), on a 1M-id load of 65,536 chunks onto in-memory storage, on a loaded Apple M3
|
|
8
|
+
* Pro: **518 ms wall, and 519 ms during which the event loop did not turn at all** (medians of 20 fresh-process
|
|
9
|
+
* runs). Wire that to a request handler and every other in-flight request on the instance — health
|
|
8
10
|
* checks included — waits out the whole load.
|
|
9
11
|
*
|
|
10
|
-
* The fix is not to make the work asynchronous. That was measured too,
|
|
11
|
-
* chunk's insert to the threadpool
|
|
12
|
-
* across ~62,000 chunks (636 ms versus 92 ms). The
|
|
12
|
+
* The fix is not to make the work asynchronous. That was measured too, on the native codec's threadpool insert, and
|
|
13
|
+
* it was a 7x *regression*: handing each chunk's insert to the threadpool cost ~9 µs of dispatch against ~1.5 µs of
|
|
14
|
+
* actual work once ids are spread across ~62,000 chunks (636 ms versus 92 ms). The TypeScript codec has no
|
|
15
|
+
* threadpool path. The work is genuinely CPU-bound and genuinely small per chunk;
|
|
13
16
|
* the only thing wrong with it is that it never stops to let anyone else go. So the fix is to keep the work
|
|
14
17
|
* synchronous and periodically hand the loop back.
|
|
15
18
|
*
|
|
@@ -19,7 +22,7 @@
|
|
|
19
22
|
* the microtask queue drains to empty before the event loop advances a single phase. A loop awaiting them
|
|
20
23
|
* yields to other *microtasks* and to nothing else; no pending I/O callback runs. Measured: 555 ms of
|
|
21
24
|
* starvation against a 568 ms unyielded baseline **on the synthetic yield-primitive benchmark below** —
|
|
22
|
-
* a different, smaller workload than the
|
|
25
|
+
* a different, smaller workload than the 518 ms end-to-end load above, which is why the two baselines
|
|
23
26
|
* differ. The yield must be a **macrotask** — hence
|
|
24
27
|
* `Clock.yieldNow`, backed by `setImmediate` in production wiring.
|
|
25
28
|
* 2. **Yielding per unit of work costs more than the work.** The yield has to be periodic, and `everyN` has to be
|
|
@@ -179,7 +179,7 @@ export declare class CrbmReader {
|
|
|
179
179
|
has(chunkKey: number): boolean;
|
|
180
180
|
/**
|
|
181
181
|
* Range-GET one chunk's payload, verifying its CRC32C before returning. Returns `null` if the chunk is
|
|
182
|
-
* absent. Throws `IntegrityError` on a CRC mismatch (the bytes must never reach the
|
|
182
|
+
* absent. Throws `IntegrityError` on a CRC mismatch (the bytes must never reach the codec's
|
|
183
183
|
* deserializer). The returned bytes may be shared (a small generation's chunks are kept by the reader and handed out
|
|
184
184
|
* again), so callers must not change them.
|
|
185
185
|
*/
|
package/dist/core/engine.d.ts
CHANGED
|
@@ -401,7 +401,7 @@ export declare class SegmentEngine {
|
|
|
401
401
|
* The AND (or OR) of one chunk key across all operands, minus the excludes that hold it, or `null` if empty.
|
|
402
402
|
* Operand chunks are fetched **in parallel** (the spec's parallel byte-range reads).
|
|
403
403
|
*
|
|
404
|
-
* The accumulator is a **clone** of
|
|
404
|
+
* The accumulator is a **clone** of one operand's chunk (the first, or for a codec that asks the one with the fewest values), and that clone is load-bearing: every other
|
|
405
405
|
* bitmap here is the cached, shared Storage instance and must never be mutated, or the cache is poisoned for
|
|
406
406
|
* every later reader. The remaining operands and the excludes are only *read* by the in-place ops, so they are
|
|
407
407
|
* used as-is — one clone per key, not one per operand.
|
package/dist/core/erase-id.d.ts
CHANGED
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
* its number after the winner's object was already in the bucket. Up there nothing collects it, and it was derived
|
|
67
67
|
* from a generation the winner has replaced, so when the winner was another erasure it still holds the id that
|
|
68
68
|
* erasure has just reported gone. That object is deleted before this call returns, once its footer matches the
|
|
69
|
-
* rewrite's and a renewal of the row has refused every publish fenced on a row read before it, under the version the
|
|
69
|
+
* rewrite's (a read of it that faults is thrown instead, and the object stays) and a renewal of the row has refused every publish fenced on a row read before it, under the version the
|
|
70
70
|
* footer read reported, unless {@link DISCARD_ATTEMPTS} renewals lose to other writes (a load, a rollback, a
|
|
71
71
|
* retention write): then it is kept, and can hold the winner's id, until a later call takes it: any erasure that
|
|
72
72
|
* rewrites the segment (this one's re-run among them, while its id is still in the current generation) numbers above it
|
|
@@ -115,10 +115,16 @@ export declare function prepareLoadInput(input: LoadInput, codec: CodecInterface
|
|
|
115
115
|
* input of a load goes through, and what a flavor offers its users to decode bytes they hold themselves.
|
|
116
116
|
*
|
|
117
117
|
* The bytes must be a `Uint8Array` (a Node `Buffer` is one), at most {@link MAX_SERIALIZED_LOAD_BYTES}, one whole
|
|
118
|
-
* bitmap and structurally sound. A view is read over the bytes it really holds, and
|
|
119
|
-
* are copied first. An empty or detached
|
|
118
|
+
* bitmap and structurally sound. A view is read over the bytes it really holds, once, and the size checks, the
|
|
119
|
+
* copy and the decode all use that one view. Bytes in a `SharedArrayBuffer` are copied first. An empty or detached
|
|
120
|
+
* buffer is the empty bitmap, unless `refuseEmpty` is set.
|
|
120
121
|
*
|
|
121
122
|
* @param what names the input in a refusal's message.
|
|
122
|
-
* @
|
|
123
|
+
* @param options `maxBytes` lowers the size cap for this call (it cannot raise it); `refuseEmpty` refuses an empty or
|
|
124
|
+
* detached buffer, which is not a bitmap.
|
|
125
|
+
* @throws {ValidationError} for anything that is not such bytes; nothing reaches the codec's decoder then.
|
|
123
126
|
*/
|
|
124
|
-
export declare function decodeSerialized(bytes: unknown, codec: CodecInterface, what?: string
|
|
127
|
+
export declare function decodeSerialized(bytes: unknown, codec: CodecInterface, what?: string, options?: {
|
|
128
|
+
readonly maxBytes?: number;
|
|
129
|
+
readonly refuseEmpty?: boolean;
|
|
130
|
+
}): CodecBitmap;
|
package/dist/core/load.d.ts
CHANGED
|
@@ -148,8 +148,8 @@ export interface LoadOptions {
|
|
|
148
148
|
* `ValidationError`, naming its position and never the id. The object is the same, byte for byte, as an unsorted load
|
|
149
149
|
* of the same ids writes under the same write identity.
|
|
150
150
|
*
|
|
151
|
-
* For ids only (an iterable or an async iterable): with `{ serialized }`, `{ bitmap }` or a
|
|
152
|
-
*
|
|
151
|
+
* For ids only (an iterable or an async iterable): with `{ serialized }`, `{ bitmap }` or a bitmap itself (an
|
|
152
|
+
* iterable with a `serialize` method, which a flavor loads as `{ bitmap }`), and on core's
|
|
153
153
|
* `loadSegmentChunks`, it throws `ValidationError`, as does a value that is not a boolean, before any request.
|
|
154
154
|
*
|
|
155
155
|
* The ids are read after the segment's row is read and judged, and after its number and key are settled, so a load
|
package/dist/driver-kit.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
mapWithConcurrency
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-BUDAVGBI.js";
|
|
4
4
|
import {
|
|
5
5
|
DEFAULT_NAMESPACE,
|
|
6
6
|
applyRegistryPatch,
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
validateNewRegistryRecord,
|
|
19
19
|
validateRegistryPatch,
|
|
20
20
|
webCryptoEntropy
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-45ML6YU4.js";
|
|
22
22
|
import {
|
|
23
23
|
CloudRoaringError,
|
|
24
24
|
IntegrityError,
|
|
@@ -45,7 +45,7 @@ import {
|
|
|
45
45
|
requireNonEmptyString,
|
|
46
46
|
unsettledConflict,
|
|
47
47
|
validateSegmentRef
|
|
48
|
-
} from "./chunk-
|
|
48
|
+
} from "./chunk-2B2QF4FU.js";
|
|
49
49
|
|
|
50
50
|
// src/drivers/_shared/object-registry-keys.ts
|
|
51
51
|
var REGISTRY_SUFFIX = ".reg";
|
package/dist/index.d.ts
CHANGED
|
@@ -24,7 +24,7 @@ export { BoundedLru } from './core/lru.js';
|
|
|
24
24
|
export { safeMetrics } from './core/metrics.js';
|
|
25
25
|
export { runExport } from './export/index.js';
|
|
26
26
|
export type { SegmentReader } from './export/index.js';
|
|
27
|
-
export { splitId } from './core/bit-route.js';
|
|
27
|
+
export { splitId, refusalOfId } from './core/bit-route.js';
|
|
28
28
|
export { mapWithConcurrency } from './core/concurrency.js';
|
|
29
29
|
export { resolveBudget, resolvePerOpBudget, checkBudget, collectWithinBudget } from './core/budget.js';
|
|
30
30
|
export { segmentExists, listSegments } from './core/discover.js';
|
|
@@ -43,7 +43,7 @@ export { compileCombineMany, rebindCombineMany, runCombineMany } from './core/co
|
|
|
43
43
|
export type { CombineManyDeps, CombineManyFeed, CombineManyOperand, CombineManyOutcome, CombineManyOutput, CombineManyRequest, CombineManyRun, CombineManyWrite, CompiledCombineMany, Expr, MaterializeManyFeedRecord, MaterializeManyOperandStats, MaterializeManyOutputStats, MaterializeManyStats, } from './core/combine-many.js';
|
|
44
44
|
export type { LoadDeps, LoadOptions, LoadGuard, GuardRefusal, LoadJudgement, LoadResult, LoadRefusal, } from './core/load.js';
|
|
45
45
|
export type { LoadInput, PortableBitmap } from './core/load-input.js';
|
|
46
|
-
export { decodeSerialized } from './core/load-input.js';
|
|
46
|
+
export { decodeSerialized, MAX_SERIALIZED_LOAD_BYTES } from './core/load-input.js';
|
|
47
47
|
export { listGenerations, rollbackSegment } from './core/rollback.js';
|
|
48
48
|
export type { GenerationListDeps, GenerationEntry, RollbackResult } from './core/rollback.js';
|
|
49
49
|
export { eraseIdFromSegment, findIdUnderTombstone } from './core/erase-id.js';
|