@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.
Files changed (88) hide show
  1. package/LICENSE +23 -0
  2. package/README.md +212 -2
  3. package/dist/cjs/exports/Mutex.d.ts +18 -0
  4. package/dist/cjs/exports/Mutex.js +37 -0
  5. package/dist/cjs/mutex/Mutex.d.ts +265 -0
  6. package/dist/cjs/mutex/Mutex.js +403 -0
  7. package/dist/cjs/mutex/MutexLock.d.ts +91 -0
  8. package/dist/cjs/mutex/MutexLock.js +113 -0
  9. package/dist/cjs/mutex/Synchronized.d.ts +90 -0
  10. package/dist/cjs/mutex/Synchronized.js +93 -0
  11. package/dist/cjs/mutex/drivers/FileMutexDriver.d.ts +115 -0
  12. package/dist/cjs/mutex/drivers/FileMutexDriver.js +230 -0
  13. package/dist/cjs/mutex/drivers/MemoryMutexDriver.d.ts +60 -0
  14. package/dist/cjs/mutex/drivers/MemoryMutexDriver.js +95 -0
  15. package/dist/cjs/mutex/drivers/MutexDriver.d.ts +82 -0
  16. package/dist/cjs/mutex/drivers/MutexDriver.js +38 -0
  17. package/dist/cjs/mutex/drivers/MysqlMutexDriver.d.ts +135 -0
  18. package/dist/cjs/mutex/drivers/MysqlMutexDriver.js +244 -0
  19. package/dist/cjs/mutex/drivers/PostgresMutexDriver.d.ts +136 -0
  20. package/dist/cjs/mutex/drivers/PostgresMutexDriver.js +230 -0
  21. package/dist/cjs/mutex/drivers/RedisMutexDriver.d.ts +129 -0
  22. package/dist/cjs/mutex/drivers/RedisMutexDriver.js +180 -0
  23. package/dist/cjs/mutex/exceptions/MutexDriverException.d.ts +12 -0
  24. package/dist/cjs/mutex/exceptions/MutexDriverException.js +19 -0
  25. package/dist/cjs/mutex/exceptions/MutexDriverNotFoundException.d.ts +12 -0
  26. package/dist/cjs/mutex/exceptions/MutexDriverNotFoundException.js +19 -0
  27. package/dist/cjs/mutex/exceptions/MutexLostException.d.ts +13 -0
  28. package/dist/cjs/mutex/exceptions/MutexLostException.js +20 -0
  29. package/dist/cjs/mutex/exceptions/MutexTimeoutException.d.ts +16 -0
  30. package/dist/cjs/mutex/exceptions/MutexTimeoutException.js +23 -0
  31. package/dist/cjs/mutex/lib/LoadDriver.d.ts +6 -0
  32. package/dist/cjs/mutex/lib/LoadDriver.js +64 -0
  33. package/dist/cjs/mutex/lib/Names.d.ts +14 -0
  34. package/dist/cjs/mutex/lib/Names.js +26 -0
  35. package/dist/cjs/mutex/options/FileMutexOptions.d.ts +33 -0
  36. package/dist/cjs/mutex/options/FileMutexOptions.js +45 -0
  37. package/dist/cjs/mutex/options/MemoryMutexOptions.d.ts +27 -0
  38. package/dist/cjs/mutex/options/MemoryMutexOptions.js +41 -0
  39. package/dist/cjs/mutex/options/MysqlMutexOptions.d.ts +70 -0
  40. package/dist/cjs/mutex/options/MysqlMutexOptions.js +77 -0
  41. package/dist/cjs/mutex/options/PostgresMutexOptions.d.ts +83 -0
  42. package/dist/cjs/mutex/options/PostgresMutexOptions.js +89 -0
  43. package/dist/cjs/mutex/options/RedisMutexOptions.d.ts +71 -0
  44. package/dist/cjs/mutex/options/RedisMutexOptions.js +77 -0
  45. package/dist/cjs/package.json +1 -0
  46. package/dist/esm/exports/Mutex.js +18 -0
  47. package/dist/esm/mutex/Mutex.js +397 -0
  48. package/dist/esm/mutex/MutexLock.js +109 -0
  49. package/dist/esm/mutex/Synchronized.js +89 -0
  50. package/dist/esm/mutex/drivers/FileMutexDriver.js +223 -0
  51. package/dist/esm/mutex/drivers/MemoryMutexDriver.js +91 -0
  52. package/dist/esm/mutex/drivers/MutexDriver.js +34 -0
  53. package/dist/esm/mutex/drivers/MysqlMutexDriver.js +240 -0
  54. package/dist/esm/mutex/drivers/PostgresMutexDriver.js +226 -0
  55. package/dist/esm/mutex/drivers/RedisMutexDriver.js +176 -0
  56. package/dist/esm/mutex/exceptions/MutexDriverException.js +15 -0
  57. package/dist/esm/mutex/exceptions/MutexDriverNotFoundException.js +15 -0
  58. package/dist/esm/mutex/exceptions/MutexLostException.js +16 -0
  59. package/dist/esm/mutex/exceptions/MutexTimeoutException.js +19 -0
  60. package/dist/esm/mutex/lib/LoadDriver.js +28 -0
  61. package/dist/esm/mutex/lib/Names.js +21 -0
  62. package/dist/esm/mutex/options/FileMutexOptions.js +41 -0
  63. package/dist/esm/mutex/options/MemoryMutexOptions.js +37 -0
  64. package/dist/esm/mutex/options/MysqlMutexOptions.js +73 -0
  65. package/dist/esm/mutex/options/PostgresMutexOptions.js +85 -0
  66. package/dist/esm/mutex/options/RedisMutexOptions.js +73 -0
  67. package/dist/types/exports/Mutex.d.ts +18 -0
  68. package/dist/types/mutex/Mutex.d.ts +265 -0
  69. package/dist/types/mutex/MutexLock.d.ts +91 -0
  70. package/dist/types/mutex/Synchronized.d.ts +90 -0
  71. package/dist/types/mutex/drivers/FileMutexDriver.d.ts +115 -0
  72. package/dist/types/mutex/drivers/MemoryMutexDriver.d.ts +60 -0
  73. package/dist/types/mutex/drivers/MutexDriver.d.ts +82 -0
  74. package/dist/types/mutex/drivers/MysqlMutexDriver.d.ts +135 -0
  75. package/dist/types/mutex/drivers/PostgresMutexDriver.d.ts +136 -0
  76. package/dist/types/mutex/drivers/RedisMutexDriver.d.ts +129 -0
  77. package/dist/types/mutex/exceptions/MutexDriverException.d.ts +12 -0
  78. package/dist/types/mutex/exceptions/MutexDriverNotFoundException.d.ts +12 -0
  79. package/dist/types/mutex/exceptions/MutexLostException.d.ts +13 -0
  80. package/dist/types/mutex/exceptions/MutexTimeoutException.d.ts +16 -0
  81. package/dist/types/mutex/lib/LoadDriver.d.ts +6 -0
  82. package/dist/types/mutex/lib/Names.d.ts +14 -0
  83. package/dist/types/mutex/options/FileMutexOptions.d.ts +33 -0
  84. package/dist/types/mutex/options/MemoryMutexOptions.d.ts +27 -0
  85. package/dist/types/mutex/options/MysqlMutexOptions.d.ts +70 -0
  86. package/dist/types/mutex/options/PostgresMutexOptions.d.ts +83 -0
  87. package/dist/types/mutex/options/RedisMutexOptions.d.ts +71 -0
  88. package/package.json +57 -4
