Commit daac250c2e18c026aabde65c97217b45485c4132

Authored by Andrii Shvaika
1 parent c1d8aa13

Correct close and cleanup of the MQTT session context

@@ -81,6 +81,7 @@ import java.util.ArrayList; @@ -81,6 +81,7 @@ import java.util.ArrayList;
81 import java.util.List; 81 import java.util.List;
82 import java.util.Optional; 82 import java.util.Optional;
83 import java.util.UUID; 83 import java.util.UUID;
  84 +import java.util.concurrent.Callable;
84 import java.util.concurrent.ConcurrentHashMap; 85 import java.util.concurrent.ConcurrentHashMap;
85 import java.util.concurrent.ConcurrentMap; 86 import java.util.concurrent.ConcurrentMap;
86 import java.util.concurrent.TimeUnit; 87 import java.util.concurrent.TimeUnit;
@@ -153,10 +154,11 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement @@ -153,10 +154,11 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
153 if (message.decoderResult().isSuccess()) { 154 if (message.decoderResult().isSuccess()) {
154 processMqttMsg(ctx, message); 155 processMqttMsg(ctx, message);
155 } else { 156 } else {
156 - log.error("[{}] Message processing failed: {}", sessionId, message.decoderResult().cause().getMessage()); 157 + log.error("[{}] Message decoding failed: {}", sessionId, message.decoderResult().cause().getMessage());
157 ctx.close(); 158 ctx.close();
158 } 159 }
159 } else { 160 } else {
  161 + log.debug("[{}] Received non mqtt message: {}", sessionId, msg.getClass().getSimpleName());
160 ctx.close(); 162 ctx.close();
161 } 163 }
162 } finally { 164 } finally {
@@ -168,7 +170,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement @@ -168,7 +170,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
168 address = getAddress(ctx); 170 address = getAddress(ctx);
169 if (msg.fixedHeader() == null) { 171 if (msg.fixedHeader() == null) {
170 log.info("[{}:{}] Invalid message received", address.getHostName(), address.getPort()); 172 log.info("[{}:{}] Invalid message received", address.getHostName(), address.getPort());
171 - processDisconnect(ctx); 173 + ctx.close();
172 return; 174 return;
173 } 175 }
174 deviceSessionCtx.setChannel(ctx); 176 deviceSessionCtx.setChannel(ctx);
@@ -208,8 +210,8 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement @@ -208,8 +210,8 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
208 } 210 }
209 } 211 }
210 } else { 212 } else {
  213 + log.debug("[{}] Unsupported topic for provisioning requests: {}!", sessionId, topicName);
211 ctx.close(); 214 ctx.close();
212 - throw new RuntimeException("Unsupported topic for provisioning requests!");  
213 } 215 }
214 } catch (RuntimeException | AdaptorException e) { 216 } catch (RuntimeException | AdaptorException e) {
215 log.warn("[{}] Failed to process publish msg [{}][{}]", sessionId, topicName, msgId, e); 217 log.warn("[{}] Failed to process publish msg [{}][{}]", sessionId, topicName, msgId, e);
@@ -220,48 +222,30 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement @@ -220,48 +222,30 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
220 ctx.writeAndFlush(new MqttMessage(new MqttFixedHeader(PINGRESP, false, AT_MOST_ONCE, false, 0))); 222 ctx.writeAndFlush(new MqttMessage(new MqttFixedHeader(PINGRESP, false, AT_MOST_ONCE, false, 0)));
221 break; 223 break;
222 case DISCONNECT: 224 case DISCONNECT:
223 - if (checkConnected(ctx, msg)) {  
224 - processDisconnect(ctx);  
225 - } 225 + ctx.close();
226 break; 226 break;
227 } 227 }
228 } 228 }
229 229
230 void enqueueRegularSessionMsg(ChannelHandlerContext ctx, MqttMessage msg) { 230 void enqueueRegularSessionMsg(ChannelHandlerContext ctx, MqttMessage msg) {
231 - final int queueSize = deviceSessionCtx.getMsgQueueSize().incrementAndGet();  
232 - if (queueSize > context.getMessageQueueSizePerDeviceLimit()) {  
233 - log.warn("Closing current session because msq queue size for device {} exceed limit {} with msgQueueSize counter {} and actual queue size {}",  
234 - deviceSessionCtx.getDeviceId(), context.getMessageQueueSizePerDeviceLimit(), queueSize, deviceSessionCtx.getMsgQueue().size()); 231 + final int queueSize = deviceSessionCtx.getMsgQueueSize();
  232 + if (queueSize >= context.getMessageQueueSizePerDeviceLimit()) {
  233 + log.info("Closing current session because msq queue size for device {} exceed limit {} with msgQueueSize counter {} and actual queue size {}",
  234 + deviceSessionCtx.getDeviceId(), context.getMessageQueueSizePerDeviceLimit(), queueSize, deviceSessionCtx.getMsgQueueSize());
235 ctx.close(); 235 ctx.close();
236 return; 236 return;
237 } 237 }
238 238
239 - deviceSessionCtx.getMsgQueue().add(msg);  
240 - ReferenceCountUtil.retain(msg); 239 + deviceSessionCtx.addToQueue(msg);
241 processMsgQueue(ctx); //Under the normal conditions the msg queue will contain 0 messages. Many messages will be processed on device connect event in separate thread pool 240 processMsgQueue(ctx); //Under the normal conditions the msg queue will contain 0 messages. Many messages will be processed on device connect event in separate thread pool
242 } 241 }
243 242
244 void processMsgQueue(ChannelHandlerContext ctx) { 243 void processMsgQueue(ChannelHandlerContext ctx) {
245 if (!deviceSessionCtx.isConnected()) { 244 if (!deviceSessionCtx.isConnected()) {
246 - log.trace("[{}][{}] Postpone processing msg due to device is not connected. Msg queue size is {}", sessionId, deviceSessionCtx.getDeviceId(), deviceSessionCtx.getMsgQueue().size()); 245 + log.trace("[{}][{}] Postpone processing msg due to device is not connected. Msg queue size is {}", sessionId, deviceSessionCtx.getDeviceId(), deviceSessionCtx.getMsgQueueSize());
247 return; 246 return;
248 } 247 }
249 - while (!deviceSessionCtx.getMsgQueue().isEmpty()) {  
250 - if (deviceSessionCtx.getMsgQueueProcessorLock().tryLock()) {  
251 - try {  
252 - MqttMessage msg;  
253 - while ((msg = deviceSessionCtx.getMsgQueue().poll()) != null) {  
254 - deviceSessionCtx.getMsgQueueSize().decrementAndGet();  
255 - processRegularSessionMsg(ctx, msg);  
256 - ReferenceCountUtil.safeRelease(msg);  
257 - }  
258 - } finally {  
259 - deviceSessionCtx.getMsgQueueProcessorLock().unlock();  
260 - }  
261 - } else {  
262 - return;  
263 - }  
264 - } 248 + deviceSessionCtx.tryProcessQueuedMsgs(msg -> processRegularSessionMsg(ctx, msg));
265 } 249 }
266 250
267 void processRegularSessionMsg(ChannelHandlerContext ctx, MqttMessage msg) { 251 void processRegularSessionMsg(ChannelHandlerContext ctx, MqttMessage msg) {
@@ -282,9 +266,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement @@ -282,9 +266,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
282 } 266 }
283 break; 267 break;
284 case DISCONNECT: 268 case DISCONNECT:
285 - if (checkConnected(ctx, msg)) {  
286 - processDisconnect(ctx);  
287 - } 269 + ctx.close();
288 break; 270 break;
289 case PUBACK: 271 case PUBACK:
290 int msgId = ((MqttPubAckMessage) msg).variableHeader().messageId(); 272 int msgId = ((MqttPubAckMessage) msg).variableHeader().messageId();
@@ -438,7 +420,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement @@ -438,7 +420,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
438 @Override 420 @Override
439 public void onError(Throwable e) { 421 public void onError(Throwable e) {
440 log.trace("[{}] Failed to publish msg: {}", sessionId, msg, e); 422 log.trace("[{}] Failed to publish msg: {}", sessionId, msg, e);
441 - processDisconnect(ctx); 423 + ctx.close();
442 } 424 }
443 }; 425 };
444 } 426 }
@@ -464,7 +446,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement @@ -464,7 +446,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
464 } else { 446 } else {
465 deviceSessionCtx.getContext().getProtoMqttAdaptor().convertToPublish(deviceSessionCtx, provisionResponseMsg).ifPresent(deviceSessionCtx.getChannel()::writeAndFlush); 447 deviceSessionCtx.getContext().getProtoMqttAdaptor().convertToPublish(deviceSessionCtx, provisionResponseMsg).ifPresent(deviceSessionCtx.getChannel()::writeAndFlush);
466 } 448 }
467 - scheduler.schedule(() -> processDisconnect(ctx), 60, TimeUnit.SECONDS); 449 + scheduler.schedule((Callable<ChannelFuture>) ctx::close, 60, TimeUnit.SECONDS);
468 } catch (Exception e) { 450 } catch (Exception e) {
469 log.trace("[{}] Failed to convert device attributes response to MQTT msg", sessionId, e); 451 log.trace("[{}] Failed to convert device attributes response to MQTT msg", sessionId, e);
470 } 452 }
@@ -473,7 +455,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement @@ -473,7 +455,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
473 @Override 455 @Override
474 public void onError(Throwable e) { 456 public void onError(Throwable e) {
475 log.trace("[{}] Failed to publish msg: {}", sessionId, msg, e); 457 log.trace("[{}] Failed to publish msg: {}", sessionId, msg, e);
476 - processDisconnect(ctx); 458 + ctx.close();
477 } 459 }
478 } 460 }
479 461
@@ -508,7 +490,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement @@ -508,7 +490,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
508 @Override 490 @Override
509 public void onError(Throwable e) { 491 public void onError(Throwable e) {
510 log.trace("[{}] Failed to get firmware: {}", sessionId, msg, e); 492 log.trace("[{}] Failed to get firmware: {}", sessionId, msg, e);
511 - processDisconnect(ctx); 493 + ctx.close();
512 } 494 }
513 } 495 }
514 496
@@ -530,7 +512,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement @@ -530,7 +512,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
530 deviceSessionCtx.getChannel().writeAndFlush(deviceSessionCtx 512 deviceSessionCtx.getChannel().writeAndFlush(deviceSessionCtx
531 .getPayloadAdaptor() 513 .getPayloadAdaptor()
532 .createMqttPublishMsg(deviceSessionCtx, MqttTopics.DEVICE_FIRMWARE_ERROR_TOPIC, error.getBytes())); 514 .createMqttPublishMsg(deviceSessionCtx, MqttTopics.DEVICE_FIRMWARE_ERROR_TOPIC, error.getBytes()));
533 - processDisconnect(ctx); 515 + ctx.close();
534 } 516 }
535 517
536 private void processSubscribe(ChannelHandlerContext ctx, MqttSubscribeMessage mqttMsg) { 518 private void processSubscribe(ChannelHandlerContext ctx, MqttSubscribeMessage mqttMsg) {
@@ -699,6 +681,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement @@ -699,6 +681,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
699 }); 681 });
700 } catch (Exception e) { 682 } catch (Exception e) {
701 ctx.writeAndFlush(createMqttConnAckMsg(CONNECTION_REFUSED_NOT_AUTHORIZED, connectMessage)); 683 ctx.writeAndFlush(createMqttConnAckMsg(CONNECTION_REFUSED_NOT_AUTHORIZED, connectMessage));
  684 + log.trace("[{}] X509 auth failure: {}", sessionId, address, e);
702 ctx.close(); 685 ctx.close();
703 } 686 }
704 } 687 }
@@ -716,12 +699,6 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement @@ -716,12 +699,6 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
716 return null; 699 return null;
717 } 700 }
718 701
719 - void processDisconnect(ChannelHandlerContext ctx) {  
720 - ctx.close();  
721 - log.info("[{}] Client disconnected!", sessionId);  
722 - doDisconnect();  
723 - }  
724 -  
725 private MqttConnAckMessage createMqttConnAckMsg(MqttConnectReturnCode returnCode, MqttConnectMessage msg) { 702 private MqttConnAckMessage createMqttConnAckMsg(MqttConnectReturnCode returnCode, MqttConnectMessage msg) {
726 MqttFixedHeader mqttFixedHeader = 703 MqttFixedHeader mqttFixedHeader =
727 new MqttFixedHeader(CONNACK, false, AT_MOST_ONCE, false, 0); 704 new MqttFixedHeader(CONNACK, false, AT_MOST_ONCE, false, 0);
@@ -766,7 +743,6 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement @@ -766,7 +743,6 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
766 return true; 743 return true;
767 } else { 744 } else {
768 log.info("[{}] Closing current session due to invalid msg order: {}", sessionId, msg); 745 log.info("[{}] Closing current session due to invalid msg order: {}", sessionId, msg);
769 - ctx.close();  
770 return false; 746 return false;
771 } 747 }
772 } 748 }
@@ -791,11 +767,13 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement @@ -791,11 +767,13 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
791 767
792 @Override 768 @Override
793 public void operationComplete(Future<? super Void> future) throws Exception { 769 public void operationComplete(Future<? super Void> future) throws Exception {
  770 + log.trace("[{}] Channel closed!", sessionId);
794 doDisconnect(); 771 doDisconnect();
795 } 772 }
796 773
797 - private void doDisconnect() { 774 + public void doDisconnect() {
798 if (deviceSessionCtx.isConnected()) { 775 if (deviceSessionCtx.isConnected()) {
  776 + log.info("[{}] Client disconnected!", sessionId);
799 transportService.process(deviceSessionCtx.getSessionInfo(), DefaultTransportService.getSessionEventMsg(SessionEvent.CLOSED), null); 777 transportService.process(deviceSessionCtx.getSessionInfo(), DefaultTransportService.getSessionEventMsg(SessionEvent.CLOSED), null);
800 transportService.deregisterSession(deviceSessionCtx.getSessionInfo()); 778 transportService.deregisterSession(deviceSessionCtx.getSessionInfo());
801 if (gatewaySessionHandler != null) { 779 if (gatewaySessionHandler != null) {
@@ -803,11 +781,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement @@ -803,11 +781,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
803 } 781 }
804 deviceSessionCtx.setDisconnected(); 782 deviceSessionCtx.setDisconnected();
805 } 783 }
806 -  
807 - if (!deviceSessionCtx.getMsgQueue().isEmpty()) {  
808 - log.warn("doDisconnect for device {} but unprocessed messages {} left in the msg queue", deviceSessionCtx.getDeviceId(), deviceSessionCtx.getMsgQueue().size());  
809 - deviceSessionCtx.getMsgQueue().clear();  
810 - } 784 + deviceSessionCtx.release();
811 } 785 }
812 786
813 787
@@ -866,7 +840,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement @@ -866,7 +840,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
866 @Override 840 @Override
867 public void onRemoteSessionCloseCommand(UUID sessionId, TransportProtos.SessionCloseNotificationProto sessionCloseNotification) { 841 public void onRemoteSessionCloseCommand(UUID sessionId, TransportProtos.SessionCloseNotificationProto sessionCloseNotification) {
868 log.trace("[{}] Received the remote command to close the session: {}", sessionId, sessionCloseNotification.getMessage()); 842 log.trace("[{}] Received the remote command to close the session: {}", sessionId, sessionCloseNotification.getMessage());
869 - processDisconnect(deviceSessionCtx.getChannel()); 843 + deviceSessionCtx.getChannel().close();
870 } 844 }
871 845
872 @Override 846 @Override
@@ -19,6 +19,7 @@ import com.google.protobuf.Descriptors; @@ -19,6 +19,7 @@ import com.google.protobuf.Descriptors;
19 import com.google.protobuf.DynamicMessage; 19 import com.google.protobuf.DynamicMessage;
20 import io.netty.channel.ChannelHandlerContext; 20 import io.netty.channel.ChannelHandlerContext;
21 import io.netty.handler.codec.mqtt.MqttMessage; 21 import io.netty.handler.codec.mqtt.MqttMessage;
  22 +import io.netty.util.ReferenceCountUtil;
