Skip to content

Commit

Permalink
feat: 馃幐 improve redirects logic
Browse files Browse the repository at this point in the history
  • Loading branch information
streamich committed Dec 13, 2023
1 parent 53f269e commit dbb0d9e
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 11 deletions.
25 changes: 17 additions & 8 deletions src/cluster/RedisCluster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ export class RedisCluster {
await this.router.rebuild(client);
if (this.stopped) return;
this.initialTableBuildAttempt = 0;
console.log('SHARD TABLE CREATED');
this.onRouter.emit();
})().catch((error) => {
const delay = Math.max(Math.min(1000 * 2 ** attempt, 1000 * 60), 1000);
Expand Down Expand Up @@ -108,24 +107,28 @@ export class RedisCluster {
}

private async createClientFromInfo(info: RedisClusterNodeInfo): Promise<RedisClusterNodeClient> {
const [client] = await this.createClient({
return this.createClientForHost(info.endpoint || info.ip, info.port);
}

private async createClientForHost(host: string, port: number): Promise<RedisClusterNodeClient> {
return this.createClient({
...this.opts.connectionConfig,
host: info.endpoint || info.ip,
port: info.port,
host,
port,
});
return client;
}

protected async createClient(config: RedisClusterNodeClientOpts): Promise<[client: RedisClusterNodeClient, id: string]> {
protected async createClient(config: RedisClusterNodeClientOpts): Promise<RedisClusterNodeClient> {
const client = this.createClientRaw(config);
client.start();
const {user, pwd} = config;
const [, id] = await Promise.all([
client.hello(3, pwd, user),
client.clusterMyId(),
]);
client.id = id;
this.router.setClient(id, client);
return [client, id];
return client;
}

protected createClientRaw(config: RedisClusterNodeClientOpts): RedisClusterNodeClient {
Expand Down Expand Up @@ -154,7 +157,13 @@ export class RedisCluster {
const redirect = parseMovedError((error as Error).message);
let host = redirect[0] || client.host;
if (!host) throw new Error('NO_HOST');
// TODO: Start router table rebuild.
call.redirects++;
if (call.redirects > call.maxRedirects) throw new Error('MAX_REDIRECTS');
const port = redirect[1];
console.log('redirect', host, port, call.redirects);
if (host === client.host && port === client.port) throw new Error('INVALID_REDIRECT');
const nextClient = await this.createClientForHost(host, port);
return this.callWithClient(call, nextClient);
}
throw error;
}
Expand Down
13 changes: 11 additions & 2 deletions src/cluster/RedisClusterCall.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,17 @@ import {RedisCall} from "../node";
*/
export class RedisClusterCall extends RedisCall {
/**
* Key to use for routing the command to the correct node. Used in cluster
* mode.
* Key to use for routing the command to the correct node.
*/
public key: string = '';

/**
* Number of redirects that have been performed for this command.
*/
public redirects: number = 0;

/**
* Maximum number of redirects to perform before giving up.
*/
public maxRedirects: number = 4;
}
5 changes: 4 additions & 1 deletion src/demo-cluster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
import {RedisCluster} from "./cluster/RedisCluster";

const main = async () => {
const host = 'localhost';
// const host = 'localhost';
const host = '127.0.0.1';
// const host = '172.17.0.2';
const port = 7000;
const user = 'default';
const pwd = 'AoQhB7bNYljT8IiZ7nbgvSQSXiGHRwQX';
Expand Down Expand Up @@ -37,6 +39,7 @@ const main = async () => {
};

await exec(['SET', 'foo', 'bar']);
// await exec(['GET', 'foo']);
};

main().catch((err) => {
Expand Down

0 comments on commit dbb0d9e

Please sign in to comment.