ioredis-toolkit 0.0.10 → 0.5.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 (267) hide show
  1. package/CHANGELOG.md +67 -0
  2. package/LICENSE +1 -1
  3. package/README.md +68 -1613
  4. package/dist/cache/cache.d.ts +30 -0
  5. package/dist/cache/cache.d.ts.map +1 -0
  6. package/dist/cache/cache.js +59 -0
  7. package/dist/cache/cache.js.map +1 -0
  8. package/dist/cache/config.d.ts +12 -0
  9. package/dist/cache/config.d.ts.map +1 -0
  10. package/dist/cache/config.js +13 -0
  11. package/dist/cache/config.js.map +1 -0
  12. package/dist/cache/types.d.ts +32 -0
  13. package/dist/cache/types.d.ts.map +1 -0
  14. package/dist/cache/types.js +5 -0
  15. package/dist/cache/types.js.map +1 -0
  16. package/dist/index.d.ts +43 -51
  17. package/dist/index.d.ts.map +1 -0
  18. package/dist/index.js +32 -44
  19. package/dist/index.js.map +1 -0
  20. package/dist/lock/config.d.ts +12 -0
  21. package/dist/lock/config.d.ts.map +1 -0
  22. package/dist/lock/config.js +8 -0
  23. package/dist/lock/config.js.map +1 -0
  24. package/dist/lock/lock.d.ts +20 -0
  25. package/dist/lock/lock.d.ts.map +1 -0
  26. package/dist/lock/lock.js +44 -0
  27. package/dist/lock/lock.js.map +1 -0
  28. package/dist/lock/types.d.ts +19 -0
  29. package/dist/lock/types.d.ts.map +1 -0
  30. package/dist/lock/types.js +2 -0
  31. package/dist/lock/types.js.map +1 -0
  32. package/dist/modules-config.d.ts +3 -0
  33. package/dist/modules-config.d.ts.map +1 -0
  34. package/dist/modules-config.js +2 -0
  35. package/dist/modules-config.js.map +1 -0
  36. package/dist/pubsub/config.d.ts +11 -0
  37. package/dist/pubsub/config.d.ts.map +1 -0
  38. package/dist/pubsub/config.js +6 -0
  39. package/dist/pubsub/config.js.map +1 -0
  40. package/dist/pubsub/pubsub.d.ts +20 -0
  41. package/dist/pubsub/pubsub.d.ts.map +1 -0
  42. package/dist/pubsub/pubsub.js +54 -0
  43. package/dist/pubsub/pubsub.js.map +1 -0
  44. package/dist/pubsub/types.d.ts +24 -0
  45. package/dist/pubsub/types.d.ts.map +1 -0
  46. package/dist/pubsub/types.js +2 -0
  47. package/dist/pubsub/types.js.map +1 -0
  48. package/dist/rate-limit/config.d.ts +12 -0
  49. package/dist/rate-limit/config.d.ts.map +1 -0
  50. package/dist/rate-limit/config.js +6 -0
  51. package/dist/rate-limit/config.js.map +1 -0
  52. package/dist/rate-limit/rate-limiter.d.ts +18 -0
  53. package/dist/rate-limit/rate-limiter.d.ts.map +1 -0
  54. package/dist/rate-limit/rate-limiter.js +37 -0
  55. package/dist/rate-limit/rate-limiter.js.map +1 -0
  56. package/dist/rate-limit/types.d.ts +27 -0
  57. package/dist/rate-limit/types.d.ts.map +1 -0
  58. package/dist/rate-limit/types.js +2 -0
  59. package/dist/rate-limit/types.js.map +1 -0
  60. package/dist/redis/client-facade.d.ts +77 -0
  61. package/dist/redis/client-facade.d.ts.map +1 -0
  62. package/dist/redis/client-facade.js +102 -0
  63. package/dist/redis/client-facade.js.map +1 -0
  64. package/dist/redis/client.d.ts +10 -0
  65. package/dist/redis/client.d.ts.map +1 -0
  66. package/dist/redis/client.js +29 -0
  67. package/dist/redis/client.js.map +1 -0
  68. package/dist/redis/cluster.d.ts +7 -0
  69. package/dist/redis/cluster.d.ts.map +1 -0
  70. package/dist/redis/cluster.js +47 -0
  71. package/dist/redis/cluster.js.map +1 -0
  72. package/dist/redis/config.d.ts +39 -0
  73. package/dist/redis/config.d.ts.map +1 -0
  74. package/dist/redis/config.js +52 -0
  75. package/dist/redis/config.js.map +1 -0
  76. package/dist/redis/errors.d.ts +5 -0
  77. package/dist/redis/errors.d.ts.map +1 -0
  78. package/dist/redis/errors.js +5 -0
  79. package/dist/redis/errors.js.map +1 -0
  80. package/dist/redis/types.d.ts +135 -0
  81. package/dist/redis/types.d.ts.map +1 -0
  82. package/dist/redis/types.js +2 -0
  83. package/dist/redis/types.js.map +1 -0
  84. package/dist/redis/wrapper.d.ts +88 -0
  85. package/dist/redis/wrapper.d.ts.map +1 -0
  86. package/dist/redis/wrapper.js +206 -0
  87. package/dist/redis/wrapper.js.map +1 -0
  88. package/dist/session/config.d.ts +47 -0
  89. package/dist/session/config.d.ts.map +1 -0
  90. package/dist/session/config.js +101 -0
  91. package/dist/session/config.js.map +1 -0
  92. package/dist/session/cookie.d.ts +16 -0
  93. package/dist/session/cookie.d.ts.map +1 -0
  94. package/dist/session/cookie.js +28 -0
  95. package/dist/session/cookie.js.map +1 -0
  96. package/dist/session/errors.d.ts +56 -0
  97. package/dist/session/errors.d.ts.map +1 -0
  98. package/dist/session/errors.js +58 -0
  99. package/dist/session/errors.js.map +1 -0
  100. package/dist/session/factory.d.ts +21 -0
  101. package/dist/session/factory.d.ts.map +1 -0
  102. package/dist/session/factory.js +30 -0
  103. package/dist/session/factory.js.map +1 -0
  104. package/dist/session/health.d.ts +12 -0
  105. package/dist/session/health.d.ts.map +1 -0
  106. package/dist/session/health.js +23 -0
  107. package/dist/session/health.js.map +1 -0
  108. package/dist/session/keys.d.ts +23 -0
  109. package/dist/session/keys.d.ts.map +1 -0
  110. package/dist/session/keys.js +27 -0
  111. package/dist/session/keys.js.map +1 -0
  112. package/dist/session/manager.d.ts +34 -0
  113. package/dist/session/manager.d.ts.map +1 -0
  114. package/dist/session/manager.js +31 -0
  115. package/dist/session/manager.js.map +1 -0
  116. package/dist/session/metrics.d.ts +11 -0
  117. package/dist/session/metrics.d.ts.map +1 -0
  118. package/dist/session/metrics.js +10 -0
  119. package/dist/session/metrics.js.map +1 -0
  120. package/dist/session/repository.d.ts +49 -0
  121. package/dist/session/repository.d.ts.map +1 -0
  122. package/dist/session/repository.js +203 -0
  123. package/dist/session/repository.js.map +1 -0
  124. package/dist/session/revocation.d.ts +22 -0
  125. package/dist/session/revocation.d.ts.map +1 -0
  126. package/dist/session/revocation.js +41 -0
  127. package/dist/session/revocation.js.map +1 -0
  128. package/dist/session/script-sources.d.ts +11 -0
  129. package/dist/session/script-sources.d.ts.map +1 -0
  130. package/dist/session/script-sources.js +140 -0
  131. package/dist/session/script-sources.js.map +1 -0
  132. package/dist/session/scripts.d.ts +15 -0
  133. package/dist/session/scripts.d.ts.map +1 -0
  134. package/dist/session/scripts.js +41 -0
  135. package/dist/session/scripts.js.map +1 -0
  136. package/dist/session/serializer.d.ts +12 -0
  137. package/dist/session/serializer.d.ts.map +1 -0
  138. package/dist/session/serializer.js +77 -0
  139. package/dist/session/serializer.js.map +1 -0
  140. package/dist/session/service.d.ts +48 -0
  141. package/dist/session/service.d.ts.map +1 -0
  142. package/dist/session/service.js +235 -0
  143. package/dist/session/service.js.map +1 -0
  144. package/dist/session/token.d.ts +16 -0
  145. package/dist/session/token.d.ts.map +1 -0
  146. package/dist/session/token.js +32 -0
  147. package/dist/session/token.js.map +1 -0
  148. package/dist/session/types.d.ts +134 -0
  149. package/dist/session/types.d.ts.map +1 -0
  150. package/dist/session/types.js +2 -0
  151. package/dist/session/types.js.map +1 -0
  152. package/dist/streams/config.d.ts +12 -0
  153. package/dist/streams/config.d.ts.map +1 -0
  154. package/dist/streams/config.js +6 -0
  155. package/dist/streams/config.js.map +1 -0
  156. package/dist/streams/streams.d.ts +24 -0
  157. package/dist/streams/streams.d.ts.map +1 -0
  158. package/dist/streams/streams.js +55 -0
  159. package/dist/streams/streams.js.map +1 -0
  160. package/dist/streams/types.d.ts +32 -0
  161. package/dist/streams/types.d.ts.map +1 -0
  162. package/dist/streams/types.js +2 -0
  163. package/dist/streams/types.js.map +1 -0
  164. package/docs/ACCEPTANCE-REPORT.md +70 -0
  165. package/docs/ARCHITECTURE.md +61 -0
  166. package/docs/CAPACITY.md +33 -0
  167. package/docs/DEPLOYMENT.md +22 -0
  168. package/docs/README-API.md +15 -0
  169. package/docs/STATE-MACHINE.md +38 -0
  170. package/docs/TESTING.md +37 -0
  171. package/docs/THREAT-MODEL.md +23 -0
  172. package/docs/TYPE-SAFETY.md +34 -0
  173. package/docs/modules/cache/README.md +7 -0
  174. package/docs/modules/cache/usage.md +156 -0
  175. package/docs/modules/lock/README.md +7 -0
  176. package/docs/modules/lock/usage.md +105 -0
  177. package/docs/modules/pubsub/README.md +7 -0
  178. package/docs/modules/pubsub/usage.md +106 -0
  179. package/docs/modules/rate-limit/README.md +7 -0
  180. package/docs/modules/rate-limit/usage.md +100 -0
  181. package/docs/modules/sessions/README.md +7 -0
  182. package/docs/modules/sessions/usage.md +262 -0
  183. package/docs/modules/streams/README.md +7 -0
  184. package/docs/modules/streams/usage.md +141 -0
  185. package/package.json +50 -60
  186. package/src/scripts/cleanup-index.lua +4 -0
  187. package/src/scripts/conditional-update.lua +21 -0
  188. package/src/scripts/consume-session.lua +21 -0
  189. package/src/scripts/create-session.lua +28 -0
  190. package/src/scripts/delete.lua +2 -0
  191. package/src/scripts/destroy-user.lua +13 -0
  192. package/src/scripts/enforce-limit.lua +17 -0
  193. package/src/scripts/revoke-session.lua +13 -0
  194. package/src/scripts/rotate.lua +24 -0
  195. package/src/scripts/touch-session.lua +28 -0
  196. package/src/scripts/update-session.lua +18 -0
  197. package/dist/cache.d.ts +0 -797
  198. package/dist/cache.js +0 -1115
  199. package/dist/client.d.ts +0 -287
  200. package/dist/client.js +0 -1113
  201. package/dist/cluster-slot.d.ts +0 -4
  202. package/dist/cluster-slot.js +0 -31
  203. package/dist/cluster.d.ts +0 -79
  204. package/dist/cluster.js +0 -156
  205. package/dist/errors.d.ts +0 -30
  206. package/dist/errors.js +0 -63
  207. package/dist/health.d.ts +0 -180
  208. package/dist/health.js +0 -239
  209. package/dist/lock.d.ts +0 -233
  210. package/dist/lock.js +0 -440
  211. package/dist/logger.d.ts +0 -12
  212. package/dist/logger.js +0 -40
  213. package/dist/pubsub.d.ts +0 -423
  214. package/dist/pubsub.js +0 -537
  215. package/dist/ratelimiter.d.ts +0 -441
  216. package/dist/ratelimiter.js +0 -539
  217. package/dist/session/index.d.ts +0 -23
  218. package/dist/session/index.js +0 -16
  219. package/dist/session/revocation-store.d.ts +0 -176
  220. package/dist/session/revocation-store.js +0 -318
  221. package/dist/session/scripts/cleanup-index.lua +0 -21
  222. package/dist/session/scripts/conditional-update-encrypted.lua +0 -60
  223. package/dist/session/scripts/conditional-update.lua +0 -63
  224. package/dist/session/scripts/create.lua +0 -83
  225. package/dist/session/scripts/delete-by-user.lua +0 -29
  226. package/dist/session/scripts/delete.lua +0 -15
  227. package/dist/session/scripts/enforce-limit.lua +0 -38
  228. package/dist/session/scripts/revoke.lua +0 -61
  229. package/dist/session/scripts/rotate-encrypted.lua +0 -149
  230. package/dist/session/scripts/rotate.lua +0 -167
  231. package/dist/session/scripts/touch-encrypted.lua +0 -89
  232. package/dist/session/scripts/touch.lua +0 -72
  233. package/dist/session/scripts/validate.lua +0 -90
  234. package/dist/session/session-circuit-breaker.d.ts +0 -42
  235. package/dist/session/session-circuit-breaker.js +0 -129
  236. package/dist/session/session-config.d.ts +0 -355
  237. package/dist/session/session-config.js +0 -171
  238. package/dist/session/session-cookie.d.ts +0 -72
  239. package/dist/session/session-cookie.js +0 -101
  240. package/dist/session/session-encryption.d.ts +0 -87
  241. package/dist/session/session-encryption.js +0 -139
  242. package/dist/session/session-errors.d.ts +0 -85
  243. package/dist/session/session-errors.js +0 -145
  244. package/dist/session/session-health.d.ts +0 -38
  245. package/dist/session/session-health.js +0 -60
  246. package/dist/session/session-keys.d.ts +0 -64
  247. package/dist/session/session-keys.js +0 -128
  248. package/dist/session/session-manager.d.ts +0 -73
  249. package/dist/session/session-manager.js +0 -94
  250. package/dist/session/session-metrics.d.ts +0 -41
  251. package/dist/session/session-metrics.js +0 -135
  252. package/dist/session/session-repository.d.ts +0 -184
  253. package/dist/session/session-repository.js +0 -763
  254. package/dist/session/session-scripts.d.ts +0 -36
  255. package/dist/session/session-scripts.js +0 -130
  256. package/dist/session/session-serializer.d.ts +0 -42
  257. package/dist/session/session-serializer.js +0 -267
  258. package/dist/session/session-service.d.ts +0 -123
  259. package/dist/session/session-service.js +0 -670
  260. package/dist/session/session-token.d.ts +0 -38
  261. package/dist/session/session-token.js +0 -86
  262. package/dist/session/session-types.d.ts +0 -281
  263. package/dist/session/session-types.js +0 -16
  264. package/dist/types.d.ts +0 -924
  265. package/dist/types.js +0 -151
  266. package/dist/utils/deepmerge.d.ts +0 -9
  267. package/dist/utils/deepmerge.js +0 -61
