1
1
'use strict' ;
2
2
require ( '../common' ) ;
3
3
const tmpdir = require ( '../common/tmpdir' ) ;
4
- const { path : fixturesPath } = require ( '../common/fixtures' ) ;
5
- const { spawn } = require ( 'node:child_process' ) ;
6
4
const { join } = require ( 'node:path' ) ;
7
5
const { DatabaseSync } = require ( 'node:sqlite' ) ;
8
6
const { test } = require ( 'node:test' ) ;
7
+ const { once } = require ( 'node:events' ) ;
8
+ const { Worker } = require ( 'node:worker_threads' ) ;
9
9
let cnt = 0 ;
10
10
11
11
tmpdir . refresh ( ) ;
@@ -14,55 +14,59 @@ function nextDb() {
14
14
return join ( tmpdir . path , `database-${ cnt ++ } .db` ) ;
15
15
}
16
16
17
- test ( 'connection can perform queries when lock is released before the timeout' , ( t , done ) => {
18
- const databasePath = nextDb ( ) ;
19
- const conn = new DatabaseSync ( databasePath , { timeout : 1100 } ) ;
20
- t . after ( ( ) => { conn . close ( ) ; } ) ;
21
-
22
- conn . exec ( 'CREATE TABLE data (key INTEGER PRIMARY KEY, value TEXT)' ) ;
23
-
24
- // Spawns a child process to locks the database for 1 second
25
- const child = spawn ( './node' , [ fixturesPath ( 'sqlite/lock-db.js' ) , databasePath ] , {
26
- stdio : [ 'inherit' , 'inherit' , 'inherit' , 'ipc' ] ,
17
+ test ( 'waits to acquire lock' , async ( t ) => {
18
+ const DB_PATH = nextDb ( ) ;
19
+ const conn = new DatabaseSync ( DB_PATH ) ;
20
+ t . after ( ( ) => {
21
+ try {
22
+ conn . close ( ) ;
23
+ } catch {
24
+ // Ignore.
25
+ }
27
26
} ) ;
28
27
29
- child . on ( 'message' , ( msg ) => {
30
- if ( msg === 'locked' ) {
31
- conn . exec ( 'INSERT INTO data (key, value) VALUES (?, ?)' , [ 1 , 'value-1' ] ) ;
32
-
33
- setTimeout ( ( ) => {
34
- done ( ) ;
35
- } , 1100 ) ;
28
+ conn . exec ( 'CREATE TABLE IF NOT EXISTS data (value TEXT)' ) ;
29
+ conn . exec ( 'BEGIN EXCLUSIVE;' ) ;
30
+ const worker = new Worker ( `
31
+ 'use strict';
32
+ const { DatabaseSync } = require('node:sqlite');
33
+ const { workerData } = require('node:worker_threads');
34
+ const conn = new DatabaseSync(workerData.database, { timeout: 30000 });
35
+ conn.exec('SELECT * FROM data');
36
+ conn.close();
37
+ ` , {
38
+ eval : true ,
39
+ workerData : {
40
+ database : DB_PATH ,
36
41
}
37
42
} ) ;
43
+ await once ( worker , 'online' ) ;
44
+ conn . exec ( 'COMMIT;' ) ;
45
+ await once ( worker , 'exit' ) ;
38
46
} ) ;
39
47
40
- test ( 'trhows if lock is holden longer than the provided timeout' , ( t , done ) => {
41
- const databasePath = nextDb ( ) ;
42
- const conn = new DatabaseSync ( databasePath , { timeout : 800 } ) ;
43
- t . after ( ( ) => { conn . close ( ) ; } ) ;
44
-
45
- conn . exec ( 'CREATE TABLE data (key INTEGER PRIMARY KEY, value TEXT)' ) ;
46
-
47
- // Spawns a child process to locks the database for 1 second
48
- const child = spawn ( './node' , [ fixturesPath ( 'sqlite/lock-db.js' ) , databasePath ] , {
49
- stdio : [ 'inherit' , 'inherit' , 'inherit' , 'ipc' ] ,
50
- } ) ;
51
-
52
- child . on ( 'message' , ( msg ) => {
53
- if ( msg === 'locked' ) {
54
- t . assert . throws ( ( ) => {
55
- conn . exec ( 'INSERT INTO data (key, value) VALUES (?, ?)' , [ 1 , 'value-1' ] ) ;
56
- } , {
57
- code : 'ERR_SQLITE_ERROR' ,
58
- message : 'database is locked' ,
59
- } ) ;
48
+ test ( 'throws if the lock cannot be acquired before timeout' , ( t ) => {
49
+ const DB_PATH = nextDb ( ) ;
50
+ const conn1 = new DatabaseSync ( DB_PATH ) ;
51
+ t . after ( ( ) => {
52
+ try {
53
+ conn1 . close ( ) ;
54
+ } catch {
55
+ // Ignore.
60
56
}
61
57
} ) ;
62
-
63
- child . on ( 'exit' , ( code ) => {
64
- if ( code === 0 ) {
65
- done ( ) ;
58
+ const conn2 = new DatabaseSync ( DB_PATH , { timeout : 1 } ) ;
59
+ t . after ( ( ) => {
60
+ try {
61
+ conn2 . close ( ) ;
62
+ } catch {
63
+ // Ignore.
66
64
}
67
65
} ) ;
66
+
67
+ conn1 . exec ( 'CREATE TABLE IF NOT EXISTS data (value TEXT)' ) ;
68
+ conn1 . exec ( 'PRAGMA locking_mode = EXCLUSIVE; BEGIN EXCLUSIVE;' ) ;
69
+ t . assert . throws ( ( ) => {
70
+ conn2 . exec ( 'SELECT * FROM data' ) ;
71
+ } , / d a t a b a s e i s l o c k e d / ) ;
68
72
} ) ;
0 commit comments