Skip to content

Commit 15d1cf9

Browse files
committed
WIP
1 parent c6b3780 commit 15d1cf9

File tree

5 files changed

+36
-32
lines changed

5 files changed

+36
-32
lines changed

src/DB.ts

+7-7
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ class DB {
3737
public static async createDB({
3838
dbPath,
3939
crypto,
40-
fs = require('fs'),
4140
deadlock = false,
41+
fs = require('fs'),
4242
logger = new Logger(this.name),
4343
fresh = false,
4444
...dbOptions
@@ -48,16 +48,16 @@ class DB {
4848
key: Buffer;
4949
ops: Crypto;
5050
};
51+
deadlock?: boolean;
5152
fs?: FileSystem;
5253
logger?: Logger;
53-
deadlock?: boolean;
5454
fresh?: boolean;
5555
} & DBOptions): Promise<DB> {
5656
logger.info(`Creating ${this.name}`);
5757
const db = new this({
5858
dbPath,
59-
fs,
6059
deadlock,
60+
fs,
6161
logger,
6262
});
6363
await db.start({
@@ -78,7 +78,7 @@ class DB {
7878
protected logger: Logger;
7979
protected workerManager?: DBWorkerManagerInterface;
8080
protected _lockBox: LockBox<RWLockWriter> = new LockBox();
81-
protected _locksPending?: Map<string, { count: number}>;
81+
protected _locksPending?: Map<string, { count: number }>;
8282
protected _db: RocksDBDatabase;
8383
/**
8484
* References to iterators
@@ -113,21 +113,21 @@ class DB {
113113

114114
constructor({
115115
dbPath,
116-
fs,
117116
deadlock,
117+
fs,
118118
logger,
119119
}: {
120120
dbPath: string;
121-
fs: FileSystem;
122121
deadlock: boolean;
122+
fs: FileSystem;
123123
logger: Logger;
124124
}) {
125125
this.logger = logger;
126126
this.dbPath = dbPath;
127-
this.fs = fs;
128127
if (deadlock) {
129128
this._locksPending = new Map();
130129
}
130+
this.fs = fs;
131131
}
132132

133133
public async start({

src/DBTransaction.ts

+2-8
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import type { ResourceRelease } from '@matrixai/resources';
21
import type { LockBox } from '@matrixai/async-locks';
32
import type DB from './DB';
43
import type {
@@ -19,7 +18,7 @@ import {
1918
Monitor,
2019
Lock,
2120
RWLockWriter,
22-
errors as asyncLocksErrors
21+
errors as asyncLocksErrors,
2322
} from '@matrixai/async-locks';
2423
import DBIterator from './DBIterator';
2524
import { rocksdbP } from './native';
@@ -63,12 +62,7 @@ class DBTransaction {
6362
logger.debug(`Constructing ${this.constructor.name}`);
6463
this.logger = logger;
6564
this._db = db;
66-
// This creates the monitor that I care about
67-
this.monitor = new Monitor(
68-
lockBox,
69-
RWLockWriter,
70-
locksPending
71-
);
65+
this.monitor = new Monitor(lockBox, RWLockWriter, locksPending);
7266
const options_ = {
7367
...options,
7468
// Transactions should be synchronous

src/errors.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,7 @@ class ErrorDBTransactionLockType<T> extends ErrorDBTransaction<T> {
8888
}
8989

9090
class ErrorDBTransactionDeadlock<T> extends ErrorDBTransaction<T> {
91-
static description =
92-
'DBTransaction encountered a pessimistic deadlock';
91+
static description = 'DBTransaction encountered a pessimistic deadlock';
9392
}
9493

9594
export {

src/types.ts

-15
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import type fs from 'fs';
2-
import type { RWLockWriter } from '@matrixai/async-locks';
32
import type { WorkerManagerInterface } from '@matrixai/workers';
43
import type {
54
RocksDBDatabaseOptions,
@@ -17,13 +16,6 @@ import type {
1716
*/
1817
type POJO = { [key: string]: any };
1918

20-
/**
21-
* Any type that can be turned into a string
22-
*/
23-
// interface ToString {
24-
// toString(): string;
25-
// }
26-
2719
/**
2820
* Opaque types are wrappers of existing types
2921
* that require smart constructors
@@ -159,14 +151,8 @@ type DBOp =
159151

160152
type DBOps = Array<DBOp>;
161153

162-
// type MultiLockRequest = [
163-
// key: ToString,
164-
// ...lockingParams: Parameters<RWLockWriter['lock']>,
165-
// ];
166-
167154
export type {
168155
POJO,
169-
// ToString,
170156
Opaque,
171157
Callback,
172158
Merge,
@@ -182,5 +168,4 @@ export type {
182168
DBBatch,
183169
DBOp,
184170
DBOps,
185-
// MultiLockRequest,
186171
};

tests/DBTransaction.test.ts

+26
Original file line numberDiff line numberDiff line change
@@ -1139,4 +1139,30 @@ describe(DBTransaction.name, () => {
11391139
});
11401140
});
11411141
});
1142+
test('deadlock detection', async () => {
1143+
const dbPath = `${dataDir}/db2`;
1144+
const db = await DB.createDB({ dbPath, crypto, deadlock: true, logger });
1145+
const barrier = await Barrier.createBarrier(2);
1146+
const results = await Promise.allSettled([
1147+
db.withTransactionF(async (tran1) => {
1148+
await tran1.lock('foo');
1149+
await barrier.wait();
1150+
await tran1.lock('bar');
1151+
}),
1152+
db.withTransactionF(async (tran2) => {
1153+
await tran2.lock('bar');
1154+
await barrier.wait();
1155+
await tran2.lock('foo');
1156+
}),
1157+
]);
1158+
expect(
1159+
results.some(
1160+
(r) =>
1161+
r.status === 'rejected' &&
1162+
r.reason instanceof errors.ErrorDBTransactionDeadlock,
1163+
),
1164+
).toBe(true);
1165+
expect(results.some((r) => r.status === 'fulfilled')).toBe(true);
1166+
await db.stop();
1167+
});
11421168
});

0 commit comments

Comments
 (0)