@cloudbitmaps/roaring 0.26.0 → 0.27.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/dist/index.d.ts CHANGED
@@ -163,7 +163,13 @@ export interface CacheOptions {
163
163
  * lapses, a read of it fails with the fault, as a cold read does. A refresh that fails with anything else, an access denial or a row that will not parse, is not
164
164
  * ridden out: the read that meets it throws that error, and the reader is dropped.
165
165
  *
166
- * `0` turns this timed refresh off, and so does wiring a bare `IStorageDriver`, which has no registry. That is
166
+ * **A pinned handle is checked on the same interval.** It never moves to another generation, but at most every
167
+ * `genTtlMs` (counted on access) its segment's row is read, one read shared by every pin of the segment, and the
168
+ * pin fails with `NotFoundError` once the segment is destroyed, gone or re-created, or its generation erased or
169
+ * collected, or recorded by its row as another object, even when its reader and chunks are still cached. A transient
170
+ * fault of the registry, or of the footer read an erasure's check makes, keeps it serving.
171
+ *
172
+ * `0` turns this timed refresh off, and the pinned handles' check with it, and so does wiring a bare `IStorageDriver`, which has no registry. That is
167
173
  * all it does. The store still moves a segment on to whatever generation is current when its reader cache
168
174
  * evicts the segment, when a read has to fetch from a generation a sweep deleted, and when it is invalidated,
169
175
  * as its own `load`, `rollback`, `eraseSubject` and `*Into` writes do and {@link CloudRoaring.invalidate} does.
@@ -889,7 +895,7 @@ export declare class CloudRoaring {
889
895
  * duration, or fix the source first and load after. A writer that lands *during* the rewrite is caught: the
890
896
  * rewrite's publish is refused **by the fence** — the publish lands its compare-and-swap only
891
897
  * while the pointer is still on the generation the rewrite streamed — and the entry says `note: 'superseded'`,
892
- * so re-run. Forward-only alone would NOT refuse it: the rewrite's number goes above everything in the bucket,
898
+ * so re-run. Forward-only alone would NOT refuse it: the rewrite's number goes above everything listed near the row's own numbers,
893
899
  * so the rewrite would out-rank the newer generation and then collect it.
894
900
  *
895
901
  * A racing **erasure** is caught before that, and reported the same way. It collects with `keep: 0`, taking
@@ -1057,7 +1063,8 @@ export declare class CloudRoaring {
1057
1063
  * It deletes nothing. The generations above the new pointer stay put — which is what makes this reversible —
1058
1064
  * and are then *above* `currentGen`, where collection never looks, and still known to the row, so rolling forward onto
1059
1065
  * one needs no flag. They remain until loads pass them (the first load whose
1060
- * number one of them holds numbers above them all, and collection then keeps `keep` of what is below its pointer, the
1066
+ * number one of them holds numbers above them all, those within 1,024 of what the row names and any contiguous run
1067
+ * touching them, and collection then keeps `keep` of what is below its pointer, the
1061
1068
  * generation that load superseded first), {@link CloudRoaring.dropSegment}
1062
1069
  * deletes them, or {@link CloudRoaring.eraseSubject} does: all of those present when it rewrites, and, when the
1063
1070
  * current generation does not hold the id, only those holding it and any no read of the segment can open, whatever
@@ -1366,7 +1373,8 @@ export declare class CloudRoaring {
1366
1373
  * the unwrapped DEK, and decrypts with them, chunks it had never fetched before the shred included, until its
1367
1374
  * snapshot re-resolves: within `cache.genTtlMs` when the store has a registry and a `genTtlMs` above 0, and
1368
1375
  * otherwise only when its caches let the segment go or a read has to fetch from a generation a sweep collected.
1369
- * A pin answers with no timed bound, until it is told or both caches let it go.
1376
+ * A pin on a store with a timed refresh fails within `cache.genTtlMs` once its segment is destroyed or its
1377
+ * generation erased; on a store with none it answers until it is told or both caches let it go.
1370
1378
  * - **Another process.** Erasing on one box invalidates nothing on the others; each store bounds its own
1371
1379
  * staleness by `cache.genTtlMs`, and a store with no registry (a bare `IStorageDriver`), with
1372
1380
  * `cache.genTtlMs: 0`, or on a `StorageChunkSource` of your own has no bound at all: it converges only when a read happens to miss its caches. If a compliance deadline depends on every
@@ -1777,7 +1785,9 @@ export declare class Segment {
1777
1785
  * `*Into` of one throws before it reads anything. Materialise one side first, with `materializeMany({ operands: { src: seg }, outputs: [{ dest, expr: { or: ['src'] } }], keep })`.
1778
1786
  *
1779
1787
  * **A pin knows its object, not only its number.** A name purged and loaded again starts again at generation
1780
- * 0, so a pin of the old segment never reads the new one: what it has already read still answers, as the
1788
+ * 0, so a pin of the old segment never reads the new one. On a store with a timed refresh the pin fails with
1789
+ * `NotFoundError` at its next check, within `cache.genTtlMs`, what it had already read included, and `invalidate`
1790
+ * does not bring it back: take a new pin. On a store with none, what it has already read still answers, as the
1781
1791
  * instant it pinned, and anything it would have to fetch fails with `NotFoundError`, as a swept pin's does.
1782
1792
  *
1783
1793
  * **It is a hold, and `pin({ leaseUntil })` makes it a bounded one.** Without a lease nothing stops a collection
@@ -1799,7 +1809,11 @@ export declare class Segment {
1799
1809
  * segment whose row is later dropped or destroyed fails once it must open its object again, rather than go empty
1800
1810
  * part-way through a call. **A pin
1801
1811
  * keeps the key its reader unwrapped for as long as that reader stays open, and answers from the chunks it
1802
- * decoded for as long as they stay cached.** This store invalidates a pin:
1812
+ * decoded for as long as they stay cached, until its next check.** On a store with a timed refresh a pin checks its
1813
+ * segment's row every `cache.genTtlMs` (from the moment it was taken, whether or not it was read) and fails with
1814
+ * `NotFoundError` once the segment is destroyed, is another incarnation, or its generation is collected or recorded by its row as another object (an object lost or replaced out of band
1815
+ * under a row that still names it is found only when the pin must fetch). This
1816
+ * store invalidates a pin:
1803
1817
  *
1804
1818
  * - a `load`, a `rollback` or an `*Into` invalidates a pin of the segment it writes;
1805
1819
  * - `dropSegment` invalidates a pin of the segment it drops, and `retireExpired` a pin of each segment its ledger
@@ -1812,16 +1826,18 @@ export declare class Segment {
1812
1826
  * where the object is still there, and fails with `NotFoundError` where it is gone. It caches nothing more of what it
1813
1827
  * began reading before the invalidation, so the pin's next read opens the object again too.
1814
1828
  * Anything else leaves the pin as it is: after a `destroySegment` beside this store, or an erasure, a drop or a
1815
- * retirement through another store, in this process or another, the pin answers from what it holds until this
1829
+ * retirement through another store, in this process or another, the pin answers from what it holds for at most
1830
+ * `cache.genTtlMs` on a store with a timed refresh, and then fails. On a store with none it answers until this
1816
1831
  * store's reader cache evicts the pin's reader and its chunk cache evicts the chunks the pin decoded, or
1817
1832
  * {@link CloudRoaring.invalidate} is called on this store. A combine on another store refuses the pin. Where the
1818
1833
  * object the pin reads has been deleted, by an erasure, a drop or a sweep, a chunk the pin has not cached fails at
1819
- * once. No timed refresh bounds any of that, as none bounds anything else a pin holds.
1834
+ * once. With no timed refresh nothing bounds any of that, as nothing bounds anything else a pin holds.
1820
1835
  *
1821
- * A replacement a pin has found is remembered, so its later chunk reads fail with no request, until the store
1836
+ * A replacement a read of the pin found is remembered, so its later chunk reads fail with no request, until the store
1822
1837
  * forgets it: an invalidation of the segment does, as does a later `pin()` of the same version that opens the object
1823
- * again, and the store remembers at most `cache.readerMax` of them. So once a restore puts the pinned object back,
1824
- * call {@link CloudRoaring.invalidate} on this store: the pin then reads the object again.
1838
+ * again; a replacement the pin's own check found is forgotten only by an invalidation. The store remembers at most `cache.readerMax` of them. So once a restore puts the pinned object back
1839
+ * into the same row, call {@link CloudRoaring.invalidate} on this store: the pin then reads the object again. A
1840
+ * restore into a purged and re-created row does not revive a pin on a store with a timed refresh: take a new pin.
1825
1841
  *
1826
1842
  * `pin()` reads the registry row and opens the generation at once, so the pin knows its object before its first
1827
1843
  * read. With a registry, pins of one generation taken while its row is unchanged share one reader while the store
package/dist/index.js CHANGED
@@ -4900,7 +4900,7 @@ var CloudRoaring = class _CloudRoaring {
4900
4900
  * duration, or fix the source first and load after. A writer that lands *during* the rewrite is caught: the
4901
4901
  * rewrite's publish is refused **by the fence** — the publish lands its compare-and-swap only
4902
4902
  * while the pointer is still on the generation the rewrite streamed — and the entry says `note: 'superseded'`,
4903
- * so re-run. Forward-only alone would NOT refuse it: the rewrite's number goes above everything in the bucket,
4903
+ * so re-run. Forward-only alone would NOT refuse it: the rewrite's number goes above everything listed near the row's own numbers,
4904
4904
  * so the rewrite would out-rank the newer generation and then collect it.
4905
4905
  *
4906
4906
  * A racing **erasure** is caught before that, and reported the same way. It collects with `keep: 0`, taking
@@ -5138,7 +5138,8 @@ var CloudRoaring = class _CloudRoaring {
5138
5138
  * It deletes nothing. The generations above the new pointer stay put — which is what makes this reversible —
5139
5139
  * and are then *above* `currentGen`, where collection never looks, and still known to the row, so rolling forward onto
5140
5140
  * one needs no flag. They remain until loads pass them (the first load whose
5141
- * number one of them holds numbers above them all, and collection then keeps `keep` of what is below its pointer, the
5141
+ * number one of them holds numbers above them all, those within 1,024 of what the row names and any contiguous run
5142
+ * touching them, and collection then keeps `keep` of what is below its pointer, the
5142
5143
  * generation that load superseded first), {@link CloudRoaring.dropSegment}
5143
5144
  * deletes them, or {@link CloudRoaring.eraseSubject} does: all of those present when it rewrites, and, when the
5144
5145
  * current generation does not hold the id, only those holding it and any no read of the segment can open, whatever
@@ -5515,7 +5516,8 @@ var CloudRoaring = class _CloudRoaring {
5515
5516
  * the unwrapped DEK, and decrypts with them, chunks it had never fetched before the shred included, until its
5516
5517
  * snapshot re-resolves: within `cache.genTtlMs` when the store has a registry and a `genTtlMs` above 0, and
5517
5518
  * otherwise only when its caches let the segment go or a read has to fetch from a generation a sweep collected.
5518
- * A pin answers with no timed bound, until it is told or both caches let it go.
5519
+ * A pin on a store with a timed refresh fails within `cache.genTtlMs` once its segment is destroyed or its
5520
+ * generation erased; on a store with none it answers until it is told or both caches let it go.
5519
5521
  * - **Another process.** Erasing on one box invalidates nothing on the others; each store bounds its own
5520
5522
  * staleness by `cache.genTtlMs`, and a store with no registry (a bare `IStorageDriver`), with
5521
5523
  * `cache.genTtlMs: 0`, or on a `StorageChunkSource` of your own has no bound at all: it converges only when a read happens to miss its caches. If a compliance deadline depends on every
@@ -5597,6 +5599,7 @@ var CloudRoaring = class _CloudRoaring {
5597
5599
  throw err;
5598
5600
  }
5599
5601
  const pinnedAt = at === null ? { generation: null, version: null, fingerprint: null } : { generation: at.generation, version: at.version, fingerprint: at.fingerprint };
5602
+ if (at !== null) crbm.startPinChecks(pinnedAt, at.checkedAtMs);
5600
5603
  const pins = /* @__PURE__ */ new Map([[segmentKey(ref), pinnedAt]]);
5601
5604
  return makeSegment({
5602
5605
  engine: this.engineWithPins(pins),
@@ -5964,7 +5967,9 @@ var Segment = class _Segment {
5964
5967
  * `*Into` of one throws before it reads anything. Materialise one side first, with `materializeMany({ operands: { src: seg }, outputs: [{ dest, expr: { or: ['src'] } }], keep })`.
5965
5968
  *
5966
5969
  * **A pin knows its object, not only its number.** A name purged and loaded again starts again at generation
5967
- * 0, so a pin of the old segment never reads the new one: what it has already read still answers, as the
5970
+ * 0, so a pin of the old segment never reads the new one. On a store with a timed refresh the pin fails with
5971
+ * `NotFoundError` at its next check, within `cache.genTtlMs`, what it had already read included, and `invalidate`
5972
+ * does not bring it back: take a new pin. On a store with none, what it has already read still answers, as the
5968
5973
  * instant it pinned, and anything it would have to fetch fails with `NotFoundError`, as a swept pin's does.
5969
5974
  *
5970
5975
  * **It is a hold, and `pin({ leaseUntil })` makes it a bounded one.** Without a lease nothing stops a collection
@@ -5986,7 +5991,11 @@ var Segment = class _Segment {
5986
5991
  * segment whose row is later dropped or destroyed fails once it must open its object again, rather than go empty
5987
5992
  * part-way through a call. **A pin
5988
5993
  * keeps the key its reader unwrapped for as long as that reader stays open, and answers from the chunks it
5989
- * decoded for as long as they stay cached.** This store invalidates a pin:
5994
+ * decoded for as long as they stay cached, until its next check.** On a store with a timed refresh a pin checks its
5995
+ * segment's row every `cache.genTtlMs` (from the moment it was taken, whether or not it was read) and fails with
5996
+ * `NotFoundError` once the segment is destroyed, is another incarnation, or its generation is collected or recorded by its row as another object (an object lost or replaced out of band
5997
+ * under a row that still names it is found only when the pin must fetch). This
5998
+ * store invalidates a pin:
5990
5999
  *
5991
6000
  * - a `load`, a `rollback` or an `*Into` invalidates a pin of the segment it writes;
5992
6001
  * - `dropSegment` invalidates a pin of the segment it drops, and `retireExpired` a pin of each segment its ledger
@@ -5999,16 +6008,18 @@ var Segment = class _Segment {
5999
6008
  * where the object is still there, and fails with `NotFoundError` where it is gone. It caches nothing more of what it
6000
6009
  * began reading before the invalidation, so the pin's next read opens the object again too.
6001
6010
  * Anything else leaves the pin as it is: after a `destroySegment` beside this store, or an erasure, a drop or a
6002
- * retirement through another store, in this process or another, the pin answers from what it holds until this
6011
+ * retirement through another store, in this process or another, the pin answers from what it holds for at most
6012
+ * `cache.genTtlMs` on a store with a timed refresh, and then fails. On a store with none it answers until this
6003
6013
  * store's reader cache evicts the pin's reader and its chunk cache evicts the chunks the pin decoded, or
6004
6014
  * {@link CloudRoaring.invalidate} is called on this store. A combine on another store refuses the pin. Where the
6005
6015
  * object the pin reads has been deleted, by an erasure, a drop or a sweep, a chunk the pin has not cached fails at
6006
- * once. No timed refresh bounds any of that, as none bounds anything else a pin holds.
6016
+ * once. With no timed refresh nothing bounds any of that, as nothing bounds anything else a pin holds.
6007
6017
  *
6008
- * A replacement a pin has found is remembered, so its later chunk reads fail with no request, until the store
6018
+ * A replacement a read of the pin found is remembered, so its later chunk reads fail with no request, until the store
6009
6019
  * forgets it: an invalidation of the segment does, as does a later `pin()` of the same version that opens the object
6010
- * again, and the store remembers at most `cache.readerMax` of them. So once a restore puts the pinned object back,
6011
- * call {@link CloudRoaring.invalidate} on this store: the pin then reads the object again.
6020
+ * again; a replacement the pin's own check found is forgotten only by an invalidation. The store remembers at most `cache.readerMax` of them. So once a restore puts the pinned object back
6021
+ * into the same row, call {@link CloudRoaring.invalidate} on this store: the pin then reads the object again. A
6022
+ * restore into a purged and re-created row does not revive a pin on a store with a timed refresh: take a new pin.
6012
6023
  *
6013
6024
  * `pin()` reads the registry row and opens the generation at once, so the pin knows its object before its first
6014
6025
  * read. With a registry, pins of one generation taken while its row is unchanged share one reader while the store