Skip to content

Commit 5821fcb

Browse files
Avital-Fineleibale
andauthored
Support CLUSTER commands (#2015)
* Support CLUSTER commands * add some client tests * remove only * delete cluster slaves * delete reset clietn test * SET SLOT * test with client * fix fail * Update CLUSTER_COUNTKEYSINSLOT.spec.ts * move commands to client/commands.ts * clusterNode * remove CLUSTER-SET-CONFIG-EPOCH test with client * clean code Co-authored-by: leibale <[email protected]>
1 parent 5ade5da commit 5821fcb

37 files changed

+393
-29
lines changed

packages/client/lib/client/commands.ts

+42-3
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,26 @@ import * as CLIENT_SETNAME from '../commands/CLIENT_SETNAME';
2424
import * as CLIENT_INFO from '../commands/CLIENT_INFO';
2525
import * as CLUSTER_ADDSLOTS from '../commands/CLUSTER_ADDSLOTS';
2626
import * as CLUSTER_ADDSLOTSRANGE from '../commands/CLUSTER_ADDSLOTSRANGE';
27+
import * as CLUSTER_BUMPEPOCH from '../commands/CLUSTER_BUMPEPOCH';
28+
import * as CLUSTER_COUNT_FAILURE_REPORTS from '../commands/CLUSTER_COUNT-FAILURE-REPORTS';
29+
import * as CLUSTER_COUNTKEYSINSLOT from '../commands/CLUSTER_COUNTKEYSINSLOT';
30+
import * as CLUSTER_DELSLOTS from '../commands/CLUSTER_DELSLOTS';
2731
import * as CLUSTER_DELSLOTSRANGE from '../commands/CLUSTER_DELSLOTSRANGE';
32+
import * as CLUSTER_FAILOVER from '../commands/CLUSTER_FAILOVER';
2833
import * as CLUSTER_FLUSHSLOTS from '../commands/CLUSTER_FLUSHSLOTS';
34+
import * as CLUSTER_FORGET from '../commands/CLUSTER_FORGET';
35+
import * as CLUSTER_GETKEYSINSLOT from '../commands/CLUSTER_GETKEYSINSLOT';
2936
import * as CLUSTER_INFO from '../commands/CLUSTER_INFO';
37+
import * as CLUSTER_KEYSLOT from '../commands/CLUSTER_KEYSLOT';
3038
import * as CLUSTER_LINKS from '../commands/CLUSTER_LINKS';
31-
import * as CLUSTER_NODES from '../commands/CLUSTER_NODES';
3239
import * as CLUSTER_MEET from '../commands/CLUSTER_MEET';
40+
import * as CLUSTER_MYID from '../commands/CLUSTER_MYID';
41+
import * as CLUSTER_NODES from '../commands/CLUSTER_NODES';
42+
import * as CLUSTER_REPLICAS from '../commands/CLUSTER_REPLICAS';
43+
import * as CLUSTER_REPLICATE from '../commands/CLUSTER_REPLICATE';
3344
import * as CLUSTER_RESET from '../commands/CLUSTER_RESET';
45+
import * as CLUSTER_SAVECONFIG from '../commands/CLUSTER_SAVECONFIG';
46+
import * as CLUSTER_SET_CONFIG_EPOCH from '../commands/CLUSTER_SET-CONFIG-EPOCH';
3447
import * as CLUSTER_SETSLOT from '../commands/CLUSTER_SETSLOT';
3548
import * as CLUSTER_SLOTS from '../commands/CLUSTER_SLOTS';
3649
import * as COMMAND_COUNT from '../commands/COMMAND_COUNT';
@@ -138,20 +151,46 @@ export default {
138151
clusterAddSlots: CLUSTER_ADDSLOTS,
139152
CLUSTER_ADDSLOTSRANGE,
140153
clusterAddSlotsRange: CLUSTER_ADDSLOTSRANGE,
154+
CLUSTER_BUMPEPOCH,
155+
clusterBumpEpoch: CLUSTER_BUMPEPOCH,
156+
CLUSTER_COUNT_FAILURE_REPORTS,
157+
clusterCountFailureReports: CLUSTER_COUNT_FAILURE_REPORTS,
158+
CLUSTER_COUNTKEYSINSLOT,
159+
clusterCountKeysInSlot: CLUSTER_COUNTKEYSINSLOT,
160+
CLUSTER_DELSLOTS,
161+
clusterDelSlots: CLUSTER_DELSLOTS,
141162
CLUSTER_DELSLOTSRANGE,
142163
clusterDelSlotsRange: CLUSTER_DELSLOTSRANGE,
164+
CLUSTER_FAILOVER,
165+
clusterFailover: CLUSTER_FAILOVER,
143166
CLUSTER_FLUSHSLOTS,
144167
clusterFlushSlots: CLUSTER_FLUSHSLOTS,
168+
CLUSTER_FORGET,
169+
clusterForget: CLUSTER_FORGET,
170+
CLUSTER_GETKEYSINSLOT,
171+
clusterGetKeysInSlot: CLUSTER_GETKEYSINSLOT,
145172
CLUSTER_INFO,
146173
clusterInfo: CLUSTER_INFO,
174+
CLUSTER_KEYSLOT,
175+
clusterKeySlot: CLUSTER_KEYSLOT,
147176
CLUSTER_LINKS,
148177
clusterLinks: CLUSTER_LINKS,
149-
CLUSTER_NODES,
150-
clusterNodes: CLUSTER_NODES,
151178
CLUSTER_MEET,
152179
clusterMeet: CLUSTER_MEET,
180+
CLUSTER_MYID,
181+
clusterMyId: CLUSTER_MYID,
182+
CLUSTER_NODES,
183+
clusterNodes: CLUSTER_NODES,
184+
CLUSTER_REPLICAS,
185+
clusterReplicas: CLUSTER_REPLICAS,
186+
CLUSTER_REPLICATE,
187+
clusterReplicate: CLUSTER_REPLICATE,
153188
CLUSTER_RESET,
154189
clusterReset: CLUSTER_RESET,
190+
CLUSTER_SAVECONFIG,
191+
clusterSaveConfig: CLUSTER_SAVECONFIG,
192+
CLUSTER_SET_CONFIG_EPOCH,
193+
clusterSetConfigEpoch: CLUSTER_SET_CONFIG_EPOCH,
155194
CLUSTER_SETSLOT,
156195
clusterSetSlot: CLUSTER_SETSLOT,
157196
CLUSTER_SLOTS,
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
1-
export function transformArguments(slots: number | Array<number>): Array<string> {
2-
const args = ['CLUSTER', 'ADDSLOTS'];
1+
import { RedisCommandArguments } from '.';
2+
import { pushVerdictNumberArguments } from './generic-transformers';
33

4-
if (typeof slots === 'number') {
5-
args.push(slots.toString());
6-
} else {
7-
args.push(...slots.map(String));
8-
}
9-
10-
return args;
4+
export function transformArguments(slots: number | Array<number>): RedisCommandArguments {
5+
return pushVerdictNumberArguments(
6+
['CLUSTER', 'ADDSLOTS'],
7+
slots
8+
);
119
}
1210

1311
export declare function transformReply(): string;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { strict as assert } from 'assert';
2+
import testUtils, { GLOBAL } from '../test-utils';
3+
import { transformArguments } from './CLUSTER_BUMPEPOCH';
4+
5+
describe('CLUSTER BUMPEPOCH', () => {
6+
it('transformArguments', () => {
7+
assert.deepEqual(
8+
transformArguments(),
9+
['CLUSTER', 'BUMPEPOCH']
10+
);
11+
});
12+
13+
testUtils.testWithCluster('clusterNode.clusterBumpEpoch', async cluster => {
14+
assert.equal(
15+
typeof await cluster.getSlotMaster(0).client.clusterBumpEpoch(),
16+
'string'
17+
);
18+
}, GLOBAL.SERVERS.OPEN);
19+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export function transformArguments(): Array<string> {
2+
return ['CLUSTER', 'BUMPEPOCH'];
3+
}
4+
5+
export declare function transformReply(): 'BUMPED' | 'STILL';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { strict as assert } from 'assert';
2+
import testUtils, { GLOBAL } from '../test-utils';
3+
import { transformArguments } from './CLUSTER_COUNT-FAILURE-REPORTS';
4+
5+
describe('CLUSTER COUNT-FAILURE-REPORTS', () => {
6+
it('transformArguments', () => {
7+
assert.deepEqual(
8+
transformArguments('0'),
9+
['CLUSTER', 'COUNT-FAILURE-REPORTS', '0']
10+
);
11+
});
12+
13+
testUtils.testWithCluster('clusterNode.clusterCountFailureReports', async cluster => {
14+
const { client } = cluster.getSlotMaster(0);
15+
assert.equal(
16+
typeof await client.clusterCountFailureReports(
17+
await client.clusterMyId()
18+
),
19+
'number'
20+
);
21+
}, GLOBAL.CLUSTERS.OPEN);
22+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export function transformArguments(nodeId: string): Array<string> {
2+
return ['CLUSTER', 'COUNT-FAILURE-REPORTS', nodeId];
3+
}
4+
5+
export declare function transformReply(): number;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { strict as assert } from 'assert';
2+
import testUtils, { GLOBAL } from '../test-utils';
3+
import { transformArguments } from './CLUSTER_COUNTKEYSINSLOT';
4+
5+
describe('CLUSTER COUNTKEYSINSLOT', () => {
6+
it('transformArguments', () => {
7+
assert.deepEqual(
8+
transformArguments(0),
9+
['CLUSTER', 'COUNTKEYSINSLOT', '0']
10+
);
11+
});
12+
13+
testUtils.testWithCluster('clusterNode.clusterCountKeysInSlot', async cluster => {
14+
assert.equal(
15+
typeof await cluster.getSlotMaster(0).client.clusterCountKeysInSlot(0),
16+
'number'
17+
);
18+
}, GLOBAL.CLUSTERS.OPEN);
19+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export function transformArguments(slot: number): Array<string> {
2+
return ['CLUSTER', 'COUNTKEYSINSLOT', slot.toString()];
3+
}
4+
5+
export declare function transformReply(): number;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { strict as assert } from 'assert';
2+
import { transformArguments } from './CLUSTER_DELSLOTS';
3+
4+
describe('CLUSTER DELSLOTS', () => {
5+
describe('transformArguments', () => {
6+
it('single', () => {
7+
assert.deepEqual(
8+
transformArguments(0),
9+
['CLUSTER', 'DELSLOTS', '0']
10+
);
11+
});
12+
13+
it('multiple', () => {
14+
assert.deepEqual(
15+
transformArguments([0, 1]),
16+
['CLUSTER', 'DELSLOTS', '0', '1']
17+
);
18+
});
19+
});
20+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { RedisCommandArguments } from '.';
2+
import { pushVerdictNumberArguments } from './generic-transformers';
3+
4+
export function transformArguments(slots: number | Array<number>): RedisCommandArguments {
5+
return pushVerdictNumberArguments(
6+
['CLUSTER', 'DELSLOTS'],
7+
slots
8+
);
9+
}
10+
11+
export declare function transformReply(): 'OK';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { strict as assert } from 'assert';
2+
import { FailoverModes, transformArguments } from './CLUSTER_FAILOVER';
3+
4+
describe('CLUSTER FAILOVER', () => {
5+
describe('transformArguments', () => {
6+
it('simple', () => {
7+
assert.deepEqual(
8+
transformArguments(),
9+
['CLUSTER', 'FAILOVER']
10+
);
11+
});
12+
13+
it('with mode', () => {
14+
assert.deepEqual(
15+
transformArguments(FailoverModes.FORCE),
16+
['CLUSTER', 'FAILOVER', 'FORCE']
17+
);
18+
});
19+
});
20+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
export enum FailoverModes {
2+
FORCE = 'FORCE',
3+
TAKEOVER = 'TAKEOVER'
4+
}
5+
6+
export function transformArguments(mode?: FailoverModes): Array<string> {
7+
const args = ['CLUSTER', 'FAILOVER'];
8+
9+
if (mode) {
10+
args.push(mode);
11+
}
12+
13+
return args;
14+
}
15+
16+
export declare function transformReply(): 'OK';

packages/client/lib/commands/CLUSTER_FLUSHSLOTS.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ export function transformArguments(): Array<string> {
22
return ['CLUSTER', 'FLUSHSLOTS'];
33
}
44

5-
export declare function transformReply(): string;
5+
export declare function transformReply(): 'OK';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { strict as assert } from 'assert';
2+
import { transformArguments } from './CLUSTER_FORGET';
3+
4+
describe('CLUSTER FORGET', () => {
5+
it('transformArguments', () => {
6+
assert.deepEqual(
7+
transformArguments('0'),
8+
['CLUSTER', 'FORGET', '0']
9+
);
10+
});
11+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export function transformArguments(nodeId: string): Array<string> {
2+
return ['CLUSTER', 'FORGET', nodeId];
3+
}
4+
5+
export declare function transformReply(): 'OK';

packages/client/lib/commands/CLUSTER_GETKEYSINSLOT.spec.ts

+9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { strict as assert } from 'assert';
2+
import testUtils, { GLOBAL } from '../test-utils';
23
import { transformArguments } from './CLUSTER_GETKEYSINSLOT';
34

45
describe('CLUSTER GETKEYSINSLOT', () => {
@@ -8,4 +9,12 @@ describe('CLUSTER GETKEYSINSLOT', () => {
89
['CLUSTER', 'GETKEYSINSLOT', '0', '10']
910
);
1011
});
12+
13+
testUtils.testWithCluster('clusterNode.clusterGetKeysInSlot', async cluster => {
14+
const reply = await cluster.getSlotMaster(0).client.clusterGetKeysInSlot(0, 1);
15+
assert.ok(Array.isArray(reply));
16+
for (const item of reply) {
17+
assert.equal(typeof item, 'string');
18+
}
19+
}, GLOBAL.CLUSTERS.OPEN);
1120
});

packages/client/lib/commands/CLUSTER_GETKEYSINSLOT.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ export function transformArguments(slot: number, count: number): Array<string> {
22
return ['CLUSTER', 'GETKEYSINSLOT', slot.toString(), count.toString()];
33
}
44

5-
export declare function transformReply(): string;
5+
export declare function transformReply(): Array<string>;

packages/client/lib/commands/CLUSTER_INFO.spec.ts

+8
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { strict as assert } from 'assert';
2+
import testUtils, { GLOBAL } from '../test-utils';
23
import { transformArguments, transformReply } from './CLUSTER_INFO';
34

45
describe('CLUSTER INFO', () => {
@@ -43,4 +44,11 @@ describe('CLUSTER INFO', () => {
4344
}
4445
);
4546
});
47+
48+
testUtils.testWithCluster('clusterNode.clusterInfo', async cluster => {
49+
assert.notEqual(
50+
await cluster.getSlotMaster(0).client.clusterInfo(),
51+
null
52+
);
53+
}, GLOBAL.CLUSTERS.OPEN);
4654
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { strict as assert } from 'assert';
2+
import testUtils, { GLOBAL } from '../test-utils';
3+
import { transformArguments } from './CLUSTER_KEYSLOT';
4+
5+
describe('CLUSTER KEYSLOT', () => {
6+
it('transformArguments', () => {
7+
assert.deepEqual(
8+
transformArguments('key'),
9+
['CLUSTER', 'KEYSLOT', 'key']
10+
);
11+
});
12+
13+
testUtils.testWithCluster('clusterNode.clusterKeySlot', async cluster => {
14+
assert.equal(
15+
typeof await cluster.getSlotMaster(0).client.clusterKeySlot('key'),
16+
'number'
17+
);
18+
}, GLOBAL.CLUSTERS.OPEN);
19+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export function transformArguments(key: string): Array<string> {
2+
return ['CLUSTER', 'KEYSLOT', key];
3+
}
4+
5+
export declare function transformReply(): number;

packages/client/lib/commands/CLUSTER_MEET.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ export function transformArguments(ip: string, port: number): Array<string> {
22
return ['CLUSTER', 'MEET', ip, port.toString()];
33
}
44

5-
export declare function transformReply(): string;
5+
export declare function transformReply(): 'OK';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { strict as assert } from 'assert';
2+
import testUtils, { GLOBAL } from '../test-utils';
3+
import { transformArguments } from './CLUSTER_MYID';
4+
5+
describe('CLUSTER MYID', () => {
6+
it('transformArguments', () => {
7+
assert.deepEqual(
8+
transformArguments(),
9+
['CLUSTER', 'MYID']
10+
);
11+
});
12+
13+
testUtils.testWithCluster('clusterNode.clusterMyId', async cluster => {
14+
assert.equal(
15+
typeof await cluster.getSlotMaster(0).client.clusterMyId(),
16+
'string'
17+
);
18+
}, GLOBAL.CLUSTERS.OPEN);
19+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export function transformArguments(): Array<string> {
2+
return ['CLUSTER', 'MYID'];
3+
}
4+
5+
export declare function transformReply(): string;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { strict as assert } from 'assert';
2+
import { transformArguments } from './CLUSTER_REPLICAS';
3+
4+
describe('CLUSTER REPLICAS', () => {
5+
it('transformArguments', () => {
6+
assert.deepEqual(
7+
transformArguments('0'),
8+
['CLUSTER', 'REPLICAS', '0']
9+
);
10+
});
11+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export function transformArguments(nodeId: string): Array<string> {
2+
return ['CLUSTER', 'REPLICAS', nodeId];
3+
}
4+
5+
export { transformReply } from './CLUSTER_NODES';

0 commit comments

Comments
 (0)