...
|
...
|
@@ -48,6 +48,7 @@ import org.thingsboard.server.common.data.kv.AttributeKvEntry; |
48
|
48
|
import org.thingsboard.server.common.data.kv.KvEntry;
|
49
|
49
|
import org.thingsboard.server.common.data.page.PageData;
|
50
|
50
|
import org.thingsboard.server.common.data.page.PageLink;
|
|
51
|
+import org.thingsboard.server.common.data.page.SortOrder;
|
51
|
52
|
import org.thingsboard.server.common.data.relation.EntityRelation;
|
52
|
53
|
import org.thingsboard.server.common.data.relation.RelationTypeGroup;
|
53
|
54
|
import org.thingsboard.server.common.data.rpc.Rpc;
|
...
|
...
|
@@ -98,6 +99,7 @@ import java.util.Arrays; |
98
|
99
|
import java.util.Collections;
|
99
|
100
|
import java.util.HashMap;
|
100
|
101
|
import java.util.HashSet;
|
|
102
|
+import java.util.LinkedHashMap;
|
101
|
103
|
import java.util.List;
|
102
|
104
|
import java.util.Map;
|
103
|
105
|
import java.util.Objects;
|
...
|
...
|
@@ -132,7 +134,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { |
132
|
134
|
this.deviceId = deviceId;
|
133
|
135
|
this.attributeSubscriptions = new HashMap<>();
|
134
|
136
|
this.rpcSubscriptions = new HashMap<>();
|
135
|
|
- this.toDeviceRpcPendingMap = new HashMap<>();
|
|
137
|
+ this.toDeviceRpcPendingMap = new LinkedHashMap<>();
|
136
|
138
|
this.sessions = new LinkedHashMapRemoveEldest<>(systemContext.getMaxConcurrentSessionsPerDevice(), this::notifyTransportAboutClosedSessionMaxSessionsLimit);
|
137
|
139
|
if (initAttributes()) {
|
138
|
140
|
restoreSessions();
|
...
|
...
|
@@ -294,10 +296,11 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { |
294
|
296
|
}
|
295
|
297
|
systemContext.getTbCoreDeviceRpcService().processRpcResponseFromDeviceActor(new FromDeviceRpcResponse(requestMd.getMsg().getMsg().getId(),
|
296
|
298
|
null, requestMd.isSent() ? RpcError.TIMEOUT : RpcError.NO_ACTIVE_CONNECTION));
|
|
299
|
+ sendNextPendingRequest(context);
|
297
|
300
|
}
|
298
|
301
|
}
|
299
|
302
|
|
300
|
|
- private void sendPendingRequests(TbActorCtx context, UUID sessionId, SessionInfoProto sessionInfo) {
|
|
303
|
+ private void sendPendingRequest(TbActorCtx context, UUID sessionId, String nodeId) {
|
301
|
304
|
SessionType sessionType = getSessionType(sessionId);
|
302
|
305
|
if (!toDeviceRpcPendingMap.isEmpty()) {
|
303
|
306
|
log.debug("[{}] Pushing {} pending RPC messages to new async session [{}]", deviceId, toDeviceRpcPendingMap.size(), sessionId);
|
...
|
...
|
@@ -309,13 +312,11 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { |
309
|
312
|
log.debug("[{}] No pending RPC messages for new async session [{}]", deviceId, sessionId);
|
310
|
313
|
}
|
311
|
314
|
Set<Integer> sentOneWayIds = new HashSet<>();
|
312
|
|
- if (sessionType == SessionType.ASYNC) {
|
313
|
|
- toDeviceRpcPendingMap.entrySet().forEach(processPendingRpc(context, sessionId, sessionInfo.getNodeId(), sentOneWayIds));
|
314
|
|
- } else {
|
315
|
|
- toDeviceRpcPendingMap.entrySet().stream().findFirst().ifPresent(processPendingRpc(context, sessionId, sessionInfo.getNodeId(), sentOneWayIds));
|
316
|
|
- }
|
|
315
|
+ toDeviceRpcPendingMap.entrySet().stream().findFirst().ifPresent(processPendingRpc(context, sessionId, nodeId, sentOneWayIds));
|
|
316
|
+ }
|
317
|
317
|
|
318
|
|
- sentOneWayIds.stream().filter(id -> !toDeviceRpcPendingMap.get(id).getMsg().getMsg().isPersisted()).forEach(toDeviceRpcPendingMap::remove);
|
|
318
|
+ private void sendNextPendingRequest(TbActorCtx context) {
|
|
319
|
+ rpcSubscriptions.forEach((id, s) -> sendPendingRequest(context, id, s.getNodeId()));
|
319
|
320
|
}
|
320
|
321
|
|
321
|
322
|
private Consumer<Map.Entry<Integer, ToDeviceRpcRequestMetadata>> processPendingRpc(TbActorCtx context, UUID sessionId, String nodeId, Set<Integer> sentOneWayIds) {
|
...
|
...
|
@@ -337,6 +338,11 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { |
337
|
338
|
.setPersisted(request.isPersisted())
|
338
|
339
|
.build();
|
339
|
340
|
sendToTransport(rpcRequest, sessionId, nodeId);
|
|
341
|
+
|
|
342
|
+ if (SessionType.ASYNC.equals(getSessionType(sessionId)) && request.isOneway() && !request.isPersisted()) {
|
|
343
|
+ toDeviceRpcPendingMap.remove(entry.getKey());
|
|
344
|
+ sendPendingRequest(context, sessionId, nodeId);
|
|
345
|
+ }
|
340
|
346
|
};
|
341
|
347
|
}
|
342
|
348
|
|
...
|
...
|
@@ -355,7 +361,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { |
355
|
361
|
processSubscriptionCommands(context, sessionInfo, msg.getSubscribeToRPC());
|
356
|
362
|
}
|
357
|
363
|
if (msg.hasSendPendingRPC()) {
|
358
|
|
- sendPendingRequests(context, getSessionId(sessionInfo), sessionInfo);
|
|
364
|
+ sendPendingRequest(context, getSessionId(sessionInfo), sessionInfo.getNodeId());
|
359
|
365
|
}
|
360
|
366
|
if (msg.hasGetAttributes()) {
|
361
|
367
|
handleGetAttributesRequest(context, sessionInfo, msg.getGetAttributes());
|
...
|
...
|
@@ -544,6 +550,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { |
544
|
550
|
}
|
545
|
551
|
systemContext.getTbRpcService().save(tenantId, new RpcId(requestMd.getMsg().getMsg().getId()), status, response);
|
546
|
552
|
}
|
|
553
|
+ sendNextPendingRequest(context);
|
547
|
554
|
} else {
|
548
|
555
|
log.debug("[{}] Rpc command response [{}] is stale!", deviceId, responseMsg.getRequestId());
|
549
|
556
|
}
|
...
|
...
|
@@ -601,7 +608,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { |
601
|
608
|
sessionMD.setSubscribedToRPC(true);
|
602
|
609
|
log.debug("[{}] Registering rpc subscription for session [{}]", deviceId, sessionId);
|
603
|
610
|
rpcSubscriptions.put(sessionId, sessionMD.getSessionInfo());
|
604
|
|
- sendPendingRequests(context, sessionId, sessionInfo);
|
|
611
|
+ sendPendingRequest(context, sessionId, sessionInfo.getNodeId());
|
605
|
612
|
dumpSessions();
|
606
|
613
|
}
|
607
|
614
|
}
|
...
|
...
|
@@ -869,7 +876,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { |
869
|
876
|
|
870
|
877
|
void init(TbActorCtx ctx) {
|
871
|
878
|
schedulePeriodicMsgWithDelay(ctx, SessionTimeoutCheckMsg.instance(), systemContext.getSessionReportTimeout(), systemContext.getSessionReportTimeout());
|
872
|
|
- PageLink pageLink = new PageLink(1024);
|
|
879
|
+ PageLink pageLink = new PageLink(1024, 0, null, new SortOrder("createdTime"));
|
873
|
880
|
PageData<Rpc> pageData;
|
874
|
881
|
do {
|
875
|
882
|
pageData = systemContext.getTbRpcService().findAllByDeviceIdAndStatus(tenantId, deviceId, RpcStatus.QUEUED, pageLink);
|
...
|
...
|
|