@harperfast/rocksdb-js 0.1.12 → 0.1.13
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 +47 -8
- package/dist/index.cjs +101 -45
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -2
- package/dist/index.d.mts +15 -2
- package/dist/index.mjs +101 -45
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -9
package/dist/index.d.cts
CHANGED
|
@@ -369,6 +369,18 @@ type TransactionOptions = {
|
|
|
369
369
|
* @default false
|
|
370
370
|
*/
|
|
371
371
|
disableSnapshot?: boolean;
|
|
372
|
+
/**
|
|
373
|
+
* The maximum number of times to retry the transaction.
|
|
374
|
+
*
|
|
375
|
+
* @default 3
|
|
376
|
+
*/
|
|
377
|
+
maxRetries?: number;
|
|
378
|
+
/**
|
|
379
|
+
* Whether to retry the transaction if it fails with `IsBusy`.
|
|
380
|
+
*
|
|
381
|
+
* @default `true` when the transaction is bound to a transaction log, otherwise `false`
|
|
382
|
+
*/
|
|
383
|
+
retryOnBusy?: boolean;
|
|
372
384
|
};
|
|
373
385
|
type NativeTransaction = {
|
|
374
386
|
id: number;
|
|
@@ -889,6 +901,7 @@ declare class DBI<T extends DBITransactional | unknown = unknown> {
|
|
|
889
901
|
}
|
|
890
902
|
//#endregion
|
|
891
903
|
//#region src/database.d.ts
|
|
904
|
+
type TransactionCallback<T> = (txn: Transaction, attempt: number) => T | PromiseLike<T>;
|
|
892
905
|
interface RocksDatabaseOptions extends StoreOptions {
|
|
893
906
|
/**
|
|
894
907
|
* The column family name.
|
|
@@ -1133,7 +1146,7 @@ declare class RocksDatabase extends DBI<DBITransactional> {
|
|
|
1133
1146
|
* });
|
|
1134
1147
|
* ```
|
|
1135
1148
|
*/
|
|
1136
|
-
transaction<T>(callback:
|
|
1149
|
+
transaction<T>(callback: TransactionCallback<T>, options?: TransactionOptions): Promise<T | void>;
|
|
1137
1150
|
/**
|
|
1138
1151
|
* Executes all operations in the callback as a single transaction.
|
|
1139
1152
|
*
|
|
@@ -1151,7 +1164,7 @@ declare class RocksDatabase extends DBI<DBITransactional> {
|
|
|
1151
1164
|
* });
|
|
1152
1165
|
* ```
|
|
1153
1166
|
*/
|
|
1154
|
-
transactionSync<T>(callback:
|
|
1167
|
+
transactionSync<T>(callback: TransactionCallback<T>, options?: TransactionOptions): T | PromiseLike<T> | void;
|
|
1155
1168
|
/**
|
|
1156
1169
|
* Attempts to acquire a lock for a given key. If the lock is available,
|
|
1157
1170
|
* the function returns `true` and the optional callback is never called.
|
package/dist/index.d.mts
CHANGED
|
@@ -369,6 +369,18 @@ type TransactionOptions = {
|
|
|
369
369
|
* @default false
|
|
370
370
|
*/
|
|
371
371
|
disableSnapshot?: boolean;
|
|
372
|
+
/**
|
|
373
|
+
* The maximum number of times to retry the transaction.
|
|
374
|
+
*
|
|
375
|
+
* @default 3
|
|
376
|
+
*/
|
|
377
|
+
maxRetries?: number;
|
|
378
|
+
/**
|
|
379
|
+
* Whether to retry the transaction if it fails with `IsBusy`.
|
|
380
|
+
*
|
|
381
|
+
* @default `true` when the transaction is bound to a transaction log, otherwise `false`
|
|
382
|
+
*/
|
|
383
|
+
retryOnBusy?: boolean;
|
|
372
384
|
};
|
|
373
385
|
type NativeTransaction = {
|
|
374
386
|
id: number;
|
|
@@ -889,6 +901,7 @@ declare class DBI<T extends DBITransactional | unknown = unknown> {
|
|
|
889
901
|
}
|
|
890
902
|
//#endregion
|
|
891
903
|
//#region src/database.d.ts
|
|
904
|
+
type TransactionCallback<T> = (txn: Transaction, attempt: number) => T | PromiseLike<T>;
|
|
892
905
|
interface RocksDatabaseOptions extends StoreOptions {
|
|
893
906
|
/**
|
|
894
907
|
* The column family name.
|
|
@@ -1133,7 +1146,7 @@ declare class RocksDatabase extends DBI<DBITransactional> {
|
|
|
1133
1146
|
* });
|
|
1134
1147
|
* ```
|
|
1135
1148
|
*/
|
|
1136
|
-
transaction<T>(callback:
|
|
1149
|
+
transaction<T>(callback: TransactionCallback<T>, options?: TransactionOptions): Promise<T | void>;
|
|
1137
1150
|
/**
|
|
1138
1151
|
* Executes all operations in the callback as a single transaction.
|
|
1139
1152
|
*
|
|
@@ -1151,7 +1164,7 @@ declare class RocksDatabase extends DBI<DBITransactional> {
|
|
|
1151
1164
|
* });
|
|
1152
1165
|
* ```
|
|
1153
1166
|
*/
|
|
1154
|
-
transactionSync<T>(callback:
|
|
1167
|
+
transactionSync<T>(callback: TransactionCallback<T>, options?: TransactionOptions): T | PromiseLike<T> | void;
|
|
1155
1168
|
/**
|
|
1156
1169
|
* Attempts to acquire a lock for a given key. If the lock is available,
|
|
1157
1170
|
* the function returns `true` and the optional callback is never called.
|
package/dist/index.mjs
CHANGED
|
@@ -986,6 +986,29 @@ function getKeyParam(keyBuffer) {
|
|
|
986
986
|
|
|
987
987
|
//#endregion
|
|
988
988
|
//#region src/transaction.ts
|
|
989
|
+
var TransactionAlreadyAbortedError = class extends Error {
|
|
990
|
+
code = "ERR_ALREADY_ABORTED";
|
|
991
|
+
};
|
|
992
|
+
var TransactionIsBusyError = class extends Error {
|
|
993
|
+
code = "ERR_BUSY";
|
|
994
|
+
hasLog;
|
|
995
|
+
txn;
|
|
996
|
+
constructor(error, txn) {
|
|
997
|
+
super(error.message);
|
|
998
|
+
this.hasLog = error.hasLog ?? false;
|
|
999
|
+
this.txn = txn;
|
|
1000
|
+
}
|
|
1001
|
+
};
|
|
1002
|
+
var TransactionAbandonedError = class extends Error {
|
|
1003
|
+
code = "ERR_TRANSACTION_ABANDONED";
|
|
1004
|
+
hasLog;
|
|
1005
|
+
txn;
|
|
1006
|
+
constructor(error, txn) {
|
|
1007
|
+
super(error.message);
|
|
1008
|
+
this.hasLog = error.hasLog ?? false;
|
|
1009
|
+
this.txn = txn;
|
|
1010
|
+
}
|
|
1011
|
+
};
|
|
989
1012
|
/**
|
|
990
1013
|
* Provides transaction level operations to a transaction callback.
|
|
991
1014
|
*/
|
|
@@ -1006,7 +1029,12 @@ var Transaction = class extends DBI {
|
|
|
1006
1029
|
* Abort the transaction.
|
|
1007
1030
|
*/
|
|
1008
1031
|
abort() {
|
|
1009
|
-
|
|
1032
|
+
try {
|
|
1033
|
+
this.#txn.abort();
|
|
1034
|
+
} catch (err) {
|
|
1035
|
+
if (err instanceof Error && "code" in err && err.code === "ERR_TRANSACTION_ABANDONED") throw new TransactionAbandonedError(err, this);
|
|
1036
|
+
throw err;
|
|
1037
|
+
}
|
|
1010
1038
|
}
|
|
1011
1039
|
/**
|
|
1012
1040
|
* Commit the transaction.
|
|
@@ -1017,6 +1045,8 @@ var Transaction = class extends DBI {
|
|
|
1017
1045
|
this.notify("beforecommit");
|
|
1018
1046
|
this.#txn.commit(resolve, reject);
|
|
1019
1047
|
});
|
|
1048
|
+
} catch (err) {
|
|
1049
|
+
throw this.#handleCommitError(err);
|
|
1020
1050
|
} finally {
|
|
1021
1051
|
this.notify("aftercommit", {
|
|
1022
1052
|
next: null,
|
|
@@ -1032,6 +1062,8 @@ var Transaction = class extends DBI {
|
|
|
1032
1062
|
try {
|
|
1033
1063
|
this.notify("beforecommit");
|
|
1034
1064
|
this.#txn.commitSync();
|
|
1065
|
+
} catch (err) {
|
|
1066
|
+
throw this.#handleCommitError(err);
|
|
1035
1067
|
} finally {
|
|
1036
1068
|
this.notify("aftercommit", {
|
|
1037
1069
|
next: null,
|
|
@@ -1041,6 +1073,19 @@ var Transaction = class extends DBI {
|
|
|
1041
1073
|
}
|
|
1042
1074
|
}
|
|
1043
1075
|
/**
|
|
1076
|
+
* Detect if error is an already aborted or busy error and return the appropriate error class.
|
|
1077
|
+
*
|
|
1078
|
+
* @param err - The error to check.
|
|
1079
|
+
* @returns The specialized error.
|
|
1080
|
+
*/
|
|
1081
|
+
#handleCommitError(err) {
|
|
1082
|
+
if (err instanceof Error && "code" in err) {
|
|
1083
|
+
if (err.code === "ERR_ALREADY_ABORTED") return new TransactionAlreadyAbortedError(err.message);
|
|
1084
|
+
if (err.code === "ERR_BUSY") return new TransactionIsBusyError(err, this);
|
|
1085
|
+
}
|
|
1086
|
+
return err;
|
|
1087
|
+
}
|
|
1088
|
+
/**
|
|
1044
1089
|
* Returns the transaction start timestamp in seconds. Defaults to the time at which
|
|
1045
1090
|
* the transaction was created.
|
|
1046
1091
|
*
|
|
@@ -1447,30 +1492,24 @@ var RocksDatabase = class RocksDatabase extends DBI {
|
|
|
1447
1492
|
*/
|
|
1448
1493
|
async transaction(callback, options) {
|
|
1449
1494
|
if (typeof callback !== "function") throw new TypeError("Callback must be a function");
|
|
1495
|
+
const maxRetries = options?.maxRetries ?? 3;
|
|
1450
1496
|
const txn = new Transaction(this.store, options);
|
|
1451
1497
|
let result;
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
result = await callback(txn);
|
|
1455
|
-
} catch (err) {
|
|
1498
|
+
this.notify("begin-transaction");
|
|
1499
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
1456
1500
|
try {
|
|
1457
|
-
txn
|
|
1458
|
-
} catch (
|
|
1459
|
-
|
|
1501
|
+
result = await callback(txn, attempt);
|
|
1502
|
+
} catch (callbackErr) {
|
|
1503
|
+
return this.#abortTransaction(txn, callbackErr);
|
|
1460
1504
|
}
|
|
1461
|
-
throw err;
|
|
1462
|
-
}
|
|
1463
|
-
try {
|
|
1464
|
-
await txn.commit();
|
|
1465
|
-
return result;
|
|
1466
|
-
} catch (err) {
|
|
1467
|
-
if (err instanceof Error && "code" in err && err.code === "ERR_ALREADY_ABORTED") return;
|
|
1468
1505
|
try {
|
|
1469
|
-
txn.
|
|
1470
|
-
|
|
1471
|
-
|
|
1506
|
+
await txn.commit();
|
|
1507
|
+
return result;
|
|
1508
|
+
} catch (commitErr) {
|
|
1509
|
+
if (commitErr instanceof TransactionAlreadyAbortedError) return;
|
|
1510
|
+
if (commitErr instanceof TransactionIsBusyError && (options?.retryOnBusy ?? commitErr.hasLog) && attempt <= maxRetries) continue;
|
|
1511
|
+
this.#abandonTransaction(txn, commitErr);
|
|
1472
1512
|
}
|
|
1473
|
-
throw err;
|
|
1474
1513
|
}
|
|
1475
1514
|
}
|
|
1476
1515
|
/**
|
|
@@ -1492,38 +1531,55 @@ var RocksDatabase = class RocksDatabase extends DBI {
|
|
|
1492
1531
|
*/
|
|
1493
1532
|
transactionSync(callback, options) {
|
|
1494
1533
|
if (typeof callback !== "function") throw new TypeError("Callback must be a function");
|
|
1495
|
-
const
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1534
|
+
const maxRetries = options?.maxRetries ?? 3;
|
|
1535
|
+
const isRetryable = (err, attempt) => {
|
|
1536
|
+
return err instanceof TransactionIsBusyError && (options?.retryOnBusy ?? err.hasLog) && attempt <= maxRetries;
|
|
1537
|
+
};
|
|
1538
|
+
const runAttempt = (attempt) => {
|
|
1539
|
+
const txn = new Transaction(this.store, options);
|
|
1540
|
+
let result;
|
|
1501
1541
|
try {
|
|
1502
|
-
txn
|
|
1503
|
-
} catch (
|
|
1504
|
-
|
|
1542
|
+
result = callback(txn, attempt);
|
|
1543
|
+
} catch (callbackErr) {
|
|
1544
|
+
return this.#abortTransaction(txn, callbackErr);
|
|
1505
1545
|
}
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1546
|
+
if (typeof result?.then === "function") return result.then((value) => {
|
|
1547
|
+
try {
|
|
1548
|
+
txn.commitSync();
|
|
1549
|
+
return value;
|
|
1550
|
+
} catch (commitErr) {
|
|
1551
|
+
if (commitErr instanceof TransactionAlreadyAbortedError) return;
|
|
1552
|
+
if (isRetryable(commitErr, attempt)) return runAttempt(attempt + 1);
|
|
1553
|
+
this.#abandonTransaction(txn, commitErr);
|
|
1554
|
+
}
|
|
1555
|
+
});
|
|
1509
1556
|
try {
|
|
1510
1557
|
txn.commitSync();
|
|
1511
|
-
return
|
|
1512
|
-
} catch (
|
|
1513
|
-
if (
|
|
1514
|
-
|
|
1558
|
+
return result;
|
|
1559
|
+
} catch (commitErr) {
|
|
1560
|
+
if (commitErr instanceof TransactionAlreadyAbortedError) return;
|
|
1561
|
+
if (isRetryable(commitErr, attempt)) return runAttempt(attempt + 1);
|
|
1562
|
+
this.#abandonTransaction(txn, commitErr);
|
|
1515
1563
|
}
|
|
1516
|
-
}
|
|
1564
|
+
};
|
|
1565
|
+
this.notify("begin-transaction");
|
|
1566
|
+
return runAttempt(1);
|
|
1567
|
+
}
|
|
1568
|
+
#abortTransaction(txn, callbackErr) {
|
|
1517
1569
|
try {
|
|
1518
|
-
txn.
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1570
|
+
txn.abort();
|
|
1571
|
+
} catch (abortErr) {
|
|
1572
|
+
if (abortErr instanceof TransactionAlreadyAbortedError) return;
|
|
1573
|
+
}
|
|
1574
|
+
throw callbackErr;
|
|
1575
|
+
}
|
|
1576
|
+
#abandonTransaction(txn, commitErr) {
|
|
1577
|
+
try {
|
|
1578
|
+
txn.abort();
|
|
1579
|
+
} catch (abortErr) {
|
|
1580
|
+
if (abortErr instanceof TransactionAbandonedError) throw abortErr;
|
|
1526
1581
|
}
|
|
1582
|
+
throw commitErr;
|
|
1527
1583
|
}
|
|
1528
1584
|
/**
|
|
1529
1585
|
* Attempts to acquire a lock for a given key. If the lock is available,
|
|
@@ -1827,7 +1883,7 @@ function loadLastPosition(transactionLog, readUncommitted) {
|
|
|
1827
1883
|
//#region src/index.ts
|
|
1828
1884
|
const versions = {
|
|
1829
1885
|
rocksdb: version,
|
|
1830
|
-
"rocksdb-js": "0.1.
|
|
1886
|
+
"rocksdb-js": "0.1.13"
|
|
1831
1887
|
};
|
|
1832
1888
|
|
|
1833
1889
|
//#endregion
|