package/dist/health.js DELETED
@@ -1,239 +0,0 @@
1
- import { defaultLogger } from './logger.js';
2
- export class HealthChecker {
3
- client;
4
- logger;
5
- timer = null;
6
- callbacks = [];
7
- lastStatus = null;
8
- /**
9
- * Creates a health checker instance.
10
- *
11
- * @param client - The underlying {@link RedisClientWrapper}.
12
- * @param logger - Optional pino-compatible logger; defaults to `console`.
13
- *
14
- * @example
15
- * ```ts
16
- * const health = new HealthChecker(client);
17
- * ```
18
- */
19
- constructor(client, logger = defaultLogger) {
20
- this.client = client;
21
- this.logger = logger.child({ component: 'HealthChecker' });
22
- }
23
- /**
24
- * Starts periodic health checks.
25
- *
26
- * **Behavior:**
27
- * - If a timer is already running, it is cleared and replaced with the new interval.
28
- * - Health checks run at the specified `interval` in milliseconds.
29
- * - Each check runs asynchronously; errors are logged but do not stop the interval.
30
- * - The first check runs immediately when `start()` is called (depending on setInterval timing).
31
- *
32
- * **Parameters:**
33
- * - `interval` - Check interval in milliseconds. Default: `10000` (10 seconds).
34
- *
35
- * @example
36
- * ```ts
37
- * // Check every 5 seconds
38
- * health.start(5000);
39
- *
40
- * // Check every 30 seconds (default)
41
- * health.start();
42
- * ```
43
- *
44
- * @returns `void`
45
- */
46
- start(interval = 10000) {
47
- if (this.timer) {
48
- clearInterval(this.timer);
49
- }
50
- this.timer = setInterval(() => {
51
- this.check().catch((error) => {
52
- this.logger.error('Health check failed:', error);
53
- });
54
- }, interval);
55
- this.logger.info(`Health checker started (interval: ${interval}ms)`);
56
- }
57
- /**
58
- * Stops the health checker.
59
- *
60
- * **Behavior:**
61
- * - Clears the internal timer, stopping further health checks.
62
- * - Logs a warning if no timer was active.
63
- *
64
- * @example
65
- * ```ts
66
- * health.stop();
67
- * ```
68
- *
69
- * @returns `void`
70
- */
71
- stop() {
72
- if (this.timer) {
73
- clearInterval(this.timer);
74
- this.timer = null;
75
- this.logger.info('Health checker stopped');
76
- }
77
- }
78
- /**
79
- * Runs a single health check.
80
- *
81
- * **Behavior:**
82
- * - Performs a PING command to verify Redis connectivity.
83
- * - Attempts to fetch Redis INFO for additional details (connections, memory).
84
- * In cluster mode, INFO may not be available and is silently ignored.
85
- * - Measures latency of the PING command.
86
- * - Updates the internal `lastStatus` and notifies all registered callbacks.
87
- *
88
- * **Returns:**
89
- * - A {@link HealthStatus} object with the current health state.
90
- *
91
- * **Example:**
92
- * ```ts
93
- * const status = await health.check();
94
- * console.log(status.healthy, status.latency);
95
- * // healthy === true, latency === 1.2 (ms)
96
- * ```
97
- *
98
- * **Parameters:**
99
- * - None
100
- *
101
- * @returns Current health status.
102
- */
103
- async check() {
104
- const start = Date.now();
105
- const details = {
106
- ping: false,
107
- };
108
- try {
109
- const ping = await this.client.ping();
110
- details.ping = ping;
111
- // Try to get some info
112
- try {
113
- const info = await this.client.raw.info();
114
- const connections = info.match(/connected_clients:(\d+)/)?.[1];
115
- const memory = info.match(/used_memory_human:([^\n]+)/)?.[1];
116
- if (connections)
117
- details.connections = parseInt(connections, 10);
118
- if (memory)
119
- details.memory = memory.trim();
120
- }
121
- catch {
122
- // Info not available in cluster mode
123
- }
124
- }
125
- catch (error) {
126
- this.logger.error('Health check error:', error);
127
- details.ping = false;
128
- }
129
- const latency = Date.now() - start;
130
- const healthy = details.ping;
131
- const status = {
132
- healthy,
133
- status: healthy ? 'healthy' : 'unhealthy',
134
- latency,
135
- timestamp: new Date(),
136
- details,
137
- };
138
- this.lastStatus = status;
139
- this.notifyCallbacks(status);
140
- return status;
141
- }
142
- /**
143
- * Returns the most recent health check result.
144
- *
145
- * @returns The last {@link HealthStatus}, or `null` before the first check.
146
- *
147
- * @example
148
- * ```ts
149
- * const status = health.getStatus();
150
- * console.log(status?.healthy, status?.latency);
151
- * ```
152
- */
153
- /**
154
- * Returns the most recent health check result.
155
- *
156
- * **Returns:**
157
- * - The last {@link HealthStatus}, or `null` before the first check.
158
- *
159
- * **Example:**
160
- * ```ts
161
- * const status = health.getStatus();
162
- * console.log(status?.healthy, status?.latency);
163
- * ```
164
- *
165
- * **Parameters:**
166
- * - None
167
- *
168
- * @returns The last result, or `null`.
169
- */
170
- getStatus() {
171
- return this.lastStatus;
172
- }
173
- /**
174
- * Registers a callback for health status changes.
175
- *
176
- * **Behavior:**
177
- * - The callback is invoked whenever a health check runs and the status changes.
178
- * - Callbacks are invoked synchronously within the `check()` method.
179
- * - Multiple callbacks can be registered; they are invoked in registration order.
180
- *
181
- * **Parameters:**
182
- * - `callback` - A function receiving a {@link HealthStatus} object.
183
- *
184
- * @example
185
- * ```ts
186
- * health.onChange((status) => {
187
- * console.log(`Health status: ${status.status}, latency: ${status.latency}ms`);
188
- * });
189
- * ```
190
- *
191
- * @returns `void`
192
- */
193
- onChange(callback) {
194
- this.callbacks.push(callback);
195
- }
196
- notifyCallbacks(status) {
197
- for (const callback of this.callbacks) {
198
- try {
199
- callback(status);
200
- }
201
- catch (error) {
202
- this.logger.error('Callback error:', error);
203
- }
204
- }
205
- }
206
- /**
207
- * Waits until the Redis connection is healthy.
208
- *
209
- * **Behavior:**
210
- * - Polls {@link check} at 1-second intervals.
211
- * - Returns `true` as soon as `status.healthy` is `true`.
212
- * - Returns `false` if the timeout is reached without becoming healthy.
213
- *
214
- * **Parameters:**
215
- * - `timeout` - Maximum time to wait in milliseconds. Default: `30000` (30 seconds).
216
- *
217
- * **Returns:**
218
- * - `true` if the connection became healthy within the timeout.
219
- * - `false` if the timeout was reached without the connection becoming healthy.
220
- *
221
- * **Example:**
222
- * ```ts
223
- * const healthy = await health.waitForHealthy(10000);
224
- * // healthy === true if Redis became healthy within 10 seconds
225
- * ```
226
- *
227
- * @returns `true` if became healthy within timeout.
228
- */
229
- async waitForHealthy(timeout = 30000) {
230
- const start = Date.now();
231
- while (Date.now() - start < timeout) {
232
- const status = await this.check();
233
- if (status.healthy)
234
- return true;
235
- await new Promise(resolve => setTimeout(resolve, 1000));
236
- }
237
- return false;
238
- }
239
- }
package/dist/lock.d.ts DELETED
@@ -1,233 +0,0 @@
1
- import { RedisClientWrapper } from './client.js';
2
- import { LoggerLike } from './logger.js';
3
- import { DistributedLockOptions, LockInfo } from './types.js';
4
- /**
5
- * Information about a distributed lock.
6
- *
7
- * **Fields:**
8
- * - `locked`: Whether the lock is currently held.
9
- * - `ttl`: Remaining TTL in seconds (when held and TTL set).
10
- * - `lockId`: Unique owner id of the lock.
11
- *
12
- * **Example:**
13
- * ```ts
14
- * const info = await lock.getLockInfo('order:42');
15
- * // { locked: true, ttl: 29, lockId: 'a1b2c3...' }
16
- * ```
17
- */
18
- /**
19
- * Options for the distributed lock.
20
- *
21
- * **Fields:**
22
- * - `ttl`: Lock TTL in milliseconds. Default: `30000`.
23
- * - `retryCount`: Number of acquisition attempts. Default: `3`.
24
- * - `retryDelay`: Base delay between retries in ms (grows exponentially). Default: `200`.
25
- *
26
- * **Example:**
27
- * ```ts
28
- * const lock = new DistributedLock(client, { ttl: 10000, retryCount: 5 });
29
- * ```
30
- */
31
- /**
32
- * Distributed mutual-exclusion lock backed by Redis.
33
- *
34
- * Works in standalone, sentinel and cluster modes. Acquisition uses atomic
35
- * `SET ... PX NX`; release and extension use Lua scripts so only the lock owner
36
- * can release or extend. `withLock` auto-extends the lock at half TTL while the
37
- * critical section runs and always releases afterwards.
38
- *
39
- * @example
40
- * ```ts
41
- * const lock = new DistributedLock(client, { ttl: 30000, retryCount: 5 });
42
- * const acquired = await lock.acquire('order:42');
43
- * if (acquired) {
44
- * try {
45
- * // critical section
46
- * } finally {
47
- * await lock.release('order:42');
48
- * }
49
- * }
50
- * ```
51
- */
52
- export declare class DistributedLock {
53
- private client;
54
- private logger;
55
- private defaultTTL;
56
- private defaultRetryCount;
57
- private defaultRetryDelay;
58
- /**
59
- * Creates a distributed lock bound to a Redis client.
60
- *
61
- * @param client - The underlying {@link RedisClientWrapper}.
62
- * @param logger - Optional pino-compatible logger; defaults to `console`.
63
- * @param options - Defaults for `ttl` (ms), `retryCount` and `retryDelay`.
64
- *
65
- * @example
66
- * ```ts
67
- * const lock = new DistributedLock(client, { ttl: 10000, retryCount: 3 });
68
- * ```
69
- */
70
- constructor(client: RedisClientWrapper, logger?: LoggerLike, options?: Partial<DistributedLockOptions>);
71
- private getLockKey;
72
- private generateLockId;
73
- private executeWithRetry;
74
- /**
75
- * Attempts to acquire the lock for a key.
76
- *
77
- * Uses atomic `SET lock:<key> <id> PX <ttl> NX` with exponential backoff
78
- * retries. Locks expire automatically after `ttl` ms, so a crashed holder
79
- * never blocks others forever.
80
- *
81
- * @param key - The resource to lock, e.g. `'order:42'` (stored as `lock:order:42`).
82
- * @param ttl - Lock TTL in milliseconds (default: `30000`).
83
- *
84
- * @returns `true` when the lock was acquired.
85
- *
86
- * @example
87
- * ```ts
88
- * const acquired = await lock.acquire('order:42', 10000);
89
- * // acquired === true when lock was successfully acquired
90
- * ```
91
- */
92
- acquire(key: string, ttl?: number): Promise<boolean>;
93
- /**
94
- * Releases the lock, but only if this process still owns it.
95
- *
96
- * Uses an atomic Lua check-and-delete so a lock whose TTL expired (and was
97
- * re-acquired by someone else) is never removed by the old owner.
98
- *
99
- * @param key - The locked resource.
100
- *
101
- * @returns `true` if the lock was released, `false` if not owned or missing.
102
- *
103
- * @example
104
- * ```ts
105
- * await lock.release('order:42');
106
- * ```
107
- */
108
- release(key: string): Promise<boolean>;
109
- /**
110
- * Force-releases a lock without checking ownership.
111
- *
112
- * Use with care: only for emergency cleanup or when the holder is known to
113
- * be gone. This is what `withLock` falls back to when a normal release fails.
114
- *
115
- * @param key - The locked resource.
116
- *
117
- * @returns `true` if a lock existed and was deleted.
118
- *
119
- * @example
120
- * ```ts
121
- * await lock.releaseForce('order:42');
122
- * ```
123
- */
124
- releaseForce(key: string): Promise<boolean>;
125
- /**
126
- * Extends the TTL of a lock this process still owns.
127
- *
128
- * Uses an atomic Lua script so a re-acquired lock is never extended by the
129
- * old owner.
130
- *
131
- * @param key - The locked resource.
132
- * @param ttl - New TTL in milliseconds (default: `30000`).
133
- *
134
- * @returns `true` if the lock was extended.
135
- *
136
- * @example
137
- * ```ts
138
- * const extended = await lock.extend('order:42', 30000);
139
- * // extended === true when lock TTL was renewed
140
- * ```
141
- */
142
- extend(key: string, ttl?: number): Promise<boolean>;
143
- /**
144
- * Runs a critical section while holding a lock.
145
- *
146
- * Acquires the lock (with retries), auto-extends it at half TTL while `fn`
147
- * runs, detects a lost lock, and always releases afterwards (force-releasing
148
- * if a normal release fails).
149
- *
150
- * @param key - The resource to lock.
151
- * @param fn - The critical section to run exclusively.
152
- * @param options - Per-call `ttl` (ms), `retryCount`, `retryDelay`.
153
- *
154
- * @returns The return value of `fn`.
155
- *
156
- * @throws {@link RedisError} with code `LOCK_ACQUISITION_FAILED` when the lock
157
- * cannot be acquired, or `LOCK_LOST` when the lock expired mid-execution.
158
- *
159
- * @example
160
- * ```ts
161
- * const result = await lock.withLock('inventory:sku-1', async () => {
162
- * return await updateStock();
163
- * });
164
- * ```
165
- */
166
- withLock<T>(key: string, fn: () => Promise<T>, options?: DistributedLockOptions): Promise<T>;
167
- /**
168
- * Checks whether a lock is currently held.
169
- *
170
- * @param key - The locked resource.
171
- *
172
- * @returns `true` if the lock exists (held by anyone).
173
- *
174
- * @example
175
- * ```ts
176
- * const busy = await lock.isLocked('order:42');
177
- * ```
178
- */
179
- isLocked(key: string): Promise<boolean>;
180
- /**
181
- * Returns details about a lock.
182
- *
183
- * @param key - The locked resource.
184
- *
185
- * @returns `{ locked: false }` when not held, otherwise `{ locked: true, ttl, lockId }`.
186
- *
187
- * @example
188
- * ```ts
189
- * const info = await lock.getLockInfo('order:42');
190
- * // { locked: true, ttl: 29, lockId: 'a1b2c3...' }
191
- * ```
192
- */
193
- getLockInfo(key: string): Promise<LockInfo>;
194
- /**
195
- * Returns the owner id of a lock.
196
- *
197
- * @param key - The locked resource.
198
- *
199
- * @returns The lock id (random hex token), or `null` when not held.
200
- *
201
- * @example
202
- * ```ts
203
- * const owner = await lock.getLockOwner('order:42');
204
- * ```
205
- */
206
- getLockOwner(key: string): Promise<string | null>;
207
- /**
208
- * Returns the remaining TTL of a lock in seconds.
209
- *
210
- * @param key - The locked resource.
211
- *
212
- * @returns Remaining seconds (`0` when not held or expired).
213
- *
214
- * @example
215
- * ```ts
216
- * const remaining = await lock.getLockTTL('order:42');
217
- * ```
218
- */
219
- getLockTTL(key: string): Promise<number>;
220
- /**
221
- * Deletes every lock key (`lock:*`) from Redis.
222
- *
223
- * Intended for tests and emergency recovery only.
224
- *
225
- * @returns The number of deleted locks.
226
- *
227
- * @example
228
- * ```ts
229
- * const removed = await lock.cleanupAll();
230
- * ```
231
- */
232
- cleanupAll(): Promise<number>;
233
- }