initial commit
This commit is contained in:
51
src/MutexLock.ts
Normal file
51
src/MutexLock.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import type { MutexOptions } from "./types";
|
||||
import redis from "redis";
|
||||
|
||||
type RedisClient = redis.RedisClientType<
|
||||
redis.RedisDefaultModules & redis.RedisModules,
|
||||
redis.RedisFunctions,
|
||||
redis.RedisScripts
|
||||
>;
|
||||
|
||||
export class MutexLock {
|
||||
redisClient: RedisClient;
|
||||
mutexOptions: MutexOptions;
|
||||
|
||||
constructor(redisClient: RedisClient, options: MutexOptions) {
|
||||
this.mutexOptions = options;
|
||||
this.redisClient = redisClient;
|
||||
}
|
||||
|
||||
static async create(options: MutexOptions) {
|
||||
const redisClient = await redis
|
||||
.createClient({
|
||||
url: `redis://${options.redis.host}:${options.redis.port}`,
|
||||
})
|
||||
.connect();
|
||||
|
||||
return new MutexLock(redisClient, options);
|
||||
}
|
||||
|
||||
async obtainLock(lockName: string) {
|
||||
const lockIdentifier = `mutexlock:${lockName}`;
|
||||
const releaseFunc = async () => {
|
||||
await this.redisClient.del(lockIdentifier);
|
||||
};
|
||||
|
||||
while (true) {
|
||||
const acquired = await this.redisClient.set(lockIdentifier, "1", {
|
||||
NX: true
|
||||
});
|
||||
|
||||
if (acquired) {
|
||||
await this.redisClient.expire(
|
||||
lockIdentifier,
|
||||
this.mutexOptions.mutex?.ttl || 60
|
||||
);
|
||||
return releaseFunc;
|
||||
}
|
||||
await new Promise(resolve =>
|
||||
setTimeout(resolve, this.mutexOptions.mutex?.checkInterval || 100)
|
||||
);
|
||||
}
|
||||
}}
|
10
src/types.ts
Normal file
10
src/types.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
export type MutexOptions = {
|
||||
redis: {
|
||||
host: string;
|
||||
port: number;
|
||||
};
|
||||
mutex?: {
|
||||
checkInterval?: number;
|
||||
ttl: number;
|
||||
};
|
||||
};
|
Reference in New Issue
Block a user