diff --git a/packages/client/lib/client/commands.ts b/packages/client/lib/client/commands.ts index 0d9f63b003..acffd4711a 100644 --- a/packages/client/lib/client/commands.ts +++ b/packages/client/lib/client/commands.ts @@ -23,8 +23,11 @@ import * as CLIENT_KILL from '../commands/CLIENT_KILL'; import * as CLIENT_SETNAME from '../commands/CLIENT_SETNAME'; import * as CLIENT_INFO from '../commands/CLIENT_INFO'; import * as CLUSTER_ADDSLOTS from '../commands/CLUSTER_ADDSLOTS'; +import * as CLUSTER_ADDSLOTSRANGE from '../commands/CLUSTER_ADDSLOTSRANGE'; +import * as CLUSTER_DELSLOTSRANGE from '../commands/CLUSTER_DELSLOTSRANGE'; import * as CLUSTER_FLUSHSLOTS from '../commands/CLUSTER_FLUSHSLOTS'; import * as CLUSTER_INFO from '../commands/CLUSTER_INFO'; +import * as CLUSTER_LINKS from '../commands/CLUSTER_LINKS'; import * as CLUSTER_NODES from '../commands/CLUSTER_NODES'; import * as CLUSTER_MEET from '../commands/CLUSTER_MEET'; import * as CLUSTER_RESET from '../commands/CLUSTER_RESET'; @@ -132,10 +135,16 @@ export default { clientInfo: CLIENT_INFO, CLUSTER_ADDSLOTS, clusterAddSlots: CLUSTER_ADDSLOTS, + CLUSTER_ADDSLOTSRANGE, + clusterAddSlotsRange: CLUSTER_ADDSLOTSRANGE, + CLUSTER_DELSLOTSRANGE, + clusterDelSlotsRange: CLUSTER_DELSLOTSRANGE, CLUSTER_FLUSHSLOTS, clusterFlushSlots: CLUSTER_FLUSHSLOTS, CLUSTER_INFO, clusterInfo: CLUSTER_INFO, + CLUSTER_LINKS, + clusterLinks: CLUSTER_LINKS, CLUSTER_NODES, clusterNodes: CLUSTER_NODES, CLUSTER_MEET, diff --git a/packages/client/lib/commands/CLUSTER_ADDSLOTSRANGE.spec.ts b/packages/client/lib/commands/CLUSTER_ADDSLOTSRANGE.spec.ts new file mode 100644 index 0000000000..ebd1e3445f --- /dev/null +++ b/packages/client/lib/commands/CLUSTER_ADDSLOTSRANGE.spec.ts @@ -0,0 +1,29 @@ +import { strict as assert } from 'assert'; +import { transformArguments } from './CLUSTER_ADDSLOTSRANGE'; + +describe('CLUSTER ADDSLOTSRANGE', () => { + describe('transformArguments', () => { + it('single', () => { + assert.deepEqual( + transformArguments({ + start: 0, + end: 1 + }), + ['CLUSTER', 'ADDSLOTSRANGE', '0', '1'] + ); + }); + + it('multiple', () => { + assert.deepEqual( + transformArguments([{ + start: 0, + end: 1 + }, { + start: 2, + end: 3 + }]), + ['CLUSTER', 'ADDSLOTSRANGE', '0', '1', '2', '3'] + ); + }); + }); +}); diff --git a/packages/client/lib/commands/CLUSTER_ADDSLOTSRANGE.ts b/packages/client/lib/commands/CLUSTER_ADDSLOTSRANGE.ts new file mode 100644 index 0000000000..6a8d6dc668 --- /dev/null +++ b/packages/client/lib/commands/CLUSTER_ADDSLOTSRANGE.ts @@ -0,0 +1,13 @@ +import { RedisCommandArguments } from '.'; +import { pushSlotRangesArguments, SlotRange } from './generic-transformers'; + +export function transformArguments( + ranges: SlotRange | Array +): RedisCommandArguments { + return pushSlotRangesArguments( + ['CLUSTER', 'ADDSLOTSRANGE'], + ranges + ); +} + +export declare function transformReply(): 'OK'; diff --git a/packages/client/lib/commands/CLUSTER_DELSLOTSRANGE.spec.ts b/packages/client/lib/commands/CLUSTER_DELSLOTSRANGE.spec.ts new file mode 100644 index 0000000000..8fd50d01a5 --- /dev/null +++ b/packages/client/lib/commands/CLUSTER_DELSLOTSRANGE.spec.ts @@ -0,0 +1,29 @@ +import { strict as assert } from 'assert'; +import { transformArguments } from './CLUSTER_DELSLOTSRANGE'; + +describe('CLUSTER DELSLOTSRANGE', () => { + describe('transformArguments', () => { + it('single', () => { + assert.deepEqual( + transformArguments({ + start: 0, + end: 1 + }), + ['CLUSTER', 'DELSLOTSRANGE', '0', '1'] + ); + }); + + it('multiple', () => { + assert.deepEqual( + transformArguments([{ + start: 0, + end: 1 + }, { + start: 2, + end: 3 + }]), + ['CLUSTER', 'DELSLOTSRANGE', '0', '1', '2', '3'] + ); + }); + }); +}); diff --git a/packages/client/lib/commands/CLUSTER_DELSLOTSRANGE.ts b/packages/client/lib/commands/CLUSTER_DELSLOTSRANGE.ts new file mode 100644 index 0000000000..b136113c65 --- /dev/null +++ b/packages/client/lib/commands/CLUSTER_DELSLOTSRANGE.ts @@ -0,0 +1,13 @@ +import { RedisCommandArguments } from '.'; +import { pushSlotRangesArguments, SlotRange } from './generic-transformers'; + +export function transformArguments( + ranges: SlotRange | Array +): RedisCommandArguments { + return pushSlotRangesArguments( + ['CLUSTER', 'DELSLOTSRANGE'], + ranges + ); +} + +export declare function transformReply(): 'OK'; diff --git a/packages/client/lib/commands/CLUSTER_LINKS.spec.ts b/packages/client/lib/commands/CLUSTER_LINKS.spec.ts new file mode 100644 index 0000000000..242e9012fb --- /dev/null +++ b/packages/client/lib/commands/CLUSTER_LINKS.spec.ts @@ -0,0 +1,27 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './CLUSTER_LINKS'; + +describe('CLUSTER LINKS', () => { + testUtils.isVersionGreaterThanHook([7, 0]); + + it('transformArguments', () => { + assert.deepEqual( + transformArguments(), + ['CLUSTER', 'LINKS'] + ); + }); + + testUtils.testWithCluster('clusterNode.clusterLinks', async cluster => { + const links = await cluster.getSlotMaster(0).client.clusterLinks(); + assert.ok(Array.isArray(links)); + for (const link of links) { + assert.equal(typeof link.direction, 'string'); + assert.equal(typeof link.node, 'string'); + assert.equal(typeof link.createTime, 'number'); + assert.equal(typeof link.events, 'string'); + assert.equal(typeof link.sendBufferAllocated, 'number'); + assert.equal(typeof link.sendBufferUsed, 'number'); + } + }, GLOBAL.CLUSTERS.OPEN); +}); diff --git a/packages/client/lib/commands/CLUSTER_LINKS.ts b/packages/client/lib/commands/CLUSTER_LINKS.ts new file mode 100644 index 0000000000..9a5608c102 --- /dev/null +++ b/packages/client/lib/commands/CLUSTER_LINKS.ts @@ -0,0 +1,38 @@ +export function transformArguments(): Array { + return ['CLUSTER', 'LINKS']; +} + +type ClusterLinksRawReply = Array<[ + 'direction', + string, + 'node', + string, + 'createTime', + number, + 'events', + string, + 'send-buffer-allocated', + number, + 'send-buffer-used', + number +]>; + +type ClusterLinksReply = Array<{ + direction: string; + node: string; + createTime: number; + events: string; + sendBufferAllocated: number; + sendBufferUsed: number; +}>; + +export function transformReply(reply: ClusterLinksRawReply): ClusterLinksReply { + return reply.map(peerLink => ({ + direction: peerLink[1], + node: peerLink[3], + createTime: Number(peerLink[5]), + events: peerLink[7], + sendBufferAllocated: Number(peerLink[9]), + sendBufferUsed: Number(peerLink[11]) + })); +} diff --git a/packages/client/lib/commands/generic-transformers.spec.ts b/packages/client/lib/commands/generic-transformers.spec.ts index 96dca31dad..6e286e284d 100644 --- a/packages/client/lib/commands/generic-transformers.spec.ts +++ b/packages/client/lib/commands/generic-transformers.spec.ts @@ -23,7 +23,8 @@ import { pushOptionalVerdictArgument, transformCommandReply, CommandFlags, - CommandCategories + CommandCategories, + pushSlotRangesArguments } from './generic-transformers'; describe('Generic Transformers', () => { @@ -639,4 +640,29 @@ describe('Generic Transformers', () => { } ); }); + + describe('pushSlotRangesArguments', () => { + it('single range', () => { + assert.deepEqual( + pushSlotRangesArguments([], { + start: 0, + end: 1 + }), + ['0', '1'] + ); + }); + + it('multiple ranges', () => { + assert.deepEqual( + pushSlotRangesArguments([], [{ + start: 0, + end: 1 + }, { + start: 2, + end: 3 + }]), + ['0', '1', '2', '3'] + ); + }); + }); }); diff --git a/packages/client/lib/commands/generic-transformers.ts b/packages/client/lib/commands/generic-transformers.ts index 0799476ae6..a7bc6805dd 100644 --- a/packages/client/lib/commands/generic-transformers.ts +++ b/packages/client/lib/commands/generic-transformers.ts @@ -422,3 +422,33 @@ export function transformCommandReply( categories: new Set(categories) }; } + +export interface SlotRange { + start: number; + end: number; +} + +function pushSlotRangeArguments( + args: RedisCommandArguments, + range: SlotRange +): void { + args.push( + range.start.toString(), + range.end.toString() + ); +} + +export function pushSlotRangesArguments( + args: RedisCommandArguments, + ranges: SlotRange | Array +): RedisCommandArguments { + if (Array.isArray(ranges)) { + for (const range of ranges) { + pushSlotRangeArguments(args, range); + } + } else { + pushSlotRangeArguments(args, ranges); + } + + return args; +}