@harperfast/rocksdb-js 1.2.0 → 1.4.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.cts CHANGED
@@ -172,6 +172,24 @@ declare class Store {
172
172
  */
173
173
  maxKeySize: number;
174
174
  /**
175
+ * The maximum number of memtables that can be queued per column family
176
+ * before writes stall. Higher values absorb write bursts while flushes catch
177
+ * up, at the cost of memory.
178
+ */
179
+ maxWriteBufferNumber?: number;
180
+ /**
181
+ * The bytes of recent memtable history to retain in memory for transaction
182
+ * conflict checking. `-1` derives the value from
183
+ * `maxWriteBufferNumber * writeBufferSize`.
184
+ */
185
+ maxWriteBufferSizeToMaintain?: number;
186
+ /**
187
+ * The total memtable budget in bytes across all column families. When the
188
+ * sum of memtables reaches this size, RocksDB flushes the largest one. `0`
189
+ * disables the global trigger so per-CF `writeBufferSize` drives flushing.
190
+ */
191
+ dbWriteBufferSize?: number;
192
+ /**
175
193
  * The name of the store (e.g. the column family). Defaults to `'default'`.
176
194
  */
177
195
  name: string;
@@ -181,9 +199,10 @@ declare class Store {
181
199
  noBlockCache?: boolean;
182
200
  /**
183
201
  * The number of threads to use for parallel operations. This is a RocksDB
184
- * option.
202
+ * option. When undefined, the native layer picks
203
+ * `max(1, hardware_concurrency() / 2)`.
185
204
  */
186
- parallelismThreads: number;
205
+ parallelismThreads?: number;
187
206
  /**
188
207
  * The path to the database.
189
208
  */
@@ -239,6 +258,11 @@ declare class Store {
239
258
  */
240
259
  transactionLogsPath?: string;
241
260
  /**
261
+ * The per-column-family memtable size in bytes at which the memtable is
262
+ * sealed and flushed.
263
+ */
264
+ writeBufferSize?: number;
265
+ /**
242
266
  * The function used to encode keys using the shared `keyBuffer`.
243
267
  */
244
268
  writeKey: WriteKeyFunction;
@@ -492,8 +516,11 @@ declare class NativeIteratorCls {
492
516
  }
493
517
  type NativeDatabaseMode = "optimistic" | "pessimistic";
494
518
  type NativeDatabaseOptions = {
519
+ dbWriteBufferSize?: number;
495
520
  disableWAL?: boolean;
496
521
  enableStats?: boolean;
522
+ maxWriteBufferNumber?: number;
523
+ maxWriteBufferSizeToMaintain?: number;
497
524
  mode?: NativeDatabaseMode;
498
525
  name?: string;
499
526
  noBlockCache?: boolean;
@@ -504,6 +531,7 @@ type NativeDatabaseOptions = {
504
531
  transactionLogMaxSize?: number;
505
532
  transactionLogRetentionMs?: number;
506
533
  transactionLogsPath?: string;
534
+ writeBufferSize?: number;
507
535
  };
508
536
  type ResolveCallback<T> = (value: T) => void;
509
537
  type RejectCallback = (err: Error) => void;
@@ -569,6 +597,40 @@ type NativeDatabase = {
569
597
  type RocksDatabaseConfig = {
570
598
  blockCacheSize?: number;
571
599
  compactOnClose?: boolean;
600
+ /**
601
+ * Total memtable memory limit (bytes) shared across every database opened
602
+ * in this process. When set, RocksDB uses a single `WriteBufferManager` so
603
+ * write buffers are bounded process-wide rather than per database. 0 (the
604
+ * default) disables the manager.
605
+ *
606
+ * Can be updated at runtime; the new size takes effect on the existing
607
+ * manager via `SetBufferSize`.
608
+ */
609
+ writeBufferManagerSize?: number;
610
+ /**
611
+ * When `true`, memtable memory is "charged" against the shared block cache
612
+ * so the block cache and write buffers draw from a single pool. During
613
+ * write bursts the cache shrinks to make room for memtables; once
614
+ * memtables flush, the cache can grow back into the reclaimed space.
615
+ *
616
+ * Has no effect when the block cache is disabled (size 0) or
617
+ * `writeBufferManagerSize` is 0. Must be set on the same `config()` call
618
+ * that first enables the manager — changing it after the manager has been
619
+ * created has no effect on the running instance.
620
+ *
621
+ * @default false
622
+ */
623
+ writeBufferManagerCostToCache?: boolean;
624
+ /**
625
+ * When `true`, writes are stalled once the manager's `buffer_size` is
626
+ * exceeded, providing a hard cap on memtable memory. When `false`,
627
+ * memtables are allowed to grow past the limit and flushes are simply
628
+ * scheduled more aggressively. Off by default to favor write throughput
629
+ * over hard memory bounding.
630
+ *
631
+ * @default false
632
+ */
633
+ writeBufferManagerAllowStall?: boolean;
572
634
  };
573
635
  type RegistryStatusDB = {
574
636
  path: string;
@@ -1353,13 +1415,16 @@ declare class RocksDatabase extends DBI<DBITransactional> {
1353
1415
  //#endregion
1354
1416
  //#region src/parse-transaction-log.d.ts
1355
1417
  interface LogEntry {
1356
- data: Buffer;
1418
+ anomalies?: string[];
1419
+ data?: Buffer;
1357
1420
  flags: number;
1358
1421
  length: number;
1359
1422
  timestamp?: number;
1360
1423
  }
1361
1424
  interface TransactionLog$1 {
1425
+ anomalies: string[];
1362
1426
  entries: LogEntry[];
1427
+ entryAnomalyCount: number;
1363
1428
  timestamp: number;
1364
1429
  size: number;
1365
1430
  version: number;
@@ -1369,7 +1434,9 @@ interface TransactionLog$1 {
1369
1434
  * @param path - The path to the transaction log file.
1370
1435
  * @returns The transaction log.
1371
1436
  */
1372
- declare function parseTransactionLog(path: string): TransactionLog$1;
1437
+ declare function parseTransactionLog(path: string, options?: {
1438
+ skipData?: boolean;
1439
+ }): TransactionLog$1;
1373
1440
  //#endregion
1374
1441
  //#region src/index.d.ts
1375
1442
  declare const versions: {
package/dist/index.d.mts CHANGED
@@ -172,6 +172,24 @@ declare class Store {
172
172
  */
173
173
  maxKeySize: number;
174
174
  /**
175
+ * The maximum number of memtables that can be queued per column family
176
+ * before writes stall. Higher values absorb write bursts while flushes catch
177
+ * up, at the cost of memory.
178
+ */
179
+ maxWriteBufferNumber?: number;
180
+ /**
181
+ * The bytes of recent memtable history to retain in memory for transaction
182
+ * conflict checking. `-1` derives the value from
183
+ * `maxWriteBufferNumber * writeBufferSize`.
184
+ */
185
+ maxWriteBufferSizeToMaintain?: number;
186
+ /**
187
+ * The total memtable budget in bytes across all column families. When the
188
+ * sum of memtables reaches this size, RocksDB flushes the largest one. `0`
189
+ * disables the global trigger so per-CF `writeBufferSize` drives flushing.
190
+ */
191
+ dbWriteBufferSize?: number;
192
+ /**
175
193
  * The name of the store (e.g. the column family). Defaults to `'default'`.
176
194
  */
177
195
  name: string;
@@ -181,9 +199,10 @@ declare class Store {
181
199
  noBlockCache?: boolean;
182
200
  /**
183
201
  * The number of threads to use for parallel operations. This is a RocksDB
184
- * option.
202
+ * option. When undefined, the native layer picks
203
+ * `max(1, hardware_concurrency() / 2)`.
185
204
  */
186
- parallelismThreads: number;
205
+ parallelismThreads?: number;
187
206
  /**
188
207
  * The path to the database.
189
208
  */
@@ -239,6 +258,11 @@ declare class Store {
239
258
  */
240
259
  transactionLogsPath?: string;
241
260
  /**
261
+ * The per-column-family memtable size in bytes at which the memtable is
262
+ * sealed and flushed.
263
+ */
264
+ writeBufferSize?: number;
265
+ /**
242
266
  * The function used to encode keys using the shared `keyBuffer`.
243
267
  */
244
268
  writeKey: WriteKeyFunction;
@@ -492,8 +516,11 @@ declare class NativeIteratorCls {
492
516
  }
493
517
  type NativeDatabaseMode = "optimistic" | "pessimistic";
494
518
  type NativeDatabaseOptions = {
519
+ dbWriteBufferSize?: number;
495
520
  disableWAL?: boolean;
496
521
  enableStats?: boolean;
522
+ maxWriteBufferNumber?: number;
523
+ maxWriteBufferSizeToMaintain?: number;
497
524
  mode?: NativeDatabaseMode;
498
525
  name?: string;
499
526
  noBlockCache?: boolean;
@@ -504,6 +531,7 @@ type NativeDatabaseOptions = {
504
531
  transactionLogMaxSize?: number;
505
532
  transactionLogRetentionMs?: number;
506
533
  transactionLogsPath?: string;
534
+ writeBufferSize?: number;
507
535
  };
508
536
  type ResolveCallback<T> = (value: T) => void;
509
537
  type RejectCallback = (err: Error) => void;
@@ -569,6 +597,40 @@ type NativeDatabase = {
569
597
  type RocksDatabaseConfig = {
570
598
  blockCacheSize?: number;
571
599
  compactOnClose?: boolean;
600
+ /**
601
+ * Total memtable memory limit (bytes) shared across every database opened
602
+ * in this process. When set, RocksDB uses a single `WriteBufferManager` so
603
+ * write buffers are bounded process-wide rather than per database. 0 (the
604
+ * default) disables the manager.
605
+ *
606
+ * Can be updated at runtime; the new size takes effect on the existing
607
+ * manager via `SetBufferSize`.
608
+ */
609
+ writeBufferManagerSize?: number;
610
+ /**
611
+ * When `true`, memtable memory is "charged" against the shared block cache
612
+ * so the block cache and write buffers draw from a single pool. During
613
+ * write bursts the cache shrinks to make room for memtables; once
614
+ * memtables flush, the cache can grow back into the reclaimed space.
615
+ *
616
+ * Has no effect when the block cache is disabled (size 0) or
617
+ * `writeBufferManagerSize` is 0. Must be set on the same `config()` call
618
+ * that first enables the manager — changing it after the manager has been
619
+ * created has no effect on the running instance.
620
+ *
621
+ * @default false
622
+ */
623
+ writeBufferManagerCostToCache?: boolean;
624
+ /**
625
+ * When `true`, writes are stalled once the manager's `buffer_size` is
626
+ * exceeded, providing a hard cap on memtable memory. When `false`,
627
+ * memtables are allowed to grow past the limit and flushes are simply
628
+ * scheduled more aggressively. Off by default to favor write throughput
629
+ * over hard memory bounding.
630
+ *
631
+ * @default false
632
+ */
633
+ writeBufferManagerAllowStall?: boolean;
572
634
  };
573
635
  type RegistryStatusDB = {
574
636
  path: string;
@@ -1353,13 +1415,16 @@ declare class RocksDatabase extends DBI<DBITransactional> {
1353
1415
  //#endregion
1354
1416
  //#region src/parse-transaction-log.d.ts
1355
1417
  interface LogEntry {
1356
- data: Buffer;
1418
+ anomalies?: string[];
1419
+ data?: Buffer;
1357
1420
  flags: number;
1358
1421
  length: number;
1359
1422
  timestamp?: number;
1360
1423
  }
1361
1424
  interface TransactionLog$1 {
1425
+ anomalies: string[];
1362
1426
  entries: LogEntry[];
1427
+ entryAnomalyCount: number;
1363
1428
  timestamp: number;
1364
1429
  size: number;
1365
1430
  version: number;
@@ -1369,7 +1434,9 @@ interface TransactionLog$1 {
1369
1434
  * @param path - The path to the transaction log file.
1370
1435
  * @returns The transaction log.
1371
1436
  */
1372
- declare function parseTransactionLog(path: string): TransactionLog$1;
1437
+ declare function parseTransactionLog(path: string, options?: {
1438
+ skipData?: boolean;
1439
+ }): TransactionLog$1;
1373
1440
  //#endregion
1374
1441
  //#region src/index.d.ts
1375
1442
  declare const versions: {
package/dist/index.mjs CHANGED
@@ -633,6 +633,24 @@ var Store = class {
633
633
  */
634
634
  maxKeySize;
635
635
  /**
636
+ * The maximum number of memtables that can be queued per column family
637
+ * before writes stall. Higher values absorb write bursts while flushes catch
638
+ * up, at the cost of memory.
639
+ */
640
+ maxWriteBufferNumber;
641
+ /**
642
+ * The bytes of recent memtable history to retain in memory for transaction
643
+ * conflict checking. `-1` derives the value from
644
+ * `maxWriteBufferNumber * writeBufferSize`.
645
+ */
646
+ maxWriteBufferSizeToMaintain;
647
+ /**
648
+ * The total memtable budget in bytes across all column families. When the
649
+ * sum of memtables reaches this size, RocksDB flushes the largest one. `0`
650
+ * disables the global trigger so per-CF `writeBufferSize` drives flushing.
651
+ */
652
+ dbWriteBufferSize;
653
+ /**
636
654
  * The name of the store (e.g. the column family). Defaults to `'default'`.
637
655
  */
638
656
  name;
@@ -642,7 +660,8 @@ var Store = class {
642
660
  noBlockCache;
643
661
  /**
644
662
  * The number of threads to use for parallel operations. This is a RocksDB
645
- * option.
663
+ * option. When undefined, the native layer picks
664
+ * `max(1, hardware_concurrency() / 2)`.
646
665
  */
647
666
  parallelismThreads;
648
667
  /**
@@ -700,6 +719,11 @@ var Store = class {
700
719
  */
701
720
  transactionLogsPath;
702
721
  /**
722
+ * The per-column-family memtable size in bytes at which the memtable is
723
+ * sealed and flushed.
724
+ */
725
+ writeBufferSize;
726
+ /**
703
727
  * The function used to encode keys using the shared `keyBuffer`.
704
728
  */
705
729
  writeKey;
@@ -714,6 +738,7 @@ var Store = class {
714
738
  if (options !== void 0 && options !== null && typeof options !== "object") throw new TypeError("Database options must be an object");
715
739
  const { keyEncoding, readKey, writeKey } = initKeyEncoder(options?.keyEncoding, options?.keyEncoder);
716
740
  this.db = new NativeDatabase();
741
+ this.dbWriteBufferSize = options?.dbWriteBufferSize;
717
742
  this.decoder = options?.decoder ?? null;
718
743
  this.disableWAL = options?.disableWAL ?? false;
719
744
  this.enableStats = options?.enableStats ?? false;
@@ -724,9 +749,11 @@ var Store = class {
724
749
  this.keyBuffer = KEY_BUFFER;
725
750
  this.keyEncoding = keyEncoding;
726
751
  this.maxKeySize = options?.maxKeySize ?? MAX_KEY_SIZE;
752
+ this.maxWriteBufferNumber = options?.maxWriteBufferNumber;
753
+ this.maxWriteBufferSizeToMaintain = options?.maxWriteBufferSizeToMaintain;
727
754
  this.name = options?.name ?? "default";
728
755
  this.noBlockCache = options?.noBlockCache;
729
- this.parallelismThreads = options?.parallelismThreads ?? 1;
756
+ this.parallelismThreads = options?.parallelismThreads;
730
757
  this.path = path;
731
758
  this.pessimistic = options?.pessimistic ?? false;
732
759
  this.readOnly = options?.readOnly ?? false;
@@ -738,6 +765,7 @@ var Store = class {
738
765
  this.transactionLogMaxSize = options?.transactionLogMaxSize;
739
766
  this.transactionLogRetention = options?.transactionLogRetention;
740
767
  this.transactionLogsPath = options?.transactionLogsPath;
768
+ this.writeBufferSize = options?.writeBufferSize;
741
769
  this.writeKey = writeKey;
742
770
  }
743
771
  /**
@@ -999,8 +1027,11 @@ var Store = class {
999
1027
  open() {
1000
1028
  if (this.db.opened) return true;
1001
1029
  this.db.open(this.path, {
1030
+ dbWriteBufferSize: this.dbWriteBufferSize,
1002
1031
  disableWAL: this.disableWAL,
1003
1032
  enableStats: this.enableStats,
1033
+ maxWriteBufferNumber: this.maxWriteBufferNumber,
1034
+ maxWriteBufferSizeToMaintain: this.maxWriteBufferSizeToMaintain,
1004
1035
  mode: this.pessimistic ? "pessimistic" : "optimistic",
1005
1036
  name: this.name,
1006
1037
  noBlockCache: this.noBlockCache,
@@ -1010,7 +1041,8 @@ var Store = class {
1010
1041
  transactionLogMaxAgeThreshold: this.transactionLogMaxAgeThreshold,
1011
1042
  transactionLogMaxSize: this.transactionLogMaxSize,
1012
1043
  transactionLogRetentionMs: this.transactionLogRetention ? parseDuration(this.transactionLogRetention) : void 0,
1013
- transactionLogsPath: this.transactionLogsPath
1044
+ transactionLogsPath: this.transactionLogsPath,
1045
+ writeBufferSize: this.writeBufferSize
1014
1046
  });
1015
1047
  return false;
1016
1048
  }
@@ -1803,12 +1835,14 @@ var RocksDatabase = class RocksDatabase extends DBI {
1803
1835
  //#endregion
1804
1836
  //#region src/parse-transaction-log.ts
1805
1837
  const { TRANSACTION_LOG_TOKEN } = constants;
1838
+ const MIN_VALID_TIMESTAMP = Date.UTC(2026, 0, 27);
1839
+ const VALID_FLAGS_MASK = 1;
1806
1840
  /**
1807
1841
  * Loads an entire transaction log file into memory.
1808
1842
  * @param path - The path to the transaction log file.
1809
1843
  * @returns The transaction log.
1810
1844
  */
1811
- function parseTransactionLog(path) {
1845
+ function parseTransactionLog(path, options = {}) {
1812
1846
  let stats;
1813
1847
  try {
1814
1848
  stats = statSync(path);
@@ -1832,7 +1866,10 @@ function parseTransactionLog(path) {
1832
1866
  const version = read(1).readUInt8(0);
1833
1867
  if (version !== 1) throw new Error(`Unsupported transaction log file version: ${version}`);
1834
1868
  const timestamp = read(8).readDoubleBE(0);
1869
+ const anomalies = [];
1870
+ if (!Number.isFinite(timestamp) || timestamp < MIN_VALID_TIMESTAMP) anomalies.push(`Header timestamp ${timestamp} predates 2026-01-27 (possible corruption)`);
1835
1871
  const entries = [];
1872
+ let entryAnomalyCount = 0;
1836
1873
  while (fileOffset < size) {
1837
1874
  const timestamp = read(8).readDoubleBE(0);
1838
1875
  if (timestamp === 0) {
@@ -1842,15 +1879,25 @@ function parseTransactionLog(path) {
1842
1879
  const length = read(4).readUInt32BE(0);
1843
1880
  const flags = read(1).readUInt8(0);
1844
1881
  const data = read(length);
1845
- entries.push({
1882
+ const entryAnomalies = [];
1883
+ if (!Number.isFinite(timestamp) || timestamp < MIN_VALID_TIMESTAMP) entryAnomalies.push(`timestamp ${timestamp} predates 2026-01-27 (possible corruption)`);
1884
+ if ((flags & ~VALID_FLAGS_MASK) !== 0) entryAnomalies.push(`flags 0x${flags.toString(16).padStart(2, "0")} contains undefined bits (expected 0x00 or 0x01)`);
1885
+ const entry = {
1846
1886
  timestamp,
1847
1887
  length,
1848
1888
  flags,
1849
- data
1850
- });
1889
+ data: options.skipData ? void 0 : Buffer.from(data)
1890
+ };
1891
+ if (entryAnomalies.length > 0) {
1892
+ entry.anomalies = entryAnomalies;
1893
+ entryAnomalyCount += entryAnomalies.length;
1894
+ }
1895
+ entries.push(entry);
1851
1896
  }
1852
1897
  return {
1898
+ anomalies,
1853
1899
  entries,
1900
+ entryAnomalyCount,
1854
1901
  timestamp,
1855
1902
  size,
1856
1903
  version
@@ -2043,7 +2090,7 @@ function loadLastPosition(transactionLog, readUncommitted) {
2043
2090
  //#region src/index.ts
2044
2091
  const versions = {
2045
2092
  rocksdb: version,
2046
- "rocksdb-js": "1.2.0"
2093
+ "rocksdb-js": "1.4.0"
2047
2094
  };
2048
2095
 
2049
2096
  //#endregion