@cloudbitmaps/roaring 0.20.0 → 0.21.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
@@ -78,7 +78,7 @@ export interface CloudRoaringOptions {
78
78
  * lands and then loses its response would, replayed blindly, report its own write as a conflict. A write is
79
79
  * retried only where that is safe: a load's registry write that gets no answer is settled by reading the row,
80
80
  * and a throttled write-once object is sent again by the S3 and GCS drivers. Pass a partial policy to tune it — anything you leave out keeps its
81
- * default — or `false` to turn the read retry off (e.g. if your injected client already retries). A GCS download is retried by
81
+ * default, except an omitted `maxDelayMs`, which is `baseDelayMs` when that is larger than 2000 ms — or `false` to turn the read retry off (e.g. if your injected client already retries). A GCS download is retried by
82
82
  * the GCS driver whatever this says.
83
83
  * Deterministic errors (`ValidationError`/`IntegrityError`/`WriteConflictError`/…) are never retried by this
84
84
  * layer.
@@ -117,8 +117,8 @@ export interface CacheOptions {
117
117
  * How long (ms) the store trusts a segment's resolved `currentGen` before re-resolving it on the next read
118
118
  * (default 2000) — the bound on read staleness after a load publishes a new generation. Applies when
119
119
  * `storage` is a **backend**, whose registry supplies the cheap `currentGen` read the refresh needs. Lazy — no
120
- * timer; ≤ one registry read per segment per window, opening a new reader only when the generation actually
121
- * advanced.
120
+ * timer; ≤ one registry read per segment per window, opening a new reader only when the row's pointer was
121
+ * renewed (a publish, a rollback, an erasure's rewrite, a status or key change); a lease or retention write does not.
122
122
  *
123
123
  * **While the registry cannot be read, the bound stretches.** A refresh that fails with a
124
124
  * {@link TransientError} keeps serving the generation of a segment still in the reader cache, and the key its reader
@@ -154,15 +154,15 @@ export interface CacheOptions {
154
154
  */
155
155
  readonly readerMax?: number;
156
156
  /**
157
- * Aggregate byte ceiling on what the open readers hold, their parsed `.crbm` indices, the metadata a
158
- * generation carries, and the chunk bytes a reader keeps when its tail read returned a whole object whose chunks
157
+ * Aggregate byte ceiling on what the open readers hold: their parsed `.crbm` indices, the metadata a
158
+ * generation carries, a fixed 3.75 KiB for the objects each open reader holds around its index, and the chunk bytes a reader keeps when its tail read returned a whole object whose chunks
159
159
  * total at most this ceiling divided by {@link CacheOptions.readerMax} (default 64 MiB) — the byte half
160
160
  * of the memory bound, complementing the {@link CacheOptions.readerMax} *count* bound. A wide/dense segment's
161
161
  * parsed index can reach about 1.3 MB, so a count-only bound could let the open readers pin over a GB and blow a small
162
- * heap (e.g. a 128 MB Lambda); this evicts the least-recently-used reader once the summed index footprint
162
+ * heap (e.g. a 128 MB Lambda); this evicts the least-recently-used reader once the summed weight
163
163
  * would exceed the ceiling — whichever of the count/byte bounds binds first. A sixteenth of it (4 MiB by default)
164
164
  * bounds the segments' resolutions a store with a timed refresh keeps besides. Lower it for memory-tight
165
- * deployments that read across wide segments. Applies whenever the store builds its own read path.
165
+ * deployments that read across wide segments. A ceiling below two readers' weight (about 7.7 KB for tiny ones) keeps one reader open at a time. Applies whenever the store builds its own read path.
166
166
  */
167
167
  readonly readerMaxBytes?: number;
168
168
  }
@@ -190,7 +190,8 @@ export interface EncryptionOptions {
190
190
  * {@link CloudRoaringOptions.retry} — a partial {@link RetryPolicy} plus the retry callback.
191
191
  *
192
192
  * Partial on purpose, so tuning one field does not mean restating all five. Anything omitted here keeps its
193
- * {@link DEFAULT_RETRY_POLICY} value.
193
+ * {@link DEFAULT_RETRY_POLICY} value, except that an omitted `maxDelayMs` is the `baseDelayMs` when that is larger
194
+ * than the default cap.
194
195
  */
195
196
  export interface RetryOptions extends Partial<RetryPolicy> {
196
197
  /**
@@ -465,7 +466,8 @@ export interface MaterializeManyDryRun {
465
466
  export interface MaterializeResult {
466
467
  /**
467
468
  * The generation written. Present even when refused: the refusal deleted that object, unless the destination's
468
- * row changed while it was writing, which leaves it in the bucket.
469
+ * row changed while it was writing, which leaves it in the bucket, an orphan a later load's collection takes; until
470
+ * then a rollback onto it needs `allowUnknown`.
469
471
  */
470
472
  readonly generation: number;
471
473
  /**
@@ -568,7 +570,7 @@ export declare class CloudRoaring {
568
570
  * row it is kept (hard invariant 1: deleting it after a purge-and-recreate would put a live row over a missing
569
571
  * generation).
570
572
  *
571
- * Where the row is gone, or keyed over a cleartext write, the object is proved the load's own by its footer, and
573
+ * Where the row is gone, or keyed over a cleartext write, the object's footer must match what the load wrote, and
572
574
  * the delete passes the version that read reported, so on a storage driver that reports `conditionalDelete` an
573
575
  * object put under the number since is kept. Where the row is unchanged or `destroyed`, the check narrows the
574
576
  * window rather than closing it: the row read and the delete are two round trips, and the delete is by number,
@@ -843,6 +845,8 @@ export declare class CloudRoaring {
843
845
  * What the bucket holds, not what the segment has ever been — collection deletes superseded objects, so this is
844
846
  * the grace window plus whatever has not been collected yet. It is the set {@link CloudRoaring.rollback} can
845
847
  * choose from, which is the reason to look at it. One registry read and one listing; it does not open the objects.
848
+ * Each entry says whether the row knows the generation (`known`): a known generation needs no `allowUnknown`; an unknown
849
+ * one does, except below a row's pointer when the row has no usable record or the target is older than a full one reaches.
846
850
  *
847
851
  * Needs a backend.
848
852
  */
@@ -915,36 +919,58 @@ export declare class CloudRoaring {
915
919
  * (`segment.rollback`), because every other pointer move can be reconstructed from "a load happened" and this
916
920
  * one cannot.
917
921
  *
918
- * It refuses rather than guesses: a generation not in the bucket (collected, or never written) throws
919
- * `NotFoundError` naming what *is* available, a crypto-shredded segment throws
920
- * {@link ValidationError} because every generation of it is unreadable, and a target that is cleartext under an
921
- * encrypted segment, or encrypted under a cleartext one, throws {@link IntegrityError} from one tail read of it,
922
- * because every read would refuse it. Rolling to the generation already current is a no-op that reports itself.
922
+ * It refuses rather than guesses. The row records, in `knownGens`, the generations its loads and rollbacks made
923
+ * current, each with the footer checksum of its object, and a rollback moves only onto one of those: a generation the
924
+ * row does not know (a load that wrote its object and died before the publish, a refused load's object, an object
925
+ * sealed under a key no row holds, a load published after the point a registry was restored to) throws
926
+ * {@link ValidationError} before any request to storage, and a known one whose object carries another checksum than
927
+ * the recorded one throws {@link IntegrityError}, with or without a keystore, since the footer is in the clear. A
928
+ * generation not in the bucket (collected, or never written) throws `NotFoundError` naming what *is* available, a
929
+ * crypto-shredded segment throws {@link ValidationError} because every generation of it is unreadable, and a target
930
+ * that is cleartext under an encrypted segment, or encrypted under a cleartext one, throws {@link IntegrityError} from
931
+ * one tail read of it, because every read would refuse it. Rolling to the generation already current is a no-op that
932
+ * reports itself, once one footer read finds its object in the bucket (and the one the row recorded); when the object is
933
+ * gone it throws `NotFoundError` naming what is.
923
934
  *
924
935
  * The same tail read (and a range read when the target's index is longer than it) gives the target's id count and
925
936
  * metadata, which the rollback writes into the row with the pointer, so a reader that sees the target as current sees
926
937
  * what describes it. The store's keystore opens an encrypted target for this; without it, or when it cannot open the
927
- * key for any reason, the segment still rolls back and the row carries no summary of the target.
938
+ * key (it holds none of the key's KEKs, one it holds does not unwrap it, or it throws `TransientError` or times out
939
+ * as `AbortSignal.timeout()` and the AWS SDK report a timeout), a rollback onto a known generation still happens,
940
+ * opening nothing, and the row carries no summary of the target. Any other failure of the keystore is
941
+ * thrown. A swap of the pointer that gets no answer is settled by reading the row: one that landed, the row being the
942
+ * one the swap leaves, is checked as any is, and otherwise its `TransientError` is thrown. After the swap the target's
943
+ * footer is read once more, and the pointer put back if the object is gone or is another.
928
944
  *
929
945
  * It deletes nothing. The generations above the new pointer stay put — which is what makes this reversible —
930
- * and are then *above* `currentGen`, where collection never looks. They remain until loads pass them (the first
931
- * load whose number one of them holds numbers above them all, and collection then keeps the newest `keep` of what is
932
- * below its pointer), {@link CloudRoaring.dropSegment}
946
+ * and are then *above* `currentGen`, where collection never looks, and still known to the row, so rolling forward onto
947
+ * one needs no flag. They remain until loads pass them (the first load whose
948
+ * number one of them holds numbers above them all, and collection then keeps `keep` of what is below its pointer, the
949
+ * generation that load superseded first), {@link CloudRoaring.dropSegment}
933
950
  * deletes them, or {@link CloudRoaring.eraseSubject} does: all of those present when it rewrites, and, when the
934
951
  * current generation does not hold the id, only those holding it and any no read of the segment can open, whatever
935
952
  * the id. An operator who has just undone a bad load should not have the
936
953
  * evidence collected out from under them, while a rollback target that still holds erased data would make the
937
954
  * erasure undoable.
938
955
  *
939
- * A target **above** the pointer needs `{ allowForward: true }`, and is refused with {@link ValidationError}
940
- * without it: that is also where objects live that were never published, such as a load that wrote its object
941
- * and died before the publish. Undoing an earlier rollback is what the opt-in is for.
956
+ * `{ allowUnknown: true }` moves onto a present object the row does not vouch for, or one whose checksum differs from
957
+ * the recorded one, as long as it is the segment's kind of object, opens, and names the generation, and records it as
958
+ * known (over a usable record; a row with none stays without one). On an encrypted segment, outside the two cases the pointer alone decides (below), it also needs the key: with no keystore, or one that holds none of the key's KEKs or
959
+ * one that does not unwrap it, it is refused with `KeyUnavailableError` before the target is read, since an object
960
+ * sealed under a key no row holds passes every check that needs no key, and a key service that did not answer in
961
+ * time is thrown as `TransientError`, to retry. Every move the row did not vouch for is audited with `unknown: true`.
962
+ * Two cases are decided by the pointer alone: a target below it needs no flag, no key and no checksum check, and the
963
+ * move is audited the same way. They are a row with no usable `knownGens` (a registry that drops the field, or a pointer
964
+ * moved by hand), and a target numbered below the bound of a full record (128 entries or more, leased ones included),
965
+ * which is its least recently current entry that no lease names (an `*Into` destination keeps every generation in the
966
+ * bucket and names only the newest 128). A generation a publish with a smaller `keep` no longer names but that stays in
967
+ * the bucket (a lease spared it, or its delete failed) needs `allowUnknown` until a later listing collects it.
942
968
  *
943
969
  * Needs a backend.
944
970
  */
945
971
  rollback(ref: SegmentRef, toGeneration: number, options?: {
946
972
  audit?: IAuditSink;
947
- allowForward?: boolean;
973
+ allowUnknown?: boolean;
948
974
  }): Promise<RollbackResult>;
949
975
  /**
950
976
  * **Replace this segment's contents** with `input`, as one new immutable generation, and make it current.
@@ -994,12 +1020,16 @@ export declare class CloudRoaring {
994
1020
  * published, a retention change, a rollback or an erasure wrote the row, or the row was deleted.
995
1021
  *
996
1022
  * A refused load deletes the object it wrote before returning — it sits above `currentGen`, where generation
997
- * collection deliberately never looks — but only while the segment's registry row is unchanged (or differs only
998
- * in its leases), `destroyed` or gone, or has key material when the load wrote cleartext, which has no place in an
999
- * encrypted segment's bucket. Under a row that is gone or keyed, a read of the object's footer must prove it the
1000
- * load's own first. Once another write has otherwise changed the row, the generation number it holds may name
1001
- * another incarnation's live object, so it leaves the orphan rather than risk deleting live data. No row's list
1002
- * names it, so it takes no place in a window, and a listing deletes it once a later generation is current above it.
1023
+ * collection deliberately never looks — but only while the segment's registry row is unchanged (or differs only in
1024
+ * its leases), `destroyed` or gone, or has key material when the load wrote cleartext, which has no place in an
1025
+ * encrypted segment's bucket. Under a row that is gone or keyed, one read of the object's footer must match what the
1026
+ * load wrote first. Once another write has otherwise changed the row, the generation number it holds may name another
1027
+ * writer's object, and a footer names bytes, not the load that wrote them, so it leaves the orphan rather than risk
1028
+ * deleting live data. A publish never adds the orphan to the row's list, and a load's listing deletes it once a
1029
+ * generation above it is current, unless the row's list names it; where the row records none (after a rollback, or
1030
+ * with a `keep` above 64), that listing's window can keep it and, at a `keep` up to 64, record it, and the publishes
1031
+ * after carry it until the window pushes it out. Until it goes, a rollback onto it is refused unless `allowUnknown` is passed, since the list never names it (a list seeded
1032
+ * over a row with none can); with the override it publishes what no load published.
1003
1033
  *
1004
1034
  * **Collection is by name at any `keep` up to 64.** The segment's row records the generations a load keeps, so a load
1005
1035
  * that found nothing above the pointer deletes the generations its publish pushed out of the window and lists
@@ -1207,7 +1237,10 @@ export declare class CloudRoaring {
1207
1237
  * reader converging, you need to signal them — this is the call to make when your own fan-out delivers.
1208
1238
  *
1209
1239
  * It also forgets any replacement this store found of a pin's object, so once it is called after a restore puts that
1210
- * object back, the pin reads it again.
1240
+ * object back, the pin reads it again. A read of the segment already running on this store, a pin's and a combine's
1241
+ * with a pinned operand included, caches nothing more of what it began reading before the call, and a pinned one
1242
+ * opens its object again before its next chunk, failing with `NotFoundError` if the object is gone or replaced, or
1243
+ * its row is gone or destroyed.
1211
1244
  *
1212
1245
  * Synchronous, best-effort, and safe to call for a segment this store has never read.
1213
1246
  *
@@ -1223,7 +1256,8 @@ export declare class CloudRoaring {
1223
1256
  *
1224
1257
  * The pinned handle gets its own engine but **shares the store's chunk cache**, under keys of its own: the
1225
1258
  * pinned view reports the version captured at pin time, marked as a pin's, so its decoded chunks are never
1226
- * those of a live read that fetched across a publish (see {@link PinnedStorageChunkSource.currentVersion}).
1259
+ * those of a live read that fetched across a publish (see {@link PinnedStorageChunkSource.currentVersion}). It
1260
+ * shares the store engine's invalidations too, so the store's writes reach a pinned read already running.
1227
1261
  */
1228
1262
  private pinSegment;
1229
1263
  /** 16 hex digits from the store's `Rng`, which names the holder of one lease: unique, not secret. */
@@ -1232,7 +1266,8 @@ export declare class CloudRoaring {
1232
1266
  * An engine reading every segment in `pins` at its pinned generation and everything else live, with the store's
1233
1267
  * retries, so a transient fault on a pinned read is retried as it would be on a live one.
1234
1268
  *
1235
- * It **shares the store's chunk cache and its memory bound**, under keys of its own for each pinned segment.
1269
+ * It **shares the store's chunk cache and its memory bound**, under keys of its own for each pinned segment, and the
1270
+ * store engine's invalidations, so an invalidation of a pinned segment reaches a read of the pin already running.
1236
1271
  */
1237
1272
  private engineWithPins;
1238
1273
  /**
@@ -1271,6 +1306,12 @@ export declare class CloudRoaring {
1271
1306
  * restore of the registry from another point than the bucket leaves a count to answer. A sealed summary is held
1272
1307
  * against its object when this store has the key, and counted in `summariesUnchecked` when it does not.
1273
1308
  *
1309
+ * With `generations: true` it also holds every generation a row's ledger of known generations names, the current one
1310
+ * included, against its object: one footer read each (104 bytes, no key, not retried), reporting
1311
+ * `known-generation-mismatch` with the `generation` where the object under that number is not the one the row
1312
+ * recorded. A named generation that is not in the bucket is not reported. A row with a pointer whose ledger cannot
1313
+ * be used is counted in `generationsUnchecked`, and none of its objects is read.
1314
+ *
1274
1315
  * It holds the registry rows it enumerates resident, at most 250,000 of them, and throws
1275
1316
  * `BudgetExceededError` past that rather than report a partial scan as a whole one. This method takes no
1276
1317
  * ceiling of its own: narrow the scan with `namespace`, or call `runConsistencyCheck` over the backend's
@@ -1280,6 +1321,7 @@ export declare class CloudRoaring {
1280
1321
  namespace?: string;
1281
1322
  concurrency?: number;
1282
1323
  summaries?: boolean;
1324
+ generations?: boolean;
1283
1325
  }): Promise<ConsistencyReport>;
1284
1326
  /**
1285
1327
  * **Export ("eject") every registered segment's current generation** through the injected `sink`, using only
@@ -1310,7 +1352,7 @@ export interface BaseCombineOptions extends IdRange {
1310
1352
  * is larger), about `concurrency × operands` MiB are held, whatever the segment's size. The stream opens 4 ranges wide
1311
1353
  * (or `concurrency`, if lower) and widens as ranges are taken, so a read that stops early has asked for little past
1312
1354
  * where it stopped, and a read that fits one range makes one request however many chunks it needs. A source that
1313
- * reads chunk by chunk (a custom one) is read as before: `concurrency` chunk keys at once, opening 8 wide. A running
1355
+ * reads chunk by chunk (a custom one) is read `concurrency` chunk keys at once, opening 8 wide. A running
1314
1356
  * stream holds its operand's reader outside the reader cache's bounds until it ends or the segment moves on.
1315
1357
  */
1316
1358
  readonly concurrency?: number;
@@ -1396,18 +1438,32 @@ export interface MaterializeOptions extends CombineOptions {
1396
1438
  */
1397
1439
  readonly keep?: number;
1398
1440
  }
1441
+ /**
1442
+ * An id stream as an iterator: the ids ascending, driven by `for await` or by hand with `next()`, `return()` and
1443
+ * `throw()`, as a generator is, on a handle that holds a lease as on one that does not. It is its own iterator and
1444
+ * single-use. {@link Segment.everyNth} returns this; the streams of {@link IdStream} add `batches()`.
1445
+ */
1446
+ export interface IdIterator extends AsyncIterableIterator<number> {
1447
+ /** Ends the read, as a generator's `return` does, and resolves done with `value`. */
1448
+ return(value?: unknown): Promise<IteratorResult<number, unknown>>;
1449
+ /** Throws `err` into the read, as a generator's `throw` does: it rejects with `err` unless the read handles it. */
1450
+ throw(err: unknown): Promise<IteratorResult<number, unknown>>;
1451
+ }
1399
1452
  /**
1400
1453
  * What a streaming read returns: the ids, ascending, one at a time under `for await`, or one chunk at a time from
1401
1454
  * {@link IdStream.batches}.
1402
1455
  *
1403
- * It is an `AsyncIterable<number>`, so every consumer of an id stream takes it as it always did. A live read is the
1456
+ * It is an `AsyncIterable<number>`, so every consumer of an id stream takes it as an async iterable, and an
1457
+ * {@link IdIterator}, so `next()`, `return()` and `throw()` are typed. A live read is the
1404
1458
  * engine's async generator itself, with `batches` attached: `for await` it, or drive it with `next()`, `return()` and
1405
- * `throw()`, exactly as before, and it is single-use (a second `for await` over it yields nothing). `batches()` is a
1459
+ * `throw()`, and it is single-use (a second `for await` over it yields nothing). A handle that holds a lease returns a
1460
+ * stream of the same shape, which checks the lease as it reads. `batches()` is a
1406
1461
  * separate, new read: it starts when called, fetches its chunks afresh and charges the per-op budget again, whether or
1407
1462
  * not the per-id stream was read, and reading both is two reads (invariant 3 applies to each separately). Nothing is
1408
- * fetched until a read is first pulled.
1463
+ * fetched until a read is first pulled. A stream pulled with `next()` and dropped without `return()` is held by nothing
1464
+ * in the store, so it is garbage once the caller lets it go.
1409
1465
  */
1410
- export interface IdStream extends AsyncIterable<number> {
1466
+ export interface IdStream extends IdIterator {
1411
1467
  /**
1412
1468
  * The same ids as the per-id stream, in the same order, one `Uint32Array` per chunk: each array ascending, holding
1413
1469
  * every id of one chunk the read yields (a range trimmed at its edges exactly as the per-id stream trims it), and
@@ -1566,11 +1622,16 @@ export declare class Segment {
1566
1622
  * - `eraseSubject` invalidates a pin of each segment it scans that is not already destroyed.
1567
1623
  *
1568
1624
  * An invalidated pin opens its object again, and fails if that object is gone or replaced, or its row is gone or
1569
- * destroyed.
1625
+ * destroyed. A read of the pin already running when the invalidation comes, a combine on this store with the pin as
1626
+ * an operand included, looks the pin up again before it hands out its next chunk: it carries on with what it holds
1627
+ * where the object is still there, and fails with `NotFoundError` where it is gone. It caches nothing more of what it
1628
+ * began reading before the invalidation, so the pin's next read opens the object again too.
1570
1629
  * Anything else leaves the pin as it is: after a `destroySegment` beside this store, or an erasure, a drop or a
1571
1630
  * retirement through another store, in this process or another, the pin answers from what it holds until this
1572
1631
  * store's reader cache evicts the pin's reader and its chunk cache evicts the chunks the pin decoded, or
1573
- * {@link CloudRoaring.invalidate} is called on this store. Where the
1632
+ * {@link CloudRoaring.invalidate} is called on this store. A combine on another store that takes the pin as an
1633
+ * operand reads it through that store's reader and chunk cache, which only that store's own writes and its
1634
+ * `invalidate` reach. Where the
1574
1635
  * object the pin reads has been deleted, by an erasure, a drop or a sweep, a chunk the pin has not cached fails at
1575
1636
  * once. No timed refresh bounds any of that, as none bounds anything else a pin holds.
1576
1637
  *
@@ -1623,6 +1684,8 @@ export declare class Segment {
1623
1684
  * the engine, so no operand, exclude or cached reader can answer past a lease.
1624
1685
  */
1625
1686
  private assertLeases;
1687
+ /** Throw this handle's lease error, if it has one. The calls that return a value instead of throwing use {@link leaseError}. */
1688
+ private assertLease;
1626
1689
  /**
1627
1690
  * Reopen a generation a pin named earlier, as a pinned handle like the one {@link Segment.pin} returns, held at
1628
1691
  * `at.generation` instead of the current one. Pass what the earlier pin recorded, `{ generation, fingerprint }`
@@ -1666,11 +1729,16 @@ export declare class Segment {
1666
1729
  /** `result` as is, or, when a handle of the call holds a lease, checking that lease each time it reads a chunk. */
1667
1730
  private guarded;
1668
1731
  /**
1669
- * Time an op with the injected clock and emit an `op` metric on completion (success or throw). Skipped
1670
- * entirely when no sink is wired, so the default path pays nothing.
1732
+ * Time an op with the injected clock and emit an `op` metric on completion (success or throw). With no sink wired it
1733
+ * reads no clock and emits nothing, but a call still passes through this async frame; `has()` and `count()` return the
1734
+ * engine's promise directly instead.
1671
1735
  */
1672
1736
  private timed;
1673
- /** Membership: one chunk — the cache, else one ranged GET. Throws {@link ValidationError} on a bad id. */
1737
+ /**
1738
+ * Membership: one chunk. A cold resolution of the segment is one registry read and a warm one none; then a cached
1739
+ * chunk answers with no request, and an uncached one is one range read, after a tail read when no reader of the
1740
+ * generation is open, unless that tail carried the chunk. Throws {@link ValidationError} on a bad id.
1741
+ */
1674
1742
  has(id: number): Promise<boolean>;
1675
1743
  /**
1676
1744
  * Cardinality of the generation this handle reads: **one registry read when cold, none when warm, and no read of the
@@ -1764,7 +1832,7 @@ export declare class Segment {
1764
1832
  * for await (const id of audience.everyNth(1_000)) ends.push(id); // the end of each window of 1,000
1765
1833
  * ```
1766
1834
  */
1767
- everyNth(n: number, options?: IdRange): AsyncIterable<number>;
1835
+ everyNth(n: number, options?: IdRange): IdIterator;
1768
1836
  /**
1769
1837
  * The options a combine hands the engine, read once, when it is called ({@link readOptions}), with the `exclude`
1770
1838
  * it was given ({@link excludesOf}) and mapped down to the plain refs
@@ -1791,7 +1859,6 @@ export declare class Segment {
1791
1859
  * override the store's per-op denial-of-wallet budget for this call (or `false` to lift it).
1792
1860
  */
1793
1861
  intersect(others: Segment[], options?: CombineOptions): IdStream;
1794
- private intersectAs;
1795
1862
  /**
1796
1863
  * Materialize `this ∩ others…` (minus `exclude`) as a **new generation of `dest`** — `dest`'s previous contents
1797
1864
  * are superseded, not added to. Streaming + bounded-memory; the result is one immutable object published
@@ -1824,7 +1891,6 @@ export declare class Segment {
1824
1891
  * segment once (`unionInto`, or a load) is the cheaper shape.
1825
1892
  */
1826
1893
  union(others: Segment[], options?: CombineOptions): IdStream;
1827
- private unionAs;
1828
1894
  /** Materialize `this ∪ others…` (minus `exclude`) as a **new generation of `dest`** — see {@link intersectInto}. */
1829
1895
  unionInto(dest: Segment, others: Segment[], options?: MaterializeOptions): Promise<MaterializeResult>;
1830
1896
  /**
@@ -1839,10 +1905,16 @@ export declare class Segment {
1839
1905
  * the suppression folds into the same pass rather than materializing an intermediate segment first.
1840
1906
  */
1841
1907
  andNot(excludes: Segment[], options?: BaseCombineOptions): IdStream;
1842
- private andNotAs;
1843
1908
  /** Materialize `this \ (excludes…)` as a **new generation of `dest`** — see {@link intersectInto}. */
1844
1909
  andNotInto(dest: Segment, excludes: Segment[], options?: AndNotIntoOptions): Promise<MaterializeResult>;
1910
+ /**
1911
+ * The one body of the three combines, read as ids or as chunks. `operands` is `others` for `intersect` and
1912
+ * `union`, and `excludes` for `andNot`, which takes no `exclude` option.
1913
+ */
1914
+ private combineAs;
1915
+ /** The one body of the three `*Into` verbs, after each has checked its own options. */
1916
+ private combineInto;
1845
1917
  }
1846
1918
  export { deserializePortable };
1847
1919
  export { MemoryStorage, LocalFsStorage, CrbmStorageChunkSource, destroySegment, eraseNamespace, excludingReservedRows, readRetentionPolicy, MIN_EXPIRES_AT_MS, LEASE_SKEW_MS, MAX_LEASE_MS, MAX_LEASES_PER_SEGMENT, InProcessKeystore, NodeAead, aadFor, CloudRoaringError, ValidationError, WriteConflictError, IntegrityError, NotFoundError, UnsupportedError, CapabilityError, TransientError, KeyUnavailableError, BudgetExceededError, LeaseExpiredError, LeaseLimitError, StaleOperandError, isCloudRoaringError, isWriteConflictError, isTransientError, isNotFoundError, isIntegrityError, isValidationError, isLeaseExpiredError, isLeaseLimitError, isStaleOperandError, isUnsupportedError, isCapabilityError, isBudgetExceededError, isKeyUnavailableError, CrbmReader, BufferReader, CountingMetricsSink, RecordingAuditSink, DEFAULT_RETRY_POLICY, } from '@cloudbitmaps/core';
1848
- export type { Aead, AeadSealed, AuditEvent, BlobReader, BlobSink, Budget, BudgetOption, ChunkRef, Clock, CodecBitmap, CodecInterface, ConsistencyErrorEntry, ConsistencyIssue, ConsistencyReport, CrbmCrypto, CrbmReaderOptions, CrbmStorageChunkSourceOptions, DestroyResult, ClearRegistrySummary, DropResult, EncodedChunk, EraseDeps, ExportFailure, ExportFormat, ExportManifest, ExportOptions, ExportSink, ExportSkipped, ExportWriter, ExportedSegment, GenKey, GenerationEntry, GenerationMetadata, GovernanceMeta, IAuditSink, IKeystore, IMetricsSink, IRegistryDriver, IStorageDriver, IdRange, InProcessKeystoreOptions, LoadGuard, LoadInput, LoadOptions, LoadRefusal, LoadResult, LocalFsStorageOptions, MemoryStorageOptions, MetricEvent, MetricOpName, MetricsSnapshot, NewRegistryRecord, PinnedAt, PinnedObject, PortableBitmap, RegCaps, RegistryPatch, RegistryRecord, RegistryStatus, RegistrySummary, RegistryWriteOptions, LeaseEntry, RetentionPolicy, RetireEntry, RetireExpiredOptions, RetireExpiredResult, RetryPolicy, Rng, RollbackResult, SealedRegistrySummary, SegmentInfo, SegmentRef, SegmentSize, SetRetentionResult, StorageBackend, StorageCaps, StorageChunkSource, StorageDeleteOptions, TailRead, Token, WrappedDek, } from '@cloudbitmaps/core';
1920
+ export type { Aead, AeadSealed, AuditEvent, BlobReader, BlobSink, Budget, BudgetOption, ChunkRef, Clock, CodecBitmap, CodecInterface, ConsistencyErrorEntry, ConsistencyIssue, ConsistencyReport, CrbmCrypto, CrbmReaderOptions, CrbmStorageChunkSourceOptions, DestroyResult, ClearRegistrySummary, DropResult, EncodedChunk, EraseDeps, ExportFailure, ExportFormat, ExportManifest, ExportOptions, ExportSink, ExportSkipped, ExportWriter, ExportedSegment, GenKey, GenerationEntry, GenerationMetadata, GovernanceMeta, IAuditSink, IKeystore, IMetricsSink, IRegistryDriver, IStorageDriver, IdRange, InProcessKeystoreOptions, LoadGuard, LoadInput, LoadOptions, LoadRefusal, LoadResult, LocalFsStorageOptions, MemoryStorageOptions, MetricEvent, MetricOpName, MetricsSnapshot, NewRegistryRecord, PinnedAt, PinnedObject, PortableBitmap, RegCaps, RegistryPatch, RegistryRecord, RegistryStatus, RegistrySummary, RegistryWriteOptions, KnownGeneration, LeaseEntry, RetentionPolicy, RetireEntry, RetireExpiredOptions, RetireExpiredResult, RetryPolicy, Rng, RollbackResult, SealedRegistrySummary, SegmentInfo, SegmentRef, SegmentSize, SetRetentionResult, StorageBackend, StorageCaps, StorageChunkSource, StorageDeleteOptions, TailRead, Token, WrappedDek, } from '@cloudbitmaps/core';