Skip to content

Commit

Permalink
JS: Allow to opt-in to RESP2 usage.
Browse files Browse the repository at this point in the history
  • Loading branch information
nihohit committed Dec 27, 2023
1 parent 8e6dc0a commit 5296004
Show file tree
Hide file tree
Showing 5 changed files with 370 additions and 303 deletions.
6 changes: 5 additions & 1 deletion node/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
export { BaseClientConfiguration, ReturnType } from "./src/BaseClient";
export {
BaseClientConfiguration,
ProtocolVersion,
ReturnType,
} from "./src/BaseClient";
export {
ExpireOptions,
InfoOptions,
Expand Down
9 changes: 8 additions & 1 deletion node/src/BaseClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ export type ReturnTypeAttribute = {
value: ReturnType;
attributes: ReturnTypeMap;
};
export type ProtocolVersion = connection_request.ProtocolVersion;
export const ProtocolVersion = connection_request.ProtocolVersion;
export type ReturnType =
| "OK"
| string
Expand Down Expand Up @@ -139,6 +141,11 @@ export type BaseClientConfiguration = {
* If not set, `Primary` will be used.
*/
readFrom?: ReadFrom;
/**
* Choose the Redis protocol to be used with the server.
* If not set, `RESP3` will be used.
*/
server_protocol?: ProtocolVersion;
};

function getRequestErrorClass(
Expand Down Expand Up @@ -882,7 +889,7 @@ export class BaseClient {
}
: undefined;
return {
protocol: connection_request.ProtocolVersion.RESP3,
protocol: options.server_protocol,
addresses: options.addresses,
tlsMode: options.useTLS
? connection_request.TlsMode.SecureTls
Expand Down
151 changes: 90 additions & 61 deletions node/tests/RedisClient.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,14 @@ import {
import { BufferReader, BufferWriter } from "protobufjs";
import RedisServer from "redis-server";
import { v4 as uuidv4 } from "uuid";
import { BaseClientConfiguration, RedisClient, Transaction } from "../build-ts";
import {
BaseClientConfiguration,
ProtocolVersion,
RedisClient,
Transaction,
} from "../build-ts";
import { redis_request } from "../src/ProtobufMessage";
import { runBaseTests } from "./SharedTests";
import { PROTOCOL_VERSIONS, runBaseTests } from "./SharedTests";
import { flushallOnPort, transactionTest } from "./TestUtilities";
/* eslint-disable @typescript-eslint/no-var-requires */
const FreePort = require("find-free-port");
Expand Down Expand Up @@ -104,67 +109,91 @@ describe("RedisClient", () => {
]);
});

it("info without parameters", async () => {
const client = await RedisClient.createClient(getOptions(port));
const result = await client.info();
expect(result).toEqual(expect.stringContaining("# Server"));
expect(result).toEqual(expect.stringContaining("# Replication"));
expect(result).toEqual(expect.not.stringContaining("# Latencystats"));
client.close();
});

it("simple select test", async () => {
const client = await RedisClient.createClient(getOptions(port));
let selectResult = await client.select(0);
expect(selectResult).toEqual("OK");

const key = uuidv4();
const value = uuidv4();
const result = await client.set(key, value);
expect(result).toEqual("OK");

selectResult = await client.select(1);
expect(selectResult).toEqual("OK");
expect(await client.get(key)).toEqual(null);

selectResult = await client.select(0);
expect(selectResult).toEqual("OK");
expect(await client.get(key)).toEqual(value);
client.close();
});

it("can send transactions", async () => {
const client = await RedisClient.createClient(getOptions(port));
const transaction = new Transaction();
const expectedRes = transactionTest(transaction);
transaction.select(0);
const result = await client.exec(transaction);
expectedRes.push("OK");
expect(result).toEqual(expectedRes);
client.close();
});

it("can return null on WATCH transaction failures", async () => {
const client1 = await RedisClient.createClient(getOptions(port));
const client2 = await RedisClient.createClient(getOptions(port));
const transaction = new Transaction();
transaction.get("key");
const result1 = await client1.customCommand(["WATCH","key"]);
expect(result1).toEqual("OK");

const result2 = await client2.set("key", "foo");
expect(result2).toEqual("OK");

const result3 = await client1.exec(transaction);
expect(result3).toBeNull();

client1.close();
client2.close();
});
it.each(PROTOCOL_VERSIONS)(
`info without parameters_%p`,
async (protocol: ProtocolVersion) => {
const options = getOptions(port);
options.server_protocol = protocol;
const client = await RedisClient.createClient(options);
const result = await client.info();
expect(result).toEqual(expect.stringContaining("# Server"));
expect(result).toEqual(expect.stringContaining("# Replication"));
expect(result).toEqual(
expect.not.stringContaining("# Latencystats")
);
client.close();
}
);

it.each(PROTOCOL_VERSIONS)(
`simple select test_%p`,
async (protocol: ProtocolVersion) => {
const options = getOptions(port);
options.server_protocol = protocol;
const client = await RedisClient.createClient(options);
let selectResult = await client.select(0);
expect(selectResult).toEqual("OK");

const key = uuidv4();
const value = uuidv4();
const result = await client.set(key, value);
expect(result).toEqual("OK");

selectResult = await client.select(1);
expect(selectResult).toEqual("OK");
expect(await client.get(key)).toEqual(null);

selectResult = await client.select(0);
expect(selectResult).toEqual("OK");
expect(await client.get(key)).toEqual(value);
client.close();
}
);

it.each(PROTOCOL_VERSIONS)(
`can send transactions_%p`,
async (protocol: ProtocolVersion) => {
const options = getOptions(port);
options.server_protocol = protocol;
const client = await RedisClient.createClient(options);
const transaction = new Transaction();
const expectedRes = transactionTest(transaction);
transaction.select(0);
const result = await client.exec(transaction);
expectedRes.push("OK");
expect(result).toEqual(expectedRes);
client.close();
}
);

it.each(PROTOCOL_VERSIONS)(
`can return null on WATCH transaction failures_%p`,
async (protocol: ProtocolVersion) => {
const options = getOptions(port);
options.server_protocol = protocol;
const client1 = await RedisClient.createClient(options);
const client2 = await RedisClient.createClient(options);
const transaction = new Transaction();
transaction.get("key");
const result1 = await client1.customCommand(["WATCH", "key"]);
expect(result1).toEqual("OK");

const result2 = await client2.set("key", "foo");
expect(result2).toEqual("OK");

const result3 = await client1.exec(transaction);
expect(result3).toBeNull();

client1.close();
client2.close();
}
);

runBaseTests<Context>({
init: async () => {
const client = await RedisClient.createClient(getOptions(port));
init: async (protocol) => {
const options = getOptions(port);
options.server_protocol = protocol;
const client = await RedisClient.createClient(options);

return { client, context: { client } };
},
Expand Down
75 changes: 37 additions & 38 deletions node/tests/RedisClusterClient.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ import {
BaseClientConfiguration,
ClusterTransaction,
InfoOptions,
ProtocolVersion,
RedisClusterClient,
} from "../";
import { runBaseTests } from "./SharedTests";
import { PROTOCOL_VERSIONS, runBaseTests } from "./SharedTests";
import { flushallOnPort, transactionTest } from "./TestUtilities";

type Context = {
Expand Down Expand Up @@ -124,11 +125,11 @@ describe("RedisClusterClient", () => {
};

runBaseTests<Context>({
init: async () => {
init: async (protocol) => {
const options = getOptions(cluster.ports());
options.server_protocol = protocol;
testsFailed += 1;
const client = await RedisClusterClient.createClient(
getOptions(cluster.ports())
);
const client = await RedisClusterClient.createClient(options);
return {
context: {
client,
Expand All @@ -145,12 +146,12 @@ describe("RedisClusterClient", () => {
timeout: TIMEOUT,
});

it(
"info with server and replication",
async () => {
const client = await RedisClusterClient.createClient(
getOptions(cluster.ports())
);
it.each(PROTOCOL_VERSIONS)(
`info with server and replication_%p`,
async (protocol: ProtocolVersion) => {
const options = getOptions(cluster.ports());
options.server_protocol = protocol;
const client = await RedisClusterClient.createClient(options);
const result = (await client.info([
InfoOptions.Server,
InfoOptions.Replication,
Expand All @@ -174,12 +175,12 @@ describe("RedisClusterClient", () => {
TIMEOUT
);

it(
"info with server and randomNode route",
async () => {
const client = await RedisClusterClient.createClient(
getOptions(cluster.ports())
);
it.each(PROTOCOL_VERSIONS)(
`info with server and randomNode route_%p`,
async (protocol: ProtocolVersion) => {
const options = getOptions(cluster.ports());
options.server_protocol = protocol;
const client = await RedisClusterClient.createClient(options);
const result = await client.info(
[InfoOptions.Server],
"randomNode"
Expand All @@ -192,12 +193,12 @@ describe("RedisClusterClient", () => {
TIMEOUT
);

it(
"config get and config set transactions test",
async () => {
const client = await RedisClusterClient.createClient(
getOptions(cluster.ports())
);
it.each(PROTOCOL_VERSIONS)(
`config get and config set transactions test_%p`,
async (protocol: ProtocolVersion) => {
const options = getOptions(cluster.ports());
options.server_protocol = protocol;
const client = await RedisClusterClient.createClient(options);
const transaction = new ClusterTransaction();
transaction.configSet({ timeout: "1000" });
transaction.configGet(["timeout"]);
Expand All @@ -208,12 +209,12 @@ describe("RedisClusterClient", () => {
TIMEOUT
);

it(
"can send transactions",
async () => {
const client = await RedisClusterClient.createClient(
getOptions(cluster.ports())
);
it.each(PROTOCOL_VERSIONS)(
`can send transactions_%p`,
async (protocol: ProtocolVersion) => {
const options = getOptions(cluster.ports());
options.server_protocol = protocol;
const client = await RedisClusterClient.createClient(options);
const transaction = new ClusterTransaction();
const expectedRes = transactionTest(transaction);
const result = await client.exec(transaction);
Expand All @@ -223,15 +224,13 @@ describe("RedisClusterClient", () => {
TIMEOUT
);

it(
"can return null on WATCH transaction failures",
async () => {
const client1 = await RedisClusterClient.createClient(
getOptions(cluster.ports())
);
const client2 = await RedisClusterClient.createClient(
getOptions(cluster.ports())
);
it.each(PROTOCOL_VERSIONS)(
`can return null on WATCH transaction failures_%p`,
async (protocol: ProtocolVersion) => {
const options = getOptions(cluster.ports());
options.server_protocol = protocol;
const client1 = await RedisClusterClient.createClient(options);
const client2 = await RedisClusterClient.createClient(options);
const transaction = new ClusterTransaction();
transaction.get("key");
const result1 = await client1.customCommand(["WATCH", "key"]);
Expand Down
Loading

0 comments on commit 5296004

Please sign in to comment.