"Connection is closed" during quit() when commandQueue has entries
Problem
Problem `await ioredis.quit()` throws an `Error` when there are still items on the `commandQueue`. [code block] Version ioredis 5.8.0 Context We have code for a health check that connects and immediately disconnects using `await ioredis.quit()`. The issue occurs often since https://github.com/redis/ioredis/pull/2011. I assume the reason for this is, that we now have entries on the `commandQueue` immediately. Workaround The issue does not occur anymore when I set `disableClientInfo` to `true`. Reason Usually the `commandQueue` is empty and the connection terminates sucessfully. However, when the error occures, we have the following entries on the `commandQueue` [code block] The `closeHandler` flushes the queue with an error (https://github.com/redis/ioredis/blob/8dad79f9d05c8891d0c70336f484b065b9865ae2/lib/redis/event_handler.ts#L227). Thus, `quit` can only ever complete successfully if the queue is empty.
Error Output
Error: Connection is closed.
Unverified for your environment
Select your OS to check compatibility.
1 Fix
Implement Command Queue Check Before Quit
The error occurs because the `quit()` method in ioredis attempts to close the connection while there are still commands in the `commandQueue`. This leads to an error as the connection cannot be closed until all queued commands are processed. The change in behavior was introduced in a previous update that altered how command queuing is handled.
Awaiting Verification
Be the first to verify this fix
- 1
Check Command Queue Before Quitting
Before calling `await ioredis.quit()`, check if the `commandQueue` is empty. If it is not empty, wait for the commands to finish processing.
typescriptif (ioredis.commandQueue.length > 0) { await ioredis.commandQueue[0].promise; } await ioredis.quit(); - 2
Implement Retry Logic
If the command queue is not empty, implement a retry mechanism that waits for a short duration before checking the queue again. This ensures that the quit operation is retried until the queue is empty.
typescriptasync function safeQuit(redis) { while (redis.commandQueue.length > 0) { await new Promise(resolve => setTimeout(resolve, 100)); } await redis.quit(); } - 3
Set disableClientInfo to True
As a temporary workaround, set the `disableClientInfo` option to true when creating the Redis client to avoid the issue until a permanent solution is implemented.
typescriptconst ioredis = new Redis({ disableClientInfo: true }); - 4
Update Documentation
Update the project documentation to inform developers about the need to check the command queue before quitting and the implications of using `disableClientInfo`.
Validation
To confirm the fix worked, run the health check multiple times and ensure that no 'Connection is closed' errors are thrown during the quit process. Additionally, monitor the command queue to verify it is empty before quitting.
Sign in to verify this fix
Environment
Submitted by
Alex Chen
2450 rep