Skip to content

Commit b00e1ec

Browse files
[Node.js] Prevent database is locked errors (#749)
1 parent 2f8b30c commit b00e1ec

File tree

4 files changed

+45
-10
lines changed

4 files changed

+45
-10
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@powersync/node': patch
3+
---
4+
5+
[`node:sqlite`] Prevent `database is locked` errors when instantiating the database.

packages/node/src/db/WorkerConnectionPool.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
1+
import * as Comlink from 'comlink';
12
import fs from 'node:fs/promises';
23
import * as path from 'node:path';
34
import { Worker } from 'node:worker_threads';
4-
import * as Comlink from 'comlink';
55

66
import {
77
BaseObserver,
88
BatchedUpdateNotification,
99
DBAdapter,
1010
DBAdapterListener,
11-
LockContext,
12-
Transaction,
1311
DBLockOptions,
14-
QueryResult
12+
LockContext,
13+
QueryResult,
14+
Transaction
1515
} from '@powersync/common';
1616
import { Remote } from 'comlink';
1717
import { AsyncResource } from 'node:async_hooks';
18+
import { isBundledToCommonJs } from '../utils/modules.js';
1819
import { AsyncDatabase, AsyncDatabaseOpener } from './AsyncDatabase.js';
1920
import { RemoteConnection } from './RemoteConnection.js';
2021
import { NodeDatabaseImplementation, NodeSQLOpenOptions } from './options.js';
21-
import { isBundledToCommonJs } from '../utils/modules.js';
2222

2323
export type BetterSQLite3LockContext = LockContext & {
2424
executeBatch(query: string, params?: any[][]): Promise<QueryResult>;
@@ -135,10 +135,12 @@ export class WorkerConnectionPool extends BaseObserver<DBAdapterListener> implem
135135
if (this.options.initializeConnection) {
136136
await this.options.initializeConnection(connection, isWriter);
137137
}
138-
139-
await connection.execute('pragma journal_mode = WAL');
140138
if (!isWriter) {
141139
await connection.execute('pragma query_only = true');
140+
} else {
141+
// We only need to enable this on the writer connection.
142+
// We can get `database is locked` errors if we enable this on concurrently opening read connections.
143+
await connection.execute('pragma journal_mode = WAL');
142144
}
143145

144146
return connection;

packages/node/tests/PowerSyncDatabase.test.ts

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import * as path from 'node:path';
22
import { Worker } from 'node:worker_threads';
33

4-
import { vi, expect, test } from 'vitest';
5-
import { AppSchema, databaseTest, tempDirectoryTest } from './utils';
4+
import { LockContext } from '@powersync/common';
5+
import { randomUUID } from 'node:crypto';
6+
import { expect, test, vi } from 'vitest';
67
import { CrudEntry, CrudTransaction, PowerSyncDatabase } from '../lib';
78
import { WorkerOpener } from '../lib/db/options';
8-
import { LockContext } from '@powersync/common';
9+
import { AppSchema, databaseTest, tempDirectoryTest } from './utils';
910

1011
test('validates options', async () => {
1112
await expect(async () => {
@@ -203,3 +204,26 @@ databaseTest('getCrudTransactions', async ({ database }) => {
203204
const remainingTransaction = await database.getNextCrudTransaction();
204205
expect(remainingTransaction?.crud).toHaveLength(15);
205206
});
207+
208+
// This is not a SemVer check, but is basic enough to skip this test on older versions of Node.js
209+
tempDirectoryTest.skipIf(process.versions.node < '22.5.0')(
210+
'should not present database is locked errors on startup',
211+
async ({ tmpdir }) => {
212+
for (let i = 0; i < 10; i++) {
213+
const database = new PowerSyncDatabase({
214+
schema: AppSchema,
215+
database: {
216+
dbFilename: `${randomUUID()}.sqlite`,
217+
dbLocation: tmpdir,
218+
implementation: {
219+
type: 'node:sqlite'
220+
}
221+
}
222+
});
223+
224+
// This should not throw
225+
await database.waitForReady();
226+
await database.close();
227+
}
228+
}
229+
);

pnpm-workspace.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,7 @@ packages:
33
- packages/*
44
- tools/*
55
- docs/
6+
7+
onlyBuiltDependencies:
8+
- better-sqlite3
9+
- better-sqlite3-multiple-ciphers

0 commit comments

Comments
 (0)