I have a weird case in my rpc request scenario. I discovered it thanks to the property of autodelete setted to true. This property said that queue that has had at least one consumer is deleted when last consumer unsubscribes.
Now, i notice that sometimes happens that the client send request to a server using the remoteCall method (below the code), the server give a response sending it to the correct reply queue (autodelete to true) declared in the remoteCall by the client, but the consumer on this queue is down and the queue is never deleted by rabbitMQ.
I don't understand how this is possibile if in the remoteCall I do basicPublish and immediately after I start to wait for a response with the consumer. This means that client should attach immediately to the reply queue, but apparently sometimes this is not the case, otherwise the queue would be deleted.
So, how is possible that using remoteCall method below i have reply queues that have never had a consumer?
I hope someone can help me. Thank you all.
public Message remoteCall(Message requestMessage) {
try {
MessagePayload messagePayload = requestMessage.getPayload();
String uid = UUID.randomUUID().toString();
long timeMillis = System.currentTimeMillis();
String customReplyName = outputQueueName + "_" + messagePayload.getOperation() + "_" + uid + "_" + timeMillis;
String replyQueueName = this.channel.queueDeclare(
customReplyName,
false,
true,
true,
null)
.getQueue();
BasicProperties remoteCallProperties = this.getRemoteCallProperties(requestMessage.getProperties(), replyQueueName);
this.channel.basicPublish(
"",
this.outputQueueName,
remoteCallProperties,
MessageUtils.payloadToByteArray(requestMessage.getPayload())
);
// Wait until response
final BlockingQueue<MessagePayload> blockingQueue = new ArrayBlockingQueue<>(1);
String tag = this.channel.basicConsume(
replyQueueName,
true,
(consumerTag, delivery) -> {
if (delivery.getProperties().getCorrelationId().equals(remoteCallProperties.getCorrelationId())) {
blockingQueue.offer(Objects.requireNonNull(MessageUtils.byteArrayToPayload(delivery.getBody())));
}
},
consumerTag -> {
});
MessagePayload responsePayload = blockingQueue.take();
this.channel.basicCancel(tag);
MessageProperties responseProperties = new MessagePropertiesBuilder()
.correlationId(remoteCallProperties.getCorrelationId())
.build();
return new MessageBuilder()
.properties(responseProperties)
.payload(responsePayload)
.build();
} catch (IOException | InterruptedException e) {
Logging.getLogger().error("MessageBrokerError: ");
Logging.getLogger().error(e.getMessage());
return null;
}
}
I expect that the consumer is always linked to the reply queue when after the basic publish in the client side the remoteCall method reach the basicConsume line.