cross-process-lock 2.0.1 → 2.1.0
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/README.md +28 -18
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/index.js.map +1 -1
- package/lock.d.ts +12 -3
- package/lock.js +55 -43
- package/lock.js.map +1 -1
- package/metadata.js +11 -11
- package/metadata.js.map +1 -1
- package/package.json +37 -32
- package/unlock.d.ts +7 -2
- package/unlock.js +26 -18
- package/unlock.js.map +1 -1
- package/with.d.ts +23 -0
- package/with.js +25 -0
- package/with.js.map +1 -0
- package/CHANGELOG.md +0 -26
package/README.md
CHANGED
|
@@ -1,23 +1,22 @@
|
|
|
1
1
|
# cross-process-lock
|
|
2
2
|
|
|
3
|
+

|
|
4
|
+

|
|
5
|
+

|
|
6
|
+
|
|
3
7
|
Cross-process file locking solution with lock-queue
|
|
4
8
|
|
|
5
9
|
## Usage
|
|
6
10
|
|
|
7
11
|
``` javascript
|
|
8
|
-
const {
|
|
9
|
-
|
|
10
|
-
} = require('cross-process-lock');
|
|
11
|
-
const {
|
|
12
|
-
writeFileSync
|
|
13
|
-
} = require('fs');
|
|
12
|
+
const { lock } = require('cross-process-lock');
|
|
13
|
+
const { writeFileSync } = require('fs');
|
|
14
14
|
// create a lock for the given file
|
|
15
|
-
lock('file.txt')
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
});
|
|
15
|
+
const unlock = await lock('file.txt')
|
|
16
|
+
// do smth with the file here
|
|
17
|
+
writeFileSync('file.txt', 'some content', 'utf8');
|
|
18
|
+
// unlock file with the received function
|
|
19
|
+
return unlock();
|
|
21
20
|
```
|
|
22
21
|
|
|
23
22
|
## API
|
|
@@ -28,8 +27,8 @@ lock('file.txt').then(unlock => {
|
|
|
28
27
|
|
|
29
28
|
**Arguments**:
|
|
30
29
|
|
|
31
|
-
* `{string} file` - path of the file needs to be locked
|
|
32
|
-
* `{lockOptions} options` - options to use to lock file, e.g timeouts
|
|
30
|
+
* `{string} file` - the path of the file needs to be locked
|
|
31
|
+
* `{lockOptions} options` - the options to use to lock file, e.g timeouts
|
|
33
32
|
|
|
34
33
|
**Returns**: `Promise<Function>` - resolved with `unlock` function in case of successful lock; rejected in case of file couldn't be lock in the given timeout
|
|
35
34
|
|
|
@@ -39,16 +38,27 @@ lock('file.txt').then(unlock => {
|
|
|
39
38
|
|
|
40
39
|
**Arguments**:
|
|
41
40
|
|
|
42
|
-
* `{string} file` - path of the file needs to be unlocked
|
|
41
|
+
* `{string} file` - the path of the file needs to be unlocked
|
|
43
42
|
|
|
44
43
|
**Returns**: `Promise` - resolved in case of successful unlock or rejected in case of any error
|
|
45
44
|
|
|
45
|
+
### WithLock
|
|
46
|
+
|
|
47
|
+
`withLock(file[, options], callback)` - executes the callback with locking before and unlocking after the execution
|
|
48
|
+
|
|
49
|
+
**Arguments**:
|
|
50
|
+
* `{string} file` - path of the file needs to be locked
|
|
51
|
+
* `{lockOptions} options` - the options to use to lock file, e.g timeouts
|
|
52
|
+
* `{() => Promise<T>} callback` - the function to be executed
|
|
53
|
+
|
|
54
|
+
**Returns**: `Promise<T>` - resolved/rejected with the result of the callback
|
|
55
|
+
|
|
46
56
|
### lockOptions
|
|
47
57
|
|
|
48
|
-
| Option
|
|
49
|
-
|
|
58
|
+
| Option | Description | Default |
|
|
59
|
+
| :--------------------- | :--------------------------------------------- | :--------: |
|
|
50
60
|
| `lockTimeout {number}` | timeout (ms) when locks automatically released | 20 minutes |
|
|
51
|
-
| `waitTimeout {number}` | timeout (ms) until lock waits to lock a file
|
|
61
|
+
| `waitTimeout {number}` | timeout (ms) until lock waits to lock a file | 10 seconds |
|
|
52
62
|
|
|
53
63
|
## Debug
|
|
54
64
|
|
package/index.d.ts
CHANGED
package/index.js
CHANGED
|
@@ -3,4 +3,5 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
4
|
tslib_1.__exportStar(require("./lock"), exports);
|
|
5
5
|
tslib_1.__exportStar(require("./unlock"), exports);
|
|
6
|
+
tslib_1.__exportStar(require("./with"), exports);
|
|
6
7
|
//# sourceMappingURL=index.js.map
|
package/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,iDAAuB;AACvB,mDAAyB"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,iDAAuB;AACvB,mDAAyB;AACzB,iDAAuB"}
|
package/lock.d.ts
CHANGED
|
@@ -1,9 +1,18 @@
|
|
|
1
|
-
import { UnlockFunction } from "./unlock";
|
|
2
1
|
export interface LockOptions {
|
|
3
2
|
lockTimeout?: number;
|
|
4
3
|
waitTimeout?: number;
|
|
5
4
|
}
|
|
6
|
-
export declare type LockFunction = (file: string, options?: LockOptions) => Promise<UnlockFunction>;
|
|
7
5
|
export declare class LockError extends Error {
|
|
8
6
|
}
|
|
9
|
-
export
|
|
7
|
+
export type UnlockFunction = (file?: string) => Promise<void>;
|
|
8
|
+
/**
|
|
9
|
+
* Creates a cross-process lock for the given file, for the actual process.
|
|
10
|
+
*
|
|
11
|
+
* Note, that it will be only a soft-lock, the file will be locked for other
|
|
12
|
+
* instances of cross-process-lock, or processes using the same API for locking.
|
|
13
|
+
*
|
|
14
|
+
* @param file The path of the file to lock.
|
|
15
|
+
* @param options The lock options/timeout.
|
|
16
|
+
* @returns The function to unlock the file.
|
|
17
|
+
*/
|
|
18
|
+
export declare function lock(file: string, options?: LockOptions): Promise<UnlockFunction>;
|
package/lock.js
CHANGED
|
@@ -14,52 +14,64 @@ const INTERVAL = 500;
|
|
|
14
14
|
class LockError extends Error {
|
|
15
15
|
}
|
|
16
16
|
exports.LockError = LockError;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Creates a cross-process lock for the given file, for the actual process.
|
|
19
|
+
*
|
|
20
|
+
* Note, that it will be only a soft-lock, the file will be locked for other
|
|
21
|
+
* instances of cross-process-lock, or processes using the same API for locking.
|
|
22
|
+
*
|
|
23
|
+
* @param file The path of the file to lock.
|
|
24
|
+
* @param options The lock options/timeout.
|
|
25
|
+
* @returns The function to unlock the file.
|
|
26
|
+
*/
|
|
27
|
+
function lock(file, options = {}) {
|
|
28
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
29
|
+
options = Object.assign(Object.assign({}, DEFAULT_OPTIONS), options);
|
|
30
|
+
(0, logger_1.logger)("lock file:%s", file);
|
|
31
|
+
(0, logger_1.logger)("lock options:%o", options);
|
|
32
|
+
if (!(0, fs_1.existsSync)(file)) {
|
|
33
|
+
(0, logger_1.logger)("lock file does not exist");
|
|
34
|
+
throw new Error(`The given file (${file}) does not exist!`);
|
|
33
35
|
}
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
let def = Promise.resolve(null);
|
|
43
|
-
if (fs_1.existsSync(lockFile)) {
|
|
44
|
-
logger_1.logger("lock read metadata");
|
|
45
|
-
def = metadata_1.readMetadata(lockFile);
|
|
46
|
-
}
|
|
47
|
-
def.then((metadata) => {
|
|
48
|
-
const actual = Date.now();
|
|
49
|
-
const lockedTime = metadata ? actual - metadata.lockTime : -1;
|
|
50
|
-
logger_1.logger("lock metadata:%o", metadata);
|
|
51
|
-
logger_1.logger("lock actual:%d lockedTime:%d", actual, lockedTime);
|
|
52
|
-
if (!metadata || metadata.pID === process.pid || lockedTime > options.lockTimeout) {
|
|
53
|
-
logger_1.logger("lock locking");
|
|
54
|
-
metadata_1.saveMetadata(lockFile, lockTime).then(done, next);
|
|
36
|
+
const lockTime = Date.now();
|
|
37
|
+
const lockFile = `${file}.lock`;
|
|
38
|
+
const tryToLock = () => new Promise((resolve, reject) => {
|
|
39
|
+
const now = Date.now();
|
|
40
|
+
(0, logger_1.logger)("lock now:%d", now);
|
|
41
|
+
if (now - lockTime >= options.waitTimeout) {
|
|
42
|
+
(0, logger_1.logger)("lock too many tries");
|
|
43
|
+
return reject(new LockError(`Couldn't lock file (${file}) in the given timeout (${options.waitTimeout} ms)!`));
|
|
55
44
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
45
|
+
const done = () => resolve(unlock_1.unlock.bind(null, file));
|
|
46
|
+
const next = () => {
|
|
47
|
+
(0, logger_1.logger)("lock schedule");
|
|
48
|
+
setTimeout(() => {
|
|
49
|
+
(0, logger_1.logger)("lock schedule called");
|
|
50
|
+
tryToLock().then(done, reject);
|
|
51
|
+
}, INTERVAL);
|
|
52
|
+
};
|
|
53
|
+
let def = Promise.resolve(null);
|
|
54
|
+
if ((0, fs_1.existsSync)(lockFile)) {
|
|
55
|
+
(0, logger_1.logger)("lock read metadata");
|
|
56
|
+
def = (0, metadata_1.readMetadata)(lockFile);
|
|
59
57
|
}
|
|
60
|
-
|
|
58
|
+
def.then((metadata) => {
|
|
59
|
+
const actual = Date.now();
|
|
60
|
+
const lockedTime = metadata ? actual - metadata.lockTime : -1;
|
|
61
|
+
(0, logger_1.logger)("lock metadata:%o", metadata);
|
|
62
|
+
(0, logger_1.logger)("lock actual:%d lockedTime:%d", actual, lockedTime);
|
|
63
|
+
if (!metadata || metadata.pID === process.pid || lockedTime > options.lockTimeout) {
|
|
64
|
+
(0, logger_1.logger)("lock locking");
|
|
65
|
+
(0, metadata_1.saveMetadata)(lockFile, lockTime).then(done, next);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
(0, logger_1.logger)("lock next iteration");
|
|
69
|
+
next();
|
|
70
|
+
}
|
|
71
|
+
}, next);
|
|
72
|
+
});
|
|
73
|
+
return tryToLock();
|
|
61
74
|
});
|
|
62
|
-
|
|
63
|
-
});
|
|
75
|
+
}
|
|
64
76
|
exports.lock = lock;
|
|
65
77
|
//# sourceMappingURL=lock.js.map
|
package/lock.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lock.js","sourceRoot":"","sources":["../src/lock.ts"],"names":[],"mappings":";;;;AAAA,qCAAkC;AAClC,
|
|
1
|
+
{"version":3,"file":"lock.js","sourceRoot":"","sources":["../src/lock.ts"],"names":[],"mappings":"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"}
|
package/metadata.js
CHANGED
|
@@ -10,21 +10,21 @@ const logger_1 = require("./logger");
|
|
|
10
10
|
*/
|
|
11
11
|
const readMetadata = (file) => {
|
|
12
12
|
return new Promise((resolve, reject) => {
|
|
13
|
-
logger_1.logger("readMetadata file:%s", file);
|
|
14
|
-
fs_1.readFile(file, { encoding: "utf8" }, (err, data) => {
|
|
15
|
-
logger_1.logger("readMetadata err:%s", err);
|
|
16
|
-
logger_1.logger("readMetadata data:%O", data);
|
|
13
|
+
(0, logger_1.logger)("readMetadata file:%s", file);
|
|
14
|
+
(0, fs_1.readFile)(file, { encoding: "utf8" }, (err, data) => {
|
|
15
|
+
(0, logger_1.logger)("readMetadata err:%s", err);
|
|
16
|
+
(0, logger_1.logger)("readMetadata data:%O", data);
|
|
17
17
|
if (err) {
|
|
18
18
|
reject(err);
|
|
19
19
|
}
|
|
20
20
|
else {
|
|
21
21
|
try {
|
|
22
22
|
const parsed = JSON.parse(String(data));
|
|
23
|
-
logger_1.logger("readMetadata parsed:%O", parsed);
|
|
23
|
+
(0, logger_1.logger)("readMetadata parsed:%O", parsed);
|
|
24
24
|
resolve(parsed);
|
|
25
25
|
}
|
|
26
26
|
catch (e) {
|
|
27
|
-
logger_1.logger("readMetadata not JSON:%s", e);
|
|
27
|
+
(0, logger_1.logger)("readMetadata not JSON:%s", e);
|
|
28
28
|
resolve(null);
|
|
29
29
|
}
|
|
30
30
|
}
|
|
@@ -40,15 +40,15 @@ exports.readMetadata = readMetadata;
|
|
|
40
40
|
*/
|
|
41
41
|
const saveMetadata = (file, lockTime) => {
|
|
42
42
|
return new Promise((resolve, reject) => {
|
|
43
|
-
logger_1.logger("saveMetadata file:%s", file);
|
|
44
|
-
logger_1.logger("saveMetadata lockTime:%d", lockTime);
|
|
43
|
+
(0, logger_1.logger)("saveMetadata file:%s", file);
|
|
44
|
+
(0, logger_1.logger)("saveMetadata lockTime:%d", lockTime);
|
|
45
45
|
const metadata = {
|
|
46
46
|
pID: process.pid,
|
|
47
47
|
lockTime
|
|
48
48
|
};
|
|
49
|
-
logger_1.logger("saveMetadata metadata:%o", metadata);
|
|
50
|
-
fs_1.writeFile(file, JSON.stringify(metadata), { encoding: "utf8" }, (err) => {
|
|
51
|
-
logger_1.logger("saveMetadata done err:%o", err);
|
|
49
|
+
(0, logger_1.logger)("saveMetadata metadata:%o", metadata);
|
|
50
|
+
(0, fs_1.writeFile)(file, JSON.stringify(metadata), { encoding: "utf8" }, (err) => {
|
|
51
|
+
(0, logger_1.logger)("saveMetadata done err:%o", err);
|
|
52
52
|
if (err) {
|
|
53
53
|
reject(err);
|
|
54
54
|
}
|
package/metadata.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../src/metadata.ts"],"names":[],"mappings":";;;AAAA,2BAAyC;AACzC,qCAAkC;AAOlC;;;;GAIG;AACI,MAAM,YAAY,GAAG,CAAC,IAAY,EAAyB,EAAE;IAChE,OAAO,IAAI,OAAO,CAAe,CAAC,OAAO,EAAE,MAAM,EAAQ,EAAE;QACvD,eAAM,
|
|
1
|
+
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../src/metadata.ts"],"names":[],"mappings":";;;AAAA,2BAAyC;AACzC,qCAAkC;AAOlC;;;;GAIG;AACI,MAAM,YAAY,GAAG,CAAC,IAAY,EAAyB,EAAE;IAChE,OAAO,IAAI,OAAO,CAAe,CAAC,OAAO,EAAE,MAAM,EAAQ,EAAE;QACvD,IAAA,eAAM,EAAC,sBAAsB,EAAE,IAAI,CAAC,CAAC;QACrC,IAAA,aAAQ,EAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,CAAC,GAAU,EAAE,IAAY,EAAE,EAAE;YAC9D,IAAA,eAAM,EAAC,qBAAqB,EAAE,GAAG,CAAC,CAAA;YAClC,IAAA,eAAM,EAAC,sBAAsB,EAAE,IAAI,CAAC,CAAC;YACrC,IAAI,GAAG,EAAE;gBACL,MAAM,CAAC,GAAG,CAAC,CAAC;aACf;iBAAM;gBACH,IAAI;oBACA,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;oBACxC,IAAA,eAAM,EAAC,wBAAwB,EAAE,MAAM,CAAC,CAAC;oBACzC,OAAO,CAAC,MAAM,CAAC,CAAC;iBACnB;gBAAC,OAAO,CAAC,EAAE;oBACR,IAAA,eAAM,EAAC,0BAA0B,EAAE,CAAC,CAAC,CAAC;oBACtC,OAAO,CAAC,IAAI,CAAC,CAAC;iBACjB;aACJ;QACL,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACP,CAAC,CAAC;AApBW,QAAA,YAAY,gBAoBvB;AAEF;;;;;GAKG;AACI,MAAM,YAAY,GAAG,CAAC,IAAY,EAAE,QAAgB,EAAiB,EAAE;IAC1E,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACnC,IAAA,eAAM,EAAC,sBAAsB,EAAE,IAAI,CAAC,CAAA;QACpC,IAAA,eAAM,EAAC,0BAA0B,EAAE,QAAQ,CAAC,CAAC;QAC7C,MAAM,QAAQ,GAAiB;YAC3B,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,QAAQ;SACX,CAAC;QACF,IAAA,eAAM,EAAC,0BAA0B,EAAE,QAAQ,CAAC,CAAC;QAC7C,IAAA,cAAS,EACL,IAAI,EACJ,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EACxB,EAAE,QAAQ,EAAE,MAAM,EAAE,EACpB,CAAC,GAAU,EAAQ,EAAE;YACjB,IAAA,eAAM,EAAC,0BAA0B,EAAE,GAAG,CAAC,CAAC;YACxC,IAAI,GAAG,EAAE;gBACL,MAAM,CAAC,GAAG,CAAC,CAAC;aACf;iBAAM;gBACH,OAAO,EAAE,CAAC;aACb;QACL,CAAC,CACJ,CAAA;IACL,CAAC,CAAC,CAAC;AACP,CAAC,CAAC;AAvBW,QAAA,YAAY,gBAuBvB"}
|
package/package.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cross-process-lock",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Cross-process file locking solution with lock-queue",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"buildUpdate": "npm run compile && npm run copyToDist",
|
|
8
|
+
"build": "npm run buildUpdate && npm test && npm run docs",
|
|
9
|
+
"buildUpdate": "npm run clean && npm run compile && npm run copyToDist",
|
|
11
10
|
"copyToDist": "copyfiles -f *.txt *.md package.json dist",
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
11
|
+
"docs": "typedoc --out ./docs ./src && touch ./docs/.nojekyll",
|
|
12
|
+
"clean": "rimraf ./dist ./docs ./reports ./coverage",
|
|
13
|
+
"test": "dotenv-ng --var JEST_JUNIT_OUTPUT_DIR=./reports -- jest --coverage",
|
|
14
|
+
"lint": "eslint . --ext .ts --fix",
|
|
15
|
+
"compile": "tsc && npm run lint"
|
|
16
16
|
},
|
|
17
17
|
"repository": {
|
|
18
18
|
"type": "git",
|
|
@@ -29,34 +29,41 @@
|
|
|
29
29
|
},
|
|
30
30
|
"homepage": "https://github.com/szikszail/cross-process-lock#readme",
|
|
31
31
|
"files": [
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
32
|
+
"**/*.js",
|
|
33
|
+
"**/*.d.ts",
|
|
34
|
+
"**/*.js.map"
|
|
35
35
|
],
|
|
36
36
|
"engines": {
|
|
37
|
-
"node": ">=
|
|
37
|
+
"node": ">=14.0.0"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"
|
|
41
|
-
"
|
|
40
|
+
"tslib": "^2.5.0",
|
|
41
|
+
"debug": "^4.3.4"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
|
-
"@types/debug": "^4.1.
|
|
45
|
-
"@types/jest": "^
|
|
46
|
-
"@types/node": "^
|
|
44
|
+
"@types/debug": "^4.1.7",
|
|
45
|
+
"@types/jest": "^29.4.0",
|
|
46
|
+
"@types/node": "^18.13.0",
|
|
47
|
+
"@typescript-eslint/eslint-plugin": "^5.52.0",
|
|
48
|
+
"@typescript-eslint/parser": "^5.52.0",
|
|
47
49
|
"copyfiles": "^2.4.1",
|
|
48
|
-
"
|
|
49
|
-
"jest": "^
|
|
50
|
-
"jest-junit": "^
|
|
50
|
+
"dotenv-ng": "^1.1.3",
|
|
51
|
+
"jest": "^29.4.2",
|
|
52
|
+
"jest-junit": "^15.0.0",
|
|
51
53
|
"proxyquire": "^2.1.3",
|
|
52
|
-
"rimraf": "^
|
|
53
|
-
"sinon": "^
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"
|
|
54
|
+
"rimraf": "^4.1.2",
|
|
55
|
+
"sinon": "^15.0.1",
|
|
56
|
+
"eslint": "^8.34.0",
|
|
57
|
+
"ts-jest": "^29.0.5",
|
|
58
|
+
"typedoc": "^0.23.25",
|
|
59
|
+
"typescript": "^4.9.5",
|
|
60
|
+
"yargs": "^17.6.2"
|
|
58
61
|
},
|
|
59
62
|
"jest": {
|
|
63
|
+
"reporters": [
|
|
64
|
+
"default",
|
|
65
|
+
"jest-junit"
|
|
66
|
+
],
|
|
60
67
|
"transform": {
|
|
61
68
|
"^.+\\.ts?$": "ts-jest"
|
|
62
69
|
},
|
|
@@ -68,16 +75,14 @@
|
|
|
68
75
|
"/node_modules/",
|
|
69
76
|
"dist"
|
|
70
77
|
],
|
|
71
|
-
"
|
|
72
|
-
"
|
|
73
|
-
|
|
78
|
+
"coverageDirectory": "./coverage",
|
|
79
|
+
"collectCoverageFrom": [
|
|
80
|
+
"./src/**/*.ts"
|
|
81
|
+
],
|
|
74
82
|
"moduleFileExtensions": [
|
|
75
83
|
"ts",
|
|
76
84
|
"js"
|
|
77
85
|
],
|
|
78
|
-
"collectCoverageFrom": [
|
|
79
|
-
"src/*.ts"
|
|
80
|
-
],
|
|
81
86
|
"coverageThreshold": {
|
|
82
87
|
"global": {
|
|
83
88
|
"branches": 85,
|
package/unlock.d.ts
CHANGED
|
@@ -1,2 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Releases the cross-process lock for the given file, for the actual process.
|
|
3
|
+
*
|
|
4
|
+
* @param file The path of the file to lock.
|
|
5
|
+
* @returns
|
|
6
|
+
*/
|
|
7
|
+
export declare function unlock(file: string): Promise<void>;
|
package/unlock.js
CHANGED
|
@@ -5,25 +5,33 @@ const tslib_1 = require("tslib");
|
|
|
5
5
|
const fs_1 = require("fs");
|
|
6
6
|
const logger_1 = require("./logger");
|
|
7
7
|
const metadata_1 = require("./metadata");
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Releases the cross-process lock for the given file, for the actual process.
|
|
10
|
+
*
|
|
11
|
+
* @param file The path of the file to lock.
|
|
12
|
+
* @returns
|
|
13
|
+
*/
|
|
14
|
+
function unlock(file) {
|
|
15
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
16
|
+
(0, logger_1.logger)("unlock file:%s", file);
|
|
17
|
+
const lockFile = `${file}.lock`;
|
|
18
|
+
if (!(0, fs_1.existsSync)(lockFile)) {
|
|
19
|
+
(0, logger_1.logger)("unlock lock file does not exist");
|
|
20
|
+
return;
|
|
19
21
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
const metadata = yield (0, metadata_1.readMetadata)(lockFile);
|
|
23
|
+
if (!metadata || metadata.pID === process.pid) {
|
|
24
|
+
try {
|
|
25
|
+
(0, fs_1.unlinkSync)(lockFile);
|
|
26
|
+
}
|
|
27
|
+
catch (e) {
|
|
28
|
+
(0, logger_1.logger)("unlock error during deleting lock file:%s", e);
|
|
29
|
+
}
|
|
22
30
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
}
|
|
31
|
+
else {
|
|
32
|
+
(0, logger_1.logger)("unlock foreign lock file");
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
}
|
|
28
36
|
exports.unlock = unlock;
|
|
29
37
|
//# sourceMappingURL=unlock.js.map
|
package/unlock.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unlock.js","sourceRoot":"","sources":["../src/unlock.ts"],"names":[],"mappings":";;;;AAAA,2BAA4C;AAC5C,qCAAkC;AAClC,yCAAwD;
|
|
1
|
+
{"version":3,"file":"unlock.js","sourceRoot":"","sources":["../src/unlock.ts"],"names":[],"mappings":";;;;AAAA,2BAA4C;AAC5C,qCAAkC;AAClC,yCAAwD;AAExD;;;;;GAKG;AACH,SAAsB,MAAM,CAAC,IAAY;;QACrC,IAAA,eAAM,EAAC,gBAAgB,EAAE,IAAI,CAAC,CAAC;QAE/B,MAAM,QAAQ,GAAG,GAAG,IAAI,OAAO,CAAC;QAEhC,IAAI,CAAC,IAAA,eAAU,EAAC,QAAQ,CAAC,EAAE;YACvB,IAAA,eAAM,EAAC,iCAAiC,CAAC,CAAC;YAC1C,OAAO;SACV;QAED,MAAM,QAAQ,GAAiB,MAAM,IAAA,uBAAY,EAAC,QAAQ,CAAC,CAAC;QAC5D,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,GAAG,KAAK,OAAO,CAAC,GAAG,EAAE;YAC3C,IAAI;gBACA,IAAA,eAAU,EAAC,QAAQ,CAAC,CAAC;aACxB;YAAC,OAAO,CAAC,EAAE;gBACR,IAAA,eAAM,EAAC,2CAA2C,EAAE,CAAC,CAAC,CAAC;aAC1D;SACJ;aAAM;YACH,IAAA,eAAM,EAAC,0BAA0B,CAAC,CAAC;SACtC;IACL,CAAC;CAAA;AApBD,wBAoBC"}
|
package/with.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { LockOptions } from "./lock";
|
|
2
|
+
export type LockCallback<T> = () => Promise<T>;
|
|
3
|
+
/**
|
|
4
|
+
* Executes the callback with locking the given file before,
|
|
5
|
+
* and releasing it after the callback is executed.
|
|
6
|
+
*
|
|
7
|
+
* Generally, the callback/operation should target the file locked.
|
|
8
|
+
*
|
|
9
|
+
* @param file The path of the file to lock.
|
|
10
|
+
* @param callback The function to execute while the file is locked.
|
|
11
|
+
*/
|
|
12
|
+
export declare function withLock<T>(file: string, callback: LockCallback<T>): Promise<T>;
|
|
13
|
+
/**
|
|
14
|
+
* Executes the callback with locking the given file before,
|
|
15
|
+
* and releasing it after the callback is executed.
|
|
16
|
+
*
|
|
17
|
+
* Generally, the callback/operation should target the file locked.
|
|
18
|
+
*
|
|
19
|
+
* @param file The path of the file to lock.
|
|
20
|
+
* @param options The lock options/timeout.
|
|
21
|
+
* @param callback The function to execute while the file is locked.
|
|
22
|
+
*/
|
|
23
|
+
export declare function withLock<T>(file: string, options: LockOptions, callback: LockCallback<T>): Promise<T>;
|
package/with.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.withLock = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const lock_1 = require("./lock");
|
|
6
|
+
function withLock(file, options, callback) {
|
|
7
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
8
|
+
if (typeof options === "function") {
|
|
9
|
+
callback = options;
|
|
10
|
+
options = {};
|
|
11
|
+
}
|
|
12
|
+
if (typeof callback !== "function") {
|
|
13
|
+
throw new TypeError("Callback function must be set!");
|
|
14
|
+
}
|
|
15
|
+
const unlock = yield (0, lock_1.lock)(file, options);
|
|
16
|
+
try {
|
|
17
|
+
return callback();
|
|
18
|
+
}
|
|
19
|
+
finally {
|
|
20
|
+
yield unlock();
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
exports.withLock = withLock;
|
|
25
|
+
//# sourceMappingURL=with.js.map
|
package/with.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"with.js","sourceRoot":"","sources":["../src/with.ts"],"names":[],"mappings":";;;;AAAA,iCAA2C;AAyB3C,SAAsB,QAAQ,CAAI,IAAY,EAAE,OAAsC,EAAE,QAA0B;;QAC9G,IAAI,OAAO,OAAO,KAAK,UAAU,EAAE;YAC/B,QAAQ,GAAG,OAAO,CAAC;YACnB,OAAO,GAAG,EAAE,CAAC;SAChB;QACD,IAAI,OAAO,QAAQ,KAAK,UAAU,EAAE;YAChC,MAAM,IAAI,SAAS,CAAC,gCAAgC,CAAC,CAAC;SACzD;QACD,MAAM,MAAM,GAAG,MAAM,IAAA,WAAI,EAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACzC,IAAI;YACA,OAAO,QAAQ,EAAE,CAAC;SACrB;gBAAS;YACN,MAAM,MAAM,EAAE,CAAC;SAClB;IACL,CAAC;CAAA;AAdD,4BAcC"}
|
package/CHANGELOG.md
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
# cross-process-lock
|
|
2
|
-
|
|
3
|
-
## 2.0.1
|
|
4
|
-
|
|
5
|
-
### Fixed
|
|
6
|
-
|
|
7
|
-
* Added `tslib`
|
|
8
|
-
* Fixed default timeouts
|
|
9
|
-
|
|
10
|
-
## 2.0.0
|
|
11
|
-
|
|
12
|
-
### Changed
|
|
13
|
-
|
|
14
|
-
* Refactored to TypeScript
|
|
15
|
-
* Replaced log4js logger with debug
|
|
16
|
-
|
|
17
|
-
## 1.0.0
|
|
18
|
-
|
|
19
|
-
### Added
|
|
20
|
-
|
|
21
|
-
* Added lock and unlock methods
|
|
22
|
-
* Added tests and documentation
|
|
23
|
-
|
|
24
|
-
## 0.0.1
|
|
25
|
-
|
|
26
|
-
Initial development release
|