@cloudbitmaps/roaring 0.18.0 → 0.18.1
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 +2 -2
- package/README.md +8 -2
- package/dist/bin/export-segments.js +4 -3
- package/dist/bin/export-segments.js.map +2 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +4 -3
- package/dist/index.js.map +2 -2
- package/package.json +2 -2
package/PRIVACY.md
CHANGED
|
@@ -45,7 +45,7 @@ from constructing a cross-region topology. The points where personal data moves
|
|
|
45
45
|
| **Storage** (object store) | immutable `.crbm` generations — every generation a segment has had, until a superseded one is collected. Azure Blob objects, and GCS objects above the simple-upload threshold, also carry a random write id in their metadata (`cbwid`): 128 random bits, no data from the bitmap or the source | the region of the bucket you wire |
|
|
46
46
|
| **Registry** (S3 / GCS / Azure Blob / local) | one row per segment: the current-generation pointer, wrapped keys, retention metadata, and the current generation's id count and your metadata (sealed when the segment is encrypted) — no IDs, unless you put one in the metadata, which you must not. An Azure Blob row also carries the random write id in its metadata | the region of the bucket you wire |
|
|
47
47
|
| **cache** (process RAM) | decoded chunks, and the stored chunk bytes (ciphertext on an encrypted segment) a reader keeps of a small generation it read whole; bounded LRU | **wherever your process/Lambda runs** — an EU segment queried from a US function is processed in the US |
|
|
48
|
-
| **Loads and rewrites** (`store.load()`, the `*Into` verbs, `eraseSubject`) | read your source (or existing generations), write a new generation | run wherever you run them — a loader in one region writing to a bucket in another is a transfer |
|
|
48
|
+
| **Loads and rewrites** (`store.load()`, the `*Into` verbs, `store.materializeMany()`, `eraseSubject`) | read your source (or existing generations), write a new generation; a fed or held operand of `materializeMany` is read from your own process's memory | run wherever you run them — a loader in one region writing to a bucket in another is a transfer |
|
|
49
49
|
| **Intersection** | pulls chunks from N segments into one process | co-locates those segments in one region |
|
|
50
50
|
|
|
51
51
|
**Guidance (not enforced by the library):** to keep EU data in EU infrastructure, wire region-local drivers
|
|
@@ -203,7 +203,7 @@ single-subject erasure is a rewrite (`eraseSubject`), while crypto-shred (`destr
|
|
|
203
203
|
handles segment/tenant-level erasure and is the only erasure that reaches immutable backups / WORM copies of the
|
|
204
204
|
objects — once no copy of the segment's registry row still holds its wrapped key, or every KEK that wrapped it
|
|
205
205
|
is destroyed (below). And a
|
|
206
|
-
**materialized segment** (`intersectInto` / `unionInto` / `andNotInto`) is a point-in-time snapshot of its
|
|
206
|
+
**materialized segment** (`intersectInto` / `unionInto` / `andNotInto`, or an output of `materializeMany`) is a point-in-time snapshot of its
|
|
207
207
|
inputs: erasing a subject from a source does not touch a destination computed earlier — which is exactly why
|
|
208
208
|
`eraseSubject` scans *every* registered segment, destinations included, rather than erasing per source. What that
|
|
209
209
|
costs is one unit of the per-op `budget` for each segment, and one more for each generation it opens in a segment
|
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ file, then ask `has`, `count`, `iterate`, `intersect`, `union` and `andNot`, wit
|
|
|
7
7
|
> **ESM-only, Node ≥ 22.12.** Use `import`; for `require()`, Jest and TypeScript, see
|
|
8
8
|
> [CommonJS, Jest and TypeScript](https://github.com/cloudbitmaps/cloudbitmaps/blob/main/docs/guide/getting-started.md#commonjs-jest-and-typescript).
|
|
9
9
|
|
|
10
|
-
> Pre-1.0: the API and the on-disk format can still change.
|
|
10
|
+
> Pre-1.0: the API and the on-disk format can still change. On npm these docs match the version they ship in; on GitHub they describe `main`, and the changelog says what each release changed.
|
|
11
11
|
|
|
12
12
|
## Install
|
|
13
13
|
|
|
@@ -52,6 +52,11 @@ request handler. `store.exists(ref)` says whether a segment has been loaded. A l
|
|
|
52
52
|
hold: `store.load(ref, { bitmap })` for a `RoaringBitmap32`, or `{ serialized }` for portable Roaring bytes, checked
|
|
53
53
|
before anything is written and loaded with no per-id work, into the same bytes its ids would write.
|
|
54
54
|
|
|
55
|
+
To write many results over the same stored operands, `store.materializeMany` reads each operand once for a whole batch of
|
|
56
|
+
`and` / `or` / `andNot` outputs instead of once per `*Into` call, and `store.memory(ids)` holds a set you already have in
|
|
57
|
+
memory as an operand of that batch. [Many outputs from one pass](https://github.com/cloudbitmaps/cloudbitmaps/blob/main/docs/guide/loading.md#many-outputs-from-one-pass-materializemany) and
|
|
58
|
+
[held operands](https://github.com/cloudbitmaps/cloudbitmaps/blob/main/docs/guide/loading.md#operands-held-in-memory-storememory) cover both.
|
|
59
|
+
|
|
55
60
|
## Options
|
|
56
61
|
|
|
57
62
|
`new CloudRoaring({ storage, ...options })`. Only `storage` is required. A key the store does not take is refused by
|
|
@@ -93,7 +98,8 @@ The [production checklist](https://github.com/cloudbitmaps/cloudbitmaps/blob/mai
|
|
|
93
98
|
## Coming from Redis bitmaps?
|
|
94
99
|
|
|
95
100
|
`GETBIT` is `has`, `BITCOUNT` is `count`, and `BITOP AND` / `OR` / `DIFF` are `intersect` / `union` / `andNot`, with
|
|
96
|
-
`intersectInto`, `unionInto` and `andNotInto` publishing the result as a new generation
|
|
101
|
+
`intersectInto`, `unionInto` and `andNotInto` publishing the result as a new generation, and `materializeMany` publishing
|
|
102
|
+
many such results from one pass. `EXPIRE` becomes
|
|
97
103
|
`setRetention` plus a `retireExpired` sweep you schedule, per segment, never per id. `SETBIT` has no equivalent:
|
|
98
104
|
there is no per-id write. Build the set upstream and load it, and do not loop one id at a time. Remove one id
|
|
99
105
|
everywhere with `eraseSubject`, a rewrite for compliance, not a hot-path verb. This is not a drop-in replacement, and
|
|
@@ -1131,8 +1131,9 @@ var CloudRoaring = class _CloudRoaring {
|
|
|
1131
1131
|
*
|
|
1132
1132
|
* **Every pinned operand an output subtracts is re-checked.** An output subtracts an operand when it is in its `exclude`
|
|
1133
1133
|
* or under any entry of an `andNot` after the first, at any depth. Immediately before the publishes the call re-reads the
|
|
1134
|
-
* registry row of each such operand and compares its generation and incarnation
|
|
1135
|
-
*
|
|
1134
|
+
* registry row of each such operand and compares its generation and incarnation, and the fingerprint of the current
|
|
1135
|
+
* object where both reads carry one, with what was pinned (a name deleted and created again is a replacement though it
|
|
1136
|
+
* is generation 0 again). If one was replaced, each output that subtracts it is
|
|
1136
1137
|
* not published and carries {@link StaleOperandError}; the others publish. It costs one registry read per such operand per
|
|
1137
1138
|
* group, and `stats.operands` carries every operand's pinned, start and end generation and whether it moved.
|
|
1138
1139
|
*
|
|
@@ -1278,7 +1279,7 @@ var CloudRoaring = class _CloudRoaring {
|
|
|
1278
1279
|
}
|
|
1279
1280
|
fedMayBeEmpty = rest;
|
|
1280
1281
|
}
|
|
1281
|
-
if (feedIn === void 0 && (
|
|
1282
|
+
if (feedIn === void 0 && (!Array.isArray(fedMayBeEmpty) || fedMayBeEmpty.length > 0)) {
|
|
1282
1283
|
throw new ValidationError2(
|
|
1283
1284
|
"materializeMany: mayBeEmpty names fed operands, and the call has no feed"
|
|
1284
1285
|
);
|