@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 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. These docs describe `main`, ahead of the npm release.
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. `EXPIRE` becomes
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 with what was pinned (a name deleted and
1135
- * created again is a replacement though it is generation 0 again). If one was replaced, each output that subtracts it is
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 && (heldHandles.size === 0 || !Array.isArray(fedMayBeEmpty) || fedMayBeEmpty.length > 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
  );