@dxos/lock-file 0.1.58-main.59c38c1 → 0.1.58-main.5e0f151
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/dist/lib/node/index.cjs
CHANGED
|
@@ -26,15 +26,15 @@ module.exports = __toCommonJS(src_exports);
|
|
|
26
26
|
|
|
27
27
|
// packages/common/lock-file/src/lock-file.ts
|
|
28
28
|
var import_fs_ext = require("fs-ext");
|
|
29
|
+
var import_node_fs = require("node:fs");
|
|
29
30
|
var import_promises = require("node:fs/promises");
|
|
30
31
|
var LockFile = class _LockFile {
|
|
31
32
|
static async acquire(filename) {
|
|
32
|
-
const handle = await (0, import_promises.open)(filename,
|
|
33
|
+
const handle = await (0, import_promises.open)(filename, import_node_fs.constants.O_CREAT);
|
|
33
34
|
await new Promise((resolve, reject) => {
|
|
34
|
-
(0, import_fs_ext.flock)(handle.fd, "exnb",
|
|
35
|
+
(0, import_fs_ext.flock)(handle.fd, "exnb", (err) => {
|
|
35
36
|
if (err) {
|
|
36
37
|
reject(err);
|
|
37
|
-
await handle.close();
|
|
38
38
|
return;
|
|
39
39
|
}
|
|
40
40
|
resolve();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/index.ts", "../../../src/lock-file.ts"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nexport * from './lock-file';\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { flock } from 'fs-ext';\nimport { open, FileHandle
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;;;;;;;ACIA,oBAAsB;AACtB,
|
|
6
|
-
"names": ["LockFile", "acquire", "filename", "handle", "open", "constants", "O_CREAT", "Promise", "resolve", "reject", "flock", "fd", "err", "
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nexport * from './lock-file';\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { flock } from 'fs-ext';\nimport { constants } from 'node:fs';\nimport { open, FileHandle } from 'node:fs/promises';\n\nexport class LockFile {\n static async acquire(filename: string): Promise<FileHandle> {\n const handle = await open(filename, constants.O_CREAT);\n await new Promise<void>((resolve, reject) => {\n flock(handle.fd, 'exnb', (err) => {\n if (err) {\n reject(err);\n return;\n }\n resolve();\n });\n });\n return handle;\n }\n\n static async release(handle: FileHandle): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n flock(handle.fd, 'un', (err) => {\n if (err) {\n reject(err);\n return;\n }\n resolve();\n });\n });\n await handle.close();\n }\n\n static async isLocked(filename: string): Promise<boolean> {\n try {\n const handle = await LockFile.acquire(filename);\n await LockFile.release(handle);\n await handle.close();\n\n return false;\n } catch (e) {\n return true;\n }\n }\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;;;;;;;ACIA,oBAAsB;AACtB,qBAA0B;AAC1B,sBAAiC;AAE1B,IAAMA,WAAN,MAAMA,UAAAA;EACX,aAAaC,QAAQC,UAAuC;AAC1D,UAAMC,SAAS,UAAMC,sBAAKF,UAAUG,yBAAUC,OAAO;AACrD,UAAM,IAAIC,QAAc,CAACC,SAASC,WAAAA;AAChCC,+BAAMP,OAAOQ,IAAI,QAAQ,CAACC,QAAAA;AACxB,YAAIA,KAAK;AACPH,iBAAOG,GAAAA;AACP;QACF;AACAJ,gBAAAA;MACF,CAAA;IACF,CAAA;AACA,WAAOL;EACT;EAEA,aAAaU,QAAQV,QAAmC;AACtD,UAAM,IAAII,QAAc,CAACC,SAASC,WAAAA;AAChCC,+BAAMP,OAAOQ,IAAI,MAAM,CAACC,QAAAA;AACtB,YAAIA,KAAK;AACPH,iBAAOG,GAAAA;AACP;QACF;AACAJ,gBAAAA;MACF,CAAA;IACF,CAAA;AACA,UAAML,OAAOW,MAAK;EACpB;EAEA,aAAaC,SAASb,UAAoC;AACxD,QAAI;AACF,YAAMC,SAAS,MAAMH,UAASC,QAAQC,QAAAA;AACtC,YAAMF,UAASa,QAAQV,MAAAA;AACvB,YAAMA,OAAOW,MAAK;AAElB,aAAO;IACT,SAASE,GAAG;AACV,aAAO;IACT;EACF;AACF;",
|
|
6
|
+
"names": ["LockFile", "acquire", "filename", "handle", "open", "constants", "O_CREAT", "Promise", "resolve", "reject", "flock", "fd", "err", "release", "close", "isLocked", "e"]
|
|
7
7
|
}
|
package/dist/lib/node/meta.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"inputs":{"packages/common/lock-file/src/lock-file.ts":{"bytes":
|
|
1
|
+
{"inputs":{"packages/common/lock-file/src/lock-file.ts":{"bytes":4104,"imports":[{"path":"fs-ext","kind":"import-statement","external":true},{"path":"node:fs","kind":"import-statement","external":true},{"path":"node:fs/promises","kind":"import-statement","external":true}],"format":"esm"},"packages/common/lock-file/src/index.ts":{"bytes":470,"imports":[{"path":"packages/common/lock-file/src/lock-file.ts","kind":"import-statement","original":"./lock-file"}],"format":"esm"}},"outputs":{"packages/common/lock-file/dist/lib/node/index.cjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":2251},"packages/common/lock-file/dist/lib/node/index.cjs":{"imports":[{"path":"fs-ext","kind":"require-call","external":true},{"path":"node:fs","kind":"require-call","external":true},{"path":"node:fs/promises","kind":"require-call","external":true}],"exports":[],"entryPoint":"packages/common/lock-file/src/index.ts","inputs":{"packages/common/lock-file/src/index.ts":{"bytesInOutput":121},"packages/common/lock-file/src/lock-file.ts":{"bytesInOutput":1044}},"bytes":2191}}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lock-file.d.ts","sourceRoot":"","sources":["../../../src/lock-file.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"lock-file.d.ts","sourceRoot":"","sources":["../../../src/lock-file.ts"],"names":[],"mappings":";AAMA,OAAO,EAAQ,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEpD,qBAAa,QAAQ;WACN,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;WAc9C,OAAO,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;WAa1C,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAW1D"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/lock-file",
|
|
3
|
-
"version": "0.1.58-main.
|
|
3
|
+
"version": "0.1.58-main.5e0f151",
|
|
4
4
|
"description": "Lock file .",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -14,9 +14,9 @@
|
|
|
14
14
|
],
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"fs-ext": "^2.0.0",
|
|
17
|
-
"@dxos/async": "0.1.58-main.
|
|
18
|
-
"@dxos/log": "0.1.58-main.
|
|
19
|
-
"@dxos/node-std": "0.1.58-main.
|
|
17
|
+
"@dxos/async": "0.1.58-main.5e0f151",
|
|
18
|
+
"@dxos/log": "0.1.58-main.5e0f151",
|
|
19
|
+
"@dxos/node-std": "0.1.58-main.5e0f151"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"@types/fs-ext": "^2.0.0",
|
package/src/lock-file.test.ts
CHANGED
|
@@ -5,24 +5,17 @@
|
|
|
5
5
|
import chai, { expect } from 'chai';
|
|
6
6
|
import chaiAsPromised from 'chai-as-promised';
|
|
7
7
|
import { spawn } from 'node:child_process';
|
|
8
|
-
import { existsSync
|
|
8
|
+
import { existsSync } from 'node:fs';
|
|
9
9
|
import { join } from 'node:path';
|
|
10
|
-
import waitForExpect from 'wait-for-expect';
|
|
11
10
|
|
|
12
|
-
import { Trigger } from '@dxos/async';
|
|
13
|
-
import {
|
|
11
|
+
import { Trigger, sleep } from '@dxos/async';
|
|
12
|
+
import { describe, test } from '@dxos/test';
|
|
14
13
|
|
|
15
14
|
import { LockFile } from './lock-file';
|
|
16
15
|
|
|
17
16
|
chai.use(chaiAsPromised);
|
|
18
17
|
|
|
19
|
-
const TEST_DIR = '/tmp/dxos/testing/lock-file';
|
|
20
|
-
|
|
21
18
|
describe('LockFile', () => {
|
|
22
|
-
beforeAll(() => {
|
|
23
|
-
mkdirSync(TEST_DIR, { recursive: true });
|
|
24
|
-
});
|
|
25
|
-
|
|
26
19
|
test('basic', async () => {
|
|
27
20
|
const filename = join('/tmp', `lock-${Math.random()}.lock`);
|
|
28
21
|
|
|
@@ -34,55 +27,32 @@ describe('LockFile', () => {
|
|
|
34
27
|
await LockFile.release(handle2);
|
|
35
28
|
});
|
|
36
29
|
|
|
37
|
-
test('released when process
|
|
38
|
-
const filename = join(
|
|
39
|
-
afterTest(() => {
|
|
40
|
-
if (existsSync(filename)) {
|
|
41
|
-
unlinkSync(filename);
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
const trigger = new Trigger();
|
|
30
|
+
test('released when process exists', async () => {
|
|
31
|
+
const filename = join('/tmp', `lock-${Math.random()}.lock`);
|
|
46
32
|
const processHandle = spawn('node', ['-e', `(${lockInProcess.toString()})(${JSON.stringify(filename)})`], {
|
|
47
|
-
stdio: '
|
|
33
|
+
stdio: 'inherit',
|
|
48
34
|
});
|
|
49
35
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
expect(data.toString().trim()).to.equal('locked');
|
|
36
|
+
// Wait for process to start
|
|
37
|
+
const trigger = new Trigger();
|
|
38
|
+
const intervalId = setInterval(() => {
|
|
39
|
+
if (existsSync(filename)) {
|
|
55
40
|
trigger.wake();
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
41
|
+
}
|
|
42
|
+
}, 100);
|
|
59
43
|
await trigger.wait({ timeout: 1_000 });
|
|
44
|
+
clearInterval(intervalId);
|
|
60
45
|
|
|
61
46
|
await expect(LockFile.acquire(filename)).to.be.rejected;
|
|
62
47
|
|
|
63
|
-
processHandle.stdin.write('close');
|
|
64
48
|
processHandle.kill();
|
|
65
49
|
|
|
66
50
|
// Wait for process to be killed
|
|
67
|
-
await
|
|
68
|
-
expect(await LockFile.isLocked(filename)).to.be.false;
|
|
69
|
-
});
|
|
51
|
+
await sleep(400);
|
|
70
52
|
|
|
71
53
|
const handle = await LockFile.acquire(filename);
|
|
72
54
|
await LockFile.release(handle);
|
|
73
55
|
});
|
|
74
|
-
|
|
75
|
-
test('spam with isLocked calls', async () => {
|
|
76
|
-
const checksNumber = 1000;
|
|
77
|
-
const filename = join('/tmp', `lock-${Math.random()}.lock`);
|
|
78
|
-
|
|
79
|
-
for (const _ of Array(checksNumber).keys()) {
|
|
80
|
-
const handle = await LockFile.acquire(filename);
|
|
81
|
-
expect(await LockFile.isLocked(filename)).to.be.true;
|
|
82
|
-
await LockFile.release(handle);
|
|
83
|
-
expect(await LockFile.isLocked(filename)).to.be.false;
|
|
84
|
-
}
|
|
85
|
-
});
|
|
86
56
|
});
|
|
87
57
|
|
|
88
58
|
// NOTE: Self-contained so when function.toString is called the code runs.
|
|
@@ -94,9 +64,6 @@ const lockInProcess = (filename: string) => {
|
|
|
94
64
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
95
65
|
const { flock } = require('fs-ext');
|
|
96
66
|
|
|
97
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
98
|
-
// @ts-ignore
|
|
99
|
-
let fileHandle;
|
|
100
67
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
101
68
|
// @ts-ignore
|
|
102
69
|
open(filename, constants.O_CREAT).then((handle) => {
|
|
@@ -104,23 +71,11 @@ const lockInProcess = (filename: string) => {
|
|
|
104
71
|
// @ts-ignore
|
|
105
72
|
flock(handle.fd, 'exnb', (err) => {
|
|
106
73
|
if (err) {
|
|
107
|
-
handle.close();
|
|
108
74
|
console.error(err);
|
|
109
75
|
return;
|
|
110
76
|
}
|
|
111
|
-
fileHandle = handle;
|
|
112
|
-
console.log('locked');
|
|
113
77
|
// Hang
|
|
114
78
|
setTimeout(() => {}, 1_000_000);
|
|
115
79
|
});
|
|
116
80
|
});
|
|
117
|
-
|
|
118
|
-
// Close file handle on stdin close.
|
|
119
|
-
process.stdin.on('data', (data) => {
|
|
120
|
-
if (data.toString().trim() === 'close') {
|
|
121
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
122
|
-
// @ts-ignore
|
|
123
|
-
fileHandle.close();
|
|
124
|
-
}
|
|
125
|
-
});
|
|
126
81
|
};
|
package/src/lock-file.ts
CHANGED
|
@@ -3,16 +3,16 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { flock } from 'fs-ext';
|
|
6
|
-
import {
|
|
6
|
+
import { constants } from 'node:fs';
|
|
7
|
+
import { open, FileHandle } from 'node:fs/promises';
|
|
7
8
|
|
|
8
9
|
export class LockFile {
|
|
9
10
|
static async acquire(filename: string): Promise<FileHandle> {
|
|
10
11
|
const handle = await open(filename, constants.O_CREAT);
|
|
11
12
|
await new Promise<void>((resolve, reject) => {
|
|
12
|
-
flock(handle.fd, 'exnb',
|
|
13
|
+
flock(handle.fd, 'exnb', (err) => {
|
|
13
14
|
if (err) {
|
|
14
15
|
reject(err);
|
|
15
|
-
await handle.close();
|
|
16
16
|
return;
|
|
17
17
|
}
|
|
18
18
|
resolve();
|