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

fix #1766 - allow .quit() in PubSub mode

This commit is contained in:
leibale
2021-12-08 10:28:34 -05:00
parent e11256854e
commit ac808ea781
3 changed files with 21 additions and 2 deletions

View File

@@ -1,15 +1,19 @@
import * as LinkedList from 'yallist';
import { AbortError } from '../errors';
import { RedisCommandArguments, RedisCommandRawReply } from '../commands';
// We need to use 'require', because it's not possible with Typescript to import
// classes that are exported as 'module.exports = class`, without esModuleInterop
// set to true.
const RedisParser = require('redis-parser');
export interface QueueCommandOptions {
asap?: boolean;
chainId?: symbol;
signal?: AbortSignal;
ignorePubSubMode?: boolean;
}
interface CommandWaitingToBeSent extends CommandWaitingForReply {
args: RedisCommandArguments;
chainId?: symbol;
@@ -18,16 +22,19 @@ interface CommandWaitingToBeSent extends CommandWaitingForReply {
listener(): void;
};
}
interface CommandWaitingForReply {
resolve(reply?: unknown): void;
reject(err: Error): void;
channelsCounter?: number;
bufferMode?: boolean;
}
export enum PubSubSubscribeCommands {
SUBSCRIBE = 'SUBSCRIBE',
PSUBSCRIBE = 'PSUBSCRIBE'
}
export enum PubSubUnsubscribeCommands {
UNSUBSCRIBE = 'UNSUBSCRIBE',
PUNSUBSCRIBE = 'PUNSUBSCRIBE'
@@ -135,7 +142,7 @@ export default class RedisCommandsQueue {
}
addCommand<T = RedisCommandRawReply>(args: RedisCommandArguments, options?: QueueCommandOptions, bufferMode?: boolean): Promise<T> {
if (this.#pubSubState) {
if (this.#pubSubState && !options?.ignorePubSubMode) {
return Promise.reject(new Error('Cannot send commands in PubSub mode'));
} else if (this.#maxLength && this.#waitingToBeSent.length + this.#waitingForReply.length >= this.#maxLength) {
return Promise.reject(new Error('The queue is full'));

View File

@@ -668,6 +668,16 @@ describe('Client', () => {
await subscriber.disconnect();
}
}, GLOBAL.SERVERS.OPEN);
testUtils.testWithClient('should be able to quit in PubSub mode', async client => {
await client.subscribe('channel', () => {
// noop
});
await assert.doesNotReject(client.quit());
assert.equal(client.isOpen, false);
}, GLOBAL.SERVERS.OPEN);
});
testUtils.testWithClient('ConnectionTimeoutError', async client => {

View File

@@ -487,7 +487,9 @@ export default class RedisClient<M extends RedisModules, S extends RedisScripts>
QUIT(): Promise<void> {
return this.#socket.quit(() => {
const quitPromise = this.#queue.addCommand(['QUIT']);
const quitPromise = this.#queue.addCommand(['QUIT'], {
ignorePubSubMode: true
});
this.#tick();
return Promise.all([
quitPromise,