@cloudbitmaps/roaring 0.19.0 → 0.19.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
@@ -119,9 +119,9 @@ ledger is not by itself proof the id is gone. A tombstoned segment is searched t
119
119
  cleartext object left under it that holds the id is deleted with everything under the tombstone, and the entry reads
120
120
  `erased: true`. A segment whose row names no generation yet (a retention policy set before its first load) is
121
121
  searched too: an object a first load wrote and never published that holds the id, or on an encrypted store cannot
122
- be searched until its load publishes the key, is reported as an `error: …` note and not deleted, because that load may
123
- still publish it. Load the segment, which makes the object collectable, or drop
124
- it, and re-run.
122
+ be searched until its load publishes the key, is reported as an `error: …` note and not deleted: the erasure writes
123
+ nothing to such a row, so the load that wrote the object may still publish it. Load the segment, which makes the
124
+ object collectable, or drop it, and re-run.
125
125
 
126
126
  **Do not roll a segment back while erasing from it.** A rollback that lands mid-erasure can move the pointer onto a
127
127
  generation the erasure did not rewrite, so the id can be current again. Roll back before the erasure starts or
@@ -668,6 +668,11 @@ var SystemRng = class {
668
668
  };
669
669
  var DEFAULT_CACHE_MAX_CHUNKS = 1024;
670
670
  var DEFAULT_ADMIN_CONCURRENCY = 8;
671
+ function rowVersionOfLive(version) {
672
+ if (version === null) return null;
673
+ const cut = version.lastIndexOf("#");
674
+ return cut < 0 ? version : version.slice(0, cut);
675
+ }
671
676
  function validateConcurrency(concurrency) {
672
677
  if (concurrency !== void 0 && (!Number.isInteger(concurrency) || concurrency < 1)) {
673
678
  throw new ValidationError2(`concurrency must be a positive integer; got ${concurrency}`);
@@ -1183,10 +1188,9 @@ var CloudRoaring = class _CloudRoaring {
1183
1188
  /**
1184
1189
  * Write `ids` as a **new generation of `dest`** and publish it — the shared body of the `*Into` verbs. An `*Into`
1185
1190
  * materialisation is a load, and publishes the same way (hard invariant 1): every load that finds a row fences its
1186
- * publish on the row's token; a guarded load (the default, since the empty refusal needs the size of the current generation)
1187
- * also fences on the pointer it judged (`expectFrom`), and one that found no row fences on that absence instead.
1188
- * Only an unguarded load (`allowEmpty: true`, with neither `guard.minRetained` nor `guard.maxGrowth`) onto a segment with no row publishes bare
1189
- * forward-only. The destination's previous generation stays readable until the publish lands (readers re-resolve
1191
+ * publish on the row's token, and every load that finds none on that absence, guarded or not; a guarded load (the
1192
+ * default, since the empty refusal needs the size of the current generation) also fences on the pointer it judged
1193
+ * (`expectFrom`). The destination's previous generation stays readable until the publish lands (readers re-resolve
1190
1194
  * within `cache.genTtlMs`).
1191
1195
  *
1192
1196
  * This routes through `loadSegment` rather than writing the generation itself, and that is the whole point
@@ -1213,9 +1217,10 @@ var CloudRoaring = class _CloudRoaring {
1213
1217
  * **A `WriteConflictError` does not by itself mean nothing was published**, and that is worth knowing
1214
1218
  * before you write the retry. `'superseded'` covers five different causes — the write-once PUT collided,
1215
1219
  * the pointer moved, a row appeared where the load found none, the row's token changed, the row was purged —
1216
- * and only the first three are the "somebody beat us" the name suggests. A token can also change on a write
1217
- * that is not a supersession at all, such as a `setRetention` on the destination. On top of that, the collection pass that runs AFTER a
1218
- * successful publish can raise the same error. So: treat it as "re-read the destination and decide",
1220
+ * and only the first two are always the "somebody beat us" the name suggests. A row can appear, and a token can
1221
+ * change, on a write that is not a supersession at all: a `setRetention` on the destination creates its row when it
1222
+ * has none, and rewrites it when it has one. On top of that, the collection pass that runs AFTER a successful
1223
+ * publish can raise the same error. So: treat it as "re-read the destination and decide",
1219
1224
  * never as "the write did not happen".
1220
1225
  *
1221
1226
  * **And by default it collects nothing**, unlike `load()`. See the `keep` default below.
@@ -1247,7 +1252,7 @@ var CloudRoaring = class _CloudRoaring {
1247
1252
  if (reason === "superseded") {
1248
1253
  const wrote = result.size > 0 ? `generation ${result.generation} was written and is not current` : `nothing was written \u2014 another writer took generation ${result.generation} first`;
1249
1254
  throw new WriteConflictError(
1250
- `${op}: the destination "${dest.segment}" changed while this materialisation was in flight, so its result is not the destination's current generation: ${wrote}. The pointer may have moved, the row may have been rewritten (a retention policy does this), dropped or purged. Re-read the destination and re-run.`
1255
+ `${op}: the destination "${dest.segment}" changed while this materialisation was in flight, so its result is not the destination's current generation: ${wrote}. The pointer may have moved, the row may have been created or rewritten (a retention policy does either), dropped or purged. Re-read the destination and re-run.`
1251
1256
  );
1252
1257
  }
1253
1258
  return {
@@ -1609,7 +1614,7 @@ var CloudRoaring = class _CloudRoaring {
1609
1614
  if (this.crbmSource !== void 0) {
1610
1615
  const held = await this.crbmSource.currentVersion(ref);
1611
1616
  const listed = rec.currentGen === null ? null : `${rec.currentGen}:${String(rec.token)}`;
1612
- if (held !== listed) this.engine.invalidate(ref);
1617
+ if (rowVersionOfLive(held) !== listed) this.engine.invalidate(ref);
1613
1618
  }
1614
1619
  return await this.engine.has(ref, id) ? { segment: rec.segment, namespace: rec.namespace } : null;
1615
1620
  }