@@ -0,0 +1,16 @@
1
+ import { Exception } from '@lakutata/core';
2
+ /**
3
+ * The abort reason of {@link MutexLock.signal} when a lock is lost: a renewal found it expired or taken by another
4
+ * holder, a renewal failed, or the connection holding it closed. It is not thrown by the component: the work holding the
5
+ * lock meets it through the signal (`signal.throwIfAborted()`, an `AbortSignal`-aware API). Its `errno` is
6
+ * `'E_MUTEX_LOST'`.
7
+ */
8
+ export class MutexLostException extends Exception {
9
+ constructor() {
10
+ super(...arguments);
11
+ /**
12
+ * `'E_MUTEX_LOST'`.
13
+ */
14
+ this.errno = 'E_MUTEX_LOST';
15
+ }
16
+ }
@@ -0,0 +1,19 @@
1
+ import { Exception } from '@lakutata/core';
2
+ /**
3
+ * Thrown by {@link Mutex.acquire} and {@link Mutex.synchronized} when the lock is not acquired before the timeout
4
+ * (another holder kept it), and by a {@link Synchronized} action whose lock is held by another request (HTTP 409
5
+ * Conflict). Its `errno` is `'E_MUTEX_TIMEOUT'`.
6
+ */
7
+ export class MutexTimeoutException extends Exception {
8
+ constructor() {
9
+ super(...arguments);
10
+ /**
11
+ * `'E_MUTEX_TIMEOUT'`.
12
+ */
13
+ this.errno = 'E_MUTEX_TIMEOUT';
14
+ /**
15
+ * The HTTP status the transports answer with: 409 (Conflict).
16
+ */
17
+ this.statusCode = 409;
18
+ }
19
+ }
@@ -0,0 +1,28 @@
1
+ import { MutexDriverNotFoundException } from '../exceptions/MutexDriverNotFoundException.js';
2
+ /**
3
+ * Whether an error reports the package itself as missing
4
+ * @param error
5
+ * @param packageName
6
+ */
7
+ function isPackageMissing(error, packageName) {
8
+ const { code, message } = error;
9
+ if (code !== 'ERR_MODULE_NOT_FOUND' && code !== 'MODULE_NOT_FOUND')
10
+ return false;
11
+ return !!message && (message.includes(`'${packageName}'`) || message.includes(`"${packageName}"`));
12
+ }
13
+ /**
14
+ * Load the client package of a driver (an optional dependency)
15
+ * @param member a member of its API, to find it in the ESM namespace or the CommonJS exports
16
+ * @param packageName
17
+ */
18
+ export async function loadDriver(member, packageName) {
19
+ try {
20
+ const driver = await import(packageName);
21
+ return (driver[member] === undefined && driver.default ? driver.default : driver);
22
+ }
23
+ catch (e) {
24
+ if (!isPackageMissing(e, packageName))
25
+ throw e;
26
+ }
27
+ throw new MutexDriverNotFoundException('Package "{packageName}" is required for this driver of the locks. Run "npm install {packageName}".', { packageName: packageName });
28
+ }
@@ -0,0 +1,21 @@
1
+ import { createHash, randomBytes } from 'node:crypto';
2
+ /**
3
+ * The token of a lock acquired (its holder checked by it)
4
+ */
5
+ export function lockToken() {
6
+ return randomBytes(16).toString('hex');
7
+ }
8
+ /**
9
+ * The digest of the name of a lock (hexadecimal)
10
+ * @param name
11
+ */
12
+ export function nameDigest(name) {
13
+ return createHash('sha256').update(name).digest('hex');
14
+ }
15
+ /**
16
+ * The key of 64 bits of the name of a lock (the advisory locks of PostgreSQL), a signed bigint as a string
17
+ * @param name
18
+ */
19
+ export function nameKey64(name) {
20
+ return createHash('sha256').update(name).digest().readBigInt64BE(0).toString();
21
+ }
@@ -0,0 +1,41 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { DTO } from '@lakutata/core';
11
+ import { Expect } from '@lakutata/core/decorator/dto';
12
+ /**
13
+ * The options of the file driver ({@link FileMutexDriver}): one lock file per lock in a directory, shared by the
14
+ * processes of one host using the same directory (several workers or applications of a machine). It needs no package.
15
+ * The locks expire after their `ttl` unless renewed, a lock whose process is gone is taken over at once, and there is no
16
+ * fencing token.
17
+ * @example
18
+ * ```typescript
19
+ * import {Application} from 'lakutata'
20
+ * import {Mutex} from 'lakutata/com/mutex'
21
+ *
22
+ * Application.run(() => ({
23
+ * id: 'file-mutex.app',
24
+ * name: 'FileMutex',
25
+ * components: {
26
+ * //Every worker of this machine uses the same directory
27
+ * mutex: {class: Mutex, driver: {type: 'file', directory: '/var/lock/my-app'}}
28
+ * }
29
+ * }))
30
+ * ```
31
+ */
32
+ export class FileMutexOptions extends DTO {
33
+ }
34
+ __decorate([
35
+ Expect(DTO.String().valid('file').required()),
36
+ __metadata("design:type", String)
37
+ ], FileMutexOptions.prototype, "type", void 0);
38
+ __decorate([
39
+ Expect(DTO.String().optional()),
40
+ __metadata("design:type", String)
41
+ ], FileMutexOptions.prototype, "directory", void 0);
@@ -0,0 +1,37 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { DTO } from '@lakutata/core';
11
+ import { Expect } from '@lakutata/core/decorator/dto';
12
+ /**
13
+ * The options of the memory driver ({@link MemoryMutexDriver}), the default of a {@link Mutex}: the locks live in the
14
+ * process memory, shared by the components of the process and invisible to the other processes. For development, tests
15
+ * and an application running as a single process; it needs no package. The locks expire after their `ttl` unless
16
+ * renewed, and carry fencing tokens counted by the process.
17
+ * @example
18
+ * ```typescript
19
+ * import {Application} from 'lakutata'
20
+ * import {Mutex} from 'lakutata/com/mutex'
21
+ *
22
+ * Application.run(() => ({
23
+ * id: 'memory-mutex.app',
24
+ * name: 'MemoryMutex',
25
+ * components: {
26
+ * //The same as {class: Mutex}
27
+ * mutex: {class: Mutex, driver: {type: 'memory'}}
28
+ * }
29
+ * }))
30
+ * ```
31
+ */
32
+ export class MemoryMutexOptions extends DTO {
33
+ }
34
+ __decorate([
35
+ Expect(DTO.String().valid('memory').required()),
36
+ __metadata("design:type", String)
37
+ ], MemoryMutexOptions.prototype, "type", void 0);
@@ -0,0 +1,73 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { DTO } from '@lakutata/core';
11
+ import { Expect } from '@lakutata/core/decorator/dto';
12
+ /**
13
+ * The options of the MySQL driver ({@link MysqlMutexDriver}), for MySQL or MariaDB: the locks are shared by every
14
+ * instance connected to the same server. It needs the optional peer dependency `mysql2` (`npm install mysql2`, 3):
15
+ * without it, the first acquisition fails with {@link MutexDriverNotFoundException}. The driver connects at the first
16
+ * acquisition, not when the component is created.
17
+ *
18
+ * In the `'advisory'` mode (the default), the locks are named locks (`GET_LOCK`) of one connection: they do not expire,
19
+ * MySQL releases them when the connection closes (a crashed process frees them at once), and they are all lost when it
20
+ * closes or fails. They have no fencing token, and are not replicated by the clusters (Galera, Group Replication): every
21
+ * holder must connect to the same server. In the `'table'` mode, the locks are rows of a table created at the first use:
22
+ * they expire after their `ttl` unless renewed, work through the poolers and the clusters, and carry fencing tokens.
23
+ * @example
24
+ * ```typescript
25
+ * import {Application} from 'lakutata'
26
+ * import {Mutex} from 'lakutata/com/mutex'
27
+ *
28
+ * Application.run(() => ({
29
+ * id: 'mysql-mutex.app',
30
+ * name: 'MysqlMutex',
31
+ * components: {
32
+ * mutex: {
33
+ * class: Mutex,
34
+ * driver: {type: 'mysql', host: 'db', database: 'app', username: 'app', password: process.env.DB_PASSWORD ?? ''}
35
+ * }
36
+ * }
37
+ * }))
38
+ * ```
39
+ */
40
+ export class MysqlMutexOptions extends DTO {
41
+ }
42
+ __decorate([
43
+ Expect(DTO.String().valid('mysql').required()),
44
+ __metadata("design:type", String)
45
+ ], MysqlMutexOptions.prototype, "type", void 0);
46
+ __decorate([
47
+ Expect(DTO.String().required()),
48
+ __metadata("design:type", String)
49
+ ], MysqlMutexOptions.prototype, "host", void 0);
50
+ __decorate([
51
+ Expect(DTO.Number().port().optional().default(3306)),
52
+ __metadata("design:type", Number)
53
+ ], MysqlMutexOptions.prototype, "port", void 0);
54
+ __decorate([
55
+ Expect(DTO.String().required()),
56
+ __metadata("design:type", String)
57
+ ], MysqlMutexOptions.prototype, "database", void 0);
58
+ __decorate([
59
+ Expect(DTO.String().required()),
60
+ __metadata("design:type", String)
61
+ ], MysqlMutexOptions.prototype, "username", void 0);
62
+ __decorate([
63
+ Expect(DTO.String().allow('').required()),
64
+ __metadata("design:type", String)
65
+ ], MysqlMutexOptions.prototype, "password", void 0);
66
+ __decorate([
67
+ Expect(DTO.String().valid('advisory', 'table').optional().default('advisory')),
68
+ __metadata("design:type", String)
69
+ ], MysqlMutexOptions.prototype, "mode", void 0);
70
+ __decorate([
71
+ Expect(DTO.String().pattern(/^[a-zA-Z_][a-zA-Z0-9_]*$/).optional().default('lakutata_mutex')),
72
+ __metadata("design:type", String)
73
+ ], MysqlMutexOptions.prototype, "table", void 0);
@@ -0,0 +1,85 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { DTO } from '@lakutata/core';
11
+ import { Expect } from '@lakutata/core/decorator/dto';
12
+ /**
13
+ * The options of the PostgreSQL driver ({@link PostgresMutexDriver}): the locks are shared by every instance connected
14
+ * to the same database. It needs the optional peer dependency `pg` (`npm install pg`, 8): without it, the first
15
+ * acquisition fails with {@link MutexDriverNotFoundException}. The driver connects at the first acquisition, not when
16
+ * the component is created.
17
+ *
18
+ * In the `'advisory'` mode (the default), the locks are session advisory locks of one connection: they do not expire,
19
+ * PostgreSQL releases them when the connection closes (a crashed process frees them at once), and they are all lost
20
+ * when it closes or fails. They have no fencing token, and do not work through a pooler in transaction mode
21
+ * (PgBouncer). In the `'table'` mode, the locks are rows of a table created at the first use: they expire after their
22
+ * `ttl` unless renewed, work through the poolers, and carry fencing tokens.
23
+ * @example
24
+ * ```typescript
25
+ * import {Application} from 'lakutata'
26
+ * import {Mutex} from 'lakutata/com/mutex'
27
+ *
28
+ * Application.run(() => ({
29
+ * id: 'postgres-mutex.app',
30
+ * name: 'PostgresMutex',
31
+ * components: {
32
+ * mutex: {
33
+ * class: Mutex,
34
+ * driver: {
35
+ * type: 'postgres',
36
+ * host: 'db',
37
+ * database: 'app',
38
+ * username: 'app',
39
+ * password: process.env.DB_PASSWORD ?? '',
40
+ * //Through PgBouncer: rows of a table, with fencing tokens
41
+ * mode: 'table'
42
+ * }
43
+ * }
44
+ * }
45
+ * }))
46
+ * ```
47
+ */
48
+ export class PostgresMutexOptions extends DTO {
49
+ }
50
+ __decorate([
51
+ Expect(DTO.String().valid('postgres').required()),
52
+ __metadata("design:type", String)
53
+ ], PostgresMutexOptions.prototype, "type", void 0);
54
+ __decorate([
55
+ Expect(DTO.String().required()),
56
+ __metadata("design:type", String)
57
+ ], PostgresMutexOptions.prototype, "host", void 0);
58
+ __decorate([
59
+ Expect(DTO.Number().port().optional().default(5432)),
60
+ __metadata("design:type", Number)
61
+ ], PostgresMutexOptions.prototype, "port", void 0);
62
+ __decorate([
63
+ Expect(DTO.String().required()),
64
+ __metadata("design:type", String)
65
+ ], PostgresMutexOptions.prototype, "database", void 0);
66
+ __decorate([
67
+ Expect(DTO.String().required()),
68
+ __metadata("design:type", String)
69
+ ], PostgresMutexOptions.prototype, "username", void 0);
70
+ __decorate([
71
+ Expect(DTO.String().allow('').required()),
72
+ __metadata("design:type", String)
73
+ ], PostgresMutexOptions.prototype, "password", void 0);
74
+ __decorate([
75
+ Expect(DTO.Boolean().optional()),
76
+ __metadata("design:type", Boolean)
77
+ ], PostgresMutexOptions.prototype, "ssl", void 0);
78
+ __decorate([
79
+ Expect(DTO.String().valid('advisory', 'table').optional().default('advisory')),
80
+ __metadata("design:type", String)
81
+ ], PostgresMutexOptions.prototype, "mode", void 0);
82
+ __decorate([
83
+ Expect(DTO.String().pattern(/^[a-zA-Z_][a-zA-Z0-9_]*(\.[a-zA-Z_][a-zA-Z0-9_]*)?$/).optional().default('lakutata_mutex')),
84
+ __metadata("design:type", String)
85
+ ], PostgresMutexOptions.prototype, "table", void 0);
@@ -0,0 +1,73 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { DTO } from '@lakutata/core';
11
+ import { Expect } from '@lakutata/core/decorator/dto';
12
+ /**
13
+ * The options of the Redis driver ({@link RedisMutexDriver}): the locks are Redis keys shared by every instance
14
+ * connected to the same server or cluster. It needs the optional peer dependency `redis` (`npm install redis`, 4.6 or
15
+ * 5): without it, the first acquisition fails with {@link MutexDriverNotFoundException}. The keys expire after their
16
+ * `ttl` unless renewed, and each acquisition gets a fencing token. Configure the server with
17
+ * `maxmemory-policy noeviction`: an evicted key is a lock lost.
18
+ *
19
+ * The client connects at the first acquisition, not when the component is created. While the server cannot be reached,
20
+ * the calls wait for it instead of failing.
21
+ * @example
22
+ * ```typescript
23
+ * import {Application} from 'lakutata'
24
+ * import {Mutex} from 'lakutata/com/mutex'
25
+ *
26
+ * Application.run(() => ({
27
+ * id: 'redis-mutex.app',
28
+ * name: 'RedisMutex',
29
+ * components: {
30
+ * mutex: {
31
+ * class: Mutex,
32
+ * driver: {type: 'redis', host: '127.0.0.1', port: 6379, password: process.env.REDIS_PASSWORD},
33
+ * //The applications sharing this Redis server keep their locks apart
34
+ * prefix: 'billing:mutex:'
35
+ * }
36
+ * }
37
+ * }))
38
+ * ```
39
+ */
40
+ export class RedisMutexOptions extends DTO {
41
+ }
42
+ __decorate([
43
+ Expect(DTO.String().valid('redis').required()),
44
+ __metadata("design:type", String)
45
+ ], RedisMutexOptions.prototype, "type", void 0);
46
+ __decorate([
47
+ Expect(DTO.String().optional()),
48
+ __metadata("design:type", String)
49
+ ], RedisMutexOptions.prototype, "url", void 0);
50
+ __decorate([
51
+ Expect(DTO.String().optional()),
52
+ __metadata("design:type", String)
53
+ ], RedisMutexOptions.prototype, "host", void 0);
54
+ __decorate([
55
+ Expect(DTO.Number().port().optional()),
56
+ __metadata("design:type", Number)
57
+ ], RedisMutexOptions.prototype, "port", void 0);
58
+ __decorate([
59
+ Expect(DTO.Number().integer().min(0).optional()),
60
+ __metadata("design:type", Number)
61
+ ], RedisMutexOptions.prototype, "database", void 0);
62
+ __decorate([
63
+ Expect(DTO.String().optional()),
64
+ __metadata("design:type", String)
65
+ ], RedisMutexOptions.prototype, "username", void 0);
66
+ __decorate([
67
+ Expect(DTO.String().optional()),
68
+ __metadata("design:type", String)
69
+ ], RedisMutexOptions.prototype, "password", void 0);
70
+ __decorate([
71
+ Expect(DTO.Boolean().optional()),
72
+ __metadata("design:type", Boolean)
73
+ ], RedisMutexOptions.prototype, "tls", void 0);
@@ -0,0 +1,18 @@
1
+ export * from '../mutex/Mutex.js';
2
+ export * from '../mutex/MutexLock.js';
3
+ export * from '../mutex/drivers/MutexDriver.js';
4
+ export * from '../mutex/drivers/MemoryMutexDriver.js';
5
+ export * from '../mutex/drivers/FileMutexDriver.js';
6
+ export * from '../mutex/drivers/RedisMutexDriver.js';
7
+ export * from '../mutex/drivers/PostgresMutexDriver.js';
8
+ export * from '../mutex/drivers/MysqlMutexDriver.js';
9
+ export * from '../mutex/options/MemoryMutexOptions.js';
10
+ export * from '../mutex/options/FileMutexOptions.js';
11
+ export * from '../mutex/options/RedisMutexOptions.js';
12
+ export * from '../mutex/options/PostgresMutexOptions.js';
13
+ export * from '../mutex/options/MysqlMutexOptions.js';
14
+ export * from '../mutex/exceptions/MutexTimeoutException.js';
15
+ export * from '../mutex/exceptions/MutexLostException.js';
16
+ export * from '../mutex/exceptions/MutexDriverException.js';
17
+ export * from '../mutex/exceptions/MutexDriverNotFoundException.js';
18
+ export * from '../mutex/Synchronized.js';