Skip to content

Commit 5b9386b

Browse files
Add lock
1 parent f5c3dff commit 5b9386b

File tree

3 files changed

+469
-21
lines changed

3 files changed

+469
-21
lines changed

server/lib/lock.ts

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
export class LockManager {
2+
/**
3+
* Acquire a distributed lock using Redis SET with NX and PX options
4+
* @param lockKey - Unique identifier for the lock
5+
* @param ttlMs - Time to live in milliseconds
6+
* @returns Promise<boolean> - true if lock acquired, false otherwise
7+
*/
8+
async acquireLock(
9+
lockKey: string,
10+
ttlMs: number = 30000
11+
): Promise<boolean> {
12+
return true;
13+
}
14+
15+
/**
16+
* Release a lock using Lua script to ensure atomicity
17+
* @param lockKey - Unique identifier for the lock
18+
*/
19+
async releaseLock(lockKey: string): Promise<void> {}
20+
21+
/**
22+
* Force release a lock regardless of owner (use with caution)
23+
* @param lockKey - Unique identifier for the lock
24+
*/
25+
async forceReleaseLock(lockKey: string): Promise<void> {}
26+
27+
/**
28+
* Check if a lock exists and get its info
29+
* @param lockKey - Unique identifier for the lock
30+
* @returns Promise<{exists: boolean, ownedByMe: boolean, ttl: number}>
31+
*/
32+
async getLockInfo(lockKey: string): Promise<{
33+
exists: boolean;
34+
ownedByMe: boolean;
35+
ttl: number;
36+
owner?: string;
37+
}> {
38+
return { exists: true, ownedByMe: true, ttl: 0 };
39+
}
40+
41+
/**
42+
* Extend the TTL of an existing lock owned by this worker
43+
* @param lockKey - Unique identifier for the lock
44+
* @param ttlMs - New TTL in milliseconds
45+
* @returns Promise<boolean> - true if extended successfully
46+
*/
47+
async extendLock(lockKey: string, ttlMs: number): Promise<boolean> {
48+
return true;
49+
}
50+
51+
/**
52+
* Attempt to acquire lock with retries and exponential backoff
53+
* @param lockKey - Unique identifier for the lock
54+
* @param ttlMs - Time to live in milliseconds
55+
* @param maxRetries - Maximum number of retry attempts
56+
* @param baseDelayMs - Base delay between retries in milliseconds
57+
* @returns Promise<boolean> - true if lock acquired
58+
*/
59+
async acquireLockWithRetry(
60+
lockKey: string,
61+
ttlMs: number = 30000,
62+
maxRetries: number = 5,
63+
baseDelayMs: number = 100
64+
): Promise<boolean> {
65+
return true;
66+
}
67+
68+
/**
69+
* Execute a function while holding a lock
70+
* @param lockKey - Unique identifier for the lock
71+
* @param fn - Function to execute while holding the lock
72+
* @param ttlMs - Lock TTL in milliseconds
73+
* @returns Promise<T> - Result of the executed function
74+
*/
75+
async withLock<T>(
76+
lockKey: string,
77+
fn: () => Promise<T>,
78+
ttlMs: number = 30000
79+
): Promise<T> {
80+
const acquired = await this.acquireLock(lockKey, ttlMs);
81+
82+
if (!acquired) {
83+
throw new Error(`Failed to acquire lock: ${lockKey}`);
84+
}
85+
86+
try {
87+
return await fn();
88+
} finally {
89+
await this.releaseLock(lockKey);
90+
}
91+
}
92+
93+
/**
94+
* Clean up expired locks - Redis handles this automatically, but this method
95+
* can be used to get statistics about locks
96+
* @returns Promise<{activeLocksCount: number, locksOwnedByMe: number}>
97+
*/
98+
async getLockStatistics(): Promise<{
99+
activeLocksCount: number;
100+
locksOwnedByMe: number;
101+
}> {
102+
return { activeLocksCount: 0, locksOwnedByMe: 0 };
103+
}
104+
105+
/**
106+
* Close the Redis connection
107+
*/
108+
async disconnect(): Promise<void> {}
109+
}
110+
111+
export const lockManager = new LockManager();

0 commit comments

Comments
 (0)