@lakutata/mutex 0.0.0-stage → 3.0.0-beta.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/LICENSE +23 -0
- package/README.md +212 -2
- package/dist/cjs/exports/Mutex.d.ts +18 -0
- package/dist/cjs/exports/Mutex.js +37 -0
- package/dist/cjs/mutex/Mutex.d.ts +265 -0
- package/dist/cjs/mutex/Mutex.js +403 -0
- package/dist/cjs/mutex/MutexLock.d.ts +91 -0
- package/dist/cjs/mutex/MutexLock.js +113 -0
- package/dist/cjs/mutex/Synchronized.d.ts +90 -0
- package/dist/cjs/mutex/Synchronized.js +93 -0
- package/dist/cjs/mutex/drivers/FileMutexDriver.d.ts +115 -0
- package/dist/cjs/mutex/drivers/FileMutexDriver.js +230 -0
- package/dist/cjs/mutex/drivers/MemoryMutexDriver.d.ts +60 -0
- package/dist/cjs/mutex/drivers/MemoryMutexDriver.js +95 -0
- package/dist/cjs/mutex/drivers/MutexDriver.d.ts +82 -0
- package/dist/cjs/mutex/drivers/MutexDriver.js +38 -0
- package/dist/cjs/mutex/drivers/MysqlMutexDriver.d.ts +135 -0
- package/dist/cjs/mutex/drivers/MysqlMutexDriver.js +244 -0
- package/dist/cjs/mutex/drivers/PostgresMutexDriver.d.ts +136 -0
- package/dist/cjs/mutex/drivers/PostgresMutexDriver.js +230 -0
- package/dist/cjs/mutex/drivers/RedisMutexDriver.d.ts +129 -0
- package/dist/cjs/mutex/drivers/RedisMutexDriver.js +180 -0
- package/dist/cjs/mutex/exceptions/MutexDriverException.d.ts +12 -0
- package/dist/cjs/mutex/exceptions/MutexDriverException.js +19 -0
- package/dist/cjs/mutex/exceptions/MutexDriverNotFoundException.d.ts +12 -0
- package/dist/cjs/mutex/exceptions/MutexDriverNotFoundException.js +19 -0
- package/dist/cjs/mutex/exceptions/MutexLostException.d.ts +13 -0
- package/dist/cjs/mutex/exceptions/MutexLostException.js +20 -0
- package/dist/cjs/mutex/exceptions/MutexTimeoutException.d.ts +16 -0
- package/dist/cjs/mutex/exceptions/MutexTimeoutException.js +23 -0
- package/dist/cjs/mutex/lib/LoadDriver.d.ts +6 -0
- package/dist/cjs/mutex/lib/LoadDriver.js +64 -0
- package/dist/cjs/mutex/lib/Names.d.ts +14 -0
- package/dist/cjs/mutex/lib/Names.js +26 -0
- package/dist/cjs/mutex/options/FileMutexOptions.d.ts +33 -0
- package/dist/cjs/mutex/options/FileMutexOptions.js +45 -0
- package/dist/cjs/mutex/options/MemoryMutexOptions.d.ts +27 -0
- package/dist/cjs/mutex/options/MemoryMutexOptions.js +41 -0
- package/dist/cjs/mutex/options/MysqlMutexOptions.d.ts +70 -0
- package/dist/cjs/mutex/options/MysqlMutexOptions.js +77 -0
- package/dist/cjs/mutex/options/PostgresMutexOptions.d.ts +83 -0
- package/dist/cjs/mutex/options/PostgresMutexOptions.js +89 -0
- package/dist/cjs/mutex/options/RedisMutexOptions.d.ts +71 -0
- package/dist/cjs/mutex/options/RedisMutexOptions.js +77 -0
- package/dist/cjs/package.json +1 -0
- package/dist/esm/exports/Mutex.js +18 -0
- package/dist/esm/mutex/Mutex.js +397 -0
- package/dist/esm/mutex/MutexLock.js +109 -0
- package/dist/esm/mutex/Synchronized.js +89 -0
- package/dist/esm/mutex/drivers/FileMutexDriver.js +223 -0
- package/dist/esm/mutex/drivers/MemoryMutexDriver.js +91 -0
- package/dist/esm/mutex/drivers/MutexDriver.js +34 -0
- package/dist/esm/mutex/drivers/MysqlMutexDriver.js +240 -0
- package/dist/esm/mutex/drivers/PostgresMutexDriver.js +226 -0
- package/dist/esm/mutex/drivers/RedisMutexDriver.js +176 -0
- package/dist/esm/mutex/exceptions/MutexDriverException.js +15 -0
- package/dist/esm/mutex/exceptions/MutexDriverNotFoundException.js +15 -0
- package/dist/esm/mutex/exceptions/MutexLostException.js +16 -0
- package/dist/esm/mutex/exceptions/MutexTimeoutException.js +19 -0
- package/dist/esm/mutex/lib/LoadDriver.js +28 -0
- package/dist/esm/mutex/lib/Names.js +21 -0
- package/dist/esm/mutex/options/FileMutexOptions.js +41 -0
- package/dist/esm/mutex/options/MemoryMutexOptions.js +37 -0
- package/dist/esm/mutex/options/MysqlMutexOptions.js +73 -0
- package/dist/esm/mutex/options/PostgresMutexOptions.js +85 -0
- package/dist/esm/mutex/options/RedisMutexOptions.js +73 -0
- package/dist/types/exports/Mutex.d.ts +18 -0
- package/dist/types/mutex/Mutex.d.ts +265 -0
- package/dist/types/mutex/MutexLock.d.ts +91 -0
- package/dist/types/mutex/Synchronized.d.ts +90 -0
- package/dist/types/mutex/drivers/FileMutexDriver.d.ts +115 -0
- package/dist/types/mutex/drivers/MemoryMutexDriver.d.ts +60 -0
- package/dist/types/mutex/drivers/MutexDriver.d.ts +82 -0
- package/dist/types/mutex/drivers/MysqlMutexDriver.d.ts +135 -0
- package/dist/types/mutex/drivers/PostgresMutexDriver.d.ts +136 -0
- package/dist/types/mutex/drivers/RedisMutexDriver.d.ts +129 -0
- package/dist/types/mutex/exceptions/MutexDriverException.d.ts +12 -0
- package/dist/types/mutex/exceptions/MutexDriverNotFoundException.d.ts +12 -0
- package/dist/types/mutex/exceptions/MutexLostException.d.ts +13 -0
- package/dist/types/mutex/exceptions/MutexTimeoutException.d.ts +16 -0
- package/dist/types/mutex/lib/LoadDriver.d.ts +6 -0
- package/dist/types/mutex/lib/Names.d.ts +14 -0
- package/dist/types/mutex/options/FileMutexOptions.d.ts +33 -0
- package/dist/types/mutex/options/MemoryMutexOptions.d.ts +27 -0
- package/dist/types/mutex/options/MysqlMutexOptions.d.ts +70 -0
- package/dist/types/mutex/options/PostgresMutexOptions.d.ts +83 -0
- package/dist/types/mutex/options/RedisMutexOptions.d.ts +71 -0
- package/package.json +57 -4
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { DTO } from '@lakutata/core';
|
|
2
|
+
/**
|
|
3
|
+
* The options of the MySQL driver ({@link MysqlMutexDriver}), for MySQL or MariaDB: the locks are shared by every
|
|
4
|
+
* instance connected to the same server. It needs the optional peer dependency `mysql2` (`npm install mysql2`, 3):
|
|
5
|
+
* without it, the first acquisition fails with {@link MutexDriverNotFoundException}. The driver connects at the first
|
|
6
|
+
* acquisition, not when the component is created.
|
|
7
|
+
*
|
|
8
|
+
* In the `'advisory'` mode (the default), the locks are named locks (`GET_LOCK`) of one connection: they do not expire,
|
|
9
|
+
* MySQL releases them when the connection closes (a crashed process frees them at once), and they are all lost when it
|
|
10
|
+
* closes or fails. They have no fencing token, and are not replicated by the clusters (Galera, Group Replication): every
|
|
11
|
+
* holder must connect to the same server. In the `'table'` mode, the locks are rows of a table created at the first use:
|
|
12
|
+
* they expire after their `ttl` unless renewed, work through the poolers and the clusters, and carry fencing tokens.
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* import {Application} from 'lakutata'
|
|
16
|
+
* import {Mutex} from 'lakutata/com/mutex'
|
|
17
|
+
*
|
|
18
|
+
* Application.run(() => ({
|
|
19
|
+
* id: 'mysql-mutex.app',
|
|
20
|
+
* name: 'MysqlMutex',
|
|
21
|
+
* components: {
|
|
22
|
+
* mutex: {
|
|
23
|
+
* class: Mutex,
|
|
24
|
+
* driver: {type: 'mysql', host: 'db', database: 'app', username: 'app', password: process.env.DB_PASSWORD ?? ''}
|
|
25
|
+
* }
|
|
26
|
+
* }
|
|
27
|
+
* }))
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export declare class MysqlMutexOptions extends DTO {
|
|
31
|
+
/**
|
|
32
|
+
* The driver type: `'mysql'`.
|
|
33
|
+
*/
|
|
34
|
+
type: 'mysql';
|
|
35
|
+
/**
|
|
36
|
+
* The host name or IP address of the server.
|
|
37
|
+
*/
|
|
38
|
+
host: string;
|
|
39
|
+
/**
|
|
40
|
+
* The port of the server.
|
|
41
|
+
* @default 3306
|
|
42
|
+
*/
|
|
43
|
+
port?: number;
|
|
44
|
+
/**
|
|
45
|
+
* The database holding the table of the `table` mode (the named locks are global to the server).
|
|
46
|
+
*/
|
|
47
|
+
database: string;
|
|
48
|
+
/**
|
|
49
|
+
* The user name.
|
|
50
|
+
*/
|
|
51
|
+
username: string;
|
|
52
|
+
/**
|
|
53
|
+
* The password (`''` for none).
|
|
54
|
+
*/
|
|
55
|
+
password: string;
|
|
56
|
+
/**
|
|
57
|
+
* How the locks are held: `'advisory'`, named locks of one connection, released when it closes (no expiration, no
|
|
58
|
+
* fencing token, not replicated by the clusters); `'table'`, rows of a table expiring unless renewed, with fencing
|
|
59
|
+
* tokens, through the poolers and the clusters.
|
|
60
|
+
* @default 'advisory'
|
|
61
|
+
*/
|
|
62
|
+
mode?: 'advisory' | 'table';
|
|
63
|
+
/**
|
|
64
|
+
* The table of the `table` mode, in the connection's database, created at the first use with its counter table
|
|
65
|
+
* `<table>_fence`; a name of letters, digits and `_`. An invalid name fails the validation of the options
|
|
66
|
+
* (`InvalidValueException`).
|
|
67
|
+
* @default 'lakutata_mutex'
|
|
68
|
+
*/
|
|
69
|
+
table?: string;
|
|
70
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { DTO } from '@lakutata/core';
|
|
2
|
+
/**
|
|
3
|
+
* The options of the PostgreSQL driver ({@link PostgresMutexDriver}): the locks are shared by every instance connected
|
|
4
|
+
* to the same database. It needs the optional peer dependency `pg` (`npm install pg`, 8): without it, the first
|
|
5
|
+
* acquisition fails with {@link MutexDriverNotFoundException}. The driver connects at the first acquisition, not when
|
|
6
|
+
* the component is created.
|
|
7
|
+
*
|
|
8
|
+
* In the `'advisory'` mode (the default), the locks are session advisory locks of one connection: they do not expire,
|
|
9
|
+
* PostgreSQL releases them when the connection closes (a crashed process frees them at once), and they are all lost
|
|
10
|
+
* when it closes or fails. They have no fencing token, and do not work through a pooler in transaction mode
|
|
11
|
+
* (PgBouncer). In the `'table'` mode, the locks are rows of a table created at the first use: they expire after their
|
|
12
|
+
* `ttl` unless renewed, work through the poolers, and carry fencing tokens.
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* import {Application} from 'lakutata'
|
|
16
|
+
* import {Mutex} from 'lakutata/com/mutex'
|
|
17
|
+
*
|
|
18
|
+
* Application.run(() => ({
|
|
19
|
+
* id: 'postgres-mutex.app',
|
|
20
|
+
* name: 'PostgresMutex',
|
|
21
|
+
* components: {
|
|
22
|
+
* mutex: {
|
|
23
|
+
* class: Mutex,
|
|
24
|
+
* driver: {
|
|
25
|
+
* type: 'postgres',
|
|
26
|
+
* host: 'db',
|
|
27
|
+
* database: 'app',
|
|
28
|
+
* username: 'app',
|
|
29
|
+
* password: process.env.DB_PASSWORD ?? '',
|
|
30
|
+
* //Through PgBouncer: rows of a table, with fencing tokens
|
|
31
|
+
* mode: 'table'
|
|
32
|
+
* }
|
|
33
|
+
* }
|
|
34
|
+
* }
|
|
35
|
+
* }))
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export declare class PostgresMutexOptions extends DTO {
|
|
39
|
+
/**
|
|
40
|
+
* The driver type: `'postgres'`.
|
|
41
|
+
*/
|
|
42
|
+
type: 'postgres';
|
|
43
|
+
/**
|
|
44
|
+
* The host name or IP address of the server.
|
|
45
|
+
*/
|
|
46
|
+
host: string;
|
|
47
|
+
/**
|
|
48
|
+
* The port of the server.
|
|
49
|
+
* @default 5432
|
|
50
|
+
*/
|
|
51
|
+
port?: number;
|
|
52
|
+
/**
|
|
53
|
+
* The database holding the locks (and the table of the `table` mode).
|
|
54
|
+
*/
|
|
55
|
+
database: string;
|
|
56
|
+
/**
|
|
57
|
+
* The user name.
|
|
58
|
+
*/
|
|
59
|
+
username: string;
|
|
60
|
+
/**
|
|
61
|
+
* The password (`''` for none).
|
|
62
|
+
*/
|
|
63
|
+
password: string;
|
|
64
|
+
/**
|
|
65
|
+
* Whether to connect with TLS (`ssl: true` given to `pg`, which verifies the server certificate).
|
|
66
|
+
* @default false
|
|
67
|
+
*/
|
|
68
|
+
ssl?: boolean;
|
|
69
|
+
/**
|
|
70
|
+
* How the locks are held: `'advisory'`, session advisory locks of one connection, released when it closes (no
|
|
71
|
+
* expiration, no fencing token, not through a transaction pooler); `'table'`, rows of a table expiring unless renewed,
|
|
72
|
+
* with fencing tokens, through the poolers.
|
|
73
|
+
* @default 'advisory'
|
|
74
|
+
*/
|
|
75
|
+
mode?: 'advisory' | 'table';
|
|
76
|
+
/**
|
|
77
|
+
* The table of the `table` mode, created at the first use with its sequence `<table>_fence`; a name of letters,
|
|
78
|
+
* digits and `_`, optionally qualified by its schema (`locks.mutex`). An invalid name fails the validation of the options
|
|
79
|
+
* (`InvalidValueException`).
|
|
80
|
+
* @default 'lakutata_mutex'
|
|
81
|
+
*/
|
|
82
|
+
table?: string;
|
|
83
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { DTO } from '@lakutata/core';
|
|
2
|
+
/**
|
|
3
|
+
* The options of the Redis driver ({@link RedisMutexDriver}): the locks are Redis keys shared by every instance
|
|
4
|
+
* connected to the same server or cluster. It needs the optional peer dependency `redis` (`npm install redis`, 4.6 or
|
|
5
|
+
* 5): without it, the first acquisition fails with {@link MutexDriverNotFoundException}. The keys expire after their
|
|
6
|
+
* `ttl` unless renewed, and each acquisition gets a fencing token. Configure the server with
|
|
7
|
+
* `maxmemory-policy noeviction`: an evicted key is a lock lost.
|
|
8
|
+
*
|
|
9
|
+
* The client connects at the first acquisition, not when the component is created. While the server cannot be reached,
|
|
10
|
+
* the calls wait for it instead of failing.
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* import {Application} from 'lakutata'
|
|
14
|
+
* import {Mutex} from 'lakutata/com/mutex'
|
|
15
|
+
*
|
|
16
|
+
* Application.run(() => ({
|
|
17
|
+
* id: 'redis-mutex.app',
|
|
18
|
+
* name: 'RedisMutex',
|
|
19
|
+
* components: {
|
|
20
|
+
* mutex: {
|
|
21
|
+
* class: Mutex,
|
|
22
|
+
* driver: {type: 'redis', host: '127.0.0.1', port: 6379, password: process.env.REDIS_PASSWORD},
|
|
23
|
+
* //The applications sharing this Redis server keep their locks apart
|
|
24
|
+
* prefix: 'billing:mutex:'
|
|
25
|
+
* }
|
|
26
|
+
* }
|
|
27
|
+
* }))
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export declare class RedisMutexOptions extends DTO {
|
|
31
|
+
/**
|
|
32
|
+
* The driver type: `'redis'`.
|
|
33
|
+
*/
|
|
34
|
+
type: 'redis';
|
|
35
|
+
/**
|
|
36
|
+
* The server URL (`redis://user:password@host:6379/0`, `rediss://` for TLS). When set, `host`, `port` and `tls` are
|
|
37
|
+
* ignored; `username`, `password` and `database` apply when the URL does not give them.
|
|
38
|
+
* @default none
|
|
39
|
+
*/
|
|
40
|
+
url?: string;
|
|
41
|
+
/**
|
|
42
|
+
* The host name or IP address of the server (without a `url`).
|
|
43
|
+
* @default '127.0.0.1'
|
|
44
|
+
*/
|
|
45
|
+
host?: string;
|
|
46
|
+
/**
|
|
47
|
+
* The port of the server (without a `url`).
|
|
48
|
+
* @default 6379
|
|
49
|
+
*/
|
|
50
|
+
port?: number;
|
|
51
|
+
/**
|
|
52
|
+
* The index of the Redis database.
|
|
53
|
+
* @default 0
|
|
54
|
+
*/
|
|
55
|
+
database?: number;
|
|
56
|
+
/**
|
|
57
|
+
* The user name (Redis 6 ACL).
|
|
58
|
+
* @default none (the default user)
|
|
59
|
+
*/
|
|
60
|
+
username?: string;
|
|
61
|
+
/**
|
|
62
|
+
* The password.
|
|
63
|
+
* @default none
|
|
64
|
+
*/
|
|
65
|
+
password?: string;
|
|
66
|
+
/**
|
|
67
|
+
* Whether to connect with TLS (without a `url`).
|
|
68
|
+
* @default false
|
|
69
|
+
*/
|
|
70
|
+
tls?: boolean;
|
|
71
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,59 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lakutata/mutex",
|
|
3
|
-
"version": "0.0.0
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "3.0.0-beta.0",
|
|
4
|
+
"description": "The locks of the lakutata framework: mutual exclusion between the instances and the processes of an application, over memory, files, Redis, PostgreSQL or MySQL, held by tokens, renewed while they are held.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/cjs/exports/Mutex.js",
|
|
7
|
+
"types": "./dist/cjs/exports/Mutex.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": {
|
|
11
|
+
"types": "./dist/types/exports/Mutex.d.ts",
|
|
12
|
+
"default": "./dist/esm/exports/Mutex.js"
|
|
13
|
+
},
|
|
14
|
+
"require": {
|
|
15
|
+
"types": "./dist/cjs/exports/Mutex.d.ts",
|
|
16
|
+
"default": "./dist/cjs/exports/Mutex.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"./package.json": "./package.json"
|
|
20
|
+
},
|
|
21
|
+
"scripts": {
|
|
22
|
+
"clean": "node -e \"require('node:fs').rmSync('dist', {recursive: true, force: true})\"",
|
|
23
|
+
"build:cjs": "tsc -p tsconfig.cjs.json",
|
|
24
|
+
"build:esm": "tsc -p tsconfig.esm.json",
|
|
25
|
+
"build:cjs-pkg": "node ../../scripts/package-build/cjs-package.mjs",
|
|
26
|
+
"build:js": "npm run build:cjs && npm run build:esm && npm run build:cjs-pkg",
|
|
27
|
+
"rebuild": "npm run clean && npm run build:js",
|
|
28
|
+
"compile": "npm run rebuild",
|
|
29
|
+
"test:unit": "npm run compile && node --test --test-concurrency=1 \"dist/esm/tests/*.spec.js\"",
|
|
30
|
+
"test:stores": "sh test-env/run.sh"
|
|
31
|
+
},
|
|
32
|
+
"peerDependencies": {
|
|
33
|
+
"@lakutata/core": "3.0.0-beta.0",
|
|
34
|
+
"mysql2": "^3.0.0",
|
|
35
|
+
"pg": "^8.0.0",
|
|
36
|
+
"redis": "^4.6.0 || ^5.0.0"
|
|
37
|
+
},
|
|
38
|
+
"peerDependenciesMeta": {
|
|
39
|
+
"mysql2": {
|
|
40
|
+
"optional": true
|
|
41
|
+
},
|
|
42
|
+
"pg": {
|
|
43
|
+
"optional": true
|
|
44
|
+
},
|
|
45
|
+
"redis": {
|
|
46
|
+
"optional": true
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"engines": {
|
|
50
|
+
"node": ">=22"
|
|
51
|
+
},
|
|
52
|
+
"files": [
|
|
53
|
+
"dist",
|
|
54
|
+
"!dist/*/tests",
|
|
55
|
+
"*.md",
|
|
56
|
+
"LICENSE",
|
|
57
|
+
"package.json"
|
|
58
|
+
]
|
|
59
|
+
}
|