11import assert from "node:assert" ;
2- import { setTimeout } from "node:timers/promises" ;
2+
33import { FaultInjectorClient } from "./fault-injector-client" ;
44import {
5+ ClientFactory ,
56 getDatabaseConfig ,
67 getDatabaseConfigFromEnv ,
78 getEnvConfig ,
89 RedisConnectionConfig ,
10+ blockSetImmediate
911} from "./test-scenario.util" ;
1012import { createClient } from "../../.." ;
1113import { before } from "mocha" ;
1214import { TestCommandRunner } from "./test-command-runner" ;
1315
1416describe ( "Timeout Handling During Notifications" , ( ) => {
1517 let clientConfig : RedisConnectionConfig ;
16- let client : ReturnType < typeof createClient < any , any , any , 3 > > ;
18+ let clientFactory : ClientFactory ;
1719 let faultInjectorClient : FaultInjectorClient ;
18- let commandRunner : TestCommandRunner ;
20+ let defaultClient : ReturnType < typeof createClient < any , any , any , any > > ;
1921
2022 before ( ( ) => {
2123 const envConfig = getEnvConfig ( ) ;
2224 const redisConfig = getDatabaseConfigFromEnv (
2325 envConfig . redisEndpointsConfigPath
2426 ) ;
2527
26- faultInjectorClient = new FaultInjectorClient ( envConfig . faultInjectorUrl ) ;
2728 clientConfig = getDatabaseConfig ( redisConfig ) ;
29+ faultInjectorClient = new FaultInjectorClient ( envConfig . faultInjectorUrl ) ;
30+ clientFactory = new ClientFactory ( clientConfig ) ;
2831 } ) ;
2932
3033 beforeEach ( async ( ) => {
31- client = createClient ( {
32- socket : {
33- host : clientConfig . host ,
34- port : clientConfig . port ,
35- ...( clientConfig . tls === true ? { tls : true } : { } ) ,
36- } ,
37- password : clientConfig . password ,
38- username : clientConfig . username ,
39- RESP : 3 ,
40- maintPushNotifications : "auto" ,
41- maintMovingEndpointType : "auto" ,
42- } ) ;
43-
44- client . on ( "error" , ( err : Error ) => {
45- throw new Error ( `Client error: ${ err . message } ` ) ;
46- } ) ;
47-
48- commandRunner = new TestCommandRunner ( client ) ;
34+ defaultClient = await clientFactory . create ( "default" ) ;
4935
50- await client . connect ( ) ;
36+ await defaultClient . flushAll ( ) ;
5137 } ) ;
5238
53- afterEach ( ( ) => {
54- client . destroy ( ) ;
39+ afterEach ( async ( ) => {
40+ clientFactory . destroyAll ( ) ;
5541 } ) ;
5642
5743 it ( "should relax command timeout on MOVING, MIGRATING, and MIGRATED" , async ( ) => {
5844 // PART 1
5945 // Set very low timeout to trigger errors
60- client . options ! . maintRelaxedCommandTimeout = 50 ;
46+ const lowTimeoutClient = await clientFactory . create ( "lowTimeout" , {
47+ maintRelaxedCommandTimeout : 50 ,
48+ } ) ;
6149
6250 const { action_id : lowTimeoutBindAndMigrateActionId } =
6351 await faultInjectorClient . migrateAndBindAction ( {
@@ -70,7 +58,10 @@ describe("Timeout Handling During Notifications", () => {
7058 ) ;
7159
7260 const lowTimeoutCommandPromises =
73- await commandRunner . fireCommandsUntilStopSignal ( lowTimeoutWaitPromise ) ;
61+ await TestCommandRunner . fireCommandsUntilStopSignal (
62+ lowTimeoutClient ,
63+ lowTimeoutWaitPromise
64+ ) ;
7465
7566 const lowTimeoutRejectedCommands = (
7667 await Promise . all ( lowTimeoutCommandPromises . commandPromises )
@@ -90,7 +81,9 @@ describe("Timeout Handling During Notifications", () => {
9081
9182 // PART 2
9283 // Set high timeout to avoid errors
93- client . options ! . maintRelaxedCommandTimeout = 10000 ;
84+ const highTimeoutClient = await clientFactory . create ( "highTimeout" , {
85+ maintRelaxedCommandTimeout : 10000 ,
86+ } ) ;
9487
9588 const { action_id : highTimeoutBindAndMigrateActionId } =
9689 await faultInjectorClient . migrateAndBindAction ( {
@@ -103,7 +96,10 @@ describe("Timeout Handling During Notifications", () => {
10396 ) ;
10497
10598 const highTimeoutCommandPromises =
106- await commandRunner . fireCommandsUntilStopSignal ( highTimeoutWaitPromise ) ;
99+ await TestCommandRunner . fireCommandsUntilStopSignal (
100+ highTimeoutClient ,
101+ highTimeoutWaitPromise
102+ ) ;
107103
108104 const highTimeoutRejectedCommands = (
109105 await Promise . all ( highTimeoutCommandPromises . commandPromises )
@@ -112,13 +108,15 @@ describe("Timeout Handling During Notifications", () => {
112108 assert . strictEqual ( highTimeoutRejectedCommands . length , 0 ) ;
113109 } ) ;
114110
115- // TODO this is WIP
116- it . skip ( "should unrelax command timeout after MAINTENANCE" , async ( ) => {
117- client . options ! . maintRelaxedCommandTimeout = 10000 ;
118- client . options ! . commandOptions = {
119- ...client . options ! . commandOptions ,
120- timeout : 1 , // Set very low timeout to trigger errors
121- } ;
111+ it ( "should unrelax command timeout after MAINTENANCE" , async ( ) => {
112+ const clientWithCommandTimeout = await clientFactory . create (
113+ "clientWithCommandTimeout" ,
114+ {
115+ commandOptions : {
116+ timeout : 100 ,
117+ } ,
118+ }
119+ ) ;
122120
123121 const { action_id : bindAndMigrateActionId } =
124122 await faultInjectorClient . migrateAndBindAction ( {
@@ -131,25 +129,31 @@ describe("Timeout Handling During Notifications", () => {
131129 ) ;
132130
133131 const relaxedTimeoutCommandPromises =
134- await commandRunner . fireCommandsUntilStopSignal ( lowTimeoutWaitPromise ) ;
132+ await TestCommandRunner . fireCommandsUntilStopSignal (
133+ clientWithCommandTimeout ,
134+ lowTimeoutWaitPromise
135+ ) ;
135136
136137 const relaxedTimeoutRejectedCommands = (
137138 await Promise . all ( relaxedTimeoutCommandPromises . commandPromises )
138139 ) . filter ( ( result ) => result . status === "rejected" ) ;
139- console . log (
140- "relaxedTimeoutRejectedCommands" ,
141- relaxedTimeoutRejectedCommands
142- ) ;
143140
144141 assert . ok ( relaxedTimeoutRejectedCommands . length === 0 ) ;
145142
146- const unrelaxedCommandPromises =
147- await commandRunner . fireCommandsUntilStopSignal ( setTimeout ( 1 * 1000 ) ) ;
143+ const start = performance . now ( ) ;
148144
149- const unrelaxedRejectedCommands = (
150- await Promise . all ( unrelaxedCommandPromises . commandPromises )
151- ) . filter ( ( result ) => result . status === "rejected" ) ;
145+ let error : any ;
146+ await blockSetImmediate ( async ( ) => {
147+ try {
148+ await clientWithCommandTimeout . set ( "key" , "value" ) ;
149+ } catch ( err : any ) {
150+ error = err ;
151+ }
152+ } ) ;
152153
153- assert . ok ( unrelaxedRejectedCommands . length > 0 ) ;
154+ // Make sure it took less than 1sec to fail
155+ assert . ok ( performance . now ( ) - start < 1000 ) ;
156+ assert . ok ( error instanceof Error ) ;
157+ assert . ok ( error . constructor . name === "TimeoutError" ) ;
154158 } ) ;
155159} ) ;
0 commit comments