Handle publish errors properly in PersistentQueueMessageSender. Create a connection descriptor store to handle all the message delivery errors and to avoid
duplicating error handling code (i.e. the connection descriptors map is null, the connection descriptor does not exist, etc).
This commit is contained in:
@@ -1,13 +1,11 @@
|
||||
package io.moquette.spi.impl;
|
||||
|
||||
import io.moquette.parser.proto.messages.PublishMessage;
|
||||
import io.moquette.server.ConnectionDescriptor;
|
||||
import io.moquette.server.ConnectionDescriptorStore;
|
||||
import io.moquette.spi.ClientSession;
|
||||
import io.netty.channel.Channel;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import static io.moquette.parser.proto.messages.AbstractMessage.QOSType.MOST_ONE;
|
||||
import static io.moquette.spi.impl.ProtocolProcessor.asStoredMessage;
|
||||
@@ -15,41 +13,34 @@ import static io.moquette.spi.impl.ProtocolProcessor.asStoredMessage;
|
||||
class PersistentQueueMessageSender {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(PersistentQueueMessageSender.class);
|
||||
private final ConcurrentMap<String, ConnectionDescriptor> connectionDescriptors;
|
||||
private final ConnectionDescriptorStore connectionDescriptorStore;
|
||||
|
||||
public PersistentQueueMessageSender(ConcurrentMap<String, ConnectionDescriptor> connectionDescriptors) {
|
||||
this.connectionDescriptors = connectionDescriptors;
|
||||
public PersistentQueueMessageSender(ConnectionDescriptorStore connectionDescriptorStore) {
|
||||
this.connectionDescriptorStore = connectionDescriptorStore;
|
||||
}
|
||||
|
||||
void sendPublish(ClientSession clientsession, PublishMessage pubMessage) {
|
||||
String clientId = clientsession.clientID;
|
||||
LOG.info("send publish message to <{}> on topic <{}>", clientId, pubMessage.getTopicName());
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("directSend invoked clientId <{}> on topic <{}> QoS {} retained {} messageID {}",
|
||||
clientId, pubMessage.getTopicName(), pubMessage.getQos(), false, pubMessage.getMessageID());
|
||||
LOG.debug("content <{}>", DebugUtils.payload2Str(pubMessage.getPayload()));
|
||||
LOG.debug("Sending PUBLISH message. MessageId = {}, mqttClientId = {}, topic = {}, qos = {}, payload = {}.",
|
||||
pubMessage.getMessageID(),
|
||||
clientId, pubMessage.getTopicName(), DebugUtils.payload2Str(pubMessage.getPayload()));
|
||||
} else {
|
||||
LOG.info("Sending PUBLISH message. MessageId = {}, mqttClientId = {}, topic = {}.", pubMessage.getMessageID(),
|
||||
clientId, pubMessage.getTopicName());
|
||||
}
|
||||
|
||||
if (connectionDescriptors == null) {
|
||||
throw new RuntimeException("Internal bad error, found connectionDescriptors to null while it should be " +
|
||||
"initialized, somewhere it's overwritten!!");
|
||||
}
|
||||
if (connectionDescriptors.get(clientId) == null) {
|
||||
//TODO while we were publishing to the target client, that client disconnected,
|
||||
// could happen is not an error HANDLE IT
|
||||
throw new RuntimeException(String.format("Can't find a ConnectionDescriptor for client <%s> in cache <%s>",
|
||||
clientId, connectionDescriptors));
|
||||
}
|
||||
Channel channel = connectionDescriptors.get(clientId).channel;
|
||||
LOG.trace("Session for clientId {}", clientId);
|
||||
if (channel.isWritable()) {
|
||||
LOG.debug("channel is writable");
|
||||
//if channel is writable don't enqueue
|
||||
channel.writeAndFlush(pubMessage);
|
||||
} else if (pubMessage.getQos() != MOST_ONE) {
|
||||
//enqueue to the client session
|
||||
LOG.debug("enqueue to client session");
|
||||
clientsession.enqueue(asStoredMessage(pubMessage));
|
||||
}
|
||||
boolean messageDelivered = connectionDescriptorStore.sendMessage(pubMessage, pubMessage.getMessageID(), clientId);
|
||||
|
||||
if (!messageDelivered && pubMessage.getQos() != MOST_ONE && !clientsession.isCleanSession()) {
|
||||
LOG.warn(
|
||||
"The PUBLISH message could not be delivered. It will be stored. MessageId = {}, mqttClientId = {}, topic = {}, qos = {}, cleanSession = {}.",
|
||||
pubMessage.getMessageID(), clientId, pubMessage.getTopicName(), pubMessage.getQos(), false);
|
||||
clientsession.enqueue(asStoredMessage(pubMessage));
|
||||
} else {
|
||||
LOG.warn(
|
||||
"The PUBLISH message could not be delivered. It will be discarded. MessageId = {}, mqttClientId = {}, topic = {}, qos = {}, cleanSession = {}.",
|
||||
pubMessage.getMessageID(), clientId, pubMessage.getTopicName(), pubMessage.getQos(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user