-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Connection hangs after temporarily lost connection from redis #2632
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
We experienced the same behavior, do you manage to find the issue or fix it ? |
I have subscribed to the error event and when it's triggered I close the connection and reopen a new one ... It's not a perfect solution but it works in my scenario. |
I tried reproducing it using the steps you described, but... its working as expected... |
Yes, and I have seen this behaviour also in PROD in a GKE |
I am starting a docker using: docker run -p 6379:6379 redis then run this script: import { createClient } from 'redis';
const client = await createClient()
.on('error', (err) => console.error('client error', err))
.on('connect', () => console.log('connect'))
.on('ready', () => console.log('ready'))
.connect();
setInterval(async () => {
try {
console.log(new Date().toJSON(), await client.ping());
} catch (err) {
console.error('command error', err);
}
}, 1000); when the server is up I see these logs:
then I take the docker down, I see this in the logs:
then when I restart the server it goes back to
am I missing something? are you doing things differently? |
It's veri similar to mine, the only difference could be that I restart the docker with Also @gguimond suffer by the same issue ... I'm on linux I don't know if it's matter |
this is my script: import { createClient } from "redis"
async function main() {
const conn = await createClient({ url: "redis://:redis@localhost:6379/1" })
.on("connect", () => {
console.log("redis connect")
})
.on("ready", () => {
console.log("redis ready")
})
.on("end", () => {
console.log("redis end")
})
.on("error", async (error) => {
console.log("redis error", error)
})
.on("reconnecting", () => {
console.log("redis reconnecting")
})
.connect()
setInterval(async () => {
console.log("set...")
await conn.set("key", "value")
console.log("get: ", await conn.get("key"))
}, 1000)
}
main().then(console.log).catch(console.log) and this is my docker-compose: ork-redis:
image: redis:6.2.6-alpine
container_name: redis
command: redis-server --requirepass redis
ports:
- "6379:6379"
volumes:
- ork-redis-data:/data
restart: unless-stopped
environment:
REDIS_PASSWORD: redis
REDIS_REPLICATION_MODE: master and then I restart with
node version 16 & 18
and
Let me know If I can help you in some way |
I'm able to reproduce with your script and docker-compose so I guess @leibale will be able also. What happens next is that the command is hanging out and the connection is never considered "ready" but no further reconnection is planned. I've made it working as expected by managing the case in socket close event callback, emitting an error if the connection is not ready. Hence, the pending AUTH command is flushed and the error is catched here node-redis/packages/client/lib/client/socket.ts Lines 164 to 173 in a8b81bd
node-redis/packages/client/lib/client/socket.ts Lines 201 to 205 in a8b81bd
replaced by .once('close', hadError => {
if (!hadError && this.#socket === socket) {
if(this.#isReady){
this.#onSocketError(new SocketClosedUnexpectedlyError());
} else {
this.emit('error', new SocketClosedUnexpectedlyError())
}
}
}) The only dawback with this solution is that the error event is emitted 2 times, on one hand in the code added above and then in the catch in #connect(). I guess the maintainer will manage to a better solution but that's the idea. |
@gguimond good job digging into it and finding the issue! edit: BTW, I think that I wasn't able to reproduce the issue because i didn't have a password on my (local only) redis server, which means the "socket initiator" phase is noop.. |
I tried to add a test besides this one https://github.com/redis/node-redis/blob/master/packages/client/lib/client/index.spec.ts#L715 with a new method testWithClientRestart which would restart docker just before launch the test function but unfortunately I don't manage to reproduce the issue in this context and even the current code is able to reconnect. |
I think I'll merge and release it as is, we can make it better in next releases.. (2 |
Thank you, it is appreciated. |
Description
If I open a connection like this:
I see this logs:
thank I can use the connection without any issue.
If I restart Redis to simulate a connection lost, I see an automatic reconnection with the following logs:
First of all, I never see ready and then if I try to use the connection
await conn.set('key', 'value');
the call remain blocked indefinitely.Node.js Version
v16.13.0 + v18.17.1
Redis Server Version
6.2.6
Node Redis Version
4.6.10
Platform
linux / docker
Logs
No response
The text was updated successfully, but these errors were encountered: