diff --git a/lib/client/index.spec.ts b/lib/client/index.spec.ts index 3e57ff3dcf..bdfebed575 100644 --- a/lib/client/index.spec.ts +++ b/lib/client/index.spec.ts @@ -2,7 +2,7 @@ import { strict as assert, AssertionError } from 'assert'; import { once } from 'events'; import { itWithClient, TEST_REDIS_SERVERS, TestRedisServers, waitTillBeenCalled, isRedisVersionGreaterThan } from '../test-utils'; import RedisClient from '.'; -import { AbortError, ClientClosedError, ConnectionTimeoutError, WatchError } from '../errors'; +import { AbortError, ClientClosedError, ConnectionTimeoutError, DisconnectsClientError, WatchError } from '../errors'; import { defineScript } from '../lua-script'; import { spy } from 'sinon'; import { RedisNetSocketOptions } from '../client/socket'; @@ -636,10 +636,36 @@ describe('Client', () => { await client.connect(); try { - const quitPromise = client.quit(); + const pingPromise = client.ping(), + quitPromise = client.quit(); + assert.equal(client.isOpen, false); + + const [ping] = await Promise.all([ + pingPromise, + assert.doesNotReject(quitPromise), + assert.rejects(client.ping(), ClientClosedError) + ]); + + assert.equal(ping, 'PONG'); + } finally { + if (client.isOpen) { + await client.disconnect(); + } + } + }); + + it('client.disconnect', async () => { + const client = RedisClient.create(TEST_REDIS_SERVERS[TestRedisServers.OPEN]); + + await client.connect(); + + try { + const pingPromise = client.ping(), + disconnectPromise = client.disconnect(); assert.equal(client.isOpen, false); await Promise.all([ - quitPromise, + assert.rejects(pingPromise, DisconnectsClientError), + assert.doesNotReject(disconnectPromise), assert.rejects(client.ping(), ClientClosedError) ]); } finally { diff --git a/lib/client/index.ts b/lib/client/index.ts index 123c3f543f..a76a56ace7 100644 --- a/lib/client/index.ts +++ b/lib/client/index.ts @@ -11,7 +11,7 @@ import { ScanCommandOptions } from '../commands/SCAN'; import { HScanTuple } from '../commands/HSCAN'; import { encodeCommand, extendWithCommands, extendWithModulesAndScripts, transformCommandArguments, transformCommandReply } from '../commander'; import { Pool, Options as PoolOptions, createPool } from 'generic-pool'; -import { ClientClosedError } from '../errors'; +import { ClientClosedError, DisconnectsClientError } from '../errors'; import { URL } from 'url'; export interface RedisClientOptions extends RedisPlugins { @@ -424,9 +424,12 @@ export default class RedisClient QUIT(): Promise { return this.#socket.quit(() => { - const promise = this.#queue.addCommand(['QUIT']); + const quitPromise = this.#queue.addCommand(['QUIT']); this.#tick(); - return promise; + return Promise.all([ + quitPromise, + this.#destroyIsolationPool() + ]); }); } @@ -519,7 +522,7 @@ export default class RedisClient } async disconnect(): Promise { - this.#queue.flushAll(new Error('Disconnecting')); + this.#queue.flushAll(new DisconnectsClientError()); await Promise.all([ this.#socket.disconnect(), this.#destroyIsolationPool() diff --git a/lib/client/socket.ts b/lib/client/socket.ts index d530948397..923d14dffd 100644 --- a/lib/client/socket.ts +++ b/lib/client/socket.ts @@ -222,6 +222,7 @@ export default class RedisSocket extends EventEmitter { } this.#socket.end(); + this.#socket.removeAllListeners('data'); await EventEmitter.once(this.#socket, 'end'); this.#socket = undefined; this.emit('end'); diff --git a/lib/errors.ts b/lib/errors.ts index 86a65587cf..3f5fe40c20 100644 --- a/lib/errors.ts +++ b/lib/errors.ts @@ -21,3 +21,9 @@ export class ClientClosedError extends Error { super('The client is closed'); } } + +export class DisconnectsClientError extends Error { + constructor() { + super('Disconnects client'); + } +}