Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(#273): Try to fix flaky tests for experimental/cluster #275

Merged
merged 14 commits into from
Nov 27, 2021
23 changes: 15 additions & 8 deletions tests/cluster/test_util.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { nextPort, startRedis, stopRedis } from "../test_util.ts";
import type { TestServer } from "../test_util.ts";
import { readAll } from "../../vendor/https/deno.land/std/io/util.ts";
import { delay } from "../../vendor/https/deno.land/std/async/delay.ts";

export interface TestCluster {
servers: TestServer[];
Expand Down Expand Up @@ -29,21 +28,29 @@ export async function startRedisCluster(ports: number[]): Promise<TestCluster> {
stderr: "piped",
});
try {
// Wait for cluster setup to complete...
const status = await redisCLI.status();
if (!status.success) {
stopRedisCluster(cluster);
const output = await readAll(redisCLI.stderr);
const errOutput = await readAll(redisCLI.stderr);
const decoder = new TextDecoder();
throw new Error(decoder.decode(output));
throw new Error(`Failed to setup cluster: ${decoder.decode(errOutput)}`);
}

// Ample time for cluster to finish startup
await delay(5000);

return cluster;
} finally {
redisCLI.stderr.close();
redisCLI.close();
tryClose(redisCLI.stderr);
tryClose(redisCLI);
}
}

function tryClose(closer: Deno.Closer): void {
try {
closer.close();
} catch (error) {
if (!(error instanceof Deno.errors.BadResource)) {
throw error;
}
}
}

Expand Down
1 change: 0 additions & 1 deletion tests/server/redis.conf
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# Base configuration
daemonize no
appendonly yes
cluster-config-file nodes.conf
cluster-node-timeout 30000
maxclients 1001
49 changes: 32 additions & 17 deletions tests/test_util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,34 +16,31 @@ export async function startRedis({
makeClusterConfigFile = false,
}): Promise<TestServer> {
const path = tempPath(String(port));

if (!(await exists(path))) {
const destPath = `${path}/redis.conf`;
Deno.mkdirSync(path);
Deno.copyFileSync(`tests/server/redis.conf`, destPath);
await Deno.mkdir(path);
}

let config = `dir ${path}\nport ${port}\n`;
if (clusterEnabled) {
config += "cluster-enabled yes\n";
if (makeClusterConfigFile) {
const clusterConfigFile = `${path}/cluster.conf`;
config += `cluster-config-file ${clusterConfigFile}`;
}
// Setup redis.conf
const destPath = `${path}/redis.conf`;
let config = await Deno.readTextFile("tests/server/redis.conf");
config += `dir ${path}\nport ${port}\n`;
if (clusterEnabled) {
config += "cluster-enabled yes\n";
if (makeClusterConfigFile) {
const clusterConfigFile = `${path}/cluster.conf`;
config += `cluster-config-file ${clusterConfigFile}`;
}

await Deno.writeFile(destPath, encoder.encode(config), {
append: true,
});
}
await Deno.writeFile(destPath, encoder.encode(config));

// Start redis server
const process = Deno.run({
cmd: ["redis-server", `${path}/redis.conf`],
stdin: "null",
stdout: "null",
});

// Ample time for server to finish startup
await delay(500);
await waitForPort(port);
return { path, port, process };
}

Expand Down Expand Up @@ -73,6 +70,24 @@ export function nextPort(): number {
return currentPort++;
}

async function waitForPort(port: number): Promise<void> {
let retries = 0;
const maxRetries = 5;
while (true) {
try {
const conn = await Deno.connect({ port });
conn.close();
break;
} catch (e) {
retries++;
if (retries === maxRetries) {
throw e;
}
await delay(200);
}
}
}

function tempPath(fileName: string): string {
const url = new URL(`./tmp/${fileName}`, import.meta.url);
return url.pathname;
Expand Down