@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.
@@ -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, import_promises.constants.O_CREAT);
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", async (err) => {
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, constants } 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', async (err) => {\n if (err) {\n reject(err);\n await handle.close();\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,sBAA4C;AAErC,IAAMA,WAAN,MAAMA,UAAAA;EACX,aAAaC,QAAQC,UAAuC;AAC1D,UAAMC,SAAS,UAAMC,sBAAKF,UAAUG,0BAAUC,OAAO;AACrD,UAAM,IAAIC,QAAc,CAACC,SAASC,WAAAA;AAChCC,+BAAMP,OAAOQ,IAAI,QAAQ,OAAOC,QAAAA;AAC9B,YAAIA,KAAK;AACPH,iBAAOG,GAAAA;AACP,gBAAMT,OAAOU,MAAK;AAClB;QACF;AACAL,gBAAAA;MACF,CAAA;IACF,CAAA;AACA,WAAOL;EACT;EAEA,aAAaW,QAAQX,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,OAAOU,MAAK;EACpB;EAEA,aAAaE,SAASb,UAAoC;AACxD,QAAI;AACF,YAAMC,SAAS,MAAMH,UAASC,QAAQC,QAAAA;AACtC,YAAMF,UAASc,QAAQX,MAAAA;AACvB,YAAMA,OAAOU,MAAK;AAElB,aAAO;IACT,SAASG,GAAG;AACV,aAAO;IACT;EACF;AACF;",
6
- "names": ["LockFile", "acquire", "filename", "handle", "open", "constants", "O_CREAT", "Promise", "resolve", "reject", "flock", "fd", "err", "close", "release", "isLocked", "e"]
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
  }
@@ -1 +1 @@
1
- {"inputs":{"packages/common/lock-file/src/lock-file.ts":{"bytes":4154,"imports":[{"path":"fs-ext","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":2274},"packages/common/lock-file/dist/lib/node/index.cjs":{"imports":[{"path":"fs-ext","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":1042}},"bytes":2189}}}
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":";AAKA,OAAO,EAAQ,UAAU,EAAa,MAAM,kBAAkB,CAAC;AAE/D,qBAAa,QAAQ;WACN,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;WAe9C,OAAO,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;WAa1C,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAW1D"}
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.59c38c1",
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.59c38c1",
18
- "@dxos/log": "0.1.58-main.59c38c1",
19
- "@dxos/node-std": "0.1.58-main.59c38c1"
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",
@@ -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, mkdirSync, unlinkSync } from 'node:fs';
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 { afterTest, beforeAll, describe, test } from '@dxos/test';
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 exits', async () => {
38
- const filename = join(TEST_DIR, `lock-${Math.random()}.lock`);
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: 'pipe',
33
+ stdio: 'inherit',
48
34
  });
49
35
 
50
- {
51
- // Wait for process to start
52
-
53
- processHandle.stdout.on('data', (data: Uint8Array) => {
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 waitForExpect(async () => {
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 { open, FileHandle, constants } from 'node:fs/promises';
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', async (err) => {
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();