@harperfast/rocksdb-js 2.9.1 → 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/README.md +377 -56
- package/bin/rocksdb-js.mjs +49 -5
- package/dist/index.cjs +206 -32
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +180 -7
- package/dist/index.d.mts +180 -7
- package/dist/index.mjs +205 -33
- package/dist/index.mjs.map +1 -1
- package/docs/backups.md +3 -2
- package/docs/performance/mutex-contention-2026-09-16.json +684 -0
- package/docs/performance/mutex-contention-admission-2026-09-17.json +730 -0
- package/docs/performance/mutex-contention.md +204 -0
- package/docs/stats.md +48 -46
- package/docs/steady-clock-design.md +121 -0
- package/docs/transaction-log.md +120 -1
- package/docs/transaction-timestamp-integrity-design.md +70 -8
- package/package.json +16 -16
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,8 @@ type StatsBasics = {
|
|
|
1378
1384
|
"txnlog.replayGapBytes": number;
|
|
1379
1385
|
"commitPipeline.logQueueDepth": number;
|
|
1380
1386
|
"commitPipeline.commitQueueDepth": number;
|
|
1387
|
+
"commitPipeline.commitThreads": number;
|
|
1388
|
+
"columnFamily.pendingReclaims": number;
|
|
1381
1389
|
"writeBufferManager.bufferSize": number;
|
|
1382
1390
|
"writeBufferManager.memoryUsage": number;
|
|
1383
1391
|
"writeBufferManager.mutableMemoryUsage": number;
|
|
@@ -1951,7 +1959,8 @@ type NativeTransaction = {
|
|
|
1951
1959
|
type LogBuffer = Buffer & {
|
|
1952
1960
|
dataView: DataView;
|
|
1953
1961
|
logId: number;
|
|
1954
|
-
|
|
1962
|
+
readonly readableExtent: number;
|
|
1963
|
+
size?: number;
|
|
1955
1964
|
};
|
|
1956
1965
|
type TransactionLogQueryOptions = {
|
|
1957
1966
|
start?: number;
|
|
@@ -2034,12 +2043,13 @@ export type TransactionLog = {
|
|
|
2034
2043
|
name: string;
|
|
2035
2044
|
path: string;
|
|
2036
2045
|
query(options?: TransactionLogQueryOptions): IterableIterator<TransactionEntry>;
|
|
2037
|
-
_currentLogBuffer: LogBuffer;
|
|
2046
|
+
_currentLogBuffer: WeakRef<LogBuffer> | undefined;
|
|
2038
2047
|
_findPosition(timestamp: number): number;
|
|
2039
2048
|
_getLastCommittedPosition(): Buffer;
|
|
2040
2049
|
_getLastFlushed(): number;
|
|
2041
2050
|
_getMemoryMapOfFile(sequenceId: number): LogBuffer | undefined;
|
|
2042
2051
|
_lastCommittedPosition: Float64Array;
|
|
2052
|
+
_nextLogId(sequenceId: number): number;
|
|
2043
2053
|
_logBuffers: Map<number, WeakRef<LogBuffer>>;
|
|
2044
2054
|
};
|
|
2045
2055
|
/**
|
|
@@ -2129,9 +2139,31 @@ type NativeDatabaseOptions = {
|
|
|
2129
2139
|
secondaryPath?: string;
|
|
2130
2140
|
statsLevel?: (typeof stats.StatsLevel)[keyof typeof stats.StatsLevel];
|
|
2131
2141
|
transactionLogMaxAgeThreshold?: number;
|
|
2142
|
+
/** Target segment size in bytes; defaults to 16 MiB. `0` is rejected. */
|
|
2132
2143
|
transactionLogMaxSize?: number;
|
|
2133
2144
|
transactionLogRetentionMs?: number;
|
|
2134
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;
|
|
2135
2167
|
/**
|
|
2136
2168
|
* When true, transaction writes to this column family invalidate the
|
|
2137
2169
|
* VerificationTable slot for each written key at write time (not at
|
|
@@ -2190,9 +2222,9 @@ type FlushOptions = {
|
|
|
2190
2222
|
* the descriptor is process-global and shared across `worker_threads`, so the stall lands on
|
|
2191
2223
|
* every other column family and every other handle that opened the same path — not just the
|
|
2192
2224
|
* one you called. It also relocates the hang rather than removing it: a stalled `db->Write()`
|
|
2193
|
-
* blocks the database's
|
|
2194
|
-
* `Transaction.commit()`
|
|
2195
|
-
*
|
|
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.
|
|
2196
2228
|
*
|
|
2197
2229
|
* Note this is a *different* knob from the `writeBufferManagerAllowStall` config, and their
|
|
2198
2230
|
* polarity is nearly opposite: that one decides whether the WriteBufferManager may stall
|
|
@@ -2220,7 +2252,7 @@ type NativeDatabase = {
|
|
|
2220
2252
|
compactSync(start?: Key, end?: Key, bottommost?: boolean): void;
|
|
2221
2253
|
columns: string[];
|
|
2222
2254
|
createCheckpoint(resolve: ResolveCallback<void>, reject: RejectCallback, targetPath: string): void;
|
|
2223
|
-
destroy(): void;
|
|
2255
|
+
destroy(readOnly?: boolean): void;
|
|
2224
2256
|
drop(resolve: ResolveCallback<void>, reject: RejectCallback): void;
|
|
2225
2257
|
dropSync(): void;
|
|
2226
2258
|
flush(resolve: ResolveCallback<void>, reject: RejectCallback, options?: FlushOptions): void;
|
|
@@ -2255,6 +2287,7 @@ type NativeDatabase = {
|
|
|
2255
2287
|
identityPath: string | undefined;
|
|
2256
2288
|
listeners(event: string | BufferWithDataView): number;
|
|
2257
2289
|
listLogs(): string[];
|
|
2290
|
+
closing: boolean;
|
|
2258
2291
|
opened: boolean;
|
|
2259
2292
|
open(path: string, options?: NativeDatabaseOptions): void;
|
|
2260
2293
|
populateVersion(keyLengthOrKeyBuffer: number | Buffer, version: number): void;
|
|
@@ -2269,6 +2302,7 @@ type NativeDatabase = {
|
|
|
2269
2302
|
removeListener(event: string | BufferWithDataView, callback: () => void): boolean;
|
|
2270
2303
|
removeSync(key: BufferWithDataView, txnId?: number): void;
|
|
2271
2304
|
resume(): void;
|
|
2305
|
+
setCompression(algorithm: string, level?: number): void;
|
|
2272
2306
|
setDefaultKeyBuffer(buffer: Buffer | Uint8Array | null): void;
|
|
2273
2307
|
setDefaultValueBuffer(buffer: Buffer | Uint8Array | null): void;
|
|
2274
2308
|
setIteratorState(buffer: Buffer | Uint8Array): void;
|
|
@@ -2280,6 +2314,38 @@ type NativeDatabase = {
|
|
|
2280
2314
|
};
|
|
2281
2315
|
type RocksDatabaseConfig = {
|
|
2282
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;
|
|
2283
2349
|
/**
|
|
2284
2350
|
* Number of slots in the process-global verification table. Each slot is
|
|
2285
2351
|
* 8 bytes; the default of 128K slots is 1 MB. Set to 0 to disable.
|
|
@@ -2289,6 +2355,11 @@ type RocksDatabaseConfig = {
|
|
|
2289
2355
|
*/
|
|
2290
2356
|
verificationTableEntries?: number;
|
|
2291
2357
|
compactOnClose?: boolean;
|
|
2358
|
+
/**
|
|
2359
|
+
* Maximum seconds an open, destroy, or shutdown call waits for another
|
|
2360
|
+
* lifecycle operation. Defaults to 30.
|
|
2361
|
+
*/
|
|
2362
|
+
lifecycleWaitSeconds?: number;
|
|
2292
2363
|
/**
|
|
2293
2364
|
* Total memtable memory limit (bytes) shared across every database opened
|
|
2294
2365
|
* in this process. When set, RocksDB uses a single `WriteBufferManager` so
|
|
@@ -2332,6 +2403,10 @@ type RegistryStatusTransaction = {
|
|
|
2332
2403
|
};
|
|
2333
2404
|
type RegistryStatusDB = {
|
|
2334
2405
|
path: string;
|
|
2406
|
+
closeError?: string;
|
|
2407
|
+
/** A prior close failed and `shutdown()`/`destroy()` is currently retrying it. */
|
|
2408
|
+
closeRetrying?: boolean;
|
|
2409
|
+
destroyCleanupPending?: boolean;
|
|
2335
2410
|
refCount: number;
|
|
2336
2411
|
columnFamilies: string[];
|
|
2337
2412
|
transactions: number;
|
|
@@ -2485,9 +2560,59 @@ export declare const supportedCompression: readonly string[];
|
|
|
2485
2560
|
declare const NativeDatabase: NativeDatabase;
|
|
2486
2561
|
declare const NativeTransaction: NativeTransaction;
|
|
2487
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
|
+
*/
|
|
2488
2573
|
export declare const registryStatus: () => RegistryStatus;
|
|
2574
|
+
/**
|
|
2575
|
+
* Flushes every open database and waits for outstanding compactions, then
|
|
2576
|
+
* releases the registry.
|
|
2577
|
+
*
|
|
2578
|
+
* **Throws** the first failure it encounters: a close whose native teardown
|
|
2579
|
+
* failed (that descriptor stays quarantined — call `shutdown()` again to retry
|
|
2580
|
+
* it), or a `lifecycleWaitSeconds` timeout waiting on a concurrent
|
|
2581
|
+
* open/destroy/shutdown. A quarantining close also emits
|
|
2582
|
+
* `database:closeFailed`; a timeout has no event, so the throw is its only
|
|
2583
|
+
* signal.
|
|
2584
|
+
*
|
|
2585
|
+
* A `process.on('exit')` listener must therefore wrap it: an exception thrown
|
|
2586
|
+
* from an `exit` listener skips every `exit` listener registered after it (and
|
|
2587
|
+
* sets exit code 1 unless an `uncaughtException` handler is installed).
|
|
2588
|
+
*
|
|
2589
|
+
* ```typescript
|
|
2590
|
+
* process.on('exit', () => {
|
|
2591
|
+
* try {
|
|
2592
|
+
* shutdown();
|
|
2593
|
+
* } catch (error) {
|
|
2594
|
+
* console.error('rocksdb-js shutdown failed', error);
|
|
2595
|
+
* }
|
|
2596
|
+
* });
|
|
2597
|
+
* ```
|
|
2598
|
+
*/
|
|
2489
2599
|
export declare const shutdown: () => void;
|
|
2490
2600
|
export declare const currentThreadId: () => number;
|
|
2601
|
+
/**
|
|
2602
|
+
* Reads the process-wide steady clock: `std::chrono::steady_clock` as
|
|
2603
|
+
* fractional milliseconds from an unspecified origin that is fixed for the life
|
|
2604
|
+
* of the process. Every sample in the process — main thread and every
|
|
2605
|
+
* `worker_threads` worker, whenever started or restarted, on Node, Bun and Deno
|
|
2606
|
+
* — is in one domain, and the difference between two samples is real elapsed
|
|
2607
|
+
* time unaffected by wall-clock steps. Non-decreasing but not unique (two
|
|
2608
|
+
* samples may be equal; treat `==` as "not later"). Windows QPC samples from
|
|
2609
|
+
* different threads within one native tick also have ambiguous ordering.
|
|
2610
|
+
* Clock readings alone do not prove causality. Not comparable with
|
|
2611
|
+
* `Date.now()`, `db.getMonotonicTimestamp()` or transaction timestamps, and not
|
|
2612
|
+
* meaningful across processes or restarts. Time spent in host suspend is
|
|
2613
|
+
* platform-defined. No open database is needed.
|
|
2614
|
+
*/
|
|
2615
|
+
export declare const steadyClockNow: () => number;
|
|
2491
2616
|
/**
|
|
2492
2617
|
* Advises the kernel that the file-backed pages of every mapped transaction log
|
|
2493
2618
|
* are cold (Linux MADV_COLD), so they are reclaimed first under memory pressure
|
|
@@ -2793,6 +2918,51 @@ export declare class RocksDatabase extends DBI<DBITransactional> {
|
|
|
2793
2918
|
* ```
|
|
2794
2919
|
*/
|
|
2795
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;
|
|
2796
2966
|
/**
|
|
2797
2967
|
* The informational-log settings currently in effect for this database,
|
|
2798
2968
|
* read live from RocksDB, as `{ maxLogFileSize, infoLogLevel }`. These are
|
|
@@ -2825,7 +2995,10 @@ export declare class RocksDatabase extends DBI<DBITransactional> {
|
|
|
2825
2995
|
* native binding use namespaced keys (e.g. `'transactionLog:warning'`).
|
|
2826
2996
|
*
|
|
2827
2997
|
* Listeners are not tied to any specific database — they fire for every
|
|
2828
|
-
* matching event emitted in this process.
|
|
2998
|
+
* matching event emitted in this process. Native lifecycle failures use
|
|
2999
|
+
* `'database:closeFailed'` with `(path, error)` string arguments. The event
|
|
3000
|
+
* reports both completed and incomplete teardowns; an incomplete close can
|
|
3001
|
+
* be retried by `shutdown()` or explicitly deleted by `destroy()`.
|
|
2829
3002
|
*
|
|
2830
3003
|
* @example
|
|
2831
3004
|
* ```typescript
|
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,8 @@ type StatsBasics = {
|
|
|
1378
1384
|
"txnlog.replayGapBytes": number;
|
|
1379
1385
|
"commitPipeline.logQueueDepth": number;
|
|
1380
1386
|
"commitPipeline.commitQueueDepth": number;
|
|
1387
|
+
"commitPipeline.commitThreads": number;
|
|
1388
|
+
"columnFamily.pendingReclaims": number;
|
|
1381
1389
|
"writeBufferManager.bufferSize": number;
|
|
1382
1390
|
"writeBufferManager.memoryUsage": number;
|
|
1383
1391
|
"writeBufferManager.mutableMemoryUsage": number;
|
|
@@ -1951,7 +1959,8 @@ type NativeTransaction = {
|
|
|
1951
1959
|
type LogBuffer = Buffer & {
|
|
1952
1960
|
dataView: DataView;
|
|
1953
1961
|
logId: number;
|
|
1954
|
-
|
|
1962
|
+
readonly readableExtent: number;
|
|
1963
|
+
size?: number;
|
|
1955
1964
|
};
|
|
1956
1965
|
type TransactionLogQueryOptions = {
|
|
1957
1966
|
start?: number;
|
|
@@ -2034,12 +2043,13 @@ export type TransactionLog = {
|
|
|
2034
2043
|
name: string;
|
|
2035
2044
|
path: string;
|
|
2036
2045
|
query(options?: TransactionLogQueryOptions): IterableIterator<TransactionEntry>;
|
|
2037
|
-
_currentLogBuffer: LogBuffer;
|
|
2046
|
+
_currentLogBuffer: WeakRef<LogBuffer> | undefined;
|
|
2038
2047
|
_findPosition(timestamp: number): number;
|
|
2039
2048
|
_getLastCommittedPosition(): Buffer;
|
|
2040
2049
|
_getLastFlushed(): number;
|
|
2041
2050
|
_getMemoryMapOfFile(sequenceId: number): LogBuffer | undefined;
|
|
2042
2051
|
_lastCommittedPosition: Float64Array;
|
|
2052
|
+
_nextLogId(sequenceId: number): number;
|
|
2043
2053
|
_logBuffers: Map<number, WeakRef<LogBuffer>>;
|
|
2044
2054
|
};
|
|
2045
2055
|
/**
|
|
@@ -2129,9 +2139,31 @@ type NativeDatabaseOptions = {
|
|
|
2129
2139
|
secondaryPath?: string;
|
|
2130
2140
|
statsLevel?: (typeof stats.StatsLevel)[keyof typeof stats.StatsLevel];
|
|
2131
2141
|
transactionLogMaxAgeThreshold?: number;
|
|
2142
|
+
/** Target segment size in bytes; defaults to 16 MiB. `0` is rejected. */
|
|
2132
2143
|
transactionLogMaxSize?: number;
|
|
2133
2144
|
transactionLogRetentionMs?: number;
|
|
2134
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;
|
|
2135
2167
|
/**
|
|
2136
2168
|
* When true, transaction writes to this column family invalidate the
|
|
2137
2169
|
* VerificationTable slot for each written key at write time (not at
|
|
@@ -2190,9 +2222,9 @@ type FlushOptions = {
|
|
|
2190
2222
|
* the descriptor is process-global and shared across `worker_threads`, so the stall lands on
|
|
2191
2223
|
* every other column family and every other handle that opened the same path — not just the
|
|
2192
2224
|
* one you called. It also relocates the hang rather than removing it: a stalled `db->Write()`
|
|
2193
|
-
* blocks the database's
|
|
2194
|
-
* `Transaction.commit()`
|
|
2195
|
-
*
|
|
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.
|
|
2196
2228
|
*
|
|
2197
2229
|
* Note this is a *different* knob from the `writeBufferManagerAllowStall` config, and their
|
|
2198
2230
|
* polarity is nearly opposite: that one decides whether the WriteBufferManager may stall
|
|
@@ -2220,7 +2252,7 @@ type NativeDatabase = {
|
|
|
2220
2252
|
compactSync(start?: Key, end?: Key, bottommost?: boolean): void;
|
|
2221
2253
|
columns: string[];
|
|
2222
2254
|
createCheckpoint(resolve: ResolveCallback<void>, reject: RejectCallback, targetPath: string): void;
|
|
2223
|
-
destroy(): void;
|
|
2255
|
+
destroy(readOnly?: boolean): void;
|
|
2224
2256
|
drop(resolve: ResolveCallback<void>, reject: RejectCallback): void;
|
|
2225
2257
|
dropSync(): void;
|
|
2226
2258
|
flush(resolve: ResolveCallback<void>, reject: RejectCallback, options?: FlushOptions): void;
|
|
@@ -2255,6 +2287,7 @@ type NativeDatabase = {
|
|
|
2255
2287
|
identityPath: string | undefined;
|
|
2256
2288
|
listeners(event: string | BufferWithDataView): number;
|
|
2257
2289
|
listLogs(): string[];
|
|
2290
|
+
closing: boolean;
|
|
2258
2291
|
opened: boolean;
|
|
2259
2292
|
open(path: string, options?: NativeDatabaseOptions): void;
|
|
2260
2293
|
populateVersion(keyLengthOrKeyBuffer: number | Buffer, version: number): void;
|
|
@@ -2269,6 +2302,7 @@ type NativeDatabase = {
|
|
|
2269
2302
|
removeListener(event: string | BufferWithDataView, callback: () => void): boolean;
|
|
2270
2303
|
removeSync(key: BufferWithDataView, txnId?: number): void;
|
|
2271
2304
|
resume(): void;
|
|
2305
|
+
setCompression(algorithm: string, level?: number): void;
|
|
2272
2306
|
setDefaultKeyBuffer(buffer: Buffer | Uint8Array | null): void;
|
|
2273
2307
|
setDefaultValueBuffer(buffer: Buffer | Uint8Array | null): void;
|
|
2274
2308
|
setIteratorState(buffer: Buffer | Uint8Array): void;
|
|
@@ -2280,6 +2314,38 @@ type NativeDatabase = {
|
|
|
2280
2314
|
};
|
|
2281
2315
|
type RocksDatabaseConfig = {
|
|
2282
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;
|
|
2283
2349
|
/**
|
|
2284
2350
|
* Number of slots in the process-global verification table. Each slot is
|
|
2285
2351
|
* 8 bytes; the default of 128K slots is 1 MB. Set to 0 to disable.
|
|
@@ -2289,6 +2355,11 @@ type RocksDatabaseConfig = {
|
|
|
2289
2355
|
*/
|
|
2290
2356
|
verificationTableEntries?: number;
|
|
2291
2357
|
compactOnClose?: boolean;
|
|
2358
|
+
/**
|
|
2359
|
+
* Maximum seconds an open, destroy, or shutdown call waits for another
|
|
2360
|
+
* lifecycle operation. Defaults to 30.
|
|
2361
|
+
*/
|
|
2362
|
+
lifecycleWaitSeconds?: number;
|
|
2292
2363
|
/**
|
|
2293
2364
|
* Total memtable memory limit (bytes) shared across every database opened
|
|
2294
2365
|
* in this process. When set, RocksDB uses a single `WriteBufferManager` so
|
|
@@ -2332,6 +2403,10 @@ type RegistryStatusTransaction = {
|
|
|
2332
2403
|
};
|
|
2333
2404
|
type RegistryStatusDB = {
|
|
2334
2405
|
path: string;
|
|
2406
|
+
closeError?: string;
|
|
2407
|
+
/** A prior close failed and `shutdown()`/`destroy()` is currently retrying it. */
|
|
2408
|
+
closeRetrying?: boolean;
|
|
2409
|
+
destroyCleanupPending?: boolean;
|
|
2335
2410
|
refCount: number;
|
|
2336
2411
|
columnFamilies: string[];
|
|
2337
2412
|
transactions: number;
|
|
@@ -2485,9 +2560,59 @@ export declare const supportedCompression: readonly string[];
|
|
|
2485
2560
|
declare const NativeDatabase: NativeDatabase;
|
|
2486
2561
|
declare const NativeTransaction: NativeTransaction;
|
|
2487
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
|
+
*/
|
|
2488
2573
|
export declare const registryStatus: () => RegistryStatus;
|
|
2574
|
+
/**
|
|
2575
|
+
* Flushes every open database and waits for outstanding compactions, then
|
|
2576
|
+
* releases the registry.
|
|
2577
|
+
*
|
|
2578
|
+
* **Throws** the first failure it encounters: a close whose native teardown
|
|
2579
|
+
* failed (that descriptor stays quarantined — call `shutdown()` again to retry
|
|
2580
|
+
* it), or a `lifecycleWaitSeconds` timeout waiting on a concurrent
|
|
2581
|
+
* open/destroy/shutdown. A quarantining close also emits
|
|
2582
|
+
* `database:closeFailed`; a timeout has no event, so the throw is its only
|
|
2583
|
+
* signal.
|
|
2584
|
+
*
|
|
2585
|
+
* A `process.on('exit')` listener must therefore wrap it: an exception thrown
|
|
2586
|
+
* from an `exit` listener skips every `exit` listener registered after it (and
|
|
2587
|
+
* sets exit code 1 unless an `uncaughtException` handler is installed).
|
|
2588
|
+
*
|
|
2589
|
+
* ```typescript
|
|
2590
|
+
* process.on('exit', () => {
|
|
2591
|
+
* try {
|
|
2592
|
+
* shutdown();
|
|
2593
|
+
* } catch (error) {
|
|
2594
|
+
* console.error('rocksdb-js shutdown failed', error);
|
|
2595
|
+
* }
|
|
2596
|
+
* });
|
|
2597
|
+
* ```
|
|
2598
|
+
*/
|
|
2489
2599
|
export declare const shutdown: () => void;
|
|
2490
2600
|
export declare const currentThreadId: () => number;
|
|
2601
|
+
/**
|
|
2602
|
+
* Reads the process-wide steady clock: `std::chrono::steady_clock` as
|
|
2603
|
+
* fractional milliseconds from an unspecified origin that is fixed for the life
|
|
2604
|
+
* of the process. Every sample in the process — main thread and every
|
|
2605
|
+
* `worker_threads` worker, whenever started or restarted, on Node, Bun and Deno
|
|
2606
|
+
* — is in one domain, and the difference between two samples is real elapsed
|
|
2607
|
+
* time unaffected by wall-clock steps. Non-decreasing but not unique (two
|
|
2608
|
+
* samples may be equal; treat `==` as "not later"). Windows QPC samples from
|
|
2609
|
+
* different threads within one native tick also have ambiguous ordering.
|
|
2610
|
+
* Clock readings alone do not prove causality. Not comparable with
|
|
2611
|
+
* `Date.now()`, `db.getMonotonicTimestamp()` or transaction timestamps, and not
|
|
2612
|
+
* meaningful across processes or restarts. Time spent in host suspend is
|
|
2613
|
+
* platform-defined. No open database is needed.
|
|
2614
|
+
*/
|
|
2615
|
+
export declare const steadyClockNow: () => number;
|
|
2491
2616
|
/**
|
|
2492
2617
|
* Advises the kernel that the file-backed pages of every mapped transaction log
|
|
2493
2618
|
* are cold (Linux MADV_COLD), so they are reclaimed first under memory pressure
|
|
@@ -2793,6 +2918,51 @@ export declare class RocksDatabase extends DBI<DBITransactional> {
|
|
|
2793
2918
|
* ```
|
|
2794
2919
|
*/
|
|
2795
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;
|
|
2796
2966
|
/**
|
|
2797
2967
|
* The informational-log settings currently in effect for this database,
|
|
2798
2968
|
* read live from RocksDB, as `{ maxLogFileSize, infoLogLevel }`. These are
|
|
@@ -2825,7 +2995,10 @@ export declare class RocksDatabase extends DBI<DBITransactional> {
|
|
|
2825
2995
|
* native binding use namespaced keys (e.g. `'transactionLog:warning'`).
|
|
2826
2996
|
*
|
|
2827
2997
|
* Listeners are not tied to any specific database — they fire for every
|
|
2828
|
-
* matching event emitted in this process.
|
|
2998
|
+
* matching event emitted in this process. Native lifecycle failures use
|
|
2999
|
+
* `'database:closeFailed'` with `(path, error)` string arguments. The event
|
|
3000
|
+
* reports both completed and incomplete teardowns; an incomplete close can
|
|
3001
|
+
* be retried by `shutdown()` or explicitly deleted by `destroy()`.
|
|
2829
3002
|
*
|
|
2830
3003
|
* @example
|
|
2831
3004
|
* ```typescript
|