@harperfast/rocksdb-js 2.7.1 → 2.9.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.mts CHANGED
@@ -142,7 +142,7 @@ interface BackupInfo {
142
142
  * await backups.restore('/path/to/backups', '/path/to/restored-db');
143
143
  * ```
144
144
  */
145
- declare const backups: {
145
+ export declare const backups: {
146
146
  /**
147
147
  * Restores a database from a backup directory into a (closed) database
148
148
  * directory. The default mode purges the destination directory, so it must
@@ -234,7 +234,7 @@ interface DBIteratorValue<T> {
234
234
  * shared `ITERATOR_STATE` buffer) instead of constructing a JS result object,
235
235
  * so this class is responsible for building the `IteratorResult`.
236
236
  */
237
- declare class DBIterator<T> implements Iterator<DBIteratorValue<T>> {
237
+ export declare class DBIterator<T> implements Iterator<DBIteratorValue<T>> {
238
238
  #private;
239
239
  iterator: InstanceType<typeof NativeIteratorCls>;
240
240
  store: Store;
@@ -369,9 +369,58 @@ interface StoreOptions extends Omit<NativeDatabaseOptions, "compression" | "comp
369
369
  randomAccessStructure?: boolean;
370
370
  /**
371
371
  * When `true`, the database is opened in read-only mode. Write operations
372
- * will throw an error with code `ERR_DATABASE_READONLY`.
372
+ * will throw an error with code `ERR_DATABASE_READONLY`, except for
373
+ * `flush()`/`flushSync()`/`compact()`/`compactSync()`, which succeed as
374
+ * no-ops.
375
+ *
376
+ * A read-only open is a **point-in-time snapshot**: it replays the MANIFEST
377
+ * as of the open and never sees later writes. It is safe against a
378
+ * quiescent database (nothing else writing), but **unsafe against a live
379
+ * writer**: the open holds no reference on the files it is about to read,
380
+ * so a concurrent compaction or blob GC in the writing process can delete
381
+ * one mid-open and the open fails with `ERR_CONCURRENT_COMPACTION` (the
382
+ * database is not corrupt — the reader lost a race). Even a successful open
383
+ * can fail *later reads* the same way: files the snapshot references are
384
+ * opened lazily, and the writer keeps deleting obsolete ones. To follow a
385
+ * database another process is actively writing, open a secondary instead
386
+ * (see `secondaryPath`) — that is the supported mode for a live follower.
373
387
  */
374
388
  readOnly?: boolean;
389
+ /**
390
+ * Opens the database as a **secondary instance**: a read-only follower of a
391
+ * live primary that tolerates the primary deleting files and sees new
392
+ * writes on each `catchUpWithPrimary()` / `catchUpWithPrimarySync()` call.
393
+ * This is the supported way to read a database another process is actively
394
+ * writing (a plain `readOnly` open is only safe against a quiescent
395
+ * database — see `readOnly`).
396
+ *
397
+ * The value is the secondary instance's own workspace directory (RocksDB
398
+ * keeps the secondary's private state there; it is created if missing).
399
+ * It must be distinct from the database `path` (enforced at open) and
400
+ * exclusive to one secondary instance — two secondaries sharing a
401
+ * workspace corrupt each other's state. Reusing a workspace in-process for
402
+ * a DIFFERENT database is rejected at open (the same database and
403
+ * workspace share the one follower instance), and a kernel advisory lock
404
+ * on `<secondaryPath>/.secondary.lock`
405
+ * excludes other processes — but on filesystems without advisory locking
406
+ * (e.g. FUSE/9p mounts behind Docker Desktop bind mounts) the lock
407
+ * degrades to a no-op, and on network filesystems it does not exclude
408
+ * across hosts, so workspace exclusivity is the caller's job there.
409
+ *
410
+ * Implies `readOnly: true` (combining with an explicit `readOnly: false`
411
+ * throws) and forces `maxOpenFiles: -1`: every table and blob file is
412
+ * opened and held for the life of each version, which is what makes the
413
+ * primary's file deletions safe — note the file-descriptor footprint on
414
+ * large databases. Column families created by the primary after the
415
+ * secondary opens are invisible until the secondary reopens.
416
+ *
417
+ * Note: RocksDB upstream documents secondary instances as unsupported in
418
+ * combination with integrated BlobDB (which this library enables for
419
+ * values >= 2KB); this library's pinned RocksDB build handles blob files
420
+ * in secondary mode and it is covered by tests, but the combination is
421
+ * not guaranteed by upstream.
422
+ */
423
+ secondaryPath?: string;
375
424
  sharedStructuresKey?: symbol;
376
425
  /**
377
426
  * A string containing the amount of time or the number of milliseconds to
@@ -405,7 +454,7 @@ type ArrayBufferWithNotify = ArrayBuffer & {
405
454
  * already owns throws. (Sharing with the owning database's `Transaction`
406
455
  * instances is expected and allowed.)
407
456
  */
408
- declare class Store {
457
+ export declare class Store {
409
458
  #private;
410
459
  /**
411
460
  * The database instance.
@@ -542,6 +591,11 @@ declare class Store {
542
591
  * The path to the database.
543
592
  */
544
593
  path: string;
594
+ /**
595
+ * The open database's resolved filesystem identity, read once from
596
+ * `NativeDatabase.identityPath`. `undefined` until opened.
597
+ */
598
+ identityPath?: string;
545
599
  /**
546
600
  * Whether to use pessimistic locking for transactions. When `true`,
547
601
  * transactions will fail as soon as a conflict is detected. When `false`,
@@ -550,9 +604,18 @@ declare class Store {
550
604
  pessimistic: boolean;
551
605
  /**
552
606
  * Whether the database is open in readonly mode. When `true`, write
553
- * operations will throw an error with code `ERR_DATABASE_READONLY`.
607
+ * operations will throw an error with code `ERR_DATABASE_READONLY`, except
608
+ * for `flush()`/`flushSync()`/`compact()`/`compactSync()`, which succeed as
609
+ * no-ops.
554
610
  */
555
611
  readOnly: boolean;
612
+ /**
613
+ * The secondary instance's workspace directory when the database is opened
614
+ * as a secondary (see `RocksDatabaseOptions.secondaryPath`); `undefined`
615
+ * otherwise. A secondary is read-only, so `readOnly` is `true` whenever
616
+ * this is set.
617
+ */
618
+ secondaryPath?: string;
556
619
  /**
557
620
  * Encoder specific flag used to signal that the encoder should use a random
558
621
  * access structure.
@@ -577,8 +640,8 @@ declare class Store {
577
640
  */
578
641
  transactionLogMaxAgeThreshold?: number;
579
642
  /**
580
- * The maximum size of a transaction log before it is rotated to the next
581
- * sequence number.
643
+ * The target maximum size of a transaction log before rotation. Transactions
644
+ * are never split across files, so one transaction may exceed this target.
582
645
  */
583
646
  transactionLogMaxSize?: number;
584
647
  /**
@@ -612,6 +675,24 @@ declare class Store {
612
675
  * @param options - The options for the store.
613
676
  */
614
677
  constructor(path: string, options?: StoreOptions);
678
+ /**
679
+ * Creates an independent `Store` for another column family of the same
680
+ * database, used by {@link RocksDatabase#use}. The returned store shares the
681
+ * underlying database but must have its own codec state: a mutable
682
+ * encoder/decoder instance cannot be shared across column families (opening a
683
+ * view mutates the encoder's `name`, and clearing a view resets its
684
+ * `structures`), so a pre-constructed instance is rejected here — supply an
685
+ * encoder factory (`{ Encoder }`) or a named `encoding` instead.
686
+ *
687
+ * Override this in a `Store` subclass whose constructor cannot be recreated
688
+ * from `(path, options)` (e.g. it takes injected dependencies) or that needs
689
+ * to control how a view's codec state is built.
690
+ *
691
+ * @param name - The column family name for the derived store.
692
+ * @param options - Options overriding this store's, for the derived store.
693
+ * @returns A new, independent `Store` bound to `name`.
694
+ */
695
+ createColumnFamilyStore(name: string, options?: StoreOptions): Store;
615
696
  /**
616
697
  * Closes the database.
617
698
  */
@@ -686,6 +767,13 @@ declare class Store {
686
767
  */
687
768
  encodeValue(value: any): BufferWithDataView | Uint8Array;
688
769
  get(context: StoreContext, key: Key, alwaysCreateNewBuffer?: boolean, options?: StoreGetOptions): any | undefined;
770
+ /**
771
+ * Estimates the number of keys in a range from RocksDB statistics
772
+ * (memtable stats + approximate SST sizes with range-local entry density)
773
+ * without iterating. Estimates always reflect committed state, so there is
774
+ * no transactional variant.
775
+ */
776
+ estimateCount(options?: CountEstimateOptions): CountEstimate;
689
777
  getCount(context: StoreContext, options?: StoreRangeOptions): number;
690
778
  getKeys(context: StoreContext, options?: StoreIteratorOptions): any | undefined;
691
779
  getKeysCount(context: StoreContext, options?: StoreRangeOptions): number;
@@ -824,7 +912,7 @@ declare const RETRY_NOW: number;
824
912
  /**
825
913
  * Provides transaction level operations to a transaction callback.
826
914
  */
827
- declare class Transaction extends DBI {
915
+ export declare class Transaction extends DBI {
828
916
  #private;
829
917
  /**
830
918
  * Create a new transaction.
@@ -858,10 +946,12 @@ declare class Transaction extends DBI {
858
946
  */
859
947
  commitSync(): void;
860
948
  /**
861
- * Returns the transaction start timestamp in seconds. Defaults to the time at which
862
- * the transaction was created.
949
+ * Returns the transaction timestamp in milliseconds since the Unix epoch. It
950
+ * defaults to a process-wide monotonic value assigned when the transaction
951
+ * was created. A producer may use this value as its write identity; the
952
+ * transaction log uses it as the batch key.
863
953
  *
864
- * @returns The transaction start timestamp in seconds.
954
+ * @returns The transaction timestamp in milliseconds.
865
955
  */
866
956
  getTimestamp(): number;
867
957
  /**
@@ -869,9 +959,14 @@ declare class Transaction extends DBI {
869
959
  */
870
960
  get id(): number;
871
961
  /**
872
- * Set the transaction start timestamp in seconds.
962
+ * Overrides the transaction timestamp in milliseconds since the Unix epoch.
963
+ * Call this before reading the timestamp or staging writes when adopting an
964
+ * origin timestamp for replication or replay. Once a write or log entry is
965
+ * staged, the timestamp is frozen, but reapplying the same timestamp remains
966
+ * idempotent while the transaction is pending. The value must be finite,
967
+ * positive, and below 8640000000000000.
873
968
  *
874
- * @param timestamp - The timestamp to set in seconds.
969
+ * @param timestamp - The timestamp to set in milliseconds.
875
970
  */
876
971
  setTimestamp(timestamp?: number): void;
877
972
  }
@@ -930,6 +1025,21 @@ interface RocksDBOptions {
930
1025
  */
931
1026
  tailing?: boolean;
932
1027
  }
1028
+ interface CountEstimate {
1029
+ /**
1030
+ * The estimated number of keys.
1031
+ */
1032
+ count: number;
1033
+ /**
1034
+ * Heuristic 0–1 indicator of how trustworthy `count` is; exactly 1 only
1035
+ * when the count is exact. Derived from the estimate's resolution
1036
+ * (SST data-block / memtable sampling granularity relative to the count),
1037
+ * the tombstone fraction of the overlapping SSTs, and — for open-ended
1038
+ * starts — the error compounded by complement subtraction. A heuristic
1039
+ * ordering signal, not a statistical bound.
1040
+ */
1041
+ confidence: number;
1042
+ }
933
1043
  interface RangeOptions extends RocksDBOptions {
934
1044
  /**
935
1045
  * The range end key, otherwise known as the "upper bound". Defaults to
@@ -952,6 +1062,13 @@ interface RangeOptions extends RocksDBOptions {
952
1062
  */
953
1063
  start?: Key | Uint8Array;
954
1064
  }
1065
+ interface CountEstimateOptions extends RangeOptions {
1066
+ /**
1067
+ * Interpret `start` as the upper bound and `end` as the lower bound, as
1068
+ * `getRange()` does for reverse iteration. Defaults to `false`.
1069
+ */
1070
+ reverse?: boolean;
1071
+ }
955
1072
  interface IteratorOptions extends RangeOptions {
956
1073
  /**
957
1074
  * The maximum number of entries to yield. When set, iteration stops after
@@ -991,7 +1108,7 @@ interface DBITransactional {
991
1108
  *
992
1109
  * This class is not meant to be used directly.
993
1110
  */
994
- declare class DBI<T extends DBITransactional | unknown = unknown> {
1111
+ export declare class DBI<T extends DBITransactional | unknown = unknown> {
995
1112
  /**
996
1113
  * The RocksDB context for `get()`, `put()`, and `remove()`.
997
1114
  */
@@ -1197,7 +1314,13 @@ declare class DBI<T extends DBITransactional | unknown = unknown> {
1197
1314
  }
1198
1315
  //#endregion
1199
1316
  //#region src/stats.d.ts
1200
- /** Database-level RocksDB statistics types for `db.getStats()` / `db.getStat()`. */
1317
+ /**
1318
+ * Database-level RocksDB statistics types for `db.getStats()` / `db.getStat()`.
1319
+ *
1320
+ * The `writeBufferManager.*` keys are the exception to "database-level": the
1321
+ * WriteBufferManager is a process-wide singleton, so those values describe every
1322
+ * database in the process. See `getWriteBufferManagerStats()`.
1323
+ */
1201
1324
  type StatsHistogramData = {
1202
1325
  average: number;
1203
1326
  count: number;
@@ -1232,6 +1355,7 @@ type StatsBasics = {
1232
1355
  "rocksdb.num-live-versions": number;
1233
1356
  "rocksdb.current-super-version-number": number;
1234
1357
  "rocksdb.oldest-snapshot-time": number;
1358
+ "rocksdb.num-snapshots": number;
1235
1359
  "rocksdb.num-blob-files": number;
1236
1360
  "rocksdb.total-blob-file-size": number;
1237
1361
  "rocksdb.live-blob-file-size": number;
@@ -1248,6 +1372,11 @@ type StatsBasics = {
1248
1372
  "txnlog.replayGapBytes": number;
1249
1373
  "commitPipeline.logQueueDepth": number;
1250
1374
  "commitPipeline.commitQueueDepth": number;
1375
+ "writeBufferManager.bufferSize": number;
1376
+ "writeBufferManager.memoryUsage": number;
1377
+ "writeBufferManager.mutableMemoryUsage": number;
1378
+ "writeBufferManager.stallActive": number;
1379
+ "writeBufferManager.stallActiveMs": number;
1251
1380
  };
1252
1381
  type StatsCuratedExtras = {
1253
1382
  "rocksdb.block.cache.hit": number;
@@ -1495,6 +1624,34 @@ type StatsAllExtras = {
1495
1624
  "rocksdb.prefetch.memory.bytes.granted": number;
1496
1625
  "rocksdb.prefetch.memory.bytes.released": number;
1497
1626
  "rocksdb.prefetch.memory.requests.blocked": number;
1627
+ "rocksdb.wal.precreate.hit": number;
1628
+ "rocksdb.wal.precreate.miss": number;
1629
+ "rocksdb.wal.precreate.waited": number;
1630
+ "rocksdb.wal.precreate.wait.micros": number;
1631
+ "rocksdb.wal.precreate.failed": number;
1632
+ "rocksdb.rate.limiter.bytes.read": number;
1633
+ "rocksdb.rate.limiter.bytes.write": number;
1634
+ "rocksdb.rate.limiter.requests.read": number;
1635
+ "rocksdb.rate.limiter.requests.write": number;
1636
+ "rocksdb.rate.limiter.delayed.requests.read": number;
1637
+ "rocksdb.rate.limiter.delayed.requests.write": number;
1638
+ "rocksdb.rate.limiter.total.wait.micros.read": number;
1639
+ "rocksdb.rate.limiter.total.wait.micros.write": number;
1640
+ "rocksdb.read.path.range.tombstones.inserted": number;
1641
+ "rocksdb.read.path.range.tombstones.discarded": number;
1642
+ "rocksdb.file.open.metadata.retrieved": number;
1643
+ "rocksdb.file.open.metadata.passed": number;
1644
+ "rocksdb.manifest.validation.failure.count": number;
1645
+ "rocksdb.flush.reason.write_buffer_full": number;
1646
+ "rocksdb.flush.reason.write_buffer_manager": number;
1647
+ "rocksdb.flush.reason.memtable_max_range_deletions": number;
1648
+ "rocksdb.atomic_flush.request.reason.write_buffer_full": number;
1649
+ "rocksdb.atomic_flush.request.reason.write_buffer_manager": number;
1650
+ "rocksdb.atomic_flush.request.reason.memtable_max_range_deletions": number;
1651
+ "rocksdb.atomic_flush.request.reason.other": number;
1652
+ "rocksdb.checkpoint.read.bytes": number;
1653
+ "rocksdb.checkpoint.write.bytes": number;
1654
+ "rocksdb.file.submit.async.read.fallback": number;
1498
1655
  "rocksdb.compaction.times.cpu_micros": StatsHistogramData;
1499
1656
  "rocksdb.subcompaction.setup.times.micros": StatsHistogramData;
1500
1657
  "rocksdb.table.sync.micros": StatsHistogramData;
@@ -1555,6 +1712,18 @@ type StatsAllExtras = {
1555
1712
  "rocksdb.multiscan.prepare.micros": StatsHistogramData;
1556
1713
  "rocksdb.multiscan.blocks.per.prepare": StatsHistogramData;
1557
1714
  "rocksdb.block.key.distribution.cv": StatsHistogramData;
1715
+ "rocksdb.ingest.external.file.prepare.micros": StatsHistogramData;
1716
+ "rocksdb.ingest.external.file.run.micros": StatsHistogramData;
1717
+ "rocksdb.iodispatcher.async.read.observed.completion.micros": StatsHistogramData;
1718
+ "rocksdb.iodispatcher.async.read.poll.wait.micros": StatsHistogramData;
1719
+ "rocksdb.iodispatcher.async.read.prefetch.lead.micros": StatsHistogramData;
1720
+ "rocksdb.rate.limiter.wait.micros.read": StatsHistogramData;
1721
+ "rocksdb.rate.limiter.wait.micros.write": StatsHistogramData;
1722
+ "rocksdb.flush.memtable.memory.bytes": StatsHistogramData;
1723
+ "rocksdb.flush.memtable.total.data.size.bytes": StatsHistogramData;
1724
+ "rocksdb.flush.write_buffer_full.memtable.memory.bytes": StatsHistogramData;
1725
+ "rocksdb.flush.write_buffer_manager.memtable.memory.bytes": StatsHistogramData;
1726
+ "rocksdb.open.and.compact.db.open.micros": StatsHistogramData;
1558
1727
  };
1559
1728
  type StatsCurated = StatsBasics & StatsCuratedExtras;
1560
1729
  type StatsAll = StatsCurated & StatsAllExtras;
@@ -1672,9 +1841,72 @@ interface ValidateTransactionLogStoreOptions {
1672
1841
  * }
1673
1842
  * ```
1674
1843
  */
1675
- declare function validateTransactionLogStore(path: string, options?: ValidateTransactionLogStoreOptions): Promise<TransactionLogStoreValidation>;
1844
+ export declare function validateTransactionLogStore(path: string, options?: ValidateTransactionLogStoreOptions): Promise<TransactionLogStoreValidation>;
1676
1845
  //#endregion
1677
1846
  //#region src/load-binding.d.ts
1847
+ /**
1848
+ * The `Error` subclass passed to `'error'` event listeners and returned by
1849
+ * `db.getLastError()` when RocksDB reports a background error (e.g. a write
1850
+ * failing at the filesystem level). A real `Error` instance (`instanceof Error`
1851
+ * and `instanceof BackgroundError` both hold) with the fields below. Only a
1852
+ * hard-or-worse error (`writesDisabled`) stops writes; a soft error is
1853
+ * auto-recoverable. When `writesDisabled` is `true` and the underlying condition
1854
+ * has cleared, call {@link RocksDatabase.resume}. See HarperFast/rocksdb-js#730.
1855
+ *
1856
+ * The runtime constructor is defined natively and exported as
1857
+ * {@link BackgroundError}; the same name is both a value (for `instanceof`) and
1858
+ * this instance type.
1859
+ *
1860
+ * @example
1861
+ * ```typescript
1862
+ * db.on('error', (err: BackgroundError) => {
1863
+ * if (err.writesDisabled) console.error(`writes disabled: ${err.message}`);
1864
+ * });
1865
+ * ```
1866
+ */
1867
+ export interface BackgroundError extends Error {
1868
+ /** Always `'BackgroundError'`. */
1869
+ name: string;
1870
+ /** Discriminator for the error class; always `'background'` here. */
1871
+ type: string;
1872
+ /**
1873
+ * The RocksDB `Status::Severity` as a number: 1 soft, 2 hard, 3 fatal,
1874
+ * 4 unrecoverable.
1875
+ */
1876
+ severity: number;
1877
+ /** Human-readable severity: `'soft'`, `'hard'`, `'fatal'`, or `'unrecoverable'`. */
1878
+ severityName: string;
1879
+ /**
1880
+ * Whether RocksDB has disabled writes on the database in response to this
1881
+ * error (severity hard or worse, i.e. `severity >= 2`). Only when `true` is
1882
+ * {@link RocksDatabase.resume} warranted; a soft error auto-recovers and
1883
+ * leaves writes enabled. Distinct from opening the database in read-only
1884
+ * mode — this is RocksDB halting writes after a background failure.
1885
+ */
1886
+ writesDisabled: boolean;
1887
+ /**
1888
+ * The RocksDB `BackgroundErrorReason` as a number, present when the error
1889
+ * originated from a reason-bearing callback (flush, compaction, etc.).
1890
+ */
1891
+ reason?: number;
1892
+ /** Human-readable reason, e.g. `'flush'` or `'compaction'`. */
1893
+ reasonName?: string;
1894
+ }
1895
+ /**
1896
+ * The shape accepted by `db.setLastError(...)` to inject or reset a background
1897
+ * error. `message` is required; the rest default/omit as with a real error.
1898
+ * `type` defaults to `'background'`. Pass `null`/nothing to `setLastError` to
1899
+ * clear instead of an object of this shape.
1900
+ */
1901
+ type BackgroundErrorOptions = {
1902
+ message: string;
1903
+ severity?: number;
1904
+ severityName?: string;
1905
+ writesDisabled?: boolean;
1906
+ reason?: number;
1907
+ reasonName?: string;
1908
+ type?: string;
1909
+ };
1678
1910
  type NativeTransactionOptions = {
1679
1911
  /**
1680
1912
  * Whether to disable snapshots.
@@ -1708,7 +1940,7 @@ type NativeTransaction = {
1708
1940
  putSync(key: Key, value: Buffer | Uint8Array, txnId?: number): void;
1709
1941
  removeSync(key: Key): void;
1710
1942
  setTimestamp(timestamp?: number): void;
1711
- useLog(name: string | number): TransactionLog;
1943
+ useLog(name: string | number, jsDatabase: NativeDatabase): TransactionLog;
1712
1944
  };
1713
1945
  type LogBuffer = Buffer & {
1714
1946
  dataView: DataView;
@@ -1788,7 +2020,7 @@ type TransactionLogStats = {
1788
2020
  maxAgeThreshold: number;
1789
2021
  };
1790
2022
  };
1791
- type TransactionLog = {
2023
+ export type TransactionLog = {
1792
2024
  new (db: NativeDatabase, name: string): TransactionLog;
1793
2025
  addEntry(data: Buffer | Uint8Array, txnId?: number): void;
1794
2026
  getLogFileSize(sequenceId?: number): number;
@@ -1829,7 +2061,7 @@ type NativeIteratorResult = number | {
1829
2061
  value?: Buffer;
1830
2062
  };
1831
2063
  declare class NativeIteratorCls {
1832
- constructor(context: StoreContext, flags: number, startKeyEnd: number, endKeyStart: number, endKeyEnd: number, options?: NativeIteratorAdvancedOptions);
2064
+ constructor(context: StoreContext, flags: number, startKeyEnd: number, endKeyStart: number, endKeyEnd: number, options?: NativeIteratorAdvancedOptions, transactionId?: number);
1833
2065
  next(): NativeIteratorResult;
1834
2066
  return(): void;
1835
2067
  throw(err?: unknown): void;
@@ -1880,6 +2112,15 @@ type NativeDatabaseOptions = {
1880
2112
  noBlockCache?: boolean;
1881
2113
  parallelismThreads?: number;
1882
2114
  readOnly?: boolean;
2115
+ /**
2116
+ * A present, non-empty string opens the database via `DB::OpenAsSecondary`:
2117
+ * a read-only follower of a live primary that advances with
2118
+ * `catchUpWithPrimary()`. The value is the secondary instance's own
2119
+ * workspace directory (created if missing), distinct from `path` (the
2120
+ * primary's data directory) and exclusive to one secondary instance.
2121
+ * Implies `readOnly: true` and forces `maxOpenFiles: -1`.
2122
+ */
2123
+ secondaryPath?: string;
1883
2124
  statsLevel?: (typeof stats.StatsLevel)[keyof typeof stats.StatsLevel];
1884
2125
  transactionLogMaxAgeThreshold?: number;
1885
2126
  transactionLogMaxSize?: number;
@@ -1915,6 +2156,47 @@ type PurgedLog = {
1915
2156
  path: string;
1916
2157
  entries: number;
1917
2158
  };
2159
+ type FlushOptions = {
2160
+ /**
2161
+ * Whether the flush may proceed even though it will stall writes for its duration.
2162
+ *
2163
+ * Maps to `rocksdb::FlushOptions::allow_write_stall`. RocksDB's default is `false`, which
2164
+ * means the opposite of what the name suggests on first read: the flush **waits** until it
2165
+ * can run without causing a stall. That wait has no timeout, so a database sitting in a stall
2166
+ * condition — immutable-memtable backlog, L0 stop trigger, pending-compaction-bytes limit, an
2167
+ * exhausted WriteBufferManager budget — blocks the caller for as long as the condition lasts.
2168
+ * `flush()` runs on the libuv threadpool, so there the wait shows up as a promise that simply
2169
+ * never settles while the event loop stays alive — and it parks that whole worker, not just
2170
+ * the caller's promise: `UV_THREADPOOL_SIZE` defaults to 4, so a handful of concurrently
2171
+ * stalled flushes can exhaust the pool and stall every unrelated `fs`/`dns`/`crypto` call and
2172
+ * cold-cache `get()` in the process, not only this database's own operations. `flushSync()`
2173
+ * takes the same wait on the JS thread, so it is the worse of the two here rather than the
2174
+ * safer one: it freezes the event loop outright instead of parking a pool worker, and it holds
2175
+ * the in-flight operation claim that `close()` waits on for the duration.
2176
+ *
2177
+ * Pass `true` when the flush is a durability gate the caller is blocked on and stalling
2178
+ * writers is the acceptable cost of it completing — decide that up front, before issuing the
2179
+ * call, since there is no way to cancel an in-flight `flush()` and turn `true` into an escape
2180
+ * hatch after the fact. It is also not a free way out of an existing stall: forcing the
2181
+ * memtable switch adds another L0 file to the level whose file count may be *causing* the
2182
+ * stop trigger, so it can prolong the condition it is meant to clear. Weigh the cost
2183
+ * database-wide, not per-caller: a flush covers **every column family** on the database, and
2184
+ * the descriptor is process-global and shared across `worker_threads`, so the stall lands on
2185
+ * every other column family and every other handle that opened the same path — not just the
2186
+ * one you called. It also relocates the hang rather than removing it: a stalled `db->Write()`
2187
+ * blocks the database's single `CommitWorker` thread, which dispatches every
2188
+ * `Transaction.commit()` in order, so the stall queues up every commit behind it — including
2189
+ * ones from callers that never touched flush — until the stall clears.
2190
+ *
2191
+ * Note this is a *different* knob from the `writeBufferManagerAllowStall` config, and their
2192
+ * polarity is nearly opposite: that one decides whether the WriteBufferManager may stall
2193
+ * writers at all, this one decides whether a manual flush is willing to cause a stall rather
2194
+ * than wait one out.
2195
+ *
2196
+ * @default false
2197
+ */
2198
+ allowWriteStall?: boolean;
2199
+ };
1918
2200
  type NativeDatabase = {
1919
2201
  new (): NativeDatabase;
1920
2202
  addListener(event: string, callback: (...args: any[]) => void): void;
@@ -1923,6 +2205,8 @@ type NativeDatabase = {
1923
2205
  flushBeforeBackup?: boolean;
1924
2206
  transactionLogs?: boolean;
1925
2207
  }): void;
2208
+ catchUpWithPrimary(resolve: ResolveCallback<void>, reject: RejectCallback): void;
2209
+ catchUpWithPrimarySync(): void;
1926
2210
  clear(resolve: ResolveCallback<void>, reject: RejectCallback): void;
1927
2211
  clearSync(): void;
1928
2212
  close(): void;
@@ -1933,15 +2217,21 @@ type NativeDatabase = {
1933
2217
  destroy(): void;
1934
2218
  drop(resolve: ResolveCallback<void>, reject: RejectCallback): void;
1935
2219
  dropSync(): void;
1936
- flush(resolve: ResolveCallback<void>, reject: RejectCallback): void;
1937
- flushSync(): void;
2220
+ flush(resolve: ResolveCallback<void>, reject: RejectCallback, options?: FlushOptions): void;
2221
+ flushSync(options?: FlushOptions): void;
1938
2222
  notify(event: string | BufferWithDataView, args?: any[]): boolean;
1939
2223
  get(keyLengthOrKeyBuffer: number | Buffer, resolve: ResolveCallback<Buffer | number>, reject: RejectCallback, txnId?: number, expectedVersion?: number): number;
2224
+ estimateCount(startKey?: Buffer, endKey?: Buffer): {
2225
+ count: number;
2226
+ confidence: number;
2227
+ };
1940
2228
  getCompression(): {
1941
2229
  algorithm: string;
1942
2230
  level?: number;
1943
2231
  };
1944
2232
  getCount(options?: RangeOptions, txnId?: number): number;
2233
+ getLastError(): BackgroundError | null;
2234
+ setLastError(error?: BackgroundErrorOptions | null): void;
1945
2235
  getDBIntProperty(propertyName: string): number | undefined;
1946
2236
  getDBProperty(propertyName: string): string | undefined;
1947
2237
  getLogOptions(): {
@@ -1956,6 +2246,7 @@ type NativeDatabase = {
1956
2246
  getSync(keyLengthOrKeyBuffer: number | Buffer, flags: number, txnId?: number, expectedVersion?: number): Buffer;
1957
2247
  getUserSharedBuffer(key: BufferWithDataView, defaultBuffer: ArrayBuffer, callback?: UserSharedBufferCallback): ArrayBuffer;
1958
2248
  hasLock(key: BufferWithDataView): boolean;
2249
+ identityPath: string | undefined;
1959
2250
  listeners(event: string | BufferWithDataView): number;
1960
2251
  listLogs(): string[];
1961
2252
  opened: boolean;
@@ -1971,12 +2262,13 @@ type NativeDatabase = {
1971
2262
  putSync(key: BufferWithDataView, value: any, txnId?: number): void;
1972
2263
  removeListener(event: string | BufferWithDataView, callback: () => void): boolean;
1973
2264
  removeSync(key: BufferWithDataView, txnId?: number): void;
2265
+ resume(): void;
1974
2266
  setDefaultKeyBuffer(buffer: Buffer | Uint8Array | null): void;
1975
2267
  setDefaultValueBuffer(buffer: Buffer | Uint8Array | null): void;
1976
2268
  setIteratorState(buffer: Buffer | Uint8Array): void;
1977
2269
  tryLock(key: BufferWithDataView, callback?: () => void): boolean;
1978
2270
  unlock(key: BufferWithDataView): void;
1979
- useLog(name: string): TransactionLog;
2271
+ useLog(name: string, jsDatabase?: NativeDatabase): TransactionLog;
1980
2272
  verifyVersion(keyLengthOrKeyBuffer: number | Buffer, version: number): boolean;
1981
2273
  withLock(key: BufferWithDataView, callback: () => void | Promise<void>): Promise<void>;
1982
2274
  };
@@ -2026,23 +2318,136 @@ type RocksDatabaseConfig = {
2026
2318
  */
2027
2319
  writeBufferManagerAllowStall?: boolean;
2028
2320
  };
2321
+ type RegistryStatusTransaction = {
2322
+ /** The transaction id assigned by the database descriptor. */
2323
+ id: number;
2324
+ /** Milliseconds since the transaction handle was created. */
2325
+ ageMs: number;
2326
+ };
2029
2327
  type RegistryStatusDB = {
2030
2328
  path: string;
2031
2329
  refCount: number;
2032
2330
  columnFamilies: string[];
2033
2331
  transactions: number;
2332
+ /**
2333
+ * One entry per live transaction handle. An `ageMs` beyond any plausible request lifetime,
2334
+ * against a nonzero `rocksdb.num-snapshots`, identifies a handle holding back reclamation for
2335
+ * its whole database.
2336
+ */
2337
+ transactionDetails: RegistryStatusTransaction[];
2034
2338
  closables: number;
2035
2339
  locks: number;
2036
2340
  userSharedBuffers: number;
2037
2341
  listenerCallbacks: number;
2038
2342
  };
2039
2343
  type RegistryStatus = RegistryStatusDB[];
2040
- declare const constants: {
2344
+ /**
2345
+ * The native `BackgroundError` constructor (a real `Error` subclass). Exported
2346
+ * as both a value — for `err instanceof BackgroundError` — and, via declaration
2347
+ * merging with the interface above, a type. Instances are produced by the
2348
+ * `'error'` event and `db.getLastError()`; consumers rarely construct their own.
2349
+ * The `details` param is required and typed to the instance fields so a bare
2350
+ * `new BackgroundError()` (which would omit `severity` / `writesDisabled` / …)
2351
+ * is a type error.
2352
+ */
2353
+ export declare const BackgroundError: new (details: Pick<BackgroundError, "message" | "severity" | "severityName" | "writesDisabled" | "reason" | "reasonName"> & {
2354
+ type?: string;
2355
+ }) => BackgroundError;
2356
+ /**
2357
+ * Live state of the process-wide `WriteBufferManager` singleton — see
2358
+ * {@link getWriteBufferManagerStats}.
2359
+ */
2360
+ type WriteBufferManagerStats = {
2361
+ /**
2362
+ * Whether a manager has been created in this process. `bufferSize`,
2363
+ * `memoryUsage`, `mutableMemoryUsage`, `stallActive`, `stallActiveMs`,
2364
+ * `watchdogRunning` and `columnFamilies` are 0/false when not; `allowStall`
2365
+ * and `costToCache` still reflect the configured setting, and
2366
+ * `inventoryAvailable` is `true`.
2367
+ */
2368
+ enabled: boolean;
2369
+ /** The manager's budget in bytes (`writeBufferManagerSize`, live). */
2370
+ bufferSize: number;
2371
+ /** Total memtable memory charged to the manager, in bytes. */
2372
+ memoryUsage: number;
2373
+ /** The share of `memoryUsage` held by active (mutable) memtables, in bytes. */
2374
+ mutableMemoryUsage: number;
2375
+ allowStall: boolean;
2376
+ costToCache: boolean;
2377
+ stallActive: boolean;
2378
+ /**
2379
+ * How long the current stall has been active, in milliseconds; 0 when not
2380
+ * stalled. Sampled once a second by the stall watchdog, so it is 0 for the
2381
+ * first second of a stall and whenever `watchdogRunning` is false.
2382
+ */
2383
+ stallActiveMs: number;
2384
+ /**
2385
+ * Whether the stall watchdog is running. It runs only while a manager exists
2386
+ * with `writeBufferManagerAllowStall`, and only when
2387
+ * `ROCKSDB_JS_WBM_STALL_WARN_MS` is not `0`.
2388
+ */
2389
+ watchdogRunning: boolean;
2390
+ /**
2391
+ * Live column families across every database attached to this manager. A
2392
+ * dropped column family keeps charging the manager until its last handle
2393
+ * closes, so it is counted until then.
2394
+ */
2395
+ columnFamilies: number;
2396
+ /**
2397
+ * `false` when the column-family inventory could not be collected because the
2398
+ * database registry was locked — most plausibly by a close that is itself
2399
+ * waiting out this stall. `columnFamilies` is then `0` and
2400
+ * `maxWriteBufferSizeToMaintain` empty; every other field is still live.
2401
+ */
2402
+ inventoryAvailable: boolean;
2403
+ /**
2404
+ * Effective per-column-family `max_write_buffer_size_to_maintain` (as a decimal
2405
+ * string) to the number of those column families holding it. Effective, not
2406
+ * requested: RocksDB rewrites a requested `0` for a transaction database.
2407
+ */
2408
+ maxWriteBufferSizeToMaintain: Record<string, number>;
2409
+ };
2410
+ /**
2411
+ * Reads the live state of the process-wide `WriteBufferManager`: its budget,
2412
+ * charged memory, mutable share, stall state, and attached column-family
2413
+ * inventory. The manager is shared by every database and worker thread in the
2414
+ * process.
2415
+ *
2416
+ * A WriteBufferManager stall does not pass through RocksDB's `WriteController`,
2417
+ * so it is not reflected by `rocksdb.stall.micros`, `db.isWriteStalled()`, or
2418
+ * the `'writeStall'` event. Use `stallActive` to distinguish this condition from
2419
+ * an idle database.
2420
+ *
2421
+ * @example
2422
+ * ```typescript
2423
+ * const wbm = getWriteBufferManagerStats();
2424
+ * if (wbm.stallActive) {
2425
+ * log.warn(`writes stalled for ${wbm.stallActiveMs}ms`);
2426
+ * }
2427
+ * ```
2428
+ */
2429
+ export declare const getWriteBufferManagerStats: () => WriteBufferManagerStats;
2430
+ export declare const constants: {
2041
2431
  ALWAYS_CREATE_NEW_BUFFER_FLAG: number;
2042
2432
  NOT_IN_MEMORY_CACHE_FLAG: number;
2043
2433
  ONLY_IF_IN_MEMORY_CACHE_FLAG: number;
2044
2434
  POPULATE_VERSION_FLAG: number;
2045
2435
  FRESH_VERSION_FLAG: number;
2436
+ /**
2437
+ * Producer flag in a value's metadata word (4 big-endian bytes at offset 8, top byte `0x0E`,
2438
+ * low 24 bits flags), declaring that this version does NOT uniquely identify the value —
2439
+ * the producer has stored more than one distinct value under it.
2440
+ *
2441
+ * Set it and the VerificationTable stops treating version equality as evidence for this value:
2442
+ * a read never answers `FRESH_VERSION_FLAG` for it and never publishes its version to a slot,
2443
+ * so a consumer holding a differing cached copy at that version cannot have it confirmed.
2444
+ * Clear it again on the next write that gives the value a version of its own.
2445
+ *
2446
+ * Read only from values in a column family that opted into the verification table. Do not call
2447
+ * `populateVersion()` for a marked version: that explicit primitive never sees the value and
2448
+ * cannot enforce this flag.
2449
+ */
2450
+ VERSION_NOT_UNIQUE_FLAG: number;
2046
2451
  /**
2047
2452
  * Sentinel value resolved (not rejected) by `commit()` when
2048
2453
  * `coordinatedRetry: true` and the transaction encountered an IsBusy
@@ -2058,6 +2463,7 @@ declare const constants: {
2058
2463
  ITERATOR_INCLUDE_VALUES_FLAG: number;
2059
2464
  ITERATOR_NEEDS_STABLE_VALUE_BUFFER_FLAG: number;
2060
2465
  ITERATOR_CONTEXT_IS_TRANSACTION_FLAG: number;
2466
+ ITERATOR_HAS_TRANSACTION_ID_FLAG: number;
2061
2467
  ITERATOR_RESULT_DONE: number;
2062
2468
  ITERATOR_RESULT_FAST: number;
2063
2469
  };
@@ -2069,13 +2475,13 @@ declare const constants: {
2069
2475
  * always present. Use it to validate a `compression` option or to pick an
2070
2476
  * algorithm that is actually available at runtime.
2071
2477
  */
2072
- declare const supportedCompression: readonly string[];
2478
+ export declare const supportedCompression: readonly string[];
2073
2479
  declare const NativeDatabase: NativeDatabase;
2074
2480
  declare const NativeTransaction: NativeTransaction;
2075
- declare const TransactionLog: TransactionLog;
2076
- declare const registryStatus: () => RegistryStatus;
2077
- declare const shutdown: () => void;
2078
- declare const currentThreadId: () => number;
2481
+ export declare const TransactionLog: TransactionLog;
2482
+ export declare const registryStatus: () => RegistryStatus;
2483
+ export declare const shutdown: () => void;
2484
+ export declare const currentThreadId: () => number;
2079
2485
  /**
2080
2486
  * Advises the kernel that the file-backed pages of every mapped transaction log
2081
2487
  * are cold (Linux MADV_COLD), so they are reclaimed first under memory pressure
@@ -2089,7 +2495,7 @@ declare const currentThreadId: () => number;
2089
2495
  *
2090
2496
  * @returns the number of maps cooled and total file-backed bytes advised.
2091
2497
  */
2092
- declare const coolTransactionLogs: () => {
2498
+ export declare const coolTransactionLogs: () => {
2093
2499
  maps: number;
2094
2500
  bytes: number;
2095
2501
  };
@@ -2104,13 +2510,13 @@ declare const coolTransactionLogs: () => {
2104
2510
  * OS handle is owned entirely in native code (no fd crosses into JS), and the
2105
2511
  * kernel releases the lock when the handle closes, including on process death.
2106
2512
  */
2107
- declare const tryFileLock: (file: string, shared?: boolean) => number;
2513
+ export declare const tryFileLock: (file: string, shared?: boolean) => number;
2108
2514
  /**
2109
2515
  * Releases a file lock acquired via `tryFileLock`. A no-op for
2110
2516
  * token `0` or an unknown token.
2111
2517
  */
2112
- declare const fileLockRelease: (token: number) => void;
2113
- declare const stats: {
2518
+ export declare const fileLockRelease: (token: number) => void;
2519
+ export declare const stats: {
2114
2520
  StatsLevel: {
2115
2521
  DisableAll: number;
2116
2522
  ExceptTickers: number;
@@ -2153,6 +2559,57 @@ interface BackupStreamOptions {
2153
2559
  transactionLogs?: boolean;
2154
2560
  }
2155
2561
  //#endregion
2562
+ //#region src/count-estimator.d.ts
2563
+ interface CountEstimatorOptions extends CountEstimateOptions {}
2564
+ /**
2565
+ * Progressively refines a range key-count estimate as an iterator traverses
2566
+ * the range. The estimate starts as the pure statistical estimate
2567
+ * (`estimateCount`) and converges toward the exact count: the traversed
2568
+ * portion is exact, and the statistical estimate of the untraversed remainder
2569
+ * is calibrated by the observed ratio of actual-to-estimated entries over the
2570
+ * portion already traversed.
2571
+ *
2572
+ * The estimator never touches the iterator itself — the caller reports
2573
+ * progress with `advance(lastKey, count)` whenever it wants a checkpoint
2574
+ * (e.g. once per page), then reads `estimate()`. The caller owns the
2575
+ * progress contract: cursors must move monotonically through the range and
2576
+ * each entry must be reported once (a re-reported page inflates the count
2577
+ * undetectably). When traversal completes, call `finish()` so `estimate()`
2578
+ * returns the exact total instead of adding a block-granular remainder.
2579
+ *
2580
+ * Each `estimate()` checkpoint queries RocksDB statistics for the two range
2581
+ * segments (cost scales with the SSTs overlapping them, not with key count);
2582
+ * results are memoized per checkpoint, so repeated reads between `advance()`
2583
+ * calls are free.
2584
+ */
2585
+ export declare class CountEstimator {
2586
+ #private;
2587
+ constructor(store: Store, options?: CountEstimatorOptions);
2588
+ /**
2589
+ * The number of entries reported traversed so far.
2590
+ */
2591
+ get traversed(): number;
2592
+ /**
2593
+ * Records that iteration has advanced through `count` more entries, ending
2594
+ * at `lastKey`. Pass `count: 0` when an empty page has no last key.
2595
+ */
2596
+ advance(lastKey: Key | Uint8Array | undefined, count?: number): void;
2597
+ /**
2598
+ * Marks traversal of the range as complete: `estimate()` becomes the exact
2599
+ * traversed count.
2600
+ */
2601
+ finish(): void;
2602
+ /**
2603
+ * Estimates the total number of entries in the full range: the exact
2604
+ * traversed count plus a calibrated statistical estimate of the remainder.
2605
+ * `confidence` is the exactness-weighted blend of the traversed portion
2606
+ * (exact) and the remainder's statistical confidence, so it approaches 1
2607
+ * as the exact portion grows (though a checkpoint can decrease when
2608
+ * calibration makes a large correction), and is exactly 1 after `finish()`.
2609
+ */
2610
+ estimate(): CountEstimate;
2611
+ }
2612
+ //#endregion
2156
2613
  //#region src/database.d.ts
2157
2614
  type TransactionCallback<T> = (txn: Transaction, attempt: number) => T | PromiseLike<T>;
2158
2615
  interface RocksDatabaseOptions extends StoreOptions {
@@ -2192,7 +2649,7 @@ type RocksDBStats = StatsDefault | StatsAll;
2192
2649
  * db.close();
2193
2650
  * ```
2194
2651
  */
2195
- declare class RocksDatabase extends DBI<DBITransactional> {
2652
+ export declare class RocksDatabase extends DBI<DBITransactional> {
2196
2653
  #private;
2197
2654
  constructor(pathOrStore: string | Store, options?: RocksDatabaseOptions);
2198
2655
  /**
@@ -2229,6 +2686,9 @@ declare class RocksDatabase extends DBI<DBITransactional> {
2229
2686
  * Compacts the entire key range of the database asynchronously.
2230
2687
  * This triggers manual compaction which removes tombstones and reclaims space.
2231
2688
  *
2689
+ * On a read-only database this is a no-op: arguments are still validated, but
2690
+ * the returned promise resolves without compacting rather than rejecting.
2691
+ *
2232
2692
  * @example
2233
2693
  * ```typescript
2234
2694
  * const db = RocksDatabase.open('/path/to/database');
@@ -2299,6 +2759,9 @@ declare class RocksDatabase extends DBI<DBITransactional> {
2299
2759
  * Compacts the entire key range of the database synchronously.
2300
2760
  * This triggers manual compaction which removes tombstones and reclaims space.
2301
2761
  *
2762
+ * On a read-only database this validates its arguments and then returns
2763
+ * without compacting, rather than throwing.
2764
+ *
2302
2765
  * @example
2303
2766
  * ```typescript
2304
2767
  * const db = RocksDatabase.open('/path/to/database');
@@ -2393,6 +2856,36 @@ declare class RocksDatabase extends DBI<DBITransactional> {
2393
2856
  * @returns `true` if there was at least one listener.
2394
2857
  */
2395
2858
  static notify(event: string, ...args: any[]): boolean;
2859
+ /**
2860
+ * Advances a secondary instance to the primary's current state by tailing
2861
+ * and replaying the primary's MANIFEST and WAL. A secondary does not see
2862
+ * the primary's writes until this (or {@link catchUpWithPrimarySync}) is
2863
+ * called. Concurrent reads through this handle remain safe while the
2864
+ * catch-up runs.
2865
+ *
2866
+ * Only valid on a database opened with the `secondaryPath` option; throws
2867
+ * with code `ERR_NOT_SECONDARY` otherwise.
2868
+ *
2869
+ * Advances the **database** view only. Against a cross-process primary,
2870
+ * transaction-log reads keep serving the stores discovered at open (a store
2871
+ * the primary creates later, and its appends, need a reopen); a primary in
2872
+ * the same process shares the store registry, so its stores and appends are
2873
+ * visible immediately. Either way a log entry can describe data this
2874
+ * handle's database view does not have yet — the log write completes before
2875
+ * the RocksDB commit for every writer, so consumers must tolerate the log
2876
+ * leading the database.
2877
+ *
2878
+ * Await one call before starting the next: the replay holds a libuv worker
2879
+ * for its whole duration and concurrent calls queue on a per-database mutex
2880
+ * while holding theirs, so overlapping catch-ups on a backlogged follower
2881
+ * can exhaust the default four-thread pool and stall unrelated I/O.
2882
+ */
2883
+ catchUpWithPrimary(): Promise<void>;
2884
+ /**
2885
+ * Synchronous version of {@link catchUpWithPrimary}. The replay runs on the
2886
+ * JS thread, so prefer the async form unless the caller is already blocking.
2887
+ */
2888
+ catchUpWithPrimarySync(): void;
2396
2889
  destroy(): void;
2397
2890
  drop(): Promise<void>;
2398
2891
  dropSync(): void;
@@ -2400,15 +2893,90 @@ declare class RocksDatabase extends DBI<DBITransactional> {
2400
2893
  /**
2401
2894
  * Flushes the underlying database by performing a commit or clearing any buffered operations.
2402
2895
  *
2896
+ * On a read-only database this is a no-op: the options bag is still validated, but the
2897
+ * returned promise resolves without flushing rather than rejecting.
2898
+ *
2899
+ * @param options - Flush options; see {@link FlushOptions.allowWriteStall} before relying on
2900
+ * this resolving promptly under write pressure.
2403
2901
  * @return {void} Does not return a value.
2404
2902
  */
2405
- flush(): Promise<void>;
2903
+ flush(options?: FlushOptions): Promise<void>;
2406
2904
  /**
2407
2905
  * Synchronously flushes the underlying database by performing a commit or clearing any buffered operations.
2408
2906
  *
2907
+ * The default `allowWriteStall: false` wait is taken on the JS thread here, so it freezes the
2908
+ * event loop rather than parking a libuv worker — a larger blast radius than {@link flush}, not
2909
+ * a smaller one.
2910
+ *
2911
+ * On a read-only database this validates its options and then returns without flushing, rather
2912
+ * than throwing.
2913
+ *
2914
+ * @param options - Flush options; see {@link FlushOptions.allowWriteStall}.
2409
2915
  * @return {void} Does not return a value.
2410
2916
  */
2411
- flushSync(): void;
2917
+ flushSync(options?: FlushOptions): void;
2918
+ /**
2919
+ * Returns the most recent {@link BackgroundError} observed on this database, or
2920
+ * `null` when none has occurred. The `'error'` event is the push counterpart;
2921
+ * this is the pull equivalent for on-demand checks (e.g. a health probe) and
2922
+ * for catching an error that fired after open but before a listener was
2923
+ * attached. (A background error that occurs *during* the initial open is a
2924
+ * narrow startup window not yet captured, addressed separately.)
2925
+ *
2926
+ * Purely historical — it is not cleared by a successful {@link RocksDatabase.resume}.
2927
+ * When the returned error's `writesDisabled` is `true`, writes are stopped
2928
+ * until recovery.
2929
+ *
2930
+ * @example
2931
+ * ```typescript
2932
+ * const err = db.getLastError();
2933
+ * if (err?.writesDisabled) {
2934
+ * // ...free disk space...
2935
+ * db.resume();
2936
+ * }
2937
+ * ```
2938
+ */
2939
+ getLastError(): BackgroundError | null;
2940
+ /**
2941
+ * Sets or clears the last background error, mirroring the Win32
2942
+ * `SetLastError`/`GetLastError` pair. Pass `null` (or no argument) to **reset**
2943
+ * it — {@link RocksDatabase.getLastError} then returns `null` and no event
2944
+ * fires; this is the intended way to clear the error after handling or
2945
+ * recovering it (e.g. after {@link RocksDatabase.resume}). Pass an object to
2946
+ * set it: it is stored and the `'error'` event fires with the reconstructed
2947
+ * {@link BackgroundError}. `type` defaults to `'background'`.
2948
+ *
2949
+ * @example
2950
+ * ```typescript
2951
+ * db.resume();
2952
+ * db.setLastError(null); // recovered — clear the historical error
2953
+ * ```
2954
+ */
2955
+ setLastError(error?: BackgroundErrorOptions | null): void;
2956
+ /**
2957
+ * Attempts to recover the database from a background error by calling
2958
+ * RocksDB's `DB::Resume()`. When a write fails at the filesystem level (e.g. a
2959
+ * full disk), RocksDB stops accepting writes and this database emits an
2960
+ * {@link BackgroundError} via the `'error'` event. Call `resume()` after the
2961
+ * underlying condition has cleared — e.g. once disk space has been freed. On
2962
+ * success writes are accepted again; on failure (the condition has not
2963
+ * actually cleared) it throws and the database stays read-only. A no-op on a
2964
+ * healthy database.
2965
+ *
2966
+ * Runs synchronously and may briefly block, since recovery can re-flush
2967
+ * memtables.
2968
+ *
2969
+ * @example
2970
+ * ```typescript
2971
+ * db.on('error', (err) => {
2972
+ * if (err.writesDisabled) {
2973
+ * // ...free disk space...
2974
+ * db.resume();
2975
+ * }
2976
+ * });
2977
+ * ```
2978
+ */
2979
+ resume(): void;
2412
2980
  /**
2413
2981
  * Gets a RocksDB database property as an integer.
2414
2982
  *
@@ -2438,7 +3006,30 @@ declare class RocksDatabase extends DBI<DBITransactional> {
2438
3006
  */
2439
3007
  getDBProperty(propertyName: string): string | undefined;
2440
3008
  /**
2441
- * Retrieves the estimated number of keys in the database.
3009
+ * Whether RocksDB is currently applying write backpressure to this database —
3010
+ * either delaying (rate-limiting) or fully stopping writes. This is the
3011
+ * authoritative, live pull counterpart to the `'writeStall'`
3012
+ * [event](../README.md#event-writestall): the event pushes per-column-family
3013
+ * transitions (and is rate-limited), while this reads the current state on
3014
+ * demand and can never be stale.
3015
+ *
3016
+ * The write controller is database-wide (shared across every column family),
3017
+ * so this reflects the database as a whole, not a single column family — a
3018
+ * stall triggered by any column family stops writes for all of them. Reads
3019
+ * `rocksdb.is-write-stopped` and `rocksdb.actual-delayed-write-rate`.
3020
+ *
3021
+ * @example
3022
+ * ```typescript
3023
+ * db.on('writeStall', (cf) => {
3024
+ * if (db.isWriteStalled()) log.warn(`writes throttled/blocked (triggered by ${cf})`);
3025
+ * });
3026
+ * ```
3027
+ */
3028
+ isWriteStalled(): boolean;
3029
+ /**
3030
+ * Retrieves the estimated number of keys in the database. This is an alias
3031
+ * for `db.estimateCount().count`; use `estimateCount()` for range support
3032
+ * and a confidence indicator.
2442
3033
  *
2443
3034
  * @example
2444
3035
  * ```typescript
@@ -2448,6 +3039,54 @@ declare class RocksDatabase extends DBI<DBITransactional> {
2448
3039
  * ```
2449
3040
  */
2450
3041
  getEstimatedKeyCount(): number;
3042
+ /**
3043
+ * Estimates the number of keys in the database, or within a key range,
3044
+ * returning `{ count, confidence }`. Unlike `getKeysCount()`, this never
3045
+ * iterates: the estimate is derived from RocksDB statistics (memtable
3046
+ * stats plus approximate SST sizes converted through the entry density of
3047
+ * the SSTs overlapping the range), so its cost scales with the number of
3048
+ * SSTs overlapping the range rather than the number of keys — though
3049
+ * reading table properties for cold files can do I/O through the table
3050
+ * cache, and a start-only range does the work of its complement below
3051
+ * `start`. Accuracy improves with range size. Resolution is bounded by SST
3052
+ * data-block granularity, so tiny ranges may over-report or report zero for
3053
+ * present keys; low `confidence` is the signal. Recently deleted or
3054
+ * overwritten entries may be counted until compaction. An inverted range
3055
+ * (`start` >= `end`) returns `{ count: 0, confidence: 1 }`.
3056
+ *
3057
+ * `confidence` is a heuristic 0–1 trust indicator (1 only when exact) —
3058
+ * see `CountEstimate`. Estimates always reflect committed state; writes
3059
+ * pending in a transaction are not included.
3060
+ *
3061
+ * @example
3062
+ * ```typescript
3063
+ * const db = RocksDatabase.open('/path/to/database');
3064
+ * const { count, confidence } = db.estimateCount({ start: 'a', end: 'z' });
3065
+ * ```
3066
+ */
3067
+ estimateCount(options?: CountEstimateOptions): CountEstimate;
3068
+ /**
3069
+ * Creates a `CountEstimator` for progressively refining a range count
3070
+ * estimate while iterating the range: report progress with
3071
+ * `advance(lastKey, count)` (e.g. once per page of results) and
3072
+ * `estimate()` returns the exact traversed count plus a calibrated
3073
+ * estimate of the remainder, converging toward the exact total. Call
3074
+ * `finish()` when traversal completes to make `estimate()` exact.
3075
+ *
3076
+ * @example
3077
+ * ```typescript
3078
+ * const estimator = db.createCountEstimator({ start: 'a', end: 'z' });
3079
+ * let lastKey;
3080
+ * let pageSize = 0;
3081
+ * for (const { key } of db.getRange({ start: 'a', end: 'z', limit: 25 })) {
3082
+ * lastKey = key;
3083
+ * pageSize++;
3084
+ * }
3085
+ * estimator.advance(lastKey, pageSize);
3086
+ * const { count, confidence } = estimator.estimate();
3087
+ * ```
3088
+ */
3089
+ createCountEstimator(options?: CountEstimatorOptions): CountEstimator;
2451
3090
  /**
2452
3091
  * Returns the current timestamp as a monotonically increasing timestamp in
2453
3092
  * milliseconds represented as a decimal number.
@@ -2555,13 +3194,22 @@ declare class RocksDatabase extends DBI<DBITransactional> {
2555
3194
  */
2556
3195
  listLogs(): string[];
2557
3196
  /**
2558
- * The name of the database.
3197
+ * The name of the database's column family.
2559
3198
  */
2560
3199
  get name(): string;
2561
3200
  /**
2562
- * Whether the database is open in readonly mode.
3201
+ * Whether the database is open in readonly mode. Also `true` for a
3202
+ * secondary instance (see {@link secondaryPath}), which is read-only by
3203
+ * construction.
2563
3204
  */
2564
3205
  get readOnly(): boolean;
3206
+ /**
3207
+ * The secondary instance's workspace directory when the database was opened
3208
+ * as a secondary (a read-only follower of a live primary — see the
3209
+ * `secondaryPath` open option), or `undefined` for a regular or plain
3210
+ * read-only open.
3211
+ */
3212
+ get secondaryPath(): string | undefined;
2565
3213
  /**
2566
3214
  * Sugar method for opening a database.
2567
3215
  *
@@ -2679,6 +3327,47 @@ declare class RocksDatabase extends DBI<DBITransactional> {
2679
3327
  * ```
2680
3328
  */
2681
3329
  unlock(key: Key): void;
3330
+ /**
3331
+ * Returns a `RocksDatabase` bound to the `name` column family of this same
3332
+ * database, opening (and creating, if missing) the column family on first
3333
+ * use. This is a factory — create-and-open sugar — not a stateful switch: the
3334
+ * returned view is an independent instance whose own reads/writes target its
3335
+ * column family, while sharing the underlying database (so a transaction,
3336
+ * backup, or checkpoint still spans every column family). Because the view
3337
+ * opens its own handle, this database need not itself be open — a discarded
3338
+ * parent (`new RocksDatabase(path).use('events')`) still yields a valid,
3339
+ * opened view.
3340
+ *
3341
+ * Get-or-create, backed by a weak cache: `db.use('events') === db.use('events')`
3342
+ * while the view is still referenced **and open**, and calling with this
3343
+ * database's own column-family name returns `this`. A view that has been
3344
+ * closed (or garbage-collected — the cache does not pin it) is transparently
3345
+ * recreated on the next `use()`. Views are independent handles: closing this
3346
+ * database does not close them, and vice versa — the underlying database
3347
+ * stays open until every handle is closed or collected.
3348
+ *
3349
+ * The view's store is derived by {@link Store#createColumnFamilyStore}, which
3350
+ * builds an independent store of the same class with its own codec state (so
3351
+ * views never share a mutable encoder/decoder) and inherits the options this
3352
+ * store was constructed with; pass `options` to override them for this column
3353
+ * family. A database configured with a pre-constructed encoder/decoder
3354
+ * instance cannot derive views (its state would be shared) — use an encoder
3355
+ * factory (`{ Encoder }`) or a named `encoding`, or override
3356
+ * `createColumnFamilyStore` on a custom `Store`.
3357
+ *
3358
+ * @param name - The column family name.
3359
+ * @param options - Options for the column family, overriding inherited ones.
3360
+ * @returns A `RocksDatabase` bound to the column family.
3361
+ *
3362
+ * @example
3363
+ * ```typescript
3364
+ * const db = RocksDatabase.open('/path/to/database');
3365
+ * const events = db.use('events');
3366
+ * await events.put('e1', payload);
3367
+ * await db.put('k', 'v'); // default column family, unaffected
3368
+ * ```
3369
+ */
3370
+ use(name: string, options?: RocksDatabaseOptions): RocksDatabase;
2682
3371
  /**
2683
3372
  * Excecutes a function using a thread-safe lock to ensure mutual
2684
3373
  * exclusion.
@@ -2718,15 +3407,37 @@ interface TransactionLog$1 {
2718
3407
  * @param path - The path to the transaction log file.
2719
3408
  * @returns The transaction log.
2720
3409
  */
2721
- declare function parseTransactionLog(path: string, options?: {
3410
+ export declare function parseTransactionLog(path: string, options?: {
2722
3411
  skipData?: boolean;
2723
3412
  }): TransactionLog$1;
2724
3413
  //#endregion
3414
+ //#region src/transaction-log-reader.d.ts
3415
+ /**
3416
+ * Thrown when an entry's framing is broken. `resyncPosition` is the offset where valid framing
3417
+ * resumes, when one was found: the frames after a mid-log break are intact and reachable, and
3418
+ * only the broken span between `position` and `resyncPosition` is unreadable. It is `undefined`
3419
+ * for a torn tail, where nothing follows the break.
3420
+ *
3421
+ * The iterator is left positioned at `resyncPosition` (or at end-of-log when there is none), so a
3422
+ * caller that chooses to recover the entries past the break calls `next()` again.
3423
+ */
3424
+ export declare class CorruptFrameError extends RangeError {
3425
+ /** Sequence number of the log file the break is in. */
3426
+ logId: number;
3427
+ /** Offset of the broken frame. */
3428
+ position: number;
3429
+ /** Offset where valid framing resumes, or `undefined` when nothing valid follows. */
3430
+ resyncPosition?: number;
3431
+ /** Bytes between the break and the resume point that cannot be read. */
3432
+ unreadableBytes: number;
3433
+ constructor(message: string, logId: number, position: number, resyncPosition: number | undefined);
3434
+ }
3435
+ //#endregion
2725
3436
  //#region src/index.d.ts
2726
- declare const versions: {
3437
+ export declare const versions: {
2727
3438
  rocksdb: string;
2728
3439
  "rocksdb-js": string;
2729
3440
  };
2730
3441
  //#endregion
2731
- export { type BackupInfo, type BackupOptions, type BackupStreamOptions, type CompressionAlgorithm, type CompressionInfo, type CompressionOption, DBI, DBIterator, type GetStatsMethod, type IteratorOptions, type Key, type LogOptions, type RestoreMode, type RestoreOptions, type RocksDBStat, type RocksDBStats, RocksDatabase, type RocksDatabaseOptions, type StatsAll, type StatsAllExtras, type StatsBasics, type StatsCurated, type StatsCuratedExtras, type StatsDefault, type StatsHistogramData, type StatsValue, Store, type StoreContext, type StoreGetOptions, type StoreIteratorOptions, type StorePutOptions, type StoreRangeOptions, type StoreRemoveOptions, Transaction, type TransactionEntry, TransactionLog, type TransactionLogFileValidation, type TransactionLogPosition, type TransactionLogStats, type TransactionLogStoreValidation, type ValidateTransactionLogStoreOptions, backups, constants, coolTransactionLogs, currentThreadId, fileLockRelease, parseTransactionLog, registryStatus, shutdown, stats, supportedCompression, tryFileLock, validateTransactionLogStore, versions };
3442
+ export type { BackgroundErrorOptions, BackupInfo, BackupOptions, BackupStreamOptions, CompressionAlgorithm, CompressionInfo, CompressionOption, CountEstimate, CountEstimateOptions, CountEstimatorOptions, FlushOptions, GetStatsMethod, IteratorOptions, Key, LogOptions, RestoreMode, RestoreOptions, RocksDBStat, RocksDBStats, RocksDatabaseOptions, StatsAll, StatsAllExtras, StatsBasics, StatsCurated, StatsCuratedExtras, StatsDefault, StatsHistogramData, StatsValue, StoreContext, StoreGetOptions, StoreIteratorOptions, StorePutOptions, StoreRangeOptions, StoreRemoveOptions, TransactionEntry, TransactionLogFileValidation, TransactionLogPosition, TransactionLogStats, TransactionLogStoreValidation, ValidateTransactionLogStoreOptions, WriteBufferManagerStats };
2732
3443
  //# sourceMappingURL=index.d.mts.map