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:
@@ -16,10 +16,16 @@
|
||||
package io.moquette.server;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import io.moquette.server.netty.AutoFlushHandler;
|
||||
import io.moquette.server.netty.NettyUtils;
|
||||
|
||||
|
||||
/**
|
||||
* Value object to maintain the information of single connection, like ClientID, Channel,
|
||||
@@ -40,7 +46,7 @@ public class ConnectionDescriptor {
|
||||
}
|
||||
|
||||
public final String clientID;
|
||||
public final Channel channel;
|
||||
private final Channel channel;
|
||||
public final boolean cleanSession;
|
||||
private final AtomicReference<ConnectionState> channelState = new AtomicReference<>(ConnectionState.DISCONNECTED);
|
||||
|
||||
@@ -49,20 +55,59 @@ public class ConnectionDescriptor {
|
||||
this.channel = session;
|
||||
this.cleanSession = cleanSession;
|
||||
}
|
||||
|
||||
public void writeAndFlush(Object payload) {
|
||||
this.channel.writeAndFlush(payload);
|
||||
}
|
||||
|
||||
public void setupAutoFlusher(int flushIntervalMs) {
|
||||
try {
|
||||
this.channel.pipeline().addAfter("idleEventHandler", "autoFlusher", new AutoFlushHandler(flushIntervalMs, TimeUnit.MILLISECONDS));
|
||||
} catch (NoSuchElementException nseex) {
|
||||
//the idleEventHandler is not present on the pipeline
|
||||
this.channel.pipeline().addFirst("autoFlusher", new AutoFlushHandler(flushIntervalMs, TimeUnit.MILLISECONDS));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean doesNotUseChannel(Channel channel) {
|
||||
return !(this.channel.equals(channel));
|
||||
}
|
||||
|
||||
public boolean close() {
|
||||
LOG.info("Closing connection descriptor. MqttClientId = {}.", clientID);
|
||||
final boolean success = assignState(ConnectionState.INTERCEPTORS_NOTIFIED, ConnectionState.DISCONNECTED);
|
||||
if (!success) {
|
||||
return false;
|
||||
}
|
||||
this.channel.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return NettyUtils.userName(this.channel);
|
||||
}
|
||||
|
||||
public void abort() {
|
||||
LOG.info("closing the channel");
|
||||
LOG.info("Closing connection descriptor. MqttClientId = {}.", clientID);
|
||||
// try {
|
||||
//this.channel.disconnect().sync();
|
||||
this.channel.close();//.sync();
|
||||
this.channel.close();//.sync();
|
||||
// } catch (InterruptedException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
}
|
||||
|
||||
public boolean assignState(ConnectionState expected, ConnectionState newState) {
|
||||
return channelState.compareAndSet(expected, newState);
|
||||
}
|
||||
LOG.debug("Updating state of connection descriptor. MqttClientId = {}, expectedState = {}, newState = {}.",
|
||||
clientID, expected, newState);
|
||||
boolean retval = channelState.compareAndSet(expected, newState);
|
||||
if (!retval) {
|
||||
LOG.error(
|
||||
"Unable to update state of connection descriptor. MqttclientId = {}, expectedState = {}, newState = {}.",
|
||||
clientID, expected, newState);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
Reference in New Issue
Block a user