-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathredis.ts
36 lines (27 loc) · 989 Bytes
/
redis.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import { Redis } from "https://deno.land/x/[email protected]/mod.ts";
export const redis = Redis.fromEnv({ automaticDeserialization: true });
type ReleaseLock = () => Promise<number>;
const key = (resource: bigint) => `lock:${resource}`;
const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
const createLock = async (resource: bigint) => {
const status = await redis.set(key(resource), 1, { nx: true, ex: 10 });
if (status === "OK") return () => redis.del(key(resource));
return "ALREADY_LOCKED";
};
const acquireLock = async (resource: bigint): Promise<ReleaseLock> => {
while (true) {
const result = await createLock(resource);
if (result === "ALREADY_LOCKED") {
await sleep(500);
} else {
return result;
}
}
};
export const lock = async <T>(
resource: bigint,
callback: () => Promise<T>,
): Promise<T> => {
const releaseLock = await acquireLock(resource);
return callback().finally(releaseLock);
};