Skip to content

Commit

Permalink
feat: improve typings for cluster
Browse files Browse the repository at this point in the history
  • Loading branch information
luin committed Mar 14, 2022
1 parent 756e1a7 commit 06782e6
Show file tree
Hide file tree
Showing 24 changed files with 10,310 additions and 1,511 deletions.
1 change: 1 addition & 0 deletions bin/generateRedisCommander/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ async function main() {
"latency",
"lolwut",
"memory",
"cluster",
],
});

Expand Down
45 changes: 45 additions & 0 deletions bin/generateRedisCommander/returnTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,51 @@ module.exports = {
return "string";
}
},
cluster: (types) => {
if (matchSubcommand(types, "SLOTS")) {
return "[startSlotRange: number, endSlotRange: number, ...nodes: [host: string, port: number, nodeId: string, info: unknown[]][]][]";
}
if (
matchSubcommand(types, [
"ADDSLOTS",
"ADDSLOTSRANGE",
"DELSLOTS",
"DELSLOTSRANGE",
"FAILOVER",
"FLUSHSLOTS",
"FORGET",
"MEET",
"REPLICATE",
"RESET",
"SAVECONFIG",
"SET-CONFIG-EPOCH",
"SETSLOT",
])
) {
return "'OK'";
}
if (matchSubcommand(types, "BUMPEPOCH")) {
return "'BUMPED' | 'STILL'";
}
if (
matchSubcommand(types, [
"COUNT-FAILURE-REPORTS",
"COUNTKEYSINSLOT",
"KEYSLOT",
])
) {
return "number";
}
if (matchSubcommand(types, "GETKEYSINSLOT")) {
return "string[]";
}
if (matchSubcommand(types, ["INFO", "MYID"])) {
return "string";
}
if (matchSubcommand(types, "LINKS")) {
return "unknown[]";
}
},
append: "number",
asking: "'OK'",
auth: "'OK'",
Expand Down
5 changes: 2 additions & 3 deletions lib/Redis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,15 +125,14 @@ class Redis extends Commander {
this.resetCommandQueue();
this.resetOfflineQueue();

if ("Connector" in this.options && this.options.Connector) {
if (this.options.Connector) {
this.connector = new this.options.Connector(this.options);
} else if ("sentinels" in this.options && this.options.sentinels) {
} else if (this.options.sentinels) {
const sentinelConnector = new SentinelConnector(this.options);
sentinelConnector.emitter = this;

this.connector = sentinelConnector;
} else {
// @ts-expect-error
this.connector = new StandaloneConnector(this.options);
}

Expand Down
12 changes: 6 additions & 6 deletions lib/cluster/ConnectionPool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ type NODE_TYPE = "all" | "master" | "slave";

export default class ConnectionPool extends EventEmitter {
// master + slave = all
private nodes: { [key in NODE_TYPE]: { [key: string]: any } } = {
private nodes: { [key in NODE_TYPE]: { [key: string]: Redis } } = {
all: {},
master: {},
slave: {},
Expand All @@ -21,16 +21,16 @@ export default class ConnectionPool extends EventEmitter {
super();
}

getNodes(role: NodeRole = "all"): any[] {
getNodes(role: NodeRole = "all"): Redis[] {
const nodes = this.nodes[role];
return Object.keys(nodes).map((key) => nodes[key]);
}

getInstanceByKey(key: NodeKey): any {
getInstanceByKey(key: NodeKey): Redis {
return this.nodes.all[key];
}

getSampleInstance(role: NodeRole): any {
getSampleInstance(role: NodeRole): Redis {
const keys = Object.keys(this.nodes[role]);
const sampleKey = sample(keys);
return this.nodes[role][sampleKey];
Expand All @@ -39,7 +39,7 @@ export default class ConnectionPool extends EventEmitter {
/**
* Find or create a connection to the node
*/
findOrCreate(node: RedisOptions, readOnly = false): any {
findOrCreate(node: RedisOptions, readOnly = false): Redis {
const key = getNodeKey(node);
readOnly = Boolean(readOnly);

Expand All @@ -49,7 +49,7 @@ export default class ConnectionPool extends EventEmitter {
this.specifiedOptions[key] = node;
}

let redis;
let redis: Redis;
if (this.nodes.all[key]) {
redis = this.nodes.all[key];
if (redis.options.readOnly !== readOnly) {
Expand Down
22 changes: 12 additions & 10 deletions lib/cluster/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ class Cluster extends Commander {
/**
* Get nodes with the specified role
*/
nodes(role: NodeRole = "all"): any[] {
nodes(role: NodeRole = "all"): Redis[] {
if (role !== "all" && role !== "master" && role !== "slave") {
throw new Error(
'Invalid role "' + role + '". Expected "all", "master" or "slave"'
Expand Down Expand Up @@ -696,7 +696,6 @@ class Cluster extends Commander {
nextRound();
}


/**
* Change cluster instance's status
*/
Expand Down Expand Up @@ -785,7 +784,7 @@ class Cluster extends Commander {
: nodeKey;
}

private getInfoFromNode(redis, callback) {
private getInfoFromNode(redis: Redis, callback) {
if (!redis) {
return callback(new Error("Node is disconnected"));
}
Expand All @@ -808,7 +807,7 @@ class Cluster extends Commander {
duplicatedConnection.on("error", noop);

duplicatedConnection.cluster(
"slots",
"SLOTS",
timeout((err, result) => {
duplicatedConnection.disconnect();
if (err) {
Expand All @@ -827,7 +826,7 @@ class Cluster extends Commander {
callback();
return;
}
const nodes = [];
const nodes: RedisOptions[] = [];

debug("cluster slots result count: %d", result.length);

Expand All @@ -841,10 +840,13 @@ class Cluster extends Commander {
if (!items[j][0]) {
continue;
}
items[j] = this.natMapper({ host: items[j][0], port: items[j][1] });
items[j].readOnly = j !== 2;
nodes.push(items[j]);
keys.push(items[j].host + ":" + items[j].port);
const node = this.natMapper({
host: items[j][0],
port: items[j][1],
});
node.readOnly = j !== 2;
nodes.push(node);
keys.push(node.host + ":" + node.port);
}

debug(
Expand Down Expand Up @@ -896,7 +898,7 @@ class Cluster extends Commander {
* Check whether Cluster is able to process commands
*/
private readyCheck(callback: Callback<void | "fail">): void {
(this as any).cluster("info", function (err, res) {
this.cluster("INFO", function (err, res) {
if (err) {
return callback(err);
}
Expand Down
13 changes: 7 additions & 6 deletions lib/connectors/StandaloneConnector.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { createConnection, TcpNetConnectOpts, IpcNetConnectOpts } from "net";
import { createConnection, IpcNetConnectOpts, TcpNetConnectOpts } from "net";
import { connect as createTLSConnection, ConnectionOptions } from "tls";
import { NetStream } from "../types";
import { CONNECTION_CLOSED_ERROR_MSG } from "../utils";
import AbstractConnector, { ErrorEmitter } from "./AbstractConnector";
import { NetStream } from "../types";

export type StandaloneConnectionOptions = (
| TcpNetConnectOpts
| IpcNetConnectOpts
) & { disconnectTimeout: number; tls?: ConnectionOptions };
export type StandaloneConnectionOptions = (Partial<TcpNetConnectOpts> &
Partial<IpcNetConnectOpts>) & {
disconnectTimeout?: number;
tls?: ConnectionOptions;
};

export default class StandaloneConnector extends AbstractConnector {
constructor(protected options: StandaloneConnectionOptions) {
Expand Down
6 changes: 4 additions & 2 deletions lib/constants/TLSProfiles.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export default {
const TLSProfiles = {
/**
* TLS settings for Redis.com Cloud Fixed plan. Updated on 2021-10-06.
*/
Expand Down Expand Up @@ -100,4 +100,6 @@ export default {
"UhWfa/HQYOAPDdEjNgnVwLI23b8t0TozyCWw7q8h\n" +
"-----END CERTIFICATE-----\n",
},
};
} as const;

export default TLSProfiles;
6 changes: 3 additions & 3 deletions lib/redis/RedisOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ interface CommonRedisOptions extends CommanderOptions {
lazyConnect?: boolean;
}

export type RedisOptions =
| (CommonRedisOptions & SentinelConnectionOptions)
| (CommonRedisOptions & StandaloneConnectionOptions);
export type RedisOptions = CommonRedisOptions &
SentinelConnectionOptions &
StandaloneConnectionOptions;

export const DEFAULT_REDIS_OPTIONS: RedisOptions = {
// Connection
Expand Down
Loading

0 comments on commit 06782e6

Please sign in to comment.