1
0
mirror of https://github.com/redis/node-redis.git synced 2025-12-11 09:22:35 +03:00
Files
node-redis/packages/client/lib/tests/test-scenario/sharded-pubsub/utils/message-tracker.ts
Nikolay Karadzhov 96d6445d66 fix(ssubscribe): properly resubscribe in case of shard failover (#3098)
* fix(ssubscribe): properly resubscribe in case of shard failover

1) when RE failover happens, there is a disconnect
2) affected Client reconnects and tries to resubscribe all existing listeners
ISSUE #1: CROSSSLOT Error - client was doing ssubscribe ch1 ch2.. chN which, after the failover could result in CROSSSLOT ( naturally, becasuse now some slots could be owned by other shards )
FIX: send one ssubscribe command per channel instead of one ssubscribe for all channels
ISSUE #2: MOVED Error - some/all of the channels might be moved somewhere else
FIX: 1: Propagate the error to the Cluster. 2: Cluster rediscovers topology.
3: Cluster resubscribes all listeners of the failed client ( possibly some/all of those will end up in a different client after the rediscovery ) 

fixes: #2902
2025-10-13 11:59:08 +03:00

53 lines
1.1 KiB
TypeScript

export interface MessageStats {
sent: number;
received: number;
failed: number;
}
export class MessageTracker {
private stats: Record<string, MessageStats> = {};
constructor(channels: string[]) {
this.initializeChannels(channels);
}
private initializeChannels(channels: string[]): void {
this.stats = channels.reduce((acc, channel) => {
acc[channel] = { sent: 0, received: 0, failed: 0 };
return acc;
}, {} as Record<string, MessageStats>);
}
reset(): void {
Object.keys(this.stats).forEach((channel) => {
this.stats[channel] = { sent: 0, received: 0, failed: 0 };
});
}
incrementSent(channel: string): void {
if (this.stats[channel]) {
this.stats[channel].sent++;
}
}
incrementReceived(channel: string): void {
if (this.stats[channel]) {
this.stats[channel].received++;
}
}
incrementFailed(channel: string): void {
if (this.stats[channel]) {
this.stats[channel].failed++;
}
}
getChannelStats(channel: string): MessageStats | undefined {
return this.stats[channel];
}
getAllStats(): Record<string, MessageStats> {
return this.stats;
}
}