You've already forked node-redis
mirror of
https://github.com/redis/node-redis.git
synced 2025-08-06 02:15:48 +03:00
V5 bringing RESP3, Sentinel and TypeMapping to node-redis
RESP3 Support - Some commands responses in RESP3 aren't stable yet and therefore return an "untyped" ReplyUnion. Sentinel TypeMapping Correctly types Multi commands Note: some API changes to be further documented in v4-to-v5.md
This commit is contained in:
@@ -1,105 +1,10 @@
|
||||
export function transformArguments(): Array<string> {
|
||||
import { VerbatimStringReply, Command } from '../RESP/types';
|
||||
|
||||
export default {
|
||||
FIRST_KEY_INDEX: undefined,
|
||||
IS_READ_ONLY: true,
|
||||
transformArguments() {
|
||||
return ['CLUSTER', 'NODES'];
|
||||
}
|
||||
|
||||
export enum RedisClusterNodeLinkStates {
|
||||
CONNECTED = 'connected',
|
||||
DISCONNECTED = 'disconnected'
|
||||
}
|
||||
|
||||
interface RedisClusterNodeAddress {
|
||||
host: string;
|
||||
port: number;
|
||||
cport: number | null;
|
||||
}
|
||||
|
||||
export interface RedisClusterReplicaNode extends RedisClusterNodeAddress {
|
||||
id: string;
|
||||
address: string;
|
||||
flags: Array<string>;
|
||||
pingSent: number;
|
||||
pongRecv: number;
|
||||
configEpoch: number;
|
||||
linkState: RedisClusterNodeLinkStates;
|
||||
}
|
||||
|
||||
export interface RedisClusterMasterNode extends RedisClusterReplicaNode {
|
||||
slots: Array<{
|
||||
from: number;
|
||||
to: number;
|
||||
}>;
|
||||
replicas: Array<RedisClusterReplicaNode>;
|
||||
}
|
||||
|
||||
export function transformReply(reply: string): Array<RedisClusterMasterNode> {
|
||||
const lines = reply.split('\n');
|
||||
lines.pop(); // last line is empty
|
||||
|
||||
const mastersMap = new Map<string, RedisClusterMasterNode>(),
|
||||
replicasMap = new Map<string, Array<RedisClusterReplicaNode>>();
|
||||
|
||||
for (const line of lines) {
|
||||
const [id, address, flags, masterId, pingSent, pongRecv, configEpoch, linkState, ...slots] = line.split(' '),
|
||||
node = {
|
||||
id,
|
||||
address,
|
||||
...transformNodeAddress(address),
|
||||
flags: flags.split(','),
|
||||
pingSent: Number(pingSent),
|
||||
pongRecv: Number(pongRecv),
|
||||
configEpoch: Number(configEpoch),
|
||||
linkState: (linkState as RedisClusterNodeLinkStates)
|
||||
};
|
||||
|
||||
if (masterId === '-') {
|
||||
let replicas = replicasMap.get(id);
|
||||
if (!replicas) {
|
||||
replicas = [];
|
||||
replicasMap.set(id, replicas);
|
||||
}
|
||||
|
||||
mastersMap.set(id, {
|
||||
...node,
|
||||
slots: slots.map(slot => {
|
||||
// TODO: importing & exporting (https://redis.io/commands/cluster-nodes#special-slot-entries)
|
||||
const [fromString, toString] = slot.split('-', 2),
|
||||
from = Number(fromString);
|
||||
return {
|
||||
from,
|
||||
to: toString ? Number(toString) : from
|
||||
};
|
||||
}),
|
||||
replicas
|
||||
});
|
||||
} else {
|
||||
const replicas = replicasMap.get(masterId);
|
||||
if (!replicas) {
|
||||
replicasMap.set(masterId, [node]);
|
||||
} else {
|
||||
replicas.push(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [...mastersMap.values()];
|
||||
}
|
||||
|
||||
function transformNodeAddress(address: string): RedisClusterNodeAddress {
|
||||
const indexOfColon = address.lastIndexOf(':'),
|
||||
indexOfAt = address.indexOf('@', indexOfColon),
|
||||
host = address.substring(0, indexOfColon);
|
||||
|
||||
if (indexOfAt === -1) {
|
||||
return {
|
||||
host,
|
||||
port: Number(address.substring(indexOfColon + 1)),
|
||||
cport: null
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
host: address.substring(0, indexOfColon),
|
||||
port: Number(address.substring(indexOfColon + 1, indexOfAt)),
|
||||
cport: Number(address.substring(indexOfAt + 1))
|
||||
};
|
||||
}
|
||||
},
|
||||
transformReply: undefined as unknown as () => VerbatimStringReply
|
||||
} as const satisfies Command;
|
||||
|
Reference in New Issue
Block a user