1
0
mirror of https://github.com/redis/node-redis.git synced 2025-08-06 02:15:48 +03:00

fix #1671 - add support for all client configurations in cluster

This commit is contained in:
leibale
2021-10-07 10:20:21 -04:00
parent 833416c4e9
commit cc83cee22c
7 changed files with 41 additions and 44 deletions

View File

@@ -53,7 +53,7 @@ The above code connects to localhost on port 6379. To connect to a different hos
```typescript
createClient({
url: 'redis://alice:foobared@awesome.redis.server:6380',
url: 'redis://alice:foobared@awesome.redis.server:6380'
});
```
@@ -78,7 +78,7 @@ Modifiers to commands are specified using a JavaScript object:
```typescript
await client.set('key', 'value', {
EX: 10,
NX: true,
NX: true
});
```
@@ -181,12 +181,9 @@ for await (const key of client.scanIterator()) {
This works with `HSCAN`, `SSCAN`, and `ZSCAN` too:
```typescript
for await (const member of client.hScanIterator('hash')) {
}
for await (const { field, value } of client.sScanIterator('set')) {
}
for await (const { member, score } of client.zScanIterator('sorted-set')) {
}
for await (const member of client.hScanIterator('hash')) {}
for await (const { field, value } of client.sScanIterator('set')) {}
for await (const { member, score } of client.zScanIterator('sorted-set')) {}
```
You can override the default options by providing a configuration object:
@@ -204,7 +201,8 @@ client.scanIterator({
Define new functions using [Lua scripts](https://redis.io/commands/eval) which execute on the Redis server:
```typescript
import { createClient, defineScript } from 'redis';
import { createClient } from 'redis';
import { defineScript } from 'redis/lua-script';
(async () => {
const client = createClient({
@@ -218,9 +216,9 @@ import { createClient, defineScript } from 'redis';
},
transformReply(reply: number): number {
return reply;
},
}),
},
}
})
}
});
await client.connect();
@@ -241,14 +239,12 @@ import { createCluster } from 'redis';
const cluster = createCluster({
rootNodes: [
{
host: '10.0.0.1',
port: 30001,
url: 'redis://10.0.0.1:30001'
},
{
host: '10.0.0.2',
port: 30002,
},
],
url: 'redis://10.0.0.2:30002'
}
]
});
cluster.on('error', (err) => console.log('Redis Cluster Error', err));
@@ -274,7 +270,7 @@ Of course, if you don't do something with your Promises you're certain to get [u
```typescript
await Promise.all([
client.set('Tm9kZSBSZWRpcw==', 'users:1'),
client.sAdd('users:1:tokens', 'Tm9kZSBSZWRpcw=='),
client.sAdd('users:1:tokens', 'Tm9kZSBSZWRpcw==')
]);
```

View File

@@ -6,5 +6,3 @@ export const createClient = RedisClient.create;
export const commandOptions = RedisClient.commandOptions;
export const createCluster = RedisCluster.create;
export { defineScript } from './lib/lua-script';

View File

@@ -2,7 +2,7 @@ import calculateSlot from 'cluster-key-slot';
import RedisClient, { RedisClientType } from './client';
import { RedisSocketOptions } from './socket';
import { RedisClusterMasterNode, RedisClusterReplicaNode } from './commands/CLUSTER_NODES';
import { RedisClusterOptions } from './cluster';
import { RedisClusterClientOptions, RedisClusterOptions } from './cluster';
import { RedisModules } from './commands';
import { RedisLuaScripts } from './lua-script';
@@ -39,21 +39,19 @@ export default class RedisClusterSlots<M extends RedisModules, S extends RedisLu
}
async discover(startWith: RedisClientType<M, S>): Promise<void> {
if (await this.#discoverNodes(startWith.options?.socket)) return;
if (await this.#discoverNodes(startWith.options)) return;
for (const { client } of this.#nodeByUrl.values()) {
if (client === startWith) continue;
if (await this.#discoverNodes(client.options?.socket)) return;
if (await this.#discoverNodes(client.options)) return;
}
throw new Error('None of the cluster nodes is available');
}
async #discoverNodes(socketOptions?: RedisSocketOptions): Promise<boolean> {
const client = RedisClient.create({
socket: socketOptions
});
async #discoverNodes(clientOptions?: RedisClusterClientOptions): Promise<boolean> {
const client = RedisClient.create(clientOptions);
await client.connect();

View File

@@ -8,7 +8,7 @@ import { ClusterSlotStates } from './commands/CLUSTER_SETSLOT';
describe('Cluster', () => {
it('sendCommand', async () => {
const cluster = RedisCluster.create({
rootNodes: TEST_REDIS_CLUSTERES[TestRedisClusters.OPEN],
...TEST_REDIS_CLUSTERES[TestRedisClusters.OPEN],
useReplicas: true
});
@@ -42,7 +42,7 @@ describe('Cluster', () => {
it('scripts', async () => {
const cluster = RedisCluster.create({
rootNodes: TEST_REDIS_CLUSTERES[TestRedisClusters.OPEN],
...TEST_REDIS_CLUSTERES[TestRedisClusters.OPEN],
scripts: {
add: defineScript({
NUMBER_OF_KEYS: 0,

View File

@@ -1,14 +1,16 @@
import { RedisCommand, RedisCommandReply, RedisModules, TransformArgumentsReply } from './commands';
import RedisClient, { ClientCommandOptions, RedisClientType, WithPlugins } from './client';
import { RedisSocketOptions } from './socket';
import RedisClient, { ClientCommandOptions, RedisClientOptions, RedisClientType, WithPlugins } from './client';
import RedisClusterSlots, { ClusterNode } from './cluster-slots';
import { RedisLuaScript, RedisLuaScripts } from './lua-script';
import { extendWithModulesAndScripts, extendWithDefaultCommands, transformCommandArguments, transformCommandReply } from './commander';
import RedisMultiCommand, { MultiQueuedCommand, RedisMultiCommandType } from './multi-command';
import { EventEmitter } from 'events';
export interface RedisClusterOptions<M = RedisModules, S = RedisLuaScripts> {
rootNodes: Array<RedisSocketOptions>;
export type RedisClusterClientOptions = Omit<RedisClientOptions<{}, {}>, 'modules' | 'scripts'>;
export interface RedisClusterOptions<M = {}, S = {}> {
rootNodes: Array<RedisClusterClientOptions>;
defaults?: RedisClusterClientOptions;
modules?: M;
scripts?: S;
useReplicas?: boolean;

View File

@@ -2,7 +2,6 @@ import { strict as assert } from 'assert';
import { TestRedisServers, itWithClient } from '../test-utils';
import { transformArguments, transformReply } from './BZPOPMAX';
import { commandOptions } from '../../index';
import { describe } from 'mocha';
describe('BZPOPMAX', () => {
describe('transformArguments', () => {

View File

@@ -5,7 +5,7 @@ import { once } from 'events';
import { RedisSocketOptions } from './socket';
import which from 'which';
import { SinonSpy } from 'sinon';
import RedisCluster, { RedisClusterType } from './cluster';
import RedisCluster, { RedisClusterOptions, RedisClusterType } from './cluster';
import { promises as fs } from 'fs';
import { Context as MochaContext } from 'mocha';
import { promiseTimeout } from './utils';
@@ -60,7 +60,7 @@ export enum TestRedisClusters {
OPEN
}
export const TEST_REDIS_CLUSTERES: Record<TestRedisClusters, Array<RedisSocketOptions>> = <any>{};
export const TEST_REDIS_CLUSTERES: Record<TestRedisClusters, RedisClusterOptions<RedisModules, RedisLuaScripts>> = <any>{};
let port = 6379;
@@ -248,9 +248,13 @@ async function spawnPasswordServer(): Promise<void> {
}
async function spawnOpenCluster(): Promise<void> {
TEST_REDIS_CLUSTERES[TestRedisClusters.OPEN] = (await spawnGlobalRedisCluster(TestRedisClusters.OPEN, 3)).map(port => ({
port
}));
TEST_REDIS_CLUSTERES[TestRedisClusters.OPEN] = {
rootNodes: (await spawnGlobalRedisCluster(TestRedisClusters.OPEN, 3)).map(port => ({
socket: {
port
}
}))
};
}
before(function () {
@@ -314,9 +318,7 @@ export function itWithCluster(
it(title, async function () {
if (handleMinimumRedisVersion(this, options?.minimumRedisVersion)) return;
const cluster = RedisCluster.create({
rootNodes: TEST_REDIS_CLUSTERES[type]
});
const cluster = RedisCluster.create(TEST_REDIS_CLUSTERES[type]);
await cluster.connect();
@@ -337,7 +339,9 @@ export function itWithDedicatedCluster(title: string, fn: (cluster: RedisCluster
const spawnResults = await spawnRedisCluster(null, 3),
cluster = RedisCluster.create({
rootNodes: [{
port: spawnResults[0].port
socket: {
port: spawnResults[0].port
}
}]
});