@harperfast/rocksdb-js 2.10.0 → 2.11.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
@@ -648,6 +648,7 @@ export declare class Store {
648
648
  /**
649
649
  * The target maximum size of a transaction log before rotation. Transactions
650
650
  * are never split across files, so one transaction may exceed this target.
651
+ * Defaults to 16 MiB. `0` (formerly unlimited) is rejected at open.
651
652
  */
652
653
  transactionLogMaxSize?: number;
653
654
  /**
@@ -661,6 +662,11 @@ export declare class Store {
661
662
  * The path to the transaction logs directory.
662
663
  */
663
664
  transactionLogsPath?: string;
665
+ /**
666
+ * The transaction log whose batch keys this process originates; seeds the
667
+ * monotonic timestamp floor at open. See `StoreOptions.timestampFloorLog`.
668
+ */
669
+ timestampFloorLog?: string;
664
670
  /**
665
671
  * Whether this store's column family participates in the VerificationTable.
666
672
  */
@@ -1378,6 +1384,7 @@ type StatsBasics = {
1378
1384
  "txnlog.replayGapBytes": number;
1379
1385
  "commitPipeline.logQueueDepth": number;
1380
1386
  "commitPipeline.commitQueueDepth": number;
1387
+ "commitPipeline.commitThreads": number;
1381
1388
  "columnFamily.pendingReclaims": number;
1382
1389
  "writeBufferManager.bufferSize": number;
1383
1390
  "writeBufferManager.memoryUsage": number;
@@ -1952,7 +1959,8 @@ type NativeTransaction = {
1952
1959
  type LogBuffer = Buffer & {
1953
1960
  dataView: DataView;
1954
1961
  logId: number;
1955
- size: number;
1962
+ readonly readableExtent: number;
1963
+ size?: number;
1956
1964
  };
1957
1965
  type TransactionLogQueryOptions = {
1958
1966
  start?: number;
@@ -2035,12 +2043,13 @@ export type TransactionLog = {
2035
2043
  name: string;
2036
2044
  path: string;
2037
2045
  query(options?: TransactionLogQueryOptions): IterableIterator<TransactionEntry>;
2038
- _currentLogBuffer: LogBuffer;
2046
+ _currentLogBuffer: WeakRef<LogBuffer> | undefined;
2039
2047
  _findPosition(timestamp: number): number;
2040
2048
  _getLastCommittedPosition(): Buffer;
2041
2049
  _getLastFlushed(): number;
2042
2050
  _getMemoryMapOfFile(sequenceId: number): LogBuffer | undefined;
2043
2051
  _lastCommittedPosition: Float64Array;
2052
+ _nextLogId(sequenceId: number): number;
2044
2053
  _logBuffers: Map<number, WeakRef<LogBuffer>>;
2045
2054
  };
2046
2055
  /**
@@ -2130,9 +2139,31 @@ type NativeDatabaseOptions = {
2130
2139
  secondaryPath?: string;
2131
2140
  statsLevel?: (typeof stats.StatsLevel)[keyof typeof stats.StatsLevel];
2132
2141
  transactionLogMaxAgeThreshold?: number;
2142
+ /** Target segment size in bytes; defaults to 16 MiB. `0` is rejected. */
2133
2143
  transactionLogMaxSize?: number;
2134
2144
  transactionLogRetentionMs?: number;
2135
2145
  transactionLogsPath?: string;
2146
+ /**
2147
+ * The name of the transaction log whose batch keys this process originates
2148
+ * (the log it passes to `useLog()` for its own writes).
2149
+ *
2150
+ * At open, the process-wide monotonic timestamp floor is raised above every
2151
+ * batch key still durable in that log, so a backward wall-clock step between
2152
+ * runs cannot reissue a transaction timestamp that is already a key in it.
2153
+ *
2154
+ * Name only a log this process originates. A log written under timestamps
2155
+ * adopted from another node (a replication receiver calling
2156
+ * `transaction.setTimestamp()`) is keyed by that node's clock, and seeding
2157
+ * from it would ratchet this process's clock to the fastest of those nodes
2158
+ * on every restart. Unset (the default), the floor is left alone; native
2159
+ * code cannot tell the two kinds of log apart.
2160
+ *
2161
+ * Safety check: an incomplete scan or a key implausibly far ahead of the
2162
+ * wall clock rejects this open rather than risk issuing a duplicate key.
2163
+ * The floor is process-wide, so it is shared by every database open in the
2164
+ * process.
2165
+ */
2166
+ timestampFloorLog?: string;
2136
2167
  /**
2137
2168
  * When true, transaction writes to this column family invalidate the
2138
2169
  * VerificationTable slot for each written key at write time (not at
@@ -2191,9 +2222,9 @@ type FlushOptions = {
2191
2222
  * the descriptor is process-global and shared across `worker_threads`, so the stall lands on
2192
2223
  * every other column family and every other handle that opened the same path — not just the
2193
2224
  * one you called. It also relocates the hang rather than removing it: a stalled `db->Write()`
2194
- * blocks the database's single `CommitWorker` thread, which dispatches every
2195
- * `Transaction.commit()` in order, so the stall queues up every commit behind it — including
2196
- * ones from callers that never touched flush — until the stall clears.
2225
+ * blocks each of the database's `CommitWorker` threads that reaches it, so the stall queues up
2226
+ * every async `Transaction.commit()` behind them — including ones from callers that never
2227
+ * touched flush — until the stall clears.
2197
2228
  *
2198
2229
  * Note this is a *different* knob from the `writeBufferManagerAllowStall` config, and their
2199
2230
  * polarity is nearly opposite: that one decides whether the WriteBufferManager may stall
@@ -2271,6 +2302,7 @@ type NativeDatabase = {
2271
2302
  removeListener(event: string | BufferWithDataView, callback: () => void): boolean;
2272
2303
  removeSync(key: BufferWithDataView, txnId?: number): void;
2273
2304
  resume(): void;
2305
+ setCompression(algorithm: string, level?: number): void;
2274
2306
  setDefaultKeyBuffer(buffer: Buffer | Uint8Array | null): void;
2275
2307
  setDefaultValueBuffer(buffer: Buffer | Uint8Array | null): void;
2276
2308
  setIteratorState(buffer: Buffer | Uint8Array): void;
@@ -2282,6 +2314,38 @@ type NativeDatabase = {
2282
2314
  };
2283
2315
  type RocksDatabaseConfig = {
2284
2316
  blockCacheSize?: number;
2317
+ /**
2318
+ * Number of commit lock buckets each writable optimistic database allocates
2319
+ * when opened with parallel validation. Defaults to 65,536 (about 2.5 MiB per
2320
+ * database on Linux x64; RocksDB's own default is 2^20); accepts integers
2321
+ * from 16 through 16,777,216. Applies to databases opened after the call; open
2322
+ * databases keep their count. Smaller pools only cost throughput when several
2323
+ * commits to the same database overlap (`commitThreads`, `commitSync()`
2324
+ * callers) and their keys collide, which large transactions make likely:
2325
+ * raise the count for databases that commit hundreds of keys at a time. This
2326
+ * does not limit transaction size.
2327
+ */
2328
+ occLockBuckets?: number;
2329
+ /**
2330
+ * How writable optimistic databases opened after the call validate commits.
2331
+ * `'parallel'` (default, RocksDB's default) uses the `occLockBuckets` pool and
2332
+ * lets concurrent commits share a RocksDB write. `'serial'` validates inside
2333
+ * the write group and allocates no bucket pool, but RocksDB never batches its
2334
+ * commits with other writers, so a database's concurrent commits (its
2335
+ * `commitThreads` and any `commitSync()` callers) lose most of their
2336
+ * throughput. Open databases keep their policy.
2337
+ */
2338
+ occValidation?: "parallel" | "serial";
2339
+ /**
2340
+ * Maximum number of dedicated threads each database opened after the call uses
2341
+ * to commit async transactions. Threads start only when commits overlap, so a
2342
+ * database committed to one transaction at a time owns one. Defaults to
2343
+ * `min(4, hardware concurrency)`; accepts integers from 1 through 64. With 1,
2344
+ * async commits to a database run one at a time in dispatch order; with more,
2345
+ * concurrent commits finish (and their promises resolve) in any order, as
2346
+ * concurrent `commitSync()` calls always have. Open databases keep their limit.
2347
+ */
2348
+ commitThreads?: number;
2285
2349
  /**
2286
2350
  * Number of slots in the process-global verification table. Each slot is
2287
2351
  * 8 bytes; the default of 128K slots is 1 MB. Set to 0 to disable.
@@ -2496,6 +2560,16 @@ export declare const supportedCompression: readonly string[];
2496
2560
  declare const NativeDatabase: NativeDatabase;
2497
2561
  declare const NativeTransaction: NativeTransaction;
2498
2562
  export declare const TransactionLog: TransactionLog;
2563
+ /**
2564
+ * Returns the status of every database currently held by the native registry.
2565
+ * Walks every registered descriptor, so it samples live state rather than
2566
+ * reading a stored property.
2567
+ */
2568
+ export declare const getRegistryStatus: () => RegistryStatus;
2569
+ /**
2570
+ * @deprecated Use {@link getRegistryStatus} instead. This alias will be removed
2571
+ * in v3.0.0.
2572
+ */
2499
2573
  export declare const registryStatus: () => RegistryStatus;
2500
2574
  /**
2501
2575
  * Flushes every open database and waits for outstanding compactions, then
@@ -2844,6 +2918,51 @@ export declare class RocksDatabase extends DBI<DBITransactional> {
2844
2918
  * ```
2845
2919
  */
2846
2920
  get compression(): CompressionInfo;
2921
+ /**
2922
+ * Dynamically changes the compression algorithm (and optional level) for
2923
+ * this database's column family on an already-open database — no close, no
2924
+ * reopen, and it does not conflict with another handle that already has
2925
+ * this column family open (unlike an explicit open-time `compression`
2926
+ * mismatch). That other handle's live options change too, silently,
2927
+ * without notice; a later explicit reopen of it is compared against the
2928
+ * new value, so a stale request it still holds can then conflict. Backed
2929
+ * by RocksDB's `DB::SetOptions()`, which documents both `compression` and
2930
+ * `blob_compression_type` as mutable column family options.
2931
+ *
2932
+ * This governs only *newly written* files (the next flush and any future
2933
+ * compaction output) going forward; SST and blob files already on disk
2934
+ * keep their existing compression until they are rewritten by a later
2935
+ * compaction. `compact()`'s default options can skip already-bottommost
2936
+ * files; use `compact({ bottommost: true })` to rewrite them under the new
2937
+ * codec. This is the live-mutation counterpart to the open-time
2938
+ * `compression` option — see the README's Compression section for when to
2939
+ * use each.
2940
+ *
2941
+ * @example
2942
+ * ```typescript
2943
+ * const db = RocksDatabase.open('/path/to/db', { compression: 'none' });
2944
+ * db.setCompression({ algorithm: 'zstd', level: 19 });
2945
+ * // new writes are now compressed with zstd; existing SSTs are untouched
2946
+ * // until compacted.
2947
+ * ```
2948
+ */
2949
+ setCompression(compression: CompressionOption): void;
2950
+ /**
2951
+ * Resyncs the store's cached open-time compression option from the live
2952
+ * database state after `setCompression()`. Also clears
2953
+ * `compressionForAllColumnFamilies`: that flag means "apply this option to
2954
+ * every column family opened for this database", which no longer describes
2955
+ * a live change scoped to a single column family — leaving it set would
2956
+ * restamp every other family with this algorithm on the next
2957
+ * same-instance `close()` + `open()`.
2958
+ *
2959
+ * The flag clear is unconditional (a plain assignment, so it cannot itself
2960
+ * fail) and comes first: a concurrent close racing the live-state read
2961
+ * below throws "Database not open" from the getter, and that read failing
2962
+ * must not also skip the flag clear -- otherwise the same restamp this
2963
+ * method exists to prevent survives on the next open().
2964
+ */
2965
+ private syncStoreCompressionFromLive;
2847
2966
  /**
2848
2967
  * The informational-log settings currently in effect for this database,
2849
2968
  * read live from RocksDB, as `{ maxLogFileSize, infoLogLevel }`. These are
package/dist/index.d.mts CHANGED
@@ -648,6 +648,7 @@ export declare class Store {
648
648
  /**
649
649
  * The target maximum size of a transaction log before rotation. Transactions
650
650
  * are never split across files, so one transaction may exceed this target.
651
+ * Defaults to 16 MiB. `0` (formerly unlimited) is rejected at open.
651
652
  */
652
653
  transactionLogMaxSize?: number;
653
654
  /**
@@ -661,6 +662,11 @@ export declare class Store {
661
662
  * The path to the transaction logs directory.
662
663
  */
663
664
  transactionLogsPath?: string;
665
+ /**
666
+ * The transaction log whose batch keys this process originates; seeds the
667
+ * monotonic timestamp floor at open. See `StoreOptions.timestampFloorLog`.
668
+ */
669
+ timestampFloorLog?: string;
664
670
  /**
665
671
  * Whether this store's column family participates in the VerificationTable.
666
672
  */
@@ -1378,6 +1384,7 @@ type StatsBasics = {
1378
1384
  "txnlog.replayGapBytes": number;
1379
1385
  "commitPipeline.logQueueDepth": number;
1380
1386
  "commitPipeline.commitQueueDepth": number;
1387
+ "commitPipeline.commitThreads": number;
1381
1388
  "columnFamily.pendingReclaims": number;
1382
1389
  "writeBufferManager.bufferSize": number;
1383
1390
  "writeBufferManager.memoryUsage": number;
@@ -1952,7 +1959,8 @@ type NativeTransaction = {
1952
1959
  type LogBuffer = Buffer & {
1953
1960
  dataView: DataView;
1954
1961
  logId: number;
1955
- size: number;
1962
+ readonly readableExtent: number;
1963
+ size?: number;
1956
1964
  };
1957
1965
  type TransactionLogQueryOptions = {
1958
1966
  start?: number;
@@ -2035,12 +2043,13 @@ export type TransactionLog = {
2035
2043
  name: string;
2036
2044
  path: string;
2037
2045
  query(options?: TransactionLogQueryOptions): IterableIterator<TransactionEntry>;
2038
- _currentLogBuffer: LogBuffer;
2046
+ _currentLogBuffer: WeakRef<LogBuffer> | undefined;
2039
2047
  _findPosition(timestamp: number): number;
2040
2048
  _getLastCommittedPosition(): Buffer;
2041
2049
  _getLastFlushed(): number;
2042
2050
  _getMemoryMapOfFile(sequenceId: number): LogBuffer | undefined;
2043
2051
  _lastCommittedPosition: Float64Array;
2052
+ _nextLogId(sequenceId: number): number;
2044
2053
  _logBuffers: Map<number, WeakRef<LogBuffer>>;
2045
2054
  };
2046
2055
  /**
@@ -2130,9 +2139,31 @@ type NativeDatabaseOptions = {
2130
2139
  secondaryPath?: string;
2131
2140
  statsLevel?: (typeof stats.StatsLevel)[keyof typeof stats.StatsLevel];
2132
2141
  transactionLogMaxAgeThreshold?: number;
2142
+ /** Target segment size in bytes; defaults to 16 MiB. `0` is rejected. */
2133
2143
  transactionLogMaxSize?: number;
2134
2144
  transactionLogRetentionMs?: number;
2135
2145
  transactionLogsPath?: string;
2146
+ /**
2147
+ * The name of the transaction log whose batch keys this process originates
2148
+ * (the log it passes to `useLog()` for its own writes).
2149
+ *
2150
+ * At open, the process-wide monotonic timestamp floor is raised above every
2151
+ * batch key still durable in that log, so a backward wall-clock step between
2152
+ * runs cannot reissue a transaction timestamp that is already a key in it.
2153
+ *
2154
+ * Name only a log this process originates. A log written under timestamps
2155
+ * adopted from another node (a replication receiver calling
2156
+ * `transaction.setTimestamp()`) is keyed by that node's clock, and seeding
2157
+ * from it would ratchet this process's clock to the fastest of those nodes
2158
+ * on every restart. Unset (the default), the floor is left alone; native
2159
+ * code cannot tell the two kinds of log apart.
2160
+ *
2161
+ * Safety check: an incomplete scan or a key implausibly far ahead of the
2162
+ * wall clock rejects this open rather than risk issuing a duplicate key.
2163
+ * The floor is process-wide, so it is shared by every database open in the
2164
+ * process.
2165
+ */
2166
+ timestampFloorLog?: string;
2136
2167
  /**
2137
2168
  * When true, transaction writes to this column family invalidate the
2138
2169
  * VerificationTable slot for each written key at write time (not at
@@ -2191,9 +2222,9 @@ type FlushOptions = {
2191
2222
  * the descriptor is process-global and shared across `worker_threads`, so the stall lands on
2192
2223
  * every other column family and every other handle that opened the same path — not just the
2193
2224
  * one you called. It also relocates the hang rather than removing it: a stalled `db->Write()`
2194
- * blocks the database's single `CommitWorker` thread, which dispatches every
2195
- * `Transaction.commit()` in order, so the stall queues up every commit behind it — including
2196
- * ones from callers that never touched flush — until the stall clears.
2225
+ * blocks each of the database's `CommitWorker` threads that reaches it, so the stall queues up
2226
+ * every async `Transaction.commit()` behind them — including ones from callers that never
2227
+ * touched flush — until the stall clears.
2197
2228
  *
2198
2229
  * Note this is a *different* knob from the `writeBufferManagerAllowStall` config, and their
2199
2230
  * polarity is nearly opposite: that one decides whether the WriteBufferManager may stall
@@ -2271,6 +2302,7 @@ type NativeDatabase = {
2271
2302
  removeListener(event: string | BufferWithDataView, callback: () => void): boolean;
2272
2303
  removeSync(key: BufferWithDataView, txnId?: number): void;
2273
2304
  resume(): void;
2305
+ setCompression(algorithm: string, level?: number): void;
2274
2306
  setDefaultKeyBuffer(buffer: Buffer | Uint8Array | null): void;
2275
2307
  setDefaultValueBuffer(buffer: Buffer | Uint8Array | null): void;
2276
2308
  setIteratorState(buffer: Buffer | Uint8Array): void;
@@ -2282,6 +2314,38 @@ type NativeDatabase = {
2282
2314
  };
2283
2315
  type RocksDatabaseConfig = {
2284
2316
  blockCacheSize?: number;
2317
+ /**
2318
+ * Number of commit lock buckets each writable optimistic database allocates
2319
+ * when opened with parallel validation. Defaults to 65,536 (about 2.5 MiB per
2320
+ * database on Linux x64; RocksDB's own default is 2^20); accepts integers
2321
+ * from 16 through 16,777,216. Applies to databases opened after the call; open
2322
+ * databases keep their count. Smaller pools only cost throughput when several
2323
+ * commits to the same database overlap (`commitThreads`, `commitSync()`
2324
+ * callers) and their keys collide, which large transactions make likely:
2325
+ * raise the count for databases that commit hundreds of keys at a time. This
2326
+ * does not limit transaction size.
2327
+ */
2328
+ occLockBuckets?: number;
2329
+ /**
2330
+ * How writable optimistic databases opened after the call validate commits.
2331
+ * `'parallel'` (default, RocksDB's default) uses the `occLockBuckets` pool and
2332
+ * lets concurrent commits share a RocksDB write. `'serial'` validates inside
2333
+ * the write group and allocates no bucket pool, but RocksDB never batches its
2334
+ * commits with other writers, so a database's concurrent commits (its
2335
+ * `commitThreads` and any `commitSync()` callers) lose most of their
2336
+ * throughput. Open databases keep their policy.
2337
+ */
2338
+ occValidation?: "parallel" | "serial";
2339
+ /**
2340
+ * Maximum number of dedicated threads each database opened after the call uses
2341
+ * to commit async transactions. Threads start only when commits overlap, so a
2342
+ * database committed to one transaction at a time owns one. Defaults to
2343
+ * `min(4, hardware concurrency)`; accepts integers from 1 through 64. With 1,
2344
+ * async commits to a database run one at a time in dispatch order; with more,
2345
+ * concurrent commits finish (and their promises resolve) in any order, as
2346
+ * concurrent `commitSync()` calls always have. Open databases keep their limit.
2347
+ */
2348
+ commitThreads?: number;
2285
2349
  /**
2286
2350
  * Number of slots in the process-global verification table. Each slot is
2287
2351
  * 8 bytes; the default of 128K slots is 1 MB. Set to 0 to disable.
@@ -2496,6 +2560,16 @@ export declare const supportedCompression: readonly string[];
2496
2560
  declare const NativeDatabase: NativeDatabase;
2497
2561
  declare const NativeTransaction: NativeTransaction;
2498
2562
  export declare const TransactionLog: TransactionLog;
2563
+ /**
2564
+ * Returns the status of every database currently held by the native registry.
2565
+ * Walks every registered descriptor, so it samples live state rather than
2566
+ * reading a stored property.
2567
+ */
2568
+ export declare const getRegistryStatus: () => RegistryStatus;
2569
+ /**
2570
+ * @deprecated Use {@link getRegistryStatus} instead. This alias will be removed
2571
+ * in v3.0.0.
2572
+ */
2499
2573
  export declare const registryStatus: () => RegistryStatus;
2500
2574
  /**
2501
2575
  * Flushes every open database and waits for outstanding compactions, then
@@ -2844,6 +2918,51 @@ export declare class RocksDatabase extends DBI<DBITransactional> {
2844
2918
  * ```
2845
2919
  */
2846
2920
  get compression(): CompressionInfo;
2921
+ /**
2922
+ * Dynamically changes the compression algorithm (and optional level) for
2923
+ * this database's column family on an already-open database — no close, no
2924
+ * reopen, and it does not conflict with another handle that already has
2925
+ * this column family open (unlike an explicit open-time `compression`
2926
+ * mismatch). That other handle's live options change too, silently,
2927
+ * without notice; a later explicit reopen of it is compared against the
2928
+ * new value, so a stale request it still holds can then conflict. Backed
2929
+ * by RocksDB's `DB::SetOptions()`, which documents both `compression` and
2930
+ * `blob_compression_type` as mutable column family options.
2931
+ *
2932
+ * This governs only *newly written* files (the next flush and any future
2933
+ * compaction output) going forward; SST and blob files already on disk
2934
+ * keep their existing compression until they are rewritten by a later
2935
+ * compaction. `compact()`'s default options can skip already-bottommost
2936
+ * files; use `compact({ bottommost: true })` to rewrite them under the new
2937
+ * codec. This is the live-mutation counterpart to the open-time
2938
+ * `compression` option — see the README's Compression section for when to
2939
+ * use each.
2940
+ *
2941
+ * @example
2942
+ * ```typescript
2943
+ * const db = RocksDatabase.open('/path/to/db', { compression: 'none' });
2944
+ * db.setCompression({ algorithm: 'zstd', level: 19 });
2945
+ * // new writes are now compressed with zstd; existing SSTs are untouched
2946
+ * // until compacted.
2947
+ * ```
2948
+ */
2949
+ setCompression(compression: CompressionOption): void;
2950
+ /**
2951
+ * Resyncs the store's cached open-time compression option from the live
2952
+ * database state after `setCompression()`. Also clears
2953
+ * `compressionForAllColumnFamilies`: that flag means "apply this option to
2954
+ * every column family opened for this database", which no longer describes
2955
+ * a live change scoped to a single column family — leaving it set would
2956
+ * restamp every other family with this algorithm on the next
2957
+ * same-instance `close()` + `open()`.
2958
+ *
2959
+ * The flag clear is unconditional (a plain assignment, so it cannot itself
2960
+ * fail) and comes first: a concurrent close racing the live-state read
2961
+ * below throws "Database not open" from the getter, and that read failing
2962
+ * must not also skip the flag clear -- otherwise the same restamp this
2963
+ * method exists to prevent survives on the next open().
2964
+ */
2965
+ private syncStoreCompressionFromLive;
2847
2966
  /**
2848
2967
  * The informational-log settings currently in effect for this database,
2849
2968
  * read live from RocksDB, as `{ maxLogFileSize, infoLogLevel }`. These are