@daiso-tech/core 0.24.0 → 0.26.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 (96) hide show
  1. package/README.md +3 -2
  2. package/dist/async/utilities/lazy-promise/lazy-promise.d.ts +12 -3
  3. package/dist/async/utilities/lazy-promise/lazy-promise.js +37 -4
  4. package/dist/async/utilities/lazy-promise/lazy-promise.js.map +1 -1
  5. package/dist/cache/contracts/cache.contract.d.ts +4 -4
  6. package/dist/cache/implementations/adapters/kysely-sqlite-cache-adapter/kysely-sqlite-cache-adapter.js +2 -2
  7. package/dist/cache/implementations/adapters/kysely-sqlite-cache-adapter/kysely-sqlite-cache-adapter.js.map +1 -1
  8. package/dist/cache/implementations/adapters/memory-cache-adapter/memory-cache-adapter.js +4 -4
  9. package/dist/cache/implementations/adapters/memory-cache-adapter/memory-cache-adapter.js.map +1 -1
  10. package/dist/cache/implementations/adapters/mongodb-cache-adapter/mongodb-cache-adapter.js +2 -2
  11. package/dist/cache/implementations/adapters/mongodb-cache-adapter/mongodb-cache-adapter.js.map +1 -1
  12. package/dist/cache/implementations/adapters/redis-cache-adapter/redis-cache-adapter.js +5 -5
  13. package/dist/cache/implementations/adapters/redis-cache-adapter/redis-cache-adapter.js.map +1 -1
  14. package/dist/cache/implementations/derivables/cache/cache.d.ts +70 -184
  15. package/dist/cache/implementations/derivables/cache/cache.js +68 -185
  16. package/dist/cache/implementations/derivables/cache/cache.js.map +1 -1
  17. package/dist/cache/implementations/derivables/cache-factory/cache-factory.d.ts +11 -15
  18. package/dist/cache/implementations/derivables/cache-factory/cache-factory.js +0 -11
  19. package/dist/cache/implementations/derivables/cache-factory/cache-factory.js.map +1 -1
  20. package/dist/collection/implementations/async-iterable-collection/async-iterable-collection.js +5 -5
  21. package/dist/collection/implementations/async-iterable-collection/async-iterable-collection.js.map +1 -1
  22. package/dist/collection/implementations/iterable-collection/iterable-collection.js +5 -5
  23. package/dist/collection/implementations/iterable-collection/iterable-collection.js.map +1 -1
  24. package/dist/collection/implementations/list-collection/list-collection.js +5 -5
  25. package/dist/collection/implementations/list-collection/list-collection.js.map +1 -1
  26. package/dist/event-bus/contracts/_shared.d.ts +0 -7
  27. package/dist/event-bus/contracts/_shared.js.map +1 -1
  28. package/dist/event-bus/contracts/event-bus-adapter.contract.d.ts +6 -5
  29. package/dist/event-bus/contracts/event-bus.contract.d.ts +21 -16
  30. package/dist/event-bus/implementations/adapters/memory-event-bus-adapter/memory-event-bus-adapter.d.ts +4 -3
  31. package/dist/event-bus/implementations/adapters/memory-event-bus-adapter/memory-event-bus-adapter.js +3 -3
  32. package/dist/event-bus/implementations/adapters/memory-event-bus-adapter/memory-event-bus-adapter.js.map +1 -1
  33. package/dist/event-bus/implementations/adapters/no-op-event-bus-adapter/no-op-event-bus-adapter.d.ts +4 -3
  34. package/dist/event-bus/implementations/adapters/no-op-event-bus-adapter/no-op-event-bus-adapter.js.map +1 -1
  35. package/dist/event-bus/implementations/adapters/redis-pub-sub-event-bus-adapter/redis-pub-sub-event-bus-adapter.d.ts +4 -3
  36. package/dist/event-bus/implementations/adapters/redis-pub-sub-event-bus-adapter/redis-pub-sub-event-bus-adapter.js +3 -3
  37. package/dist/event-bus/implementations/adapters/redis-pub-sub-event-bus-adapter/redis-pub-sub-event-bus-adapter.js.map +1 -1
  38. package/dist/event-bus/implementations/derivables/event-bus/event-bus.d.ts +64 -33
  39. package/dist/event-bus/implementations/derivables/event-bus/event-bus.js +92 -33
  40. package/dist/event-bus/implementations/derivables/event-bus/event-bus.js.map +1 -1
  41. package/dist/event-bus/implementations/test-utilities/event-bus.test-suite.js +957 -201
  42. package/dist/event-bus/implementations/test-utilities/event-bus.test-suite.js.map +1 -1
  43. package/dist/lock/contracts/lock-provider.contract.d.ts +2 -2
  44. package/dist/lock/contracts/lock.contract.d.ts +24 -6
  45. package/dist/lock/implementations/adapters/kysely-lock-adapter/kysely-lock-adapter.js +2 -2
  46. package/dist/lock/implementations/adapters/kysely-lock-adapter/kysely-lock-adapter.js.map +1 -1
  47. package/dist/lock/implementations/adapters/memory-lock-adapter/memory-lock-adapter.js +4 -4
  48. package/dist/lock/implementations/adapters/memory-lock-adapter/memory-lock-adapter.js.map +1 -1
  49. package/dist/lock/implementations/adapters/mongodb-lock-adapter/mongodb-lock-adapter.js +2 -2
  50. package/dist/lock/implementations/adapters/mongodb-lock-adapter/mongodb-lock-adapter.js.map +1 -1
  51. package/dist/lock/implementations/adapters/redis-lock-adapter/redis-lock-adapter.js +4 -4
  52. package/dist/lock/implementations/adapters/redis-lock-adapter/redis-lock-adapter.js.map +1 -1
  53. package/dist/lock/implementations/derivables/lock-provider/lock-provider.d.ts +90 -48
  54. package/dist/lock/implementations/derivables/lock-provider/lock-provider.js +67 -43
  55. package/dist/lock/implementations/derivables/lock-provider/lock-provider.js.map +1 -1
  56. package/dist/lock/implementations/derivables/lock-provider/lock-serde-transformer.d.ts +4 -23
  57. package/dist/lock/implementations/derivables/lock-provider/lock-serde-transformer.js +8 -2
  58. package/dist/lock/implementations/derivables/lock-provider/lock-serde-transformer.js.map +1 -1
  59. package/dist/lock/implementations/derivables/lock-provider/lock.d.ts +744 -11
  60. package/dist/lock/implementations/derivables/lock-provider/lock.js +770 -3
  61. package/dist/lock/implementations/derivables/lock-provider/lock.js.map +1 -1
  62. package/dist/lock/implementations/derivables/lock-provider-factory/lock-provider-factory.d.ts +36 -5
  63. package/dist/lock/implementations/derivables/lock-provider-factory/lock-provider-factory.js +10 -4
  64. package/dist/lock/implementations/derivables/lock-provider-factory/lock-provider-factory.js.map +1 -1
  65. package/dist/lock/implementations/test-utilities/lock-provider.test-suite.d.ts +1 -0
  66. package/dist/lock/implementations/test-utilities/lock-provider.test-suite.js +417 -0
  67. package/dist/lock/implementations/test-utilities/lock-provider.test-suite.js.map +1 -1
  68. package/dist/serde/implementations/derivables/serde.js +4 -4
  69. package/dist/serde/implementations/derivables/serde.js.map +1 -1
  70. package/dist/utilities/{constants.js → _constants.js} +1 -1
  71. package/dist/utilities/_constants.js.map +1 -0
  72. package/dist/utilities/_module-exports.d.ts +1 -1
  73. package/dist/utilities/_module-exports.js +1 -1
  74. package/dist/utilities/_module-exports.js.map +1 -1
  75. package/dist/utilities/contracts/_module.d.ts +0 -1
  76. package/dist/utilities/contracts/_module.js +0 -1
  77. package/dist/utilities/contracts/_module.js.map +1 -1
  78. package/dist/utilities/functions.d.ts +3 -7
  79. package/dist/utilities/functions.js +3 -10
  80. package/dist/utilities/functions.js.map +1 -1
  81. package/dist/utilities/pipeline/_module.d.ts +1 -0
  82. package/dist/utilities/pipeline/_module.js +2 -0
  83. package/dist/utilities/pipeline/_module.js.map +1 -0
  84. package/dist/utilities/pipeline/pipeline.d.ts +45 -0
  85. package/dist/utilities/pipeline/pipeline.js +75 -0
  86. package/dist/utilities/pipeline/pipeline.js.map +1 -0
  87. package/dist/utilities/time-span/time-span.d.ts +3 -12
  88. package/dist/utilities/time-span/time-span.js +3 -6
  89. package/dist/utilities/time-span/time-span.js.map +1 -1
  90. package/dist/utilities/types.d.ts +19 -2
  91. package/package.json +1 -1
  92. package/dist/utilities/constants.js.map +0 -1
  93. package/dist/utilities/contracts/buildable.contract.d.ts +0 -11
  94. package/dist/utilities/contracts/buildable.contract.js +0 -5
  95. package/dist/utilities/contracts/buildable.contract.js.map +0 -1
  96. /package/dist/utilities/{constants.d.ts → _constants.d.ts} +0 -0
