You've already forked node-redis
mirror of
https://github.com/redis/node-redis.git
synced 2025-12-09 21:21:11 +03:00
* refactor(test): improve test scenario reliability and maintainability * tests: add resp3 check test (#1) * test: refactor connection handoff tests with enhanced spy utility (#2) * test: add comprehensive push notification disabled scenarios (#3) * tests: add params config tests (#4) * tests: add feature enablement tests (#5) --------- Co-authored-by: Nikolay Karadzhov <nikolay.karadzhov@redis.com>
350 lines
10 KiB
TypeScript
350 lines
10 KiB
TypeScript
import assert from "node:assert";
|
|
import diagnostics_channel from "node:diagnostics_channel";
|
|
import { FaultInjectorClient } from "./fault-injector-client";
|
|
import {
|
|
createTestClient,
|
|
getDatabaseConfig,
|
|
getDatabaseConfigFromEnv,
|
|
getEnvConfig,
|
|
RedisConnectionConfig,
|
|
} from "./test-scenario.util";
|
|
import { createClient } from "../../..";
|
|
import { DiagnosticsEvent } from "../../client/enterprise-maintenance-manager";
|
|
import { before } from "mocha";
|
|
|
|
describe("Push Notifications", () => {
|
|
const createNotificationMessageHandler = (
|
|
result: Record<DiagnosticsEvent["type"], number>,
|
|
notifications: Array<DiagnosticsEvent["type"]>
|
|
) => {
|
|
return (message: unknown) => {
|
|
if (notifications.includes((message as DiagnosticsEvent).type)) {
|
|
const event = message as DiagnosticsEvent;
|
|
result[event.type] = (result[event.type] ?? 0) + 1;
|
|
}
|
|
};
|
|
};
|
|
|
|
let onMessageHandler: ReturnType<typeof createNotificationMessageHandler>;
|
|
let clientConfig: RedisConnectionConfig;
|
|
let client: ReturnType<typeof createClient<any, any, any, any>>;
|
|
let faultInjectorClient: FaultInjectorClient;
|
|
|
|
before(() => {
|
|
const envConfig = getEnvConfig();
|
|
const redisConfig = getDatabaseConfigFromEnv(
|
|
envConfig.redisEndpointsConfigPath
|
|
);
|
|
|
|
faultInjectorClient = new FaultInjectorClient(envConfig.faultInjectorUrl);
|
|
clientConfig = getDatabaseConfig(redisConfig);
|
|
});
|
|
|
|
afterEach(() => {
|
|
if (onMessageHandler!) {
|
|
diagnostics_channel.unsubscribe("redis.maintenance", onMessageHandler);
|
|
}
|
|
|
|
if (client && client.isOpen) {
|
|
client.destroy();
|
|
}
|
|
});
|
|
|
|
describe("Push Notifications Enabled", () => {
|
|
beforeEach(async () => {
|
|
client = await createTestClient(clientConfig);
|
|
|
|
await client.flushAll();
|
|
});
|
|
|
|
it("should receive MOVING, MIGRATING, and MIGRATED push notifications", async () => {
|
|
const notifications: Array<DiagnosticsEvent["type"]> = [
|
|
"MOVING",
|
|
"MIGRATING",
|
|
"MIGRATED",
|
|
];
|
|
|
|
const diagnosticsMap: Record<DiagnosticsEvent["type"], number> = {};
|
|
|
|
onMessageHandler = createNotificationMessageHandler(
|
|
diagnosticsMap,
|
|
notifications
|
|
);
|
|
|
|
diagnostics_channel.subscribe("redis.maintenance", onMessageHandler);
|
|
|
|
const { action_id: bindAndMigrateActionId } =
|
|
await faultInjectorClient.migrateAndBindAction({
|
|
bdbId: clientConfig.bdbId,
|
|
clusterIndex: 0,
|
|
});
|
|
|
|
await faultInjectorClient.waitForAction(bindAndMigrateActionId);
|
|
|
|
assert.strictEqual(
|
|
diagnosticsMap.MOVING,
|
|
1,
|
|
"Should have received exactly one MOVING notification"
|
|
);
|
|
assert.strictEqual(
|
|
diagnosticsMap.MIGRATING,
|
|
1,
|
|
"Should have received exactly one MIGRATING notification"
|
|
);
|
|
assert.strictEqual(
|
|
diagnosticsMap.MIGRATED,
|
|
1,
|
|
"Should have received exactly one MIGRATED notification"
|
|
);
|
|
});
|
|
|
|
it("should receive FAILING_OVER and FAILED_OVER push notifications", async () => {
|
|
const notifications: Array<DiagnosticsEvent["type"]> = [
|
|
"FAILING_OVER",
|
|
"FAILED_OVER",
|
|
];
|
|
|
|
const diagnosticsMap: Record<DiagnosticsEvent["type"], number> = {};
|
|
|
|
onMessageHandler = createNotificationMessageHandler(
|
|
diagnosticsMap,
|
|
notifications
|
|
);
|
|
|
|
diagnostics_channel.subscribe("redis.maintenance", onMessageHandler);
|
|
|
|
const { action_id: failoverActionId } =
|
|
await faultInjectorClient.triggerAction({
|
|
type: "failover",
|
|
parameters: {
|
|
bdb_id: clientConfig.bdbId.toString(),
|
|
cluster_index: 0,
|
|
},
|
|
});
|
|
|
|
await faultInjectorClient.waitForAction(failoverActionId);
|
|
|
|
assert.strictEqual(
|
|
diagnosticsMap.FAILING_OVER,
|
|
1,
|
|
"Should have received exactly one FAILING_OVER notification"
|
|
);
|
|
assert.strictEqual(
|
|
diagnosticsMap.FAILED_OVER,
|
|
1,
|
|
"Should have received exactly one FAILED_OVER notification"
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("Push Notifications Disabled - Client", () => {
|
|
beforeEach(async () => {
|
|
client = await createTestClient(clientConfig, {
|
|
maintPushNotifications: "disabled",
|
|
});
|
|
|
|
client.on("error", (_err) => {
|
|
// Expect the socket to be closed
|
|
// Ignore errors
|
|
});
|
|
|
|
await client.flushAll();
|
|
});
|
|
|
|
it("should NOT receive MOVING, MIGRATING, and MIGRATED push notifications", async () => {
|
|
const notifications: Array<DiagnosticsEvent["type"]> = [
|
|
"MOVING",
|
|
"MIGRATING",
|
|
"MIGRATED",
|
|
];
|
|
|
|
const diagnosticsMap: Record<DiagnosticsEvent["type"], number> = {};
|
|
|
|
onMessageHandler = createNotificationMessageHandler(
|
|
diagnosticsMap,
|
|
notifications
|
|
);
|
|
|
|
diagnostics_channel.subscribe("redis.maintenance", onMessageHandler);
|
|
|
|
const { action_id: bindAndMigrateActionId } =
|
|
await faultInjectorClient.migrateAndBindAction({
|
|
bdbId: clientConfig.bdbId,
|
|
clusterIndex: 0,
|
|
});
|
|
|
|
await faultInjectorClient.waitForAction(bindAndMigrateActionId);
|
|
|
|
assert.strictEqual(
|
|
diagnosticsMap.MOVING,
|
|
undefined,
|
|
"Should NOT have received exactly one MOVING notification"
|
|
);
|
|
assert.strictEqual(
|
|
diagnosticsMap.MIGRATING,
|
|
undefined,
|
|
"Should NOT have received exactly one MIGRATING notification"
|
|
);
|
|
assert.strictEqual(
|
|
diagnosticsMap.MIGRATED,
|
|
undefined,
|
|
"Should NOT have received exactly one MIGRATED notification"
|
|
);
|
|
});
|
|
|
|
it("should NOT receive FAILING_OVER and FAILED_OVER push notifications", async () => {
|
|
const notifications: Array<DiagnosticsEvent["type"]> = [
|
|
"FAILING_OVER",
|
|
"FAILED_OVER",
|
|
];
|
|
|
|
const diagnosticsMap: Record<DiagnosticsEvent["type"], number> = {};
|
|
|
|
onMessageHandler = createNotificationMessageHandler(
|
|
diagnosticsMap,
|
|
notifications
|
|
);
|
|
|
|
diagnostics_channel.subscribe("redis.maintenance", onMessageHandler);
|
|
|
|
const { action_id: failoverActionId } =
|
|
await faultInjectorClient.triggerAction({
|
|
type: "failover",
|
|
parameters: {
|
|
bdb_id: clientConfig.bdbId.toString(),
|
|
cluster_index: 0,
|
|
},
|
|
});
|
|
|
|
await faultInjectorClient.waitForAction(failoverActionId);
|
|
|
|
assert.strictEqual(
|
|
diagnosticsMap.FAILING_OVER,
|
|
undefined,
|
|
"Should have received exactly one FAILING_OVER notification"
|
|
);
|
|
assert.strictEqual(
|
|
diagnosticsMap.FAILED_OVER,
|
|
undefined,
|
|
"Should have received exactly one FAILED_OVER notification"
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("Push Notifications Disabled - Server", () => {
|
|
beforeEach(async () => {
|
|
client = await createTestClient(clientConfig);
|
|
|
|
client.on("error", (_err) => {
|
|
// Expect the socket to be closed
|
|
// Ignore errors
|
|
});
|
|
|
|
await client.flushAll();
|
|
});
|
|
|
|
before(async () => {
|
|
const { action_id: disablePushNotificationsActionId } =
|
|
await faultInjectorClient.triggerAction({
|
|
type: "update_cluster_config",
|
|
parameters: {
|
|
config: { client_maint_notifications: false },
|
|
},
|
|
});
|
|
|
|
await faultInjectorClient.waitForAction(disablePushNotificationsActionId);
|
|
});
|
|
|
|
after(async () => {
|
|
const { action_id: enablePushNotificationsActionId } =
|
|
await faultInjectorClient.triggerAction({
|
|
type: "update_cluster_config",
|
|
parameters: {
|
|
config: { client_maint_notifications: true },
|
|
},
|
|
});
|
|
|
|
await faultInjectorClient.waitForAction(enablePushNotificationsActionId);
|
|
});
|
|
|
|
it("should NOT receive MOVING, MIGRATING, and MIGRATED push notifications", async () => {
|
|
const notifications: Array<DiagnosticsEvent["type"]> = [
|
|
"MOVING",
|
|
"MIGRATING",
|
|
"MIGRATED",
|
|
];
|
|
|
|
const diagnosticsMap: Record<DiagnosticsEvent["type"], number> = {};
|
|
|
|
onMessageHandler = createNotificationMessageHandler(
|
|
diagnosticsMap,
|
|
notifications
|
|
);
|
|
|
|
diagnostics_channel.subscribe("redis.maintenance", onMessageHandler);
|
|
|
|
const { action_id: bindAndMigrateActionId } =
|
|
await faultInjectorClient.migrateAndBindAction({
|
|
bdbId: clientConfig.bdbId,
|
|
clusterIndex: 0,
|
|
});
|
|
|
|
await faultInjectorClient.waitForAction(bindAndMigrateActionId);
|
|
|
|
assert.strictEqual(
|
|
diagnosticsMap.MOVING,
|
|
undefined,
|
|
"Should NOT have received exactly one MOVING notification"
|
|
);
|
|
assert.strictEqual(
|
|
diagnosticsMap.MIGRATING,
|
|
undefined,
|
|
"Should NOT have received exactly one MIGRATING notification"
|
|
);
|
|
assert.strictEqual(
|
|
diagnosticsMap.MIGRATED,
|
|
undefined,
|
|
"Should NOT have received exactly one MIGRATED notification"
|
|
);
|
|
});
|
|
|
|
it("should NOT receive FAILING_OVER and FAILED_OVER push notifications", async () => {
|
|
const notifications: Array<DiagnosticsEvent["type"]> = [
|
|
"FAILING_OVER",
|
|
"FAILED_OVER",
|
|
];
|
|
|
|
const diagnosticsMap: Record<DiagnosticsEvent["type"], number> = {};
|
|
|
|
onMessageHandler = createNotificationMessageHandler(
|
|
diagnosticsMap,
|
|
notifications
|
|
);
|
|
|
|
diagnostics_channel.subscribe("redis.maintenance", onMessageHandler);
|
|
|
|
const { action_id: failoverActionId } =
|
|
await faultInjectorClient.triggerAction({
|
|
type: "failover",
|
|
parameters: {
|
|
bdb_id: clientConfig.bdbId.toString(),
|
|
cluster_index: 0,
|
|
},
|
|
});
|
|
|
|
await faultInjectorClient.waitForAction(failoverActionId);
|
|
|
|
assert.strictEqual(
|
|
diagnosticsMap.FAILING_OVER,
|
|
undefined,
|
|
"Should have received exactly one FAILING_OVER notification"
|
|
);
|
|
assert.strictEqual(
|
|
diagnosticsMap.FAILED_OVER,
|
|
undefined,
|
|
"Should have received exactly one FAILED_OVER notification"
|
|
);
|
|
});
|
|
});
|
|
});
|