22 import lombok.Getter; 23 import lombok.Getter;
23 import lombok.Setter; 24 import lombok.Setter;
24 import lombok.extern.slf4j.Slf4j; 25 import lombok.extern.slf4j.Slf4j;
@@ -35,12 +36,16 @@ import org.thingsboard.server.transport.mqtt.adaptors.MqttTransportAdaptor; @@ -35,12 +36,16 @@ import org.thingsboard.server.transport.mqtt.adaptors.MqttTransportAdaptor;
35 import org.thingsboard.server.transport.mqtt.util.MqttTopicFilter; 36 import org.thingsboard.server.transport.mqtt.util.MqttTopicFilter;
36 import org.thingsboard.server.transport.mqtt.util.MqttTopicFilterFactory; 37 import org.thingsboard.server.transport.mqtt.util.MqttTopicFilterFactory;
37 38
  39 +import java.util.Collection;
  40 +import java.util.Collections;
  41 +import java.util.Queue;
38 import java.util.UUID; 42 import java.util.UUID;
39 import java.util.concurrent.ConcurrentLinkedQueue; 43 import java.util.concurrent.ConcurrentLinkedQueue;
40 import java.util.concurrent.ConcurrentMap; 44 import java.util.concurrent.ConcurrentMap;
41 import java.util.concurrent.atomic.AtomicInteger; 45 import java.util.concurrent.atomic.AtomicInteger;
42 import java.util.concurrent.locks.Lock; 46 import java.util.concurrent.locks.Lock;
43 import java.util.concurrent.locks.ReentrantLock; 47 import java.util.concurrent.locks.ReentrantLock;
  48 +import java.util.function.Consumer;