@@ -1,13 +1,17 @@
1
1
  /**
2
2
  * @module Lock
3
3
  */
4
- import { LazyPromise } from "../../../../async/_module-exports.js";
4
+ import { delay, LazyPromise } from "../../../../async/_module-exports.js";
5
5
  import { UnexpectedErrorLockEvent, KeyAcquiredLockEvent, KeyAlreadyAcquiredLockError, KeyAlreadyAcquiredLockEvent, KeyForceReleasedLockEvent, KeyReleasedLockEvent, KeyRefreshedLockEvent, UnableToAquireLockError, UnownedRefreshLockError, UnownedRefreshLockEvent, UnownedReleaseLockError, UnownedReleaseLockEvent, } from "../../../../lock/contracts/_module-exports.js";
6
6
  import { LockState, } from "../../../../lock/implementations/derivables/lock-provider/lock-state.js";
7
7
  /**
8
- * @internal
8
+ * IMPORTANT: This class is not intended to be instantiated directly, instead it should be created by the <i>LockProvider</i> class instance.
9
+ * @group Derivables
9
10
  */
10
11
  export class Lock {
12
+ /**
13
+ * @internal
14
+ */
11
15
  static serialize(deserializedValue) {
12
16
  return {
13
17
  group: deserializedValue.adapter.getGroup(),
@@ -23,13 +27,20 @@ export class Lock {
23
27
  key;
24
28
  owner;
25
29
  ttl;
30
+ defaultBlockingInterval;
31
+ defaultBlockingTime;
26
32
  defaultRefreshTime;
27
33
  lazyPromiseSettings;
28
34
  state;
35
+ /**
36
+ * @internal
37
+ */
29
38
  constructor(settings) {
30
- const { lockProviderEventDispatcher, lockEventBus, defaultRefreshTime, adapter, key, owner, ttl, lazyPromiseSettings, stateRecord, expirationInMs, } = settings;
39
+ const { lockProviderEventDispatcher, lockEventBus, defaultBlockingInterval, defaultBlockingTime, defaultRefreshTime, adapter, key, owner, ttl, lazyPromiseSettings, stateRecord, expirationInMs, } = settings;
31
40
  this.lockProviderEventDispatcher = lockProviderEventDispatcher;
32
41
  this.lockEventBus = lockEventBus.withGroup([adapter.getGroup(), key]);
42
+ this.defaultBlockingInterval = defaultBlockingInterval;
43
+ this.defaultBlockingTime = defaultBlockingTime;
33
44
  this.defaultRefreshTime = defaultRefreshTime;
34
45
  this.adapter = adapter;
35
46
  this.key = key;
@@ -46,6 +57,104 @@ export class Lock {
46
57
  .setRetryPolicy(this.lazyPromiseSettings.retryPolicy)
47
58
  .setTimeout(this.lazyPromiseSettings.timeout);
48
59
  }
60
+ /**
61
+ * @example
62
+ * ```ts
63
+ * import { type IGroupableLockProvider, type LockEvents, KeyAcquiredLockEvent } from "@daiso-tech/core/lock/contracts";
64
+ * import { LockProvider } from "@daiso-tech/core/lock/implementations/derivables";
65
+ * import { MemoryLockAdapter } from "@daiso-tech/core/lock/implementations/adapters";
66
+ * import type { Invokable } from "@daiso-tech/core/event-bus/contracts";
67
+ * import { EventBus } from "@daiso-tech/core/event-bus/implementations/derivables";
68
+ * import { MemoryEventBusAdapter } from "@daiso-tech/core/event-bus/implementations/adapters";
69
+ * import { Serde } from "@daiso-tech/core/serde/implementations/derivables";
70
+ * import { SuperJsonSerdeAdapter } from "@daiso-tech/core/serde/implementations/adapters";
71
+ * import { TimeSpan } from "@daiso-tech/core/utilities";
72
+ * import { delay } from "@daiso-tech/core/async";
73
+ *
74
+ * const eventBus = new EventBus({
75
+ * adapter: new MemoryEventBusAdapter({ rootGroup: "@global" })
76
+ * });
77
+ * const serde = new Serde(SuperJsonSerdeAdapter);
78
+ * const lockProvider: IGroupableLockProvider = new LockProvider({
79
+ * serde,
80
+ * adapter: new MemoryLockAdapter({
81
+ * rootGroup: "@global"
82
+ * }),
83
+ * eventBus,
84
+ * });
85
+ *
86
+ * const lock = lockProvider.create("a");
87
+ *
88
+ * async function fn(): Promise<void> {
89
+ * await lock.run(async () => {
90
+ * console.log("START: ", 1);
91
+ * // Let’s pretend we’re doing async database work.
92
+ * await delay(TimeSpan.fromSeconds(2));
93
+ * console.log("END: ", 2);
94
+ * });
95
+ * }
96
+ *
97
+ * await Promise.allSettled([
98
+ * fn(),
99
+ * fn(),
100
+ * fn(),
101
+ * fn(),
102
+ * ]);
103
+ * ```
104
+ *
105
+ * You can also pass an <i>{@link LazyPromise}</i> instead of async function.
106
+ * @example
107
+ * ```ts
108
+ * import { type IGroupableLockProvider, type LockEvents, KeyAcquiredLockEvent } from "@daiso-tech/core/lock/contracts";
109
+ * import { LockProvider } from "@daiso-tech/core/lock/implementations/derivables";
110
+ * import { MemoryLockAdapter } from "@daiso-tech/core/lock/implementations/adapters";
111
+ * import type { Invokable } from "@daiso-tech/core/event-bus/contracts";
112
+ * import { EventBus } from "@daiso-tech/core/event-bus/implementations/derivables";
113
+ * import { MemoryEventBusAdapter } from "@daiso-tech/core/event-bus/implementations/adapters";
114
+ * import { Serde } from "@daiso-tech/core/serde/implementations/derivables";
115
+ * import { SuperJsonSerdeAdapter } from "@daiso-tech/core/serde/implementations/adapters";
116
+ * import { TimeSpan } from "@daiso-tech/core/utilities";
117
+ * import { delay } from "@daiso-tech/core/async";
118
+ * import { Cache } from "@daiso-tech/core/cache/implementations/derivables";
119
+ * import { MemoryCacheAdapter } from "@daiso-tech/core/cache/implementations/adapters";
120
+ * import type { IGroupableCache } from "@daiso-tech/core/cache/contracts";
121
+ *
122
+ * const eventBus = new EventBus({
123
+ * adapter: new MemoryEventBusAdapter({ rootGroup: "@global" })
124
+ * });
125
+ * const serde = new Serde(SuperJsonSerdeAdapter);
126
+ * const lockProvider: IGroupableLockProvider = new LockProvider({
127
+ * serde,
128
+ * adapter: new MemoryLockAdapter({
129
+ * rootGroup: "@global"
130
+ * }),
131
+ * eventBus,
132
+ * });
133
+ *
134
+ * const cache: IGroupableCache = new Cache({
135
+ * // Let's pretend when the cache adapter increments a key it will occur in 2 async, get the value, increment the value in memory and update the key.
136
+ * adapter: new MemoryCacheAdapter({
137
+ * rootGroup: "@global"
138
+ * }),
139
+ * eventBus,
140
+ * });
141
+ * await cache.put("a", 0);
142
+ *
143
+ * const lock = lockProvider.create("a");
144
+ *
145
+ * async function fn(): Promise<void> {
146
+ * // The lock will ensure the key will be incremented correctly
147
+ * await lock.run(cache.increment("a", 1));
148
+ * }
149
+ *
150
+ * await Promise.allSettled([
151
+ * fn(),
152
+ * fn(),
153
+ * fn(),
154
+ * fn(),
155
+ * ]);
156
+ * ```
157
+ */
49
158
  run(asyncFn) {
50
159
  return this.createLayPromise(async () => {
51
160
  if (typeof asyncFn === "function") {
@@ -66,6 +175,109 @@ export class Lock {
66
175
  }
67
176
  }).setRetryPolicy((error) => error instanceof UnableToAquireLockError);
68
177
  }
178
+ /**
179
+ * @example
180
+ * ```ts
181
+ * import { type IGroupableLockProvider, type LockEvents, KeyAcquiredLockEvent } from "@daiso-tech/core/lock/contracts";
182
+ * import { LockProvider } from "@daiso-tech/core/lock/implementations/derivables";
183
+ * import { MemoryLockAdapter } from "@daiso-tech/core/lock/implementations/adapters";
184
+ * import type { Invokable } from "@daiso-tech/core/event-bus/contracts";
185
+ * import { EventBus } from "@daiso-tech/core/event-bus/implementations/derivables";
186
+ * import { MemoryEventBusAdapter } from "@daiso-tech/core/event-bus/implementations/adapters";
187
+ * import { Serde } from "@daiso-tech/core/serde/implementations/derivables";
188
+ * import { SuperJsonSerdeAdapter } from "@daiso-tech/core/serde/implementations/adapters";
189
+ * import { TimeSpan } from "@daiso-tech/core/utilities";
190
+ * import { delay } from "@daiso-tech/core/async";
191
+ *
192
+ * const eventBus = new EventBus({
193
+ * adapter: new MemoryEventBusAdapter({ rootGroup: "@global" })
194
+ * });
195
+ * const serde = new Serde(SuperJsonSerdeAdapter);
196
+ * const lockProvider: IGroupableLockProvider = new LockProvider({
197
+ * serde,
198
+ * adapter: new MemoryLockAdapter({
199
+ * rootGroup: "@global"
200
+ * }),
201
+ * eventBus,
202
+ * });
203
+ *
204
+ * const lock = lockProvider.create("a");
205
+ *
206
+ * async function fn(): Promise<void> {
207
+ * await lock.runOrFail(async () => {
208
+ * console.log("START: ", 1);
209
+ * // Let’s pretend we’re doing async database work.
210
+ * await delay(TimeSpan.fromSeconds(2));
211
+ * console.log("END: ", 2);
212
+ * })
213
+ * // Retries 4 times to acquire the lock, then throws an error.
214
+ * .setRetryAttempts(4);
215
+ * }
216
+ *
217
+ * await Promise.allSettled([
218
+ * fn(),
219
+ * fn(),
220
+ * fn(),
221
+ * fn(),
222
+ * ]);
223
+ * ```
224
+ *
225
+ * You can also pass an <i>{@link LazyPromise}</i> instead of async function.
226
+ * @example
227
+ * ```ts
228
+ * import { type IGroupableLockProvider, type LockEvents, KeyAcquiredLockEvent } from "@daiso-tech/core/lock/contracts";
229
+ * import { LockProvider } from "@daiso-tech/core/lock/implementations/derivables";
230
+ * import { MemoryLockAdapter } from "@daiso-tech/core/lock/implementations/adapters";
231
+ * import type { Invokable } from "@daiso-tech/core/event-bus/contracts";
232
+ * import { EventBus } from "@daiso-tech/core/event-bus/implementations/derivables";
233
+ * import { MemoryEventBusAdapter } from "@daiso-tech/core/event-bus/implementations/adapters";
234
+ * import { Serde } from "@daiso-tech/core/serde/implementations/derivables";
235
+ * import { SuperJsonSerdeAdapter } from "@daiso-tech/core/serde/implementations/adapters";
236
+ * import { TimeSpan } from "@daiso-tech/core/utilities";
237
+ * import { delay } from "@daiso-tech/core/async";
238
+ * import { Cache } from "@daiso-tech/core/cache/implementations/derivables";
239
+ * import { MemoryCacheAdapter } from "@daiso-tech/core/cache/implementations/adapters";
240
+ * import type { IGroupableCache } from "@daiso-tech/core/cache/contracts";
241
+ *
242
+ * const eventBus = new EventBus({
243
+ * adapter: new MemoryEventBusAdapter({ rootGroup: "@global" })
244
+ * });
245
+ * const serde = new Serde(SuperJsonSerdeAdapter);
246
+ * const lockProvider: IGroupableLockProvider = new LockProvider({
247
+ * serde,
248
+ * adapter: new MemoryLockAdapter({
249
+ * rootGroup: "@global"
250
+ * }),
251
+ * eventBus,
252
+ * });
253
+ *
254
+ * const cache: IGroupableCache = new Cache({
255
+ * // Let's pretend when the cache adapter increments a key it will occur in 2 async, get the value, increment the value in memory and update the key.
256
+ * adapter: new MemoryCacheAdapter({
257
+ * rootGroup: "@global"
258
+ * }),
259
+ * eventBus,
260
+ * });
261
+ * await cache.put("a", 0);
262
+ *
263
+ * const lock = lockProvider.create("a");
264
+ *
265
+ * async function fn(): Promise<void> {
266
+ * await lock
267
+ * // The lock will ensure the key will be incremented correctly
268
+ * .runOrFail(cache.increment("a", 1));
269
+ * // Retries 4 times to acquire the lock, then throws an error.
270
+ * .setRetryAttempts(4);
271
+ * }
272
+ *
273
+ * await Promise.allSettled([
274
+ * fn(),
275
+ * fn(),
276
+ * fn(),
277
+ * fn(),
278
+ * ]);
279
+ * ```
280
+ */
69
281
  runOrFail(asyncFn) {
70
282
  return this.createLayPromise(async () => {
71
283
  try {
@@ -81,6 +293,177 @@ export class Lock {
81
293
  }).setRetryPolicy((error) => error instanceof UnableToAquireLockError ||
82
294
  error instanceof KeyAlreadyAcquiredLockError);
83
295
  }
296
+ /**
297
+ * @example
298
+ * ```ts
299
+ * import { type IGroupableLockProvider, type LockEvents, KeyAcquiredLockEvent } from "@daiso-tech/core/lock/contracts";
300
+ * import { LockProvider } from "@daiso-tech/core/lock/implementations/derivables";
301
+ * import { MemoryLockAdapter } from "@daiso-tech/core/lock/implementations/adapters";
302
+ * import type { Invokable } from "@daiso-tech/core/event-bus/contracts";
303
+ * import { EventBus } from "@daiso-tech/core/event-bus/implementations/derivables";
304
+ * import { MemoryEventBusAdapter } from "@daiso-tech/core/event-bus/implementations/adapters";
305
+ * import { Serde } from "@daiso-tech/core/serde/implementations/derivables";
306
+ * import { SuperJsonSerdeAdapter } from "@daiso-tech/core/serde/implementations/adapters";
307
+ * import { TimeSpan } from "@daiso-tech/core/utilities";
308
+ * import { delay } from "@daiso-tech/core/async";
309
+ *
310
+ * const eventBus = new EventBus({
311
+ * adapter: new MemoryEventBusAdapter({ rootGroup: "@global" })
312
+ * });
313
+ * const serde = new Serde(SuperJsonSerdeAdapter);
314
+ * const lockProvider: IGroupableLockProvider = new LockProvider({
315
+ * serde,
316
+ * adapter: new MemoryLockAdapter({
317
+ * rootGroup: "@global"
318
+ * }),
319
+ * eventBus,
320
+ * });
321
+ *
322
+ * const lock = lockProvider.create("a");
323
+ *
324
+ * async function fn(): Promise<void> {
325
+ * await lock.runBlocking(async () => {
326
+ * console.log("START: ", 1);
327
+ * // Let’s pretend we’re doing async database work.
328
+ * await delay(TimeSpan.fromSeconds(2));
329
+ * console.log("END: ", 2);
330
+ * });
331
+ * }
332
+ *
333
+ * await Promise.allSettled([
334
+ * fn(),
335
+ * fn(),
336
+ * fn(),
337
+ * fn(),
338
+ * ]);
339
+ * ```
340
+ *
341
+ * You can also pass an <i>{@link LazyPromise}</i> instead of async function.
342
+ * @example
343
+ * ```ts
344
+ * import { type IGroupableLockProvider, type LockEvents, KeyAcquiredLockEvent } from "@daiso-tech/core/lock/contracts";
345
+ * import { LockProvider } from "@daiso-tech/core/lock/implementations/derivables";
346
+ * import { MemoryLockAdapter } from "@daiso-tech/core/lock/implementations/adapters";
347
+ * import type { Invokable } from "@daiso-tech/core/event-bus/contracts";
348
+ * import { EventBus } from "@daiso-tech/core/event-bus/implementations/derivables";
349
+ * import { MemoryEventBusAdapter } from "@daiso-tech/core/event-bus/implementations/adapters";
350
+ * import { Serde } from "@daiso-tech/core/serde/implementations/derivables";
351
+ * import { SuperJsonSerdeAdapter } from "@daiso-tech/core/serde/implementations/adapters";
352
+ * import { TimeSpan } from "@daiso-tech/core/utilities";
353
+ * import { delay } from "@daiso-tech/core/async";
354
+ * import { Cache } from "@daiso-tech/core/cache/implementations/derivables";
355
+ * import { MemoryCacheAdapter } from "@daiso-tech/core/cache/implementations/adapters";
356
+ * import type { IGroupableCache } from "@daiso-tech/core/cache/contracts";
357
+ *
358
+ * const eventBus = new EventBus({
359
+ * adapter: new MemoryEventBusAdapter({ rootGroup: "@global" })
360
+ * });
361
+ * const serde = new Serde(SuperJsonSerdeAdapter);
362
+ * const lockProvider: IGroupableLockProvider = new LockProvider({
363
+ * serde,
364
+ * adapter: new MemoryLockAdapter({
365
+ * rootGroup: "@global"
366
+ * }),
367
+ * eventBus,
368
+ * });
369
+ *
370
+ * const cache: IGroupableCache = new Cache({
371
+ * // Let's pretend when the cache adapter increments a key it will occur in 2 async, get the value, increment the value in memory and update the key.
372
+ * adapter: new MemoryCacheAdapter({
373
+ * rootGroup: "@global"
374
+ * }),
375
+ * eventBus,
376
+ * });
377
+ * await cache.put("a", 0);
378
+ *
379
+ * const lock = lockProvider.create("a");
380
+ *
381
+ * async function fn(): Promise<void> {
382
+ * // The lock will ensure the key will be incremented correctly
383
+ * await lock.runBlocking(cache.increment("a", 1));
384
+ * }
385
+ *
386
+ * await Promise.allSettled([
387
+ * fn(),
388
+ * fn(),
389
+ * fn(),
390
+ * fn(),
391
+ * ]);
392
+ * ```
393
+ */
394
+ runBlocking(asyncFn, settings) {
395
+ return this.createLayPromise(async () => {
396
+ if (typeof asyncFn === "function") {
397
+ asyncFn = new LazyPromise(asyncFn);
398
+ }
399
+ try {
400
+ const hasAquired = await this.acquireBlocking(settings);
401
+ if (!hasAquired) {
402
+ return [
403
+ null,
404
+ new KeyAlreadyAcquiredLockError(`Key "${this.key}" already acquired`),
405
+ ];
406
+ }
407
+ return [await asyncFn, null];
408
+ }
409
+ finally {
410
+ await this.release();
411
+ }
412
+ }).setRetryPolicy((error) => error instanceof UnableToAquireLockError);
413
+ }
414
+ /**
415
+ * @example
416
+ * ```ts
417
+ * import { type IGroupableLockProvider, type LockEvents, KeyAcquiredLockEvent } from "@daiso-tech/core/lock/contracts";
418
+ * import { LockProvider } from "@daiso-tech/core/lock/implementations/derivables";
419
+ * import { MemoryLockAdapter } from "@daiso-tech/core/lock/implementations/adapters";
420
+ * import type { Invokable } from "@daiso-tech/core/event-bus/contracts";
421
+ * import { EventBus } from "@daiso-tech/core/event-bus/implementations/derivables";
422
+ * import { MemoryEventBusAdapter } from "@daiso-tech/core/event-bus/implementations/adapters";
423
+ * import { Serde } from "@daiso-tech/core/serde/implementations/derivables";
424
+ * import { SuperJsonSerdeAdapter } from "@daiso-tech/core/serde/implementations/adapters";
425
+ * import { TimeSpan } from "@daiso-tech/core/utilities";
426
+ * import { delay } from "@daiso-tech/core/async";
427
+ *
428
+ * const eventBus = new EventBus({
429
+ * adapter: new MemoryEventBusAdapter({ rootGroup: "@global" })
430
+ * });
431
+ * const serde = new Serde(SuperJsonSerdeAdapter);
432
+ * const lockProvider: IGroupableLockProvider = new LockProvider({
433
+ * serde,
434
+ * adapter: new MemoryLockAdapter({
435
+ * rootGroup: "@global"
436
+ * }),
437
+ * eventBus,
438
+ * });
439
+ *
440
+ * const lock = lockProvider.create("a");
441
+ *
442
+ * async function fn(): Promise<void> {
443
+ * // Use try-finally when acquiring a lock to ensure it’s released if an error happens.
444
+ * try {
445
+ * const hasAquired = await lock.acquire();
446
+ * if (!hasAquired) {
447
+ * return;
448
+ * }
449
+ * console.log("START: ", 1);
450
+ * // Let’s pretend we’re doing async database work.
451
+ * await delay(TimeSpan.fromSeconds(2));
452
+ * console.log("END: ", 2);
453
+ * }
454
+ * finally {
455
+ * await lock.release();
456
+ * }
457
+ * }
458
+ *
459
+ * await Promise.allSettled([
460
+ * fn(),
461
+ * fn(),
462
+ * fn(),
463
+ * fn(),
464
+ * ]);
465
+ * ```
466
+ */
84
467
  acquire() {
85
468
  return this.createLayPromise(async () => {
86
469
  try {
@@ -119,6 +502,57 @@ export class Lock {
119
502
  }
120
503
  });
121
504
  }
505
+ /**
506
+ * @example
507
+ * ```ts
508
+ * import { type IGroupableLockProvider, type LockEvents, KeyAcquiredLockEvent } from "@daiso-tech/core/lock/contracts";
509
+ * import { LockProvider } from "@daiso-tech/core/lock/implementations/derivables";
510
+ * import { MemoryLockAdapter } from "@daiso-tech/core/lock/implementations/adapters";
511
+ * import type { Invokable } from "@daiso-tech/core/event-bus/contracts";
512
+ * import { EventBus } from "@daiso-tech/core/event-bus/implementations/derivables";
513
+ * import { MemoryEventBusAdapter } from "@daiso-tech/core/event-bus/implementations/adapters";
514
+ * import { Serde } from "@daiso-tech/core/serde/implementations/derivables";
515
+ * import { SuperJsonSerdeAdapter } from "@daiso-tech/core/serde/implementations/adapters";
516
+ * import { TimeSpan } from "@daiso-tech/core/utilities";
517
+ * import { delay } from "@daiso-tech/core/async";
518
+ *
519
+ * const eventBus = new EventBus({
520
+ * adapter: new MemoryEventBusAdapter({ rootGroup: "@global" })
521
+ * });
522
+ * const serde = new Serde(SuperJsonSerdeAdapter);
523
+ * const lockProvider: IGroupableLockProvider = new LockProvider({
524
+ * serde,
525
+ * adapter: new MemoryLockAdapter({
526
+ * rootGroup: "@global"
527
+ * }),
528
+ * eventBus,
529
+ * });
530
+ *
531
+ * const lock = lockProvider.create("a");
532
+ *
533
+ * async function fn(): Promise<void> {
534
+ * // Use try-finally when acquiring a lock to ensure it’s released if an error happens.
535
+ * try {
536
+ * // Retries 4 times to acquire the lock, then throws an error.
537
+ * await lock.acquireOrFail().setRetryAttempts(4);
538
+ * console.log("START: ", 1);
539
+ * // Let’s pretend we’re doing async database work.
540
+ * await delay(TimeSpan.fromSeconds(2));
541
+ * console.log("END: ", 2);
542
+ * }
543
+ * finally {
544
+ * await lock.release();
545
+ * }
546
+ * }
547
+ *
548
+ * await Promise.allSettled([
549
+ * fn(),
550
+ * fn(),
551
+ * fn(),
552
+ * fn(),
553
+ * ]);
554
+ * ```
555
+ */
122
556
  acquireOrFail() {
123
557
  return this.createLayPromise(async () => {
124
558
  const hasAquired = await this.acquire();
@@ -127,6 +561,73 @@ export class Lock {
127
561
  }
128
562
  });
129
563
  }
564
+ /**
565
+ * @example
566
+ * ```ts
567
+ * import { type IGroupableLockProvider, type LockEvents, KeyAcquiredLockEvent } from "@daiso-tech/core/lock/contracts";
568
+ * import { LockProvider } from "@daiso-tech/core/lock/implementations/derivables";
569
+ * import { MemoryLockAdapter } from "@daiso-tech/core/lock/implementations/adapters";
570
+ * import type { Invokable } from "@daiso-tech/core/event-bus/contracts";
571
+ * import { EventBus } from "@daiso-tech/core/event-bus/implementations/derivables";
572
+ * import { MemoryEventBusAdapter } from "@daiso-tech/core/event-bus/implementations/adapters";
573
+ * import { Serde } from "@daiso-tech/core/serde/implementations/derivables";
574
+ * import { SuperJsonSerdeAdapter } from "@daiso-tech/core/serde/implementations/adapters";
575
+ * import { TimeSpan } from "@daiso-tech/core/utilities";
576
+ * import { delay } from "@daiso-tech/core/async";
577
+ *
578
+ * const eventBus = new EventBus({
579
+ * adapter: new MemoryEventBusAdapter({ rootGroup: "@global" })
580
+ * });
581
+ * const serde = new Serde(SuperJsonSerdeAdapter);
582
+ * const lockProvider: IGroupableLockProvider = new LockProvider({
583
+ * serde,
584
+ * adapter: new MemoryLockAdapter({
585
+ * rootGroup: "@global"
586
+ * }),
587
+ * eventBus,
588
+ * });
589
+ *
590
+ * const lock = lockProvider.create("a");
591
+ *
592
+ * async function fn(): Promise<void> {
593
+ * // Use try-finally when acquiring a lock to ensure it’s released if an error happens.
594
+ * try {
595
+ * const hasAquired = await lock.acquireBlocking();
596
+ * if (!hasAquired) {
597
+ * return;
598
+ * }
599
+ * console.log("START: ", 1);
600
+ * // Let’s pretend we’re doing async database work.
601
+ * await delay(TimeSpan.fromSeconds(2));
602
+ * console.log("END: ", 2);
603
+ * }
604
+ * finally {
605
+ * await lock.release();
606
+ * }
607
+ * }
608
+ *
609
+ * await Promise.allSettled([
610
+ * fn(),
611
+ * fn(),
612
+ * fn(),
613
+ * fn(),
614
+ * ]);
615
+ * ```
616
+ */
617
+ acquireBlocking(settings = {}) {
618
+ return new LazyPromise(async () => {
619
+ const { time = this.defaultBlockingInterval, interval = this.defaultBlockingInterval, } = settings;
620
+ const endDate = time.toEndDate();
621
+ while (endDate.getTime() > new Date().getTime()) {
622
+ const hasAquired = await this.acquire();
623
+ if (hasAquired) {
624
+ return true;
625
+ }
626
+ await delay(interval);
627
+ }
628
+ return false;
629
+ });
630
+ }
130
631
  release() {
131
632
  return this.createLayPromise(async () => {
132
633
  try {
@@ -277,24 +778,290 @@ export class Lock {
277
778
  return this.owner;
278
779
  });
279
780
  }
781
+ /**
782
+ * You can listen to different events of the current <i>Lock</i> class instance.
783
+ *
784
+ * Refer to <i>{@link LockEvents}</i>, to se all events dispatched by <i>LockProvider</i> class instance.
785
+ * Refer to <i>{@link IEventListenable}</i> for details on how the method works.
786
+ * @example
787
+ * ```ts
788
+ * import { type IGroupableLockProvider, type LockEvents, KeyAcquiredLockEvent } from "@daiso-tech/core/lock/contracts";
789
+ * import { LockProvider } from "@daiso-tech/core/lock/implementations/derivables";
790
+ * import { MemoryLockAdapter } from "@daiso-tech/core/lock/implementations/adapters";
791
+ * import type { Invokable } from "@daiso-tech/core/event-bus/contracts";
792
+ * import { EventBus } from "@daiso-tech/core/event-bus/implementations/derivables";
793
+ * import { MemoryEventBusAdapter } from "@daiso-tech/core/event-bus/implementations/adapters";
794
+ * import { Serde } from "@daiso-tech/core/serde/implementations/derivables";
795
+ * import { SuperJsonSerdeAdapter } from "@daiso-tech/core/serde/implementations/adapters";
796
+ *
797
+ * const eventBus = new EventBus({
798
+ * adapter: new MemoryEventBusAdapter({ rootGroup: "@global" })
799
+ * });
800
+ * const serde = new Serde(SuperJsonSerdeAdapter);
801
+ * const lockProvider: IGroupableLockProvider = new LockProvider({
802
+ * serde,
803
+ * adapter: new MemoryLockAdapter({
804
+ * rootGroup: "@global"
805
+ * }),
806
+ * eventBus,
807
+ * });
808
+ *
809
+ * const lock = lockProvider.create("a");
810
+ *
811
+ * const listener: Invokable <LockEvents> = event => {
812
+ * console.log(event);
813
+ * }
814
+ * await lock.addListener(KeyAcquiredLockEvent, listener);
815
+ * await lock.acquire();
816
+ * ```
817
+ */
280
818
  addListener(event, listener) {
281
819
  return this.lockEventBus.addListener(event, listener);
282
820
  }
821
+ /**
822
+ * You can listen to different events of the current <i>Lock</i> class instance.
823
+ *
824
+ * Refer to <i>{@link LockEvents}</i>, to se all events dispatched by <i>LockProvider</i> class instance.
825
+ * Refer to <i>{@link IEventListenable}</i> for details on how the method works.
826
+ * @example
827
+ * ```ts
828
+ * import { type IGroupableLockProvider, type LockEvents, KeyAcquiredLockEvent } from "@daiso-tech/core/lock/contracts";
829
+ * import { LockProvider } from "@daiso-tech/core/lock/implementations/derivables";
830
+ * import { MemoryLockAdapter } from "@daiso-tech/core/lock/implementations/adapters";
831
+ * import type { Invokable } from "@daiso-tech/core/event-bus/contracts";
832
+ * import { EventBus } from "@daiso-tech/core/event-bus/implementations/derivables";
833
+ * import { MemoryEventBusAdapter } from "@daiso-tech/core/event-bus/implementations/adapters";
834
+ * import { Serde } from "@daiso-tech/core/serde/implementations/derivables";
835
+ * import { SuperJsonSerdeAdapter } from "@daiso-tech/core/serde/implementations/adapters";
836
+ *
837
+ * const eventBus = new EventBus({
838
+ * adapter: new MemoryEventBusAdapter({ rootGroup: "@global" })
839
+ * });
840
+ * const serde = new Serde(SuperJsonSerdeAdapter);
841
+ * const lockProvider: IGroupableLockProvider = new LockProvider({
842
+ * serde,
843
+ * adapter: new MemoryLockAdapter({
844
+ * rootGroup: "@global"
845
+ * }),
846
+ * eventBus,
847
+ * });
848
+ *
849
+ * const lock = lockProvider.create("a");
850
+ *
851
+ * const listener: Invokable <LockEvents> = event => {
852
+ * console.log(event);
853
+ * }
854
+ * await lock.addListenerMany([KeyAcquiredLockEvent], listener);
855
+ * await lock.acquire();
856
+ * ```
857
+ */
283
858
  addListenerMany(events, listener) {
284
859
  return this.lockEventBus.addListenerMany(events, listener);
285
860
  }
861
+ /**
862
+ * You can listen to different events of the current <i>Lock</i> class instance.
863
+ *
864
+ * Refer to <i>{@link LockEvents}</i>, to se all events dispatched by <i>LockProvider</i> class instance.
865
+ * Refer to <i>{@link IEventListenable}</i> for details on how the method works.
866
+ * @example
867
+ * ```ts
868
+ * import { type IGroupableLockProvider, type LockEvents, KeyAcquiredLockEvent } from "@daiso-tech/core/lock/contracts";
869
+ * import { LockProvider } from "@daiso-tech/core/lock/implementations/derivables";
870
+ * import { MemoryLockAdapter } from "@daiso-tech/core/lock/implementations/adapters";
871
+ * import type { Invokable } from "@daiso-tech/core/event-bus/contracts";
872
+ * import { EventBus } from "@daiso-tech/core/event-bus/implementations/derivables";
873
+ * import { MemoryEventBusAdapter } from "@daiso-tech/core/event-bus/implementations/adapters";
874
+ * import { Serde } from "@daiso-tech/core/serde/implementations/derivables";
875
+ * import { SuperJsonSerdeAdapter } from "@daiso-tech/core/serde/implementations/adapters";
876
+ *
877
+ * const eventBus = new EventBus({
878
+ * adapter: new MemoryEventBusAdapter({ rootGroup: "@global" })
879
+ * });
880
+ * const serde = new Serde(SuperJsonSerdeAdapter);
881
+ * const lockProvider: IGroupableLockProvider = new LockProvider({
882
+ * serde,
883
+ * adapter: new MemoryLockAdapter({
884
+ * rootGroup: "@global"
885
+ * }),
886
+ * eventBus,
887
+ * });
888
+ *
889
+ * const lock = lockProvider.create("a");
890
+ *
891
+ * const listener: Invokable <LockEvents> = event => {
892
+ * console.log(event);
893
+ * }
894
+ * await lock.addListener(KeyAcquiredLockEvent, listener);
895
+ * await lock.removeListener(KeyAcquiredLockEvent, listener);
896
+ * await lock.acquire();
897
+ * ```
898
+ */
286
899
  removeListener(event, listener) {
287
900
  return this.lockEventBus.removeListener(event, listener);
288
901
  }
902
+ /**
903
+ * You can listen to different events of the current <i>Lock</i> class instance.
904
+ *
905
+ * Refer to <i>{@link LockEvents}</i>, to se all events dispatched by <i>LockProvider</i> class instance.
906
+ * Refer to <i>{@link IEventListenable}</i> for details on how the method works.
907
+ * @example
908
+ * ```ts
909
+ * import { type IGroupableLockProvider, type LockEvents, KeyAcquiredLockEvent } from "@daiso-tech/core/lock/contracts";
910
+ * import { LockProvider } from "@daiso-tech/core/lock/implementations/derivables";
911
+ * import { MemoryLockAdapter } from "@daiso-tech/core/lock/implementations/adapters";
912
+ * import type { Invokable } from "@daiso-tech/core/event-bus/contracts";
913
+ * import { EventBus } from "@daiso-tech/core/event-bus/implementations/derivables";
914
+ * import { MemoryEventBusAdapter } from "@daiso-tech/core/event-bus/implementations/adapters";
915
+ * import { Serde } from "@daiso-tech/core/serde/implementations/derivables";
916
+ * import { SuperJsonSerdeAdapter } from "@daiso-tech/core/serde/implementations/adapters";
917
+ *
918
+ * const eventBus = new EventBus({
919
+ * adapter: new MemoryEventBusAdapter({ rootGroup: "@global" })
920
+ * });
921
+ * const serde = new Serde(SuperJsonSerdeAdapter);
922
+ * const lockProvider: IGroupableLockProvider = new LockProvider({
923
+ * serde,
924
+ * adapter: new MemoryLockAdapter({
925
+ * rootGroup: "@global"
926
+ * }),
927
+ * eventBus,
928
+ * });
929
+ *
930
+ * const lock = lockProvider.create("a");
931
+ *
932
+ * const listener: Invokable <LockEvents> = event => {
933
+ * console.log(event);
934
+ * }
935
+ * await lock.addListenerMany([KeyAcquiredLockEvent], listener);
936
+ * await lock.removeListenerMany([KeyAcquiredLockEvent], listener);
937
+ * await lock.acquire();
938
+ * ```
939
+ */
289
940
  removeListenerMany(events, listener) {
290
941
  return this.lockEventBus.removeListenerMany(events, listener);
291
942
  }
943
+ /**
944
+ * You can listen to different events of the current <i>Lock</i> class instance.
945
+ *
946
+ * Refer to <i>{@link LockEvents}</i>, to se all events dispatched by <i>LockProvider</i> class instance.
947
+ * Refer to <i>{@link IEventListenable}</i> for details on how the method works.
948
+ * @example
949
+ * ```ts
950
+ * import { type IGroupableLockProvider, type LockEvents, KeyAcquiredLockEvent } from "@daiso-tech/core/lock/contracts";
951
+ * import { LockProvider } from "@daiso-tech/core/lock/implementations/derivables";
952
+ * import { MemoryLockAdapter } from "@daiso-tech/core/lock/implementations/adapters";
953
+ * import type { Invokable } from "@daiso-tech/core/event-bus/contracts";
954
+ * import { EventBus } from "@daiso-tech/core/event-bus/implementations/derivables";
955
+ * import { MemoryEventBusAdapter } from "@daiso-tech/core/event-bus/implementations/adapters";
956
+ * import { Serde } from "@daiso-tech/core/serde/implementations/derivables";
957
+ * import { SuperJsonSerdeAdapter } from "@daiso-tech/core/serde/implementations/adapters";
958
+ *
959
+ * const eventBus = new EventBus({
960
+ * adapter: new MemoryEventBusAdapter({ rootGroup: "@global" })
961
+ * });
962
+ * const serde = new Serde(SuperJsonSerdeAdapter);
963
+ * const lockProvider: IGroupableLockProvider = new LockProvider({
964
+ * serde,
965
+ * adapter: new MemoryLockAdapter({
966
+ * rootGroup: "@global"
967
+ * }),
968
+ * eventBus,
969
+ * });
970
+ *
971
+ * const lock = lockProvider.create("a");
972
+ *
973
+ * const listener: Invokable <LockEvents> = event => {
974
+ * console.log(event);
975
+ * }
976
+ * await lock.listenOnce(KeyAcquiredLockEvent, listener);
977
+ * await lock.acquire();
978
+ * ```
979
+ */
292
980
  listenOnce(event, listener) {
293
981
  return this.lockEventBus.listenOnce(event, listener);
294
982
  }
983
+ asPromise(event) {
984
+ return this.lockEventBus.asPromise(event);
985
+ }
986
+ /**
987
+ * You can listen to different events of the current <i>Lock</i> class instance.
988
+ *
989
+ * Refer to <i>{@link LockEvents}</i>, to se all events dispatched by <i>LockProvider</i> class instance.
990
+ * Refer to <i>{@link IEventListenable}</i> for details on how the method works.
991
+ * @example
992
+ * ```ts
993
+ * import { type IGroupableLockProvider, type LockEvents, KeyAcquiredLockEvent } from "@daiso-tech/core/lock/contracts";
994
+ * import { LockProvider } from "@daiso-tech/core/lock/implementations/derivables";
995
+ * import { MemoryLockAdapter } from "@daiso-tech/core/lock/implementations/adapters";
996
+ * import type { Invokable } from "@daiso-tech/core/event-bus/contracts";
997
+ * import { EventBus } from "@daiso-tech/core/event-bus/implementations/derivables";
998
+ * import { MemoryEventBusAdapter } from "@daiso-tech/core/event-bus/implementations/adapters";
999
+ * import { Serde } from "@daiso-tech/core/serde/implementations/derivables";
1000
+ * import { SuperJsonSerdeAdapter } from "@daiso-tech/core/serde/implementations/adapters";
1001
+ *
1002
+ * const eventBus = new EventBus({
1003
+ * adapter: new MemoryEventBusAdapter({ rootGroup: "@global" })
1004
+ * });
1005
+ * const serde = new Serde(SuperJsonSerdeAdapter);
1006
+ * const lockProvider: IGroupableLockProvider = new LockProvider({
1007
+ * serde,
1008
+ * adapter: new MemoryLockAdapter({
1009
+ * rootGroup: "@global"
1010
+ * }),
1011
+ * eventBus,
1012
+ * });
1013
+ *
1014
+ * const lock = lockProvider.create("a");
1015
+ *
1016
+ * const listener: Invokable <LockEvents> = event => {
1017
+ * console.log(event);
1018
+ * }
1019
+ * const unsubscribe = await lock.subscribe(KeyAcquiredLockEvent, listener);
1020
+ * await lock.acquire();
1021
+ * await unsubscribe();
1022
+ * ```
1023
+ */
295
1024
  subscribe(event, listener) {
296
1025
  return this.lockEventBus.subscribe(event, listener);
297
1026
  }
1027
+ /**
1028
+ * You can listen to different events of the current <i>Lock</i> class instance.
1029
+ *
1030
+ * Refer to <i>{@link LockEvents}</i>, to se all events dispatched by <i>LockProvider</i> class instance.
1031
+ * Refer to <i>{@link IEventListenable}</i> for details on how the method works.
1032
+ * @example
1033
+ * ```ts
1034
+ * import { type IGroupableLockProvider, type LockEvents, KeyAcquiredLockEvent } from "@daiso-tech/core/lock/contracts";
1035
+ * import { LockProvider } from "@daiso-tech/core/lock/implementations/derivables";
1036
+ * import { MemoryLockAdapter } from "@daiso-tech/core/lock/implementations/adapters";
1037
+ * import type { Invokable } from "@daiso-tech/core/event-bus/contracts";
1038
+ * import { EventBus } from "@daiso-tech/core/event-bus/implementations/derivables";
1039
+ * import { MemoryEventBusAdapter } from "@daiso-tech/core/event-bus/implementations/adapters";
1040
+ * import { Serde } from "@daiso-tech/core/serde/implementations/derivables";
1041
+ * import { SuperJsonSerdeAdapter } from "@daiso-tech/core/serde/implementations/adapters";
1042
+ *
1043
+ * const eventBus = new EventBus({
1044
+ * adapter: new MemoryEventBusAdapter({ rootGroup: "@global" })
1045
+ * });
1046
+ * const serde = new Serde(SuperJsonSerdeAdapter);
1047
+ * const lockProvider: IGroupableLockProvider = new LockProvider({
1048
+ * serde,
1049
+ * adapter: new MemoryLockAdapter({
1050
+ * rootGroup: "@global"
1051
+ * }),
1052
+ * eventBus,
1053
+ * });
1054
+ *
1055
+ * const lock = lockProvider.create("a");
1056
+ *
1057
+ * const listener: Invokable <LockEvents> = event => {
1058
+ * console.log(event);
1059
+ * }
1060
+ * const unsubscribe = await lock.subscribeMany([KeyAcquiredLockEvent], listener);
1061
+ * await lock.acquire();
1062
+ * await unsubscribe();
1063
+ * ```
1064
+ */
298
1065
  subscribeMany(events, listener) {
299
1066
  return this.lockEventBus.subscribeMany(events, listener);
300
1067
  }