Skip to content

Commit d9c97ac

Browse files
[CAE-342] Reverted legacy testing framework improvements
1 parent 6bdbae6 commit d9c97ac

File tree

2 files changed

+35
-188
lines changed

2 files changed

+35
-188
lines changed

packages/client/lib/sentinel/test-util.ts

Lines changed: 35 additions & 175 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ export interface RedisServerDocker {
5555
abstract class DockerBase {
5656
async spawnRedisServerDocker({ image, version }: RedisServerDockerConfig, serverArguments: Array<string>, environment?: string): Promise<RedisServerDocker> {
5757
const port = (await portIterator.next()).value;
58-
let cmdLine = `docker run --init -d --network host -e PORT=${port.toString()} `;
58+
let cmdLine = `docker run --init -d --network host `;
5959
if (environment !== undefined) {
6060
cmdLine += `-e ${environment} `;
6161
}
@@ -80,7 +80,7 @@ abstract class DockerBase {
8080

8181
async dockerRemove(dockerId: string): Promise<void> {
8282
try {
83-
await this.dockerStop(dockerId);
83+
await this.dockerStop(dockerId); ``
8484
} catch (err) {
8585
// its ok if stop failed, as we are just going to remove, will just be slower
8686
console.log(`dockerStop failed in remove: ${err}`);
@@ -180,14 +180,9 @@ export class SentinelFramework extends DockerBase {
180180
RedisScripts,
181181
RespVersions,
182182
TypeMapping>>, errors = true) {
183-
// remove this safeguard
184-
// in order to test the case when
185-
// connecting to sentinel fails
186-
187-
// if (opts?.sentinelRootNodes !== undefined) {
188-
// throw new Error("cannot specify sentinelRootNodes here");
189-
// }
190-
183+
if (opts?.sentinelRootNodes !== undefined) {
184+
throw new Error("cannot specify sentinelRootNodes here");
185+
}
191186
if (opts?.name !== undefined) {
192187
throw new Error("cannot specify sentinel db name here");
193188
}
@@ -250,13 +245,13 @@ export class SentinelFramework extends DockerBase {
250245
}
251246

252247
protected async spawnRedisSentinelNodeDocker() {
253-
const imageInfo: RedisServerDockerConfig = this.config.nodeDockerConfig ?? { image: "redislabs/client-libs-test", version: "8.0-M05-pre" };
248+
const imageInfo: RedisServerDockerConfig = this.config.nodeDockerConfig ?? { image: "redis/redis-stack-server", version: "latest" };
254249
const serverArguments: Array<string> = this.config.nodeServerArguments ?? [];
255250
let environment;
256251
if (this.config.password !== undefined) {
257-
environment = `REDIS_PASSWORD=${this.config.password}`;
252+
environment = `REDIS_ARGS="{port} --requirepass ${this.config.password}"`;
258253
} else {
259-
environment = undefined;
254+
environment = 'REDIS_ARGS="{port}"';
260255
}
261256

262257
const docker = await this.spawnRedisServerDocker(imageInfo, serverArguments, environment);
@@ -281,6 +276,9 @@ export class SentinelFramework extends DockerBase {
281276
for (let i = 0; i < (this.config.numberOfNodes ?? 0) - 1; i++) {
282277
promises.push(
283278
this.spawnRedisSentinelNodeDocker().then(async node => {
279+
if (this.config.password !== undefined) {
280+
await node.client.configSet({'masterauth': this.config.password})
281+
}
284282
await node.client.replicaOf('127.0.0.1', master.docker.port);
285283
return node;
286284
})
@@ -349,156 +347,34 @@ export class SentinelFramework extends DockerBase {
349347
);
350348
}
351349

352-
const sentinels = await Promise.all(promises);
353-
354-
await this.validateSentinelConfiguration(sentinels);
355-
356-
return sentinels;
357-
}
358-
359-
// Add this new method to validate sentinel configuration
360-
private async validateSentinelConfiguration(
361-
sentinels: Awaited<ReturnType<SentinelFramework['spawnRedisSentinelSentinelDocker']>>[]
362-
): Promise<void> {
363-
const maxRetries = 10;
364-
const retryDelay = 2000;
365-
366-
// Wait for all sentinels to recognize each other
367-
for (let retry = 0; retry < maxRetries; retry++) {
368-
try {
369-
let allConfigured = true;
370-
371-
// Check that each sentinel recognizes all other sentinels
372-
for (const sentinel of sentinels) {
373-
if (!sentinel.client.isReady) {
374-
allConfigured = false;
375-
break;
376-
}
377-
378-
// Check if this sentinel can see the master
379-
const masterInfo = await sentinel.client.sentinel.sentinelMaster(this.config.sentinelName)
380-
.catch(() => null);
381-
382-
if (!masterInfo) {
383-
allConfigured = false;
384-
break;
385-
}
386-
387-
// Check if this sentinel can see other sentinels
388-
const knownSentinels = await sentinel.client.sentinel.sentinelSentinels(this.config.sentinelName)
389-
.catch(() => []);
390-
391-
// Ensure this sentinel knows about all other sentinels (minus itself)
392-
if (knownSentinels.length < sentinels.length - 1) {
393-
allConfigured = false;
394-
break;
395-
}
396-
}
397-
398-
if (allConfigured) {
399-
// All sentinels are properly configured
400-
return;
401-
}
402-
403-
// Wait before retrying
404-
await setTimeout(retryDelay);
405-
} catch (err) {
406-
// Wait before retrying after an error
407-
await setTimeout(retryDelay);
408-
}
350+
return [
351+
...await Promise.all(promises)
352+
]
409353
}
410-
411-
throw new Error('Sentinel configuration did not propagate correctly within the timeout period');
412-
}
413354

414-
async getAllRunning(): Promise<void> {
415-
const MAX_RETRIES = 5;
416-
const RETRY_DELAY = 500;
417-
418-
// Fix for Redis nodes
355+
async getAllRunning() {
419356
for (const port of this.getAllNodesPort()) {
420-
let retries = 0;
421-
422-
while (await isPortAvailable(port)) {
423-
if (retries >= MAX_RETRIES) {
424-
throw new Error(`Failed to restart Redis node at port ${port} after ${MAX_RETRIES} attempts`);
425-
}
426-
427-
try {
428-
await this.restartNode(port.toString());
429-
await setTimeout(RETRY_DELAY); // Give the node time to start
430-
} catch (err) {
431-
console.error(`Error restarting Redis node at port ${port}:`, err);
357+
let first = true;
358+
while (await isPortAvailable(port)) {
359+
if (!first) {
360+
console.log(`problematic restart ${port}`);
361+
await setTimeout(500);
362+
} else {
363+
first = false;
432364
}
433-
434-
retries++;
365+
await this.restartNode(port.toString());
435366
}
436367
}
437368

438-
// Fix for Sentinel nodes
439369
for (const port of this.getAllSentinelsPort()) {
440-
let retries = 0;
441-
442-
while (await isPortAvailable(port)) {
443-
if (retries >= MAX_RETRIES) {
444-
throw new Error(`Failed to restart Sentinel node at port ${port} after ${MAX_RETRIES} attempts`);
445-
}
446-
447-
try {
448-
await this.restartSentinel(port.toString());
449-
await setTimeout(RETRY_DELAY); // Give the sentinel time to start
450-
} catch (err) {
451-
console.error(`Error restarting Sentinel at port ${port}:`, err);
452-
}
453-
454-
retries++;
455-
}
456-
}
457-
458-
// Verify all nodes are actually responsive
459-
await this.verifyNodesResponsive();
460-
}
461-
462-
// Add a method to verify nodes are responsive
463-
private async verifyNodesResponsive(): Promise<void> {
464-
const MAX_ATTEMPTS = 10;
465-
const ATTEMPT_DELAY = 2000;
466-
467-
// Check Redis nodes
468-
for (const nodeInfo of this.#nodeMap.values()) {
469-
if (!nodeInfo.client.isReady) {
470-
// Try to reconnect client if not ready
471-
for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {
472-
try {
473-
await nodeInfo.client.connect();
474-
await nodeInfo.client.ping();
475-
break;
476-
} catch (err) {
477-
if (attempt === MAX_ATTEMPTS - 1) {
478-
throw new Error(`Node at port ${nodeInfo.docker.port} is not responsive after ${MAX_ATTEMPTS} attempts`);
479-
}
480-
await setTimeout(ATTEMPT_DELAY);
481-
}
482-
}
483-
}
484-
}
485-
486-
// Check Sentinel nodes
487-
for (const sentinelInfo of this.#sentinelMap.values()) {
488-
if (!sentinelInfo.client.isReady) {
489-
// Try to reconnect client if not ready
490-
for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {
491-
try {
492-
await sentinelInfo.client.connect();
493-
await sentinelInfo.client.ping();
494-
break;
495-
} catch (err) {
496-
if (attempt === MAX_ATTEMPTS - 1) {
497-
throw new Error(`Sentinel at port ${sentinelInfo.docker.port} is not responsive after ${MAX_ATTEMPTS} attempts`);
498-
}
499-
await setTimeout(ATTEMPT_DELAY);
500-
}
370+
let first = true;
371+
while (await isPortAvailable(port)) {
372+
if (!first) {
373+
await setTimeout(500);
374+
} else {
375+
first = false;
501376
}
377+
await this.restartSentinel(port.toString());
502378
}
503379
}
504380
}
@@ -525,6 +401,9 @@ private async validateSentinelConfiguration(
525401
const masterPort = await this.getMasterPort();
526402
const newNode = await this.spawnRedisSentinelNodeDocker();
527403

404+
if (this.config.password !== undefined) {
405+
await newNode.client.configSet({'masterauth': this.config.password})
406+
}
528407
await newNode.client.replicaOf('127.0.0.1', masterPort);
529408

530409
this.#nodeList.push(newNode);
@@ -608,16 +487,8 @@ private async validateSentinelConfiguration(
608487
if (node === undefined) {
609488
throw new Error("unknown node: " + id);
610489
}
611-
612-
let masterPort: number | null = null;
613-
try {
614-
masterPort = await this.getMasterPort();
615-
} catch (err) {
616-
console.log(`Could not determine master before restarting node ${id}: ${err}`);
617-
}
618-
490+
619491
await this.dockerStart(node.docker.dockerId);
620-
621492
if (!node.client.isOpen) {
622493
node.client = await RedisClient.create({
623494
password: this.config.password,
@@ -626,17 +497,6 @@ private async validateSentinelConfiguration(
626497
}
627498
}).on("error", () => { }).connect();
628499
}
629-
630-
// Wait for node to be ready
631-
await setTimeout(500);
632-
633-
if (masterPort && node.docker.port !== masterPort) {
634-
try {
635-
await node.client.replicaOf('127.0.0.1', masterPort);
636-
} catch (err) {
637-
console.error(`Failed to reconfigure node ${id} as replica: ${err}`);
638-
}
639-
}
640500
}
641501

642502
async stopSentinel(id: string) {
@@ -742,4 +602,4 @@ private async validateSentinelConfiguration(
742602
}
743603
}
744604
}
745-
}
605+
}

packages/test-utils/lib/dockers.ts

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ const portIterator = (async function* (): AsyncIterableIterator<number> {
4343
interface RedisServerDockerConfig {
4444
image: string;
4545
version: string;
46-
env?: Map<string, string>;
4746
}
4847

4948
interface SentinelConfig {
@@ -86,10 +85,6 @@ options: RedisServerDockerOptions, serverArguments: Array<string>): Promise<Redi
8685
});
8786
}
8887

89-
options.env?.forEach((key: string, value: string) => {
90-
dockerArgs.push('-e', `${key}:${value}`);
91-
});
92-
9388
dockerArgs.push(
9489
'-d',
9590
'--network', 'host',
@@ -338,21 +333,13 @@ export async function spawnRedisSentinel(
338333
if (runningNodes) {
339334
return runningNodes;
340335
}
341-
342-
if (!dockerConfigs.env) {
343-
dockerConfigs.env = new Map();
344-
}
345336

346337
const passIndex = serverArguments.indexOf('--requirepass')+1;
347338
let password: string | undefined = undefined;
348339
if (passIndex != 0) {
349340
password = serverArguments[passIndex];
350341
}
351342

352-
if (password !== undefined) {
353-
dockerConfigs.env.set("REDIS_PASSWORD", password);
354-
}
355-
356343
const master = await spawnRedisServerDocker(dockerConfigs, serverArguments);
357344
const redisNodes: Array<RedisServerDocker> = [master];
358345
const replicaPromises: Array<Promise<RedisServerDocker>> = [];

0 commit comments

Comments
 (0)