@@ -3,6 +3,10 @@ import test, { ExecutionContext } from "ava";
33import Redis , { Redis as Client , Cluster } from "ioredis" ;
44import Redlock , { ExecutionError , ResourceLockedError } from "./index.js" ;
55
6+ async function wait ( ms : number ) : Promise < number > {
7+ return new Promise ( ( resolve ) => setTimeout ( ( ) => resolve ( ms ) , ms ) ) ;
8+ }
9+
610async function fail (
711 t : ExecutionContext < unknown > ,
812 error : unknown
@@ -135,6 +139,26 @@ function run(namespace: string, redis: Client | Cluster): void {
135139 }
136140 } ) ;
137141
142+ test ( `${ namespace } - releasing expired lock doesn't fail` , async ( t ) => {
143+ try {
144+ const redlock = new Redlock ( [ redis ] ) ;
145+
146+ const duration = 1000 ;
147+
148+ // Acquire a lock.
149+ const lock = await redlock . acquire ( [ "{redlock}a" ] , duration ) ;
150+
151+ // Wait for duration + drift to be sure that lock has expired
152+ await wait ( duration + redlock . calculateDrift ( duration ) ) ;
153+
154+ // Release the lock.
155+ await lock . release ( ) ;
156+ t . is ( await redis . get ( "{redlock}a" ) , null , "The lock was not released" ) ;
157+ } catch ( error ) {
158+ fail ( t , error ) ;
159+ }
160+ } ) ;
161+
138162 test ( `${ namespace } - acquires, extends, and releases a multi-resource lock` , async ( t ) => {
139163 try {
140164 const redlock = new Redlock ( [ redis ] ) ;
@@ -199,6 +223,30 @@ function run(namespace: string, redis: Client | Cluster): void {
199223 }
200224 } ) ;
201225
226+ test ( `${ namespace } - releasing expired multi-resource lock doesn't fail` , async ( t ) => {
227+ try {
228+ const redlock = new Redlock ( [ redis ] ) ;
229+
230+ const duration = 1000 ;
231+
232+ // Acquire a lock.
233+ const lock = await redlock . acquire (
234+ [ "{redlock}a1" , "{redlock}a2" ] ,
235+ duration
236+ ) ;
237+
238+ // Wait for duration + drift to be sure that lock has expired
239+ await wait ( duration + redlock . calculateDrift ( duration ) ) ;
240+
241+ // Release the lock.
242+ await lock . release ( ) ;
243+ t . is ( await redis . get ( "{redlock}a1" ) , null , "The lock was not released" ) ;
244+ t . is ( await redis . get ( "{redlock}a2" ) , null , "The lock was not released" ) ;
245+ } catch ( error ) {
246+ fail ( t , error ) ;
247+ }
248+ } ) ;
249+
202250 test ( `${ namespace } - locks fail when redis is unreachable` , async ( t ) => {
203251 try {
204252 const redis = new Redis ( {
0 commit comments