@beignet/provider-locks-redis 0.0.14 → 0.0.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/dist/index.d.ts +112 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +349 -0
- package/dist/index.js.map +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @beignet/provider-locks-redis
|
|
3
|
+
*
|
|
4
|
+
* Redis-backed locks provider for Beignet.
|
|
5
|
+
*/
|
|
6
|
+
import type { LocksPort } from "@beignet/core/locks";
|
|
7
|
+
import { type ProviderInstrumentationTarget } from "@beignet/core/providers";
|
|
8
|
+
import { Redis } from "ioredis";
|
|
9
|
+
import { z } from "zod";
|
|
10
|
+
declare const RedisLocksConfigSchema: z.ZodObject<{
|
|
11
|
+
URL: z.ZodString;
|
|
12
|
+
DB: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>>;
|
|
13
|
+
PREFIX: z.ZodDefault<z.ZodString>;
|
|
14
|
+
CONNECT_TIMEOUT_MS: z.ZodDefault<z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>>;
|
|
15
|
+
MAX_RETRIES_PER_REQUEST: z.ZodDefault<z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>>;
|
|
16
|
+
CONNECT_MAX_ATTEMPTS: z.ZodDefault<z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>>;
|
|
17
|
+
}, z.core.$strip>;
|
|
18
|
+
export type RedisLocksConfig = z.infer<typeof RedisLocksConfigSchema>;
|
|
19
|
+
/**
|
|
20
|
+
* Redis client surface used by the locks adapter.
|
|
21
|
+
*/
|
|
22
|
+
export interface RedisLocksClient {
|
|
23
|
+
eval(script: string, numberOfKeys: number, ...args: unknown[]): Promise<unknown>;
|
|
24
|
+
del(key: string): Promise<number>;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Escape hatch for apps that need the raw Redis client.
|
|
28
|
+
*/
|
|
29
|
+
export interface RedisLocksEscapeHatch {
|
|
30
|
+
client: RedisLocksClient;
|
|
31
|
+
prefix: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Ports contributed by the Redis locks provider.
|
|
35
|
+
*/
|
|
36
|
+
export interface RedisLocksProviderPorts {
|
|
37
|
+
locks: LocksPort;
|
|
38
|
+
redisLocks: RedisLocksEscapeHatch;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Options for the direct Redis locks factory.
|
|
42
|
+
*/
|
|
43
|
+
export interface CreateRedisLocksOptions {
|
|
44
|
+
client: RedisLocksClient;
|
|
45
|
+
prefix?: string;
|
|
46
|
+
instrumentation?: ProviderInstrumentationTarget;
|
|
47
|
+
createOwnerToken?: () => string;
|
|
48
|
+
sleep?: (ms: number) => Promise<void>;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Options for the Redis locks lifecycle provider.
|
|
52
|
+
*/
|
|
53
|
+
export interface CreateRedisLocksProviderOptions {
|
|
54
|
+
client?: RedisLocksClient;
|
|
55
|
+
prefix?: string;
|
|
56
|
+
connectTimeoutMs?: number;
|
|
57
|
+
maxRetriesPerRequest?: number;
|
|
58
|
+
retryStrategy?: (times: number) => number | null;
|
|
59
|
+
db?: number;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Create a Redis-backed locks port.
|
|
63
|
+
*/
|
|
64
|
+
export declare function createRedisLocks(options: CreateRedisLocksOptions): LocksPort;
|
|
65
|
+
/**
|
|
66
|
+
* Create an env-backed Redis locks provider.
|
|
67
|
+
*/
|
|
68
|
+
export declare function createRedisLocksProvider(options?: CreateRedisLocksProviderOptions): import("@beignet/core/providers").ServiceProvider<unknown, import("@standard-schema/spec").StandardSchemaV1<void, void>, {
|
|
69
|
+
locks: LocksPort;
|
|
70
|
+
redisLocks: {
|
|
71
|
+
client: RedisLocksClient;
|
|
72
|
+
prefix: string;
|
|
73
|
+
};
|
|
74
|
+
}, unknown, void> | import("@beignet/core/providers").ServiceProvider<unknown, z.ZodObject<{
|
|
75
|
+
URL: z.ZodString;
|
|
76
|
+
CONNECT_MAX_ATTEMPTS: z.ZodDefault<z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>>;
|
|
77
|
+
DB: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>> | z.ZodDefault<z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>>;
|
|
78
|
+
PREFIX: z.ZodDefault<z.ZodString>;
|
|
79
|
+
CONNECT_TIMEOUT_MS: z.ZodDefault<z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>>;
|
|
80
|
+
MAX_RETRIES_PER_REQUEST: z.ZodDefault<z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>>;
|
|
81
|
+
}, z.core.$strip>, {
|
|
82
|
+
locks: LocksPort;
|
|
83
|
+
redisLocks: {
|
|
84
|
+
client: Redis;
|
|
85
|
+
prefix: string;
|
|
86
|
+
};
|
|
87
|
+
}, unknown, void>;
|
|
88
|
+
/**
|
|
89
|
+
* Default env-backed Redis locks provider.
|
|
90
|
+
*/
|
|
91
|
+
export declare const redisLocksProvider: import("@beignet/core/providers").ServiceProvider<unknown, import("@standard-schema/spec").StandardSchemaV1<void, void>, {
|
|
92
|
+
locks: LocksPort;
|
|
93
|
+
redisLocks: {
|
|
94
|
+
client: RedisLocksClient;
|
|
95
|
+
prefix: string;
|
|
96
|
+
};
|
|
97
|
+
}, unknown, void> | import("@beignet/core/providers").ServiceProvider<unknown, z.ZodObject<{
|
|
98
|
+
URL: z.ZodString;
|
|
99
|
+
CONNECT_MAX_ATTEMPTS: z.ZodDefault<z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>>;
|
|
100
|
+
DB: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>> | z.ZodDefault<z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>>;
|
|
101
|
+
PREFIX: z.ZodDefault<z.ZodString>;
|
|
102
|
+
CONNECT_TIMEOUT_MS: z.ZodDefault<z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>>;
|
|
103
|
+
MAX_RETRIES_PER_REQUEST: z.ZodDefault<z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>>;
|
|
104
|
+
}, z.core.$strip>, {
|
|
105
|
+
locks: LocksPort;
|
|
106
|
+
redisLocks: {
|
|
107
|
+
client: Redis;
|
|
108
|
+
prefix: string;
|
|
109
|
+
};
|
|
110
|
+
}, unknown, void>;
|
|
111
|
+
export {};
|
|
112
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAIV,SAAS,EACV,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAGL,KAAK,6BAA6B,EACnC,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAmCxB,QAAA,MAAM,sBAAsB;;;;;;;iBAS1B,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CACF,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,GAAG,IAAI,EAAE,OAAO,EAAE,GACjB,OAAO,CAAC,OAAO,CAAC,CAAC;IACpB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,gBAAgB,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,SAAS,CAAC;IACjB,UAAU,EAAE,qBAAqB,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,gBAAgB,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,6BAA6B,CAAC;IAChD,gBAAgB,CAAC,EAAE,MAAM,MAAM,CAAC;IAChC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC;AAED;;GAEG;AACH,MAAM,WAAW,+BAA+B;IAC9C,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IACjD,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,SAAS,CA+H5E;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,GAAE,+BAAoC;;;;;;;;;;;;;;;;;;;kBA+F9C;AAED;;GAEG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;iBAA6B,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @beignet/provider-locks-redis
|
|
3
|
+
*
|
|
4
|
+
* Redis-backed locks provider for Beignet.
|
|
5
|
+
*/
|
|
6
|
+
import { LeaseOptionsError } from "@beignet/core/locks";
|
|
7
|
+
import { createProvider, createProviderInstrumentation, } from "@beignet/core/providers";
|
|
8
|
+
import { Redis } from "ioredis";
|
|
9
|
+
import { z } from "zod";
|
|
10
|
+
const DEFAULT_CONNECT_TIMEOUT_MS = 5000;
|
|
11
|
+
const DEFAULT_MAX_RETRIES_PER_REQUEST = 2;
|
|
12
|
+
const DEFAULT_CONNECT_MAX_ATTEMPTS = 3;
|
|
13
|
+
const DEFAULT_PREFIX = "beignet:locks";
|
|
14
|
+
const DEFAULT_RETRY_DELAY_MS = 50;
|
|
15
|
+
const RECONNECT_BACKOFF_CAP_MS = 2000;
|
|
16
|
+
const ACQUIRE_SCRIPT = `
|
|
17
|
+
if redis.call("set", KEYS[1], ARGV[1], "PX", ARGV[2], "NX") then
|
|
18
|
+
return redis.call("incr", KEYS[2])
|
|
19
|
+
end
|
|
20
|
+
return nil
|
|
21
|
+
`;
|
|
22
|
+
const RELEASE_SCRIPT = `
|
|
23
|
+
if redis.call("get", KEYS[1]) == ARGV[1] then
|
|
24
|
+
return redis.call("del", KEYS[1])
|
|
25
|
+
end
|
|
26
|
+
return 0
|
|
27
|
+
`;
|
|
28
|
+
const RENEW_SCRIPT = `
|
|
29
|
+
if redis.call("get", KEYS[1]) == ARGV[1] then
|
|
30
|
+
return redis.call("pexpire", KEYS[1], ARGV[2])
|
|
31
|
+
end
|
|
32
|
+
return 0
|
|
33
|
+
`;
|
|
34
|
+
const NumberString = z
|
|
35
|
+
.string()
|
|
36
|
+
.regex(/^\d+$/, "Expected a non-negative integer string")
|
|
37
|
+
.transform((value) => Number.parseInt(value, 10));
|
|
38
|
+
const RedisLocksConfigSchema = z.object({
|
|
39
|
+
URL: z.string().url(),
|
|
40
|
+
DB: NumberString.optional(),
|
|
41
|
+
PREFIX: z.string().default(DEFAULT_PREFIX),
|
|
42
|
+
CONNECT_TIMEOUT_MS: NumberString.default(DEFAULT_CONNECT_TIMEOUT_MS),
|
|
43
|
+
MAX_RETRIES_PER_REQUEST: NumberString.default(DEFAULT_MAX_RETRIES_PER_REQUEST),
|
|
44
|
+
CONNECT_MAX_ATTEMPTS: NumberString.default(DEFAULT_CONNECT_MAX_ATTEMPTS),
|
|
45
|
+
});
|
|
46
|
+
/**
|
|
47
|
+
* Create a Redis-backed locks port.
|
|
48
|
+
*/
|
|
49
|
+
export function createRedisLocks(options) {
|
|
50
|
+
const client = options.client;
|
|
51
|
+
const prefix = options.prefix ?? DEFAULT_PREFIX;
|
|
52
|
+
const sleep = options.sleep ?? defaultSleep;
|
|
53
|
+
const createOwnerToken = options.createOwnerToken ?? createRandomToken;
|
|
54
|
+
const instrumentation = createProviderInstrumentation(options.instrumentation, {
|
|
55
|
+
providerName: "locks-redis",
|
|
56
|
+
watcher: "locks",
|
|
57
|
+
});
|
|
58
|
+
const fullKey = (key) => (prefix ? `${prefix}:${key}` : key);
|
|
59
|
+
const fencingKey = (key) => `${fullKey(key)}:fence`;
|
|
60
|
+
const locks = {
|
|
61
|
+
async acquire(key, acquireOptions) {
|
|
62
|
+
validateAcquireOptions(key, acquireOptions);
|
|
63
|
+
const startedAt = Date.now();
|
|
64
|
+
const waitMs = acquireOptions.waitMs ?? 0;
|
|
65
|
+
const retryDelayMs = acquireOptions.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS;
|
|
66
|
+
const deadline = Date.now() + waitMs;
|
|
67
|
+
const ownerToken = acquireOptions.ownerToken ?? createOwnerToken();
|
|
68
|
+
while (true) {
|
|
69
|
+
const fencingToken = await client.eval(ACQUIRE_SCRIPT, 2, fullKey(key), fencingKey(key), ownerToken, acquireOptions.ttlMs);
|
|
70
|
+
if (fencingToken !== null && fencingToken !== undefined) {
|
|
71
|
+
const lease = createRedisLease({
|
|
72
|
+
client,
|
|
73
|
+
key,
|
|
74
|
+
redisKey: fullKey(key),
|
|
75
|
+
ownerToken,
|
|
76
|
+
ttlMs: acquireOptions.ttlMs,
|
|
77
|
+
fencingToken: Number(fencingToken),
|
|
78
|
+
});
|
|
79
|
+
recordAcquire({
|
|
80
|
+
instrumentation,
|
|
81
|
+
key,
|
|
82
|
+
acquired: true,
|
|
83
|
+
ttlMs: acquireOptions.ttlMs,
|
|
84
|
+
waitMs,
|
|
85
|
+
durationMs: Date.now() - startedAt,
|
|
86
|
+
metadata: acquireOptions.metadata,
|
|
87
|
+
});
|
|
88
|
+
return { acquired: true, lease };
|
|
89
|
+
}
|
|
90
|
+
if (waitMs <= 0) {
|
|
91
|
+
recordAcquire({
|
|
92
|
+
instrumentation,
|
|
93
|
+
key,
|
|
94
|
+
acquired: false,
|
|
95
|
+
reason: "unavailable",
|
|
96
|
+
ttlMs: acquireOptions.ttlMs,
|
|
97
|
+
waitMs,
|
|
98
|
+
durationMs: Date.now() - startedAt,
|
|
99
|
+
metadata: acquireOptions.metadata,
|
|
100
|
+
});
|
|
101
|
+
return { acquired: false, reason: "unavailable" };
|
|
102
|
+
}
|
|
103
|
+
const remainingMs = deadline - Date.now();
|
|
104
|
+
if (remainingMs <= 0) {
|
|
105
|
+
recordAcquire({
|
|
106
|
+
instrumentation,
|
|
107
|
+
key,
|
|
108
|
+
acquired: false,
|
|
109
|
+
reason: "timeout",
|
|
110
|
+
ttlMs: acquireOptions.ttlMs,
|
|
111
|
+
waitMs,
|
|
112
|
+
durationMs: Date.now() - startedAt,
|
|
113
|
+
metadata: acquireOptions.metadata,
|
|
114
|
+
});
|
|
115
|
+
return { acquired: false, reason: "timeout" };
|
|
116
|
+
}
|
|
117
|
+
await sleep(Math.min(retryDelayMs, remainingMs));
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
async withLease(key, acquireOptions, fn) {
|
|
121
|
+
const result = await locks.acquire(key, acquireOptions);
|
|
122
|
+
if (!result.acquired)
|
|
123
|
+
return undefined;
|
|
124
|
+
try {
|
|
125
|
+
return await fn({ lease: result.lease });
|
|
126
|
+
}
|
|
127
|
+
finally {
|
|
128
|
+
await result.lease.release();
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
restore(key, ownerToken) {
|
|
132
|
+
if (!key)
|
|
133
|
+
throw new LeaseOptionsError("Lease key is required.");
|
|
134
|
+
if (!ownerToken) {
|
|
135
|
+
throw new LeaseOptionsError("Lease owner token is required.");
|
|
136
|
+
}
|
|
137
|
+
return createRedisLease({
|
|
138
|
+
client,
|
|
139
|
+
key,
|
|
140
|
+
redisKey: fullKey(key),
|
|
141
|
+
ownerToken,
|
|
142
|
+
ttlMs: 1,
|
|
143
|
+
});
|
|
144
|
+
},
|
|
145
|
+
async forceRelease(key) {
|
|
146
|
+
if (!key)
|
|
147
|
+
throw new LeaseOptionsError("Lease key is required.");
|
|
148
|
+
const released = (await client.del(fullKey(key))) > 0;
|
|
149
|
+
instrumentation.custom({
|
|
150
|
+
name: "locks.forceRelease",
|
|
151
|
+
label: "Lock force release",
|
|
152
|
+
summary: released ? "Lease force released" : "Lease not found",
|
|
153
|
+
details: { key, prefix, released },
|
|
154
|
+
});
|
|
155
|
+
return released;
|
|
156
|
+
},
|
|
157
|
+
};
|
|
158
|
+
return locks;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Create an env-backed Redis locks provider.
|
|
162
|
+
*/
|
|
163
|
+
export function createRedisLocksProvider(options = {}) {
|
|
164
|
+
const ConfigSchema = RedisLocksConfigSchema.extend({
|
|
165
|
+
DB: options.db !== undefined
|
|
166
|
+
? NumberString.default(options.db)
|
|
167
|
+
: RedisLocksConfigSchema.shape.DB,
|
|
168
|
+
PREFIX: options.prefix !== undefined
|
|
169
|
+
? z.string().default(options.prefix)
|
|
170
|
+
: RedisLocksConfigSchema.shape.PREFIX,
|
|
171
|
+
CONNECT_TIMEOUT_MS: options.connectTimeoutMs !== undefined
|
|
172
|
+
? NumberString.default(options.connectTimeoutMs)
|
|
173
|
+
: RedisLocksConfigSchema.shape.CONNECT_TIMEOUT_MS,
|
|
174
|
+
MAX_RETRIES_PER_REQUEST: options.maxRetriesPerRequest !== undefined
|
|
175
|
+
? NumberString.default(options.maxRetriesPerRequest)
|
|
176
|
+
: RedisLocksConfigSchema.shape.MAX_RETRIES_PER_REQUEST,
|
|
177
|
+
});
|
|
178
|
+
const providerMetadata = {
|
|
179
|
+
packageName: "@beignet/provider-locks-redis",
|
|
180
|
+
ports: ["locks", "redisLocks"],
|
|
181
|
+
watchers: ["locks"],
|
|
182
|
+
};
|
|
183
|
+
if (options.client) {
|
|
184
|
+
const client = options.client;
|
|
185
|
+
return createProvider({
|
|
186
|
+
name: "locks-redis",
|
|
187
|
+
metadata: providerMetadata,
|
|
188
|
+
async setup({ ports }) {
|
|
189
|
+
const configuredPrefix = options.prefix ?? DEFAULT_PREFIX;
|
|
190
|
+
return {
|
|
191
|
+
ports: {
|
|
192
|
+
locks: createRedisLocks({
|
|
193
|
+
client,
|
|
194
|
+
prefix: configuredPrefix,
|
|
195
|
+
instrumentation: ports,
|
|
196
|
+
}),
|
|
197
|
+
redisLocks: {
|
|
198
|
+
client,
|
|
199
|
+
prefix: configuredPrefix,
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
};
|
|
203
|
+
},
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
return createProvider({
|
|
207
|
+
name: "locks-redis",
|
|
208
|
+
metadata: providerMetadata,
|
|
209
|
+
config: {
|
|
210
|
+
schema: ConfigSchema,
|
|
211
|
+
envPrefix: "REDIS_LOCKS_",
|
|
212
|
+
},
|
|
213
|
+
async setup({ ports, config }) {
|
|
214
|
+
const configuredPrefix = config?.PREFIX ?? options.prefix ?? DEFAULT_PREFIX;
|
|
215
|
+
if (!config) {
|
|
216
|
+
throw new Error("[redisLocksProvider] Missing Redis locks config. " +
|
|
217
|
+
"Please set REDIS_LOCKS_URL environment variable.");
|
|
218
|
+
}
|
|
219
|
+
const client = await connectRedisClient(config, options);
|
|
220
|
+
return {
|
|
221
|
+
ports: {
|
|
222
|
+
locks: createRedisLocks({
|
|
223
|
+
client,
|
|
224
|
+
prefix: configuredPrefix,
|
|
225
|
+
instrumentation: ports,
|
|
226
|
+
}),
|
|
227
|
+
redisLocks: {
|
|
228
|
+
client,
|
|
229
|
+
prefix: configuredPrefix,
|
|
230
|
+
},
|
|
231
|
+
},
|
|
232
|
+
async stop() {
|
|
233
|
+
try {
|
|
234
|
+
await client.quit();
|
|
235
|
+
}
|
|
236
|
+
catch {
|
|
237
|
+
// Ignore shutdown errors.
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
};
|
|
241
|
+
},
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Default env-backed Redis locks provider.
|
|
246
|
+
*/
|
|
247
|
+
export const redisLocksProvider = createRedisLocksProvider();
|
|
248
|
+
function createRedisLease(args) {
|
|
249
|
+
const lease = {
|
|
250
|
+
key: args.key,
|
|
251
|
+
ownerToken: args.ownerToken,
|
|
252
|
+
expiresAt: new Date(Date.now() + args.ttlMs),
|
|
253
|
+
fencingToken: args.fencingToken,
|
|
254
|
+
async renew(options) {
|
|
255
|
+
const ttlMs = options?.ttlMs ?? args.ttlMs;
|
|
256
|
+
if (!Number.isFinite(ttlMs) || ttlMs <= 0) {
|
|
257
|
+
throw new LeaseOptionsError("Lease ttlMs must be a positive number.");
|
|
258
|
+
}
|
|
259
|
+
const renewed = Number(await args.client.eval(RENEW_SCRIPT, 1, args.redisKey, args.ownerToken, ttlMs));
|
|
260
|
+
if (renewed !== 1)
|
|
261
|
+
return false;
|
|
262
|
+
args.ttlMs = ttlMs;
|
|
263
|
+
lease.expiresAt = new Date(Date.now() + ttlMs);
|
|
264
|
+
return true;
|
|
265
|
+
},
|
|
266
|
+
async release() {
|
|
267
|
+
const released = Number(await args.client.eval(RELEASE_SCRIPT, 1, args.redisKey, args.ownerToken));
|
|
268
|
+
return released === 1;
|
|
269
|
+
},
|
|
270
|
+
};
|
|
271
|
+
return lease;
|
|
272
|
+
}
|
|
273
|
+
async function connectRedisClient(config, options) {
|
|
274
|
+
const connectMaxAttempts = config.CONNECT_MAX_ATTEMPTS ?? DEFAULT_CONNECT_MAX_ATTEMPTS;
|
|
275
|
+
let connectedOnce = false;
|
|
276
|
+
const defaultRetryStrategy = (attempt) => {
|
|
277
|
+
if (!connectedOnce) {
|
|
278
|
+
if (attempt >= connectMaxAttempts)
|
|
279
|
+
return null;
|
|
280
|
+
return reconnectBackoff(attempt);
|
|
281
|
+
}
|
|
282
|
+
return reconnectBackoff(attempt);
|
|
283
|
+
};
|
|
284
|
+
const client = new Redis(config.URL, {
|
|
285
|
+
db: config.DB ?? options.db ?? 0,
|
|
286
|
+
lazyConnect: true,
|
|
287
|
+
connectTimeout: config.CONNECT_TIMEOUT_MS ??
|
|
288
|
+
options.connectTimeoutMs ??
|
|
289
|
+
DEFAULT_CONNECT_TIMEOUT_MS,
|
|
290
|
+
maxRetriesPerRequest: config.MAX_RETRIES_PER_REQUEST ??
|
|
291
|
+
options.maxRetriesPerRequest ??
|
|
292
|
+
DEFAULT_MAX_RETRIES_PER_REQUEST,
|
|
293
|
+
retryStrategy: options.retryStrategy ?? defaultRetryStrategy,
|
|
294
|
+
});
|
|
295
|
+
try {
|
|
296
|
+
await client.connect();
|
|
297
|
+
connectedOnce = true;
|
|
298
|
+
}
|
|
299
|
+
catch (error) {
|
|
300
|
+
client.disconnect();
|
|
301
|
+
throw new Error(`[redisLocksProvider] Failed to connect to Redis at ${config.URL}: ${errorMessage(error)}`);
|
|
302
|
+
}
|
|
303
|
+
return client;
|
|
304
|
+
}
|
|
305
|
+
function recordAcquire(args) {
|
|
306
|
+
args.instrumentation.custom({
|
|
307
|
+
name: "locks.acquire",
|
|
308
|
+
label: "Lock acquire",
|
|
309
|
+
summary: args.acquired ? "Lease acquired" : "Lease not acquired",
|
|
310
|
+
details: {
|
|
311
|
+
key: args.key,
|
|
312
|
+
acquired: args.acquired,
|
|
313
|
+
reason: args.reason,
|
|
314
|
+
ttlMs: args.ttlMs,
|
|
315
|
+
waitMs: args.waitMs,
|
|
316
|
+
durationMs: args.durationMs,
|
|
317
|
+
metadata: args.metadata,
|
|
318
|
+
},
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
function validateAcquireOptions(key, options) {
|
|
322
|
+
if (!key)
|
|
323
|
+
throw new LeaseOptionsError("Lease key is required.");
|
|
324
|
+
if (!Number.isFinite(options.ttlMs) || options.ttlMs <= 0) {
|
|
325
|
+
throw new LeaseOptionsError("Lease ttlMs must be a positive number.");
|
|
326
|
+
}
|
|
327
|
+
if (options.waitMs !== undefined && options.waitMs < 0) {
|
|
328
|
+
throw new LeaseOptionsError("Lease waitMs must be zero or greater.");
|
|
329
|
+
}
|
|
330
|
+
if (options.retryDelayMs !== undefined && options.retryDelayMs <= 0) {
|
|
331
|
+
throw new LeaseOptionsError("Lease retryDelayMs must be positive.");
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
function reconnectBackoff(attempt) {
|
|
335
|
+
return Math.min(2 ** attempt * 100, RECONNECT_BACKOFF_CAP_MS);
|
|
336
|
+
}
|
|
337
|
+
function createRandomToken() {
|
|
338
|
+
if (typeof crypto !== "undefined" && "randomUUID" in crypto) {
|
|
339
|
+
return crypto.randomUUID();
|
|
340
|
+
}
|
|
341
|
+
return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
|
|
342
|
+
}
|
|
343
|
+
function defaultSleep(ms) {
|
|
344
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
345
|
+
}
|
|
346
|
+
function errorMessage(error) {
|
|
347
|
+
return error instanceof Error ? error.message : String(error);
|
|
348
|
+
}
|
|
349
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|