1+ // test/redis-lock-fallback.test.mjs
2+ /**
3+ * Redis Lock Fallback 測試
4+ *
5+ * 測試當 Redis 不可用時,是否會正確 fallback 到 file lock
6+ */
7+
8+ import { describe , it } from "node:test" ;
9+ import assert from "node:assert/strict" ;
10+ import { mkdtempSync , rmSync } from "node:fs" ;
11+ import { tmpdir } from "node:os" ;
12+ import { join } from "node:path" ;
13+ import jitiFactory from "jiti" ;
14+
15+ const jiti = jitiFactory ( import . meta. url , { interopDefault : true } ) ;
16+ const { RedisLockManager } = jiti ( "../src/redis-lock.ts" ) ;
17+
18+ describe ( "Redis Lock Fallback" , ( ) => {
19+ // 測試 1:Redis 不可用時使用 file lock
20+ it ( "should fallback to file lock when Redis unavailable" , async ( ) => {
21+ // 故意用一個不會有 Redis 的 URL
22+ const manager = new RedisLockManager ( {
23+ redisUrl : 'redis://localhost:9999' , // 不存在的 Redis
24+ ttl : 5000 ,
25+ maxWait : 5000 ,
26+ } ) ;
27+
28+ const release = await manager . acquire ( "fallback-test-key" ) ;
29+
30+ // 應該成功取得 lock(file lock fallback)
31+ assert . ok ( release , "Should return a release function" ) ;
32+
33+ // 執行 release
34+ await release ( ) ;
35+
36+ console . log ( "[Fallback test] Successfully used file lock fallback" ) ;
37+ } ) ;
38+
39+ // 測試 2:多次取得不同 key 的 lock
40+ it ( "should handle multiple locks with fallback" , async ( ) => {
41+ const manager = new RedisLockManager ( {
42+ redisUrl : 'redis://localhost:9999' ,
43+ ttl : 3000 ,
44+ } ) ;
45+
46+ const locks = [ ] ;
47+ for ( let i = 0 ; i < 3 ; i ++ ) {
48+ const release = await manager . acquire ( `fallback-multi-${ i } ` ) ;
49+ locks . push ( release ) ;
50+ }
51+
52+ // 應該成功取得 3 個 lock
53+ assert . strictEqual ( locks . length , 3 , "Should acquire 3 locks" ) ;
54+
55+ // 全部 release
56+ for ( const release of locks ) {
57+ await release ( ) ;
58+ }
59+
60+ console . log ( "[Fallback test] Multiple locks handled successfully" ) ;
61+ } ) ;
62+
63+ // 測試 3:file lock 的 TTL 行為
64+ it ( "should respect TTL in file lock fallback" , async ( ) => {
65+ const shortTTL = 1000 ; // 1 秒
66+
67+ const manager = new RedisLockManager ( {
68+ redisUrl : 'redis://localhost:9999' ,
69+ ttl : shortTTL ,
70+ } ) ;
71+
72+ const release = await manager . acquire ( "fallback-ttl-test" ) ;
73+
74+ // 等待 TTL 過期
75+ await new Promise ( r => setTimeout ( r , shortTTL + 500 ) ) ;
76+
77+ // 應該可以再次取得同一個 key(因為 TTL 過期了)
78+ const release2 = await manager . acquire ( "fallback-ttl-test" ) ;
79+
80+ await release ( ) ;
81+ await release2 ( ) ;
82+
83+ console . log ( "[Fallback test] TTL respected in file lock" ) ;
84+ } ) ;
85+ } ) ;
86+
87+ console . log ( "=== Redis Lock Fallback Tests ===" ) ;
0 commit comments