44 49
45 /** 50 /**
46 * @author Andrew Shvayka 51 * @author Andrew Shvayka
@@ -57,13 +62,11 @@ public class DeviceSessionCtx extends MqttDeviceAwareSessionContext { @@ -57,13 +62,11 @@ public class DeviceSessionCtx extends MqttDeviceAwareSessionContext {
57 62
58 private final AtomicInteger msgIdSeq = new AtomicInteger(0); 63 private final AtomicInteger msgIdSeq = new AtomicInteger(0);
59 64
60 - @Getter  
61 private final ConcurrentLinkedQueue<MqttMessage> msgQueue = new ConcurrentLinkedQueue<>(); 65 private final ConcurrentLinkedQueue<MqttMessage> msgQueue = new ConcurrentLinkedQueue<>();
62 66
63 @Getter 67 @Getter
64 private final Lock msgQueueProcessorLock = new ReentrantLock(); 68 private final Lock msgQueueProcessorLock = new ReentrantLock();
65 69
66 - @Getter  
67 private final AtomicInteger msgQueueSize = new AtomicInteger(0); 70 private final AtomicInteger msgQueueSize = new AtomicInteger(0);
68 71
69 @Getter 72 @Getter
@@ -160,4 +163,49 @@ public class DeviceSessionCtx extends MqttDeviceAwareSessionContext { @@ -160,4 +163,49 @@ public class DeviceSessionCtx extends MqttDeviceAwareSessionContext {
160 rpcResponseDynamicMessageDescriptor = protoTransportPayloadConfig.getRpcResponseDynamicMessageDescriptor(protoTransportPayloadConfig.getDeviceRpcResponseProtoSchema()); 163 rpcResponseDynamicMessageDescriptor = protoTransportPayloadConfig.getRpcResponseDynamicMessageDescriptor(protoTransportPayloadConfig.getDeviceRpcResponseProtoSchema());
161 rpcRequestDynamicMessageBuilder = protoTransportPayloadConfig.getRpcRequestDynamicMessageBuilder(protoTransportPayloadConfig.getDeviceRpcRequestProtoSchema()); 164 rpcRequestDynamicMessageBuilder = protoTransportPayloadConfig.getRpcRequestDynamicMessageBuilder(protoTransportPayloadConfig.getDeviceRpcRequestProtoSchema());
162 } 165 }
  166 +
  167 + public void addToQueue(MqttMessage msg) {
  168 + msgQueueSize.incrementAndGet();
  169 + ReferenceCountUtil.retain(msg);
  170 + msgQueue.add(msg);
  171 + }
  172 +
  173 + public void tryProcessQueuedMsgs(Consumer<MqttMessage> msgProcessor) {
  174 + while (!msgQueue.isEmpty()) {
  175 + if (msgQueueProcessorLock.tryLock()) {
  176 + try {
  177 + MqttMessage msg;
  178 + while ((msg = msgQueue.poll()) != null) {
  179 + try {
  180 + msgQueueSize.decrementAndGet();
  181 + msgProcessor.accept(msg);
  182 + } finally {
  183 + ReferenceCountUtil.safeRelease(msg);
  184 + }
  185 + }
  186 + } finally {
  187 + msgQueueProcessorLock.unlock();
  188 + }
  189 + } else {
  190 + return;
  191 + }
  192 + }
  193 + }
  194 +
  195 + public int getMsgQueueSize() {
  196 + return msgQueueSize.get();
  197 + }
  198 +
  199 + public void release() {
  200 + if (!msgQueue.isEmpty()) {
  201 + log.warn("doDisconnect for device {} but unprocessed messages {} left in the msg queue", getDeviceId(), msgQueue.size());
  202 + msgQueue.forEach(ReferenceCountUtil::safeRelease);
  203 + msgQueue.clear();
  204 + }
  205 + }
  206 +
  207 + public Collection<MqttMessage> getMsgQueueSnapshot(){
  208 + return Collections.unmodifiableCollection(msgQueue);
  209 + }
  210 +
163 } 211 }
@@ -112,18 +112,6 @@ public class MqttTransportHandlerTest { @@ -112,18 +112,6 @@ public class MqttTransportHandlerTest {
112 } 112 }
113 113
114 @Test 114 @Test
115 - public void givenMessageWithoutFixedHeader_whenProcessMqttMsg_thenProcessDisconnect() {  
116 - MqttFixedHeader mqttFixedHeader = null;  
117 - MqttMessage msg = new MqttMessage(mqttFixedHeader);  
118 - willDoNothing().given(handler).processDisconnect(ctx);  
119 -  
120 - handler.processMqttMsg(ctx, msg);  
121 -  
122 - assertThat(handler.address, is(IP_ADDR));  
123 - verify(handler, times(1)).processDisconnect(ctx);  
124 - }  
125 -  
126 - @Test  
127 public void givenMqttConnectMessage_whenProcessMqttMsg_thenProcessConnect() { 115 public void givenMqttConnectMessage_whenProcessMqttMsg_thenProcessConnect() {
128 MqttConnectMessage msg = getMqttConnectMessage(); 116 MqttConnectMessage msg = getMqttConnectMessage();
129 willDoNothing().given(handler).processConnect(ctx, msg); 117 willDoNothing().given(handler).processConnect(ctx, msg);
@@ -132,7 +120,7 @@ public class MqttTransportHandlerTest { @@ -132,7 +120,7 @@ public class MqttTransportHandlerTest {
132 120
133 assertThat(handler.address, is(IP_ADDR)); 121 assertThat(handler.address, is(IP_ADDR));
134 assertThat(handler.deviceSessionCtx.getChannel(), is(ctx)); 122 assertThat(handler.deviceSessionCtx.getChannel(), is(ctx));
135 - verify(handler, never()).processDisconnect(any()); 123 + verify(handler, never()).doDisconnect();
136 verify(handler, times(1)).processConnect(ctx, msg); 124 verify(handler, times(1)).processConnect(ctx, msg);
137 } 125 }
138 126
@@ -140,8 +128,8 @@ public class MqttTransportHandlerTest { @@ -140,8 +128,8 @@ public class MqttTransportHandlerTest {
140 public void givenQueueLimit_whenEnqueueRegularSessionMsgOverLimit_thenOK() { 128 public void givenQueueLimit_whenEnqueueRegularSessionMsgOverLimit_thenOK() {
141 List<MqttPublishMessage> messages = Stream.generate(this::getMqttPublishMessage).limit(MSG_QUEUE_LIMIT).collect(Collectors.toList()); 129 List<MqttPublishMessage> messages = Stream.generate(this::getMqttPublishMessage).limit(MSG_QUEUE_LIMIT).collect(Collectors.toList());
142 messages.forEach(msg -> handler.enqueueRegularSessionMsg(ctx, msg)); 130 messages.forEach(msg -> handler.enqueueRegularSessionMsg(ctx, msg));
143 - assertThat(handler.deviceSessionCtx.getMsgQueueSize().get(), is(MSG_QUEUE_LIMIT));  
144 - assertThat(handler.deviceSessionCtx.getMsgQueue(), contains(messages.toArray())); 131 + assertThat(handler.deviceSessionCtx.getMsgQueueSize(), is(MSG_QUEUE_LIMIT));
  132 + assertThat(handler.deviceSessionCtx.getMsgQueueSnapshot(), contains(messages.toArray()));
145 } 133 }
146 134
147 @Test 135 @Test
@@ -152,7 +140,7 @@ public class MqttTransportHandlerTest { @@ -152,7 +140,7 @@ public class MqttTransportHandlerTest {
152 140
153 messages.forEach((msg) -> handler.enqueueRegularSessionMsg(ctx, msg)); 141 messages.forEach((msg) -> handler.enqueueRegularSessionMsg(ctx, msg));
154 142
155 - assertThat(handler.deviceSessionCtx.getMsgQueueSize().get(), is(limit)); 143 + assertThat(handler.deviceSessionCtx.getMsgQueueSize(), is(MSG_QUEUE_LIMIT));
156 verify(handler, times(limit)).enqueueRegularSessionMsg(any(), any()); 144 verify(handler, times(limit)).enqueueRegularSessionMsg(any(), any());
157 verify(handler, times(MSG_QUEUE_LIMIT)).processMsgQueue(any()); 145 verify(handler, times(MSG_QUEUE_LIMIT)).processMsgQueue(any());
158 verify(ctx, times(1)).close(); 146 verify(ctx, times(1)).close();
@@ -169,9 +157,9 @@ public class MqttTransportHandlerTest { @@ -169,9 +157,9 @@ public class MqttTransportHandlerTest {
169 assertThat(handler.address, is(IP_ADDR)); 157 assertThat(handler.address, is(IP_ADDR));
170 assertThat(handler.deviceSessionCtx.getChannel(), is(ctx)); 158 assertThat(handler.deviceSessionCtx.getChannel(), is(ctx));
171 assertThat(handler.deviceSessionCtx.isConnected(), is(false)); 159 assertThat(handler.deviceSessionCtx.isConnected(), is(false));
172 - assertThat(handler.deviceSessionCtx.getMsgQueueSize().get(), is(MSG_QUEUE_LIMIT));  
173 - assertThat(handler.deviceSessionCtx.getMsgQueue(), contains(messages.toArray()));  
174 - verify(handler, never()).processDisconnect(any()); 160 + assertThat(handler.deviceSessionCtx.getMsgQueueSize(), is(MSG_QUEUE_LIMIT));
  161 + assertThat(handler.deviceSessionCtx.getMsgQueueSnapshot(), contains(messages.toArray()));
  162 + verify(handler, never()).doDisconnect();
175 verify(handler, times(1)).processConnect(any(), any()); 163 verify(handler, times(1)).processConnect(any(), any());
176 verify(handler, times(MSG_QUEUE_LIMIT)).enqueueRegularSessionMsg(any(), any()); 164 verify(handler, times(MSG_QUEUE_LIMIT)).enqueueRegularSessionMsg(any(), any());
177 verify(handler, never()).processRegularSessionMsg(any(), any()); 165 verify(handler, never()).processRegularSessionMsg(any(), any());
@@ -212,8 +200,8 @@ public class MqttTransportHandlerTest { @@ -212,8 +200,8 @@ public class MqttTransportHandlerTest {
212 assertThat(finishLatch.await(TIMEOUT, TimeUnit.SECONDS), is(true)); 200 assertThat(finishLatch.await(TIMEOUT, TimeUnit.SECONDS), is(true));
213 201
214 //then 202 //then
215 - assertThat(handler.deviceSessionCtx.getMsgQueueSize().get(), is(0));  
216 - assertThat(handler.deviceSessionCtx.getMsgQueue(), empty()); 203 + assertThat(handler.deviceSessionCtx.getMsgQueueSize(), is(0));
  204 + assertThat(handler.deviceSessionCtx.getMsgQueueSnapshot(), empty());
217 verify(handler, times(MSG_QUEUE_LIMIT)).processRegularSessionMsg(any(), any()); 205 verify(handler, times(MSG_QUEUE_LIMIT)).processRegularSessionMsg(any(), any());
218 messages.forEach((msg) -> verify(handler, times(1)).processRegularSessionMsg(ctx, msg)); 206 messages.forEach((msg) -> verify(handler, times(1)).processRegularSessionMsg(ctx, msg));
219 } 207 }