Chunked Pub/Sub message receive with interleaved command responses leaves commands uncompleted
See original GitHub issuelettuce version: 5.1.2.RELEASE
When i subscribe multi channels at one time, is there a problem? see blew.
// io.lettuce.core.pubsub.PubSubCommandHandler#decode
// when i call: pubSubCommands.subscribe("test1","test2","test3"...);
protected void decode(ChannelHandlerContext ctx, ByteBuf buffer) throws InterruptedException {
if (!getStack().isEmpty()) {
//first channel("test1") decoded here, and cmd polled from stack
super.decode(ctx, buffer);
}
ReplayOutput<K, V> replay;
while ((replay = queue.poll()) != null) {
replay.replay(output);
endpoint.notifyMessage(output);
output = new PubSubOutput<>(codec);
}
while (super.getStack().isEmpty() && buffer.isReadable()) {
// other channels decode here, like "test2" "test3"...
// is this a problem here, in my opinion, all channels should decode on the first place where "test1" decoded.
if (!super.decode(buffer, output)) {
return;
}
endpoint.notifyMessage(output);
output = new PubSubOutput<>(codec);
}
buffer.discardReadBytes();
}
When i attempt to subscribe multi channels cyclic with 100 threads in one redis connection, I get an RedisCommandTimeoutException . Maybe you thought i shouldn’t call it like this. But i truly have this requirement in my Application. Let’s see the blew code.
// code in io.lettuce.core.pubsub.PubSubCommandHandler#decode
// when i call pubSubCommands.subscribe("test1","test2","test3"...) cyclic in 100 threads in one redis connection.
if (!super.decode(buffer, output)) {
//channel "test2" "test3"... may be decoded here. image that, if super.decode(buffer, output)
//return false, it means the byte pack is not enough for "test2" decoding. Then function returned.
//at the same time, other thread put a command to stack. When netty channel get another bytes.
//we step this method at second time, super.decode(ctx, buffer) while perform nothing
//because output.type() is not null. super.getStack().isEmpty() will be false,
//then the bytes will never be decoded .
return;
}
If i just subscribe one channel. but there also maybe a problem.it same to previous problem. Image that, if i get a message from a redis topic(channel),then decode message here
if (!super.decode(buffer, output)) {return}
if the message byte pack is not complete, super.decode(buffer, output) will return false and method return. at the same time i call a subscribe use the same connection, then output.type() will not be null, and super.getStack().isEmpty() will be false, we get a death loop, bytes will never be decoded ,like previous problem.
My Application use one connection to dynamic subscribe lots of channel,so I will subscribe and receive message at same time in multi threads.
Issue Analytics
- State:
- Created 5 years ago
- Reactions:2
- Comments:9 (5 by maintainers)
Top GitHub Comments
I pushed a change to our feature branch for this ticket and the branch build that has produced artifact snapshots with version
5.2.0.gh936-SNAPSHOT
. Care to upgrade to see whether the change fixes your issue? The above mentioned reproducer no longer produces timeouts.Make sure to include our snapshot repository:
The artifact was cleared out from the repository. 5.1.4 is scheduled for Feb 12.