Showing
12 changed files
with
105 additions
and
85 deletions
... | ... | @@ -80,9 +80,9 @@ import org.thingsboard.server.gen.transport.TransportProtos.SessionType; |
80 | 80 | import org.thingsboard.server.gen.transport.TransportProtos.SubscribeToAttributeUpdatesMsg; |
81 | 81 | import org.thingsboard.server.gen.transport.TransportProtos.SubscribeToRPCMsg; |
82 | 82 | import org.thingsboard.server.gen.transport.TransportProtos.SubscriptionInfoProto; |
83 | -import org.thingsboard.server.gen.transport.TransportProtos.ToDevicePersistedRpcResponseMsg; | |
84 | 83 | import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcRequestMsg; |
85 | 84 | import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcResponseMsg; |
85 | +import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcResponseStatusMsg; | |
86 | 86 | import org.thingsboard.server.gen.transport.TransportProtos.ToServerRpcResponseMsg; |
87 | 87 | import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; |
88 | 88 | import org.thingsboard.server.gen.transport.TransportProtos.ToTransportUpdateCredentialsProto; |
... | ... | @@ -298,7 +298,9 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { |
298 | 298 | } |
299 | 299 | systemContext.getTbCoreDeviceRpcService().processRpcResponseFromDeviceActor(new FromDeviceRpcResponse(requestMd.getMsg().getMsg().getId(), |
300 | 300 | null, requestMd.isSent() ? RpcError.TIMEOUT : RpcError.NO_ACTIVE_CONNECTION)); |
301 | - sendNextPendingRequest(context); | |
301 | + if (!requestMd.isDelivered()) { | |
302 | + sendNextPendingRequest(context); | |
303 | + } | |
302 | 304 | } |
303 | 305 | } |
304 | 306 | |
... | ... | @@ -315,22 +317,10 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { |
315 | 317 | } |
316 | 318 | Set<Integer> sentOneWayIds = new HashSet<>(); |
317 | 319 | |
318 | - if (sessionType == SessionType.ASYNC) { | |
319 | - if (rpcSequenceEnabled) { | |
320 | - List<Map.Entry<Integer, ToDeviceRpcRequestMetadata>> entries = new ArrayList<>(); | |
321 | - for (Map.Entry<Integer, ToDeviceRpcRequestMetadata> entry : toDeviceRpcPendingMap.entrySet()) { | |
322 | - if (entry.getValue().isDelivered()) { | |
323 | - continue; | |
324 | - } | |
325 | - entries.add(entry); | |
326 | - if (entry.getValue().getMsg().getMsg().isPersisted() || entry.getValue().getMsg().getMsg().isOneway()) { | |
327 | - break; | |
328 | - } | |
329 | - } | |
330 | - entries.forEach(processPendingRpc(context, sessionId, nodeId, sentOneWayIds)); | |
331 | - } else { | |
332 | - toDeviceRpcPendingMap.entrySet().forEach(processPendingRpc(context, sessionId, nodeId, sentOneWayIds)); | |
333 | - } | |
320 | + if (rpcSequenceEnabled) { | |
321 | + toDeviceRpcPendingMap.entrySet().stream().filter(e -> !e.getValue().isDelivered()).findFirst().ifPresent(processPendingRpc(context, sessionId, nodeId, sentOneWayIds)); | |
322 | + } else if (sessionType == SessionType.ASYNC) { | |
323 | + toDeviceRpcPendingMap.entrySet().forEach(processPendingRpc(context, sessionId, nodeId, sentOneWayIds)); | |
334 | 324 | } else { |
335 | 325 | toDeviceRpcPendingMap.entrySet().stream().findFirst().ifPresent(processPendingRpc(context, sessionId, nodeId, sentOneWayIds)); |
336 | 326 | } |
... | ... | @@ -348,7 +338,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { |
348 | 338 | return entry -> { |
349 | 339 | ToDeviceRpcRequest request = entry.getValue().getMsg().getMsg(); |
350 | 340 | ToDeviceRpcRequestBody body = request.getBody(); |
351 | - if (request.isOneway()) { | |
341 | + if (request.isOneway() && !rpcSequenceEnabled) { | |
352 | 342 | sentOneWayIds.add(entry.getKey()); |
353 | 343 | systemContext.getTbCoreDeviceRpcService().processRpcResponseFromDeviceActor(new FromDeviceRpcResponse(request.getId(), null, null)); |
354 | 344 | } |
... | ... | @@ -357,6 +347,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { |
357 | 347 | .setMethodName(body.getMethod()) |
358 | 348 | .setParams(body.getParams()) |
359 | 349 | .setExpirationTime(request.getExpirationTime()) |
350 | + .setTimeout(request.getTimeout()) | |
360 | 351 | .setRequestIdMSB(request.getId().getMostSignificantBits()) |
361 | 352 | .setRequestIdLSB(request.getId().getLeastSignificantBits()) |
362 | 353 | .setOneway(request.isOneway()) |
... | ... | @@ -395,8 +386,8 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { |
395 | 386 | if (msg.hasClaimDevice()) { |
396 | 387 | handleClaimDeviceMsg(context, sessionInfo, msg.getClaimDevice()); |
397 | 388 | } |
398 | - if (msg.hasPersistedRpcResponseMsg()) { | |
399 | - processPersistedRpcResponses(context, sessionInfo, msg.getPersistedRpcResponseMsg()); | |
389 | + if (msg.hasRpcResponseStatusMsg()) { | |
390 | + processPersistedRpcResponses(context, sessionInfo, msg.getRpcResponseStatusMsg()); | |
400 | 391 | } |
401 | 392 | if (msg.hasUplinkNotificationMsg()) { |
402 | 393 | processUplinkNotificationMsg(context, sessionInfo, msg.getUplinkNotificationMsg()); |
... | ... | @@ -556,27 +547,32 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { |
556 | 547 | boolean success = requestMd != null; |
557 | 548 | if (success) { |
558 | 549 | boolean hasError = StringUtils.isNotEmpty(responseMsg.getError()); |
559 | - String payload = hasError ? responseMsg.getError() : responseMsg.getPayload(); | |
560 | - systemContext.getTbCoreDeviceRpcService().processRpcResponseFromDeviceActor( | |
561 | - new FromDeviceRpcResponse(requestMd.getMsg().getMsg().getId(), | |
562 | - payload, null)); | |
563 | - if (requestMd.getMsg().getMsg().isPersisted()) { | |
564 | - RpcStatus status = hasError ? RpcStatus.FAILED : RpcStatus.SUCCESSFUL; | |
565 | - JsonNode response; | |
566 | - try { | |
567 | - response = JacksonUtil.toJsonNode(payload); | |
568 | - } catch (IllegalArgumentException e) { | |
569 | - response = JacksonUtil.newObjectNode().put("error", payload); | |
550 | + try { | |
551 | + String payload = hasError ? responseMsg.getError() : responseMsg.getPayload(); | |
552 | + systemContext.getTbCoreDeviceRpcService().processRpcResponseFromDeviceActor( | |
553 | + new FromDeviceRpcResponse(requestMd.getMsg().getMsg().getId(), | |
554 | + payload, null)); | |
555 | + if (requestMd.getMsg().getMsg().isPersisted()) { | |
556 | + RpcStatus status = hasError ? RpcStatus.FAILED : RpcStatus.SUCCESSFUL; | |
557 | + JsonNode response; | |
558 | + try { | |
559 | + response = JacksonUtil.toJsonNode(payload); | |
560 | + } catch (IllegalArgumentException e) { | |
561 | + response = JacksonUtil.newObjectNode().put("error", payload); | |
562 | + } | |
563 | + systemContext.getTbRpcService().save(tenantId, new RpcId(requestMd.getMsg().getMsg().getId()), status, response); | |
564 | + } | |
565 | + } finally { | |
566 | + if (!requestMd.isDelivered() && hasError) { | |
567 | + sendNextPendingRequest(context); | |
570 | 568 | } |
571 | - systemContext.getTbRpcService().save(tenantId, new RpcId(requestMd.getMsg().getMsg().getId()), status, response); | |
572 | 569 | } |
573 | - sendNextPendingRequest(context); | |
574 | 570 | } else { |
575 | 571 | log.debug("[{}] Rpc command response [{}] is stale!", deviceId, responseMsg.getRequestId()); |
576 | 572 | } |
577 | 573 | } |
578 | 574 | |
579 | - private void processPersistedRpcResponses(TbActorCtx context, SessionInfoProto sessionInfo, ToDevicePersistedRpcResponseMsg responseMsg) { | |
575 | + private void processPersistedRpcResponses(TbActorCtx context, SessionInfoProto sessionInfo, ToDeviceRpcResponseStatusMsg responseMsg) { | |
580 | 576 | UUID rpcId = new UUID(responseMsg.getRequestIdMSB(), responseMsg.getRequestIdLSB()); |
581 | 577 | RpcStatus status = RpcStatus.valueOf(responseMsg.getStatus()); |
582 | 578 | ToDeviceRpcRequestMetadata md = toDeviceRpcPendingMap.get(responseMsg.getRequestId()); |
... | ... | @@ -585,6 +581,9 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { |
585 | 581 | if (status.equals(RpcStatus.DELIVERED)) { |
586 | 582 | if (md.getMsg().getMsg().isOneway()) { |
587 | 583 | toDeviceRpcPendingMap.remove(responseMsg.getRequestId()); |
584 | + if (rpcSequenceEnabled) { | |
585 | + systemContext.getTbCoreDeviceRpcService().processRpcResponseFromDeviceActor(new FromDeviceRpcResponse(rpcId, null, null)); | |
586 | + } | |
588 | 587 | } else { |
589 | 588 | md.setDelivered(true); |
590 | 589 | } |
... | ... | @@ -597,7 +596,9 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { |
597 | 596 | } |
598 | 597 | } |
599 | 598 | |
600 | - systemContext.getTbRpcService().save(tenantId, new RpcId(rpcId), status, null); | |
599 | + if (md.getMsg().getMsg().isPersisted()) { | |
600 | + systemContext.getTbRpcService().save(tenantId, new RpcId(rpcId), status, null); | |
601 | + } | |
601 | 602 | if (status != RpcStatus.SENT) { |
602 | 603 | sendNextPendingRequest(context); |
603 | 604 | } | ... | ... |
... | ... | @@ -75,8 +75,8 @@ public abstract class AbstractRpcController extends BaseController { |
75 | 75 | SecurityUser currentUser = getCurrentUser(); |
76 | 76 | TenantId tenantId = currentUser.getTenantId(); |
77 | 77 | final DeferredResult<ResponseEntity> response = new DeferredResult<>(); |
78 | - long timeout = rpcRequestBody.has("timeout") ? rpcRequestBody.get("timeout").asLong() : defaultTimeout; | |
79 | - long expTime = System.currentTimeMillis() + Math.max(minTimeout, timeout); | |
78 | + long timeout = rpcRequestBody.has(DataConstants.TIMEOUT) ? rpcRequestBody.get(DataConstants.TIMEOUT).asLong() : defaultTimeout; | |
79 | + long expTime = rpcRequestBody.has(DataConstants.EXPIRATION_TIME) ? rpcRequestBody.get(DataConstants.EXPIRATION_TIME).asLong() : System.currentTimeMillis() + Math.max(minTimeout, timeout); | |
80 | 80 | UUID rpcRequestUUID = rpcRequestBody.has("requestUUID") ? UUID.fromString(rpcRequestBody.get("requestUUID").asText()) : UUID.randomUUID(); |
81 | 81 | boolean persisted = rpcRequestBody.has(DataConstants.PERSISTENT) && rpcRequestBody.get(DataConstants.PERSISTENT).asBoolean(); |
82 | 82 | String additionalInfo = JacksonUtil.toString(rpcRequestBody.get(DataConstants.ADDITIONAL_INFO)); |
... | ... | @@ -88,6 +88,7 @@ public abstract class AbstractRpcController extends BaseController { |
88 | 88 | deviceId, |
89 | 89 | oneWay, |
90 | 90 | expTime, |
91 | + timeout, | |
91 | 92 | body, |
92 | 93 | persisted, |
93 | 94 | additionalInfo | ... | ... |
... | ... | @@ -101,7 +101,7 @@ public class DefaultTbRuleEngineRpcService implements TbRuleEngineDeviceRpcServi |
101 | 101 | @Override |
102 | 102 | public void sendRpcRequestToDevice(RuleEngineDeviceRpcRequest src, Consumer<RuleEngineDeviceRpcResponse> consumer) { |
103 | 103 | ToDeviceRpcRequest request = new ToDeviceRpcRequest(src.getRequestUUID(), src.getTenantId(), src.getDeviceId(), |
104 | - src.isOneway(), src.getExpirationTime(), new ToDeviceRpcRequestBody(src.getMethod(), src.getBody()), src.isPersisted(), src.getAdditionalInfo()); | |
104 | + src.isOneway(), src.getExpirationTime(), src.getTimeout(), new ToDeviceRpcRequestBody(src.getMethod(), src.getBody()), src.isPersisted(), src.getAdditionalInfo()); | |
105 | 105 | forwardRpcRequestToDeviceActor(request, response -> { |
106 | 106 | if (src.isRestApiCall()) { |
107 | 107 | sendRpcResponseToTbCore(src.getOriginServiceId(), response); | ... | ... |
... | ... | @@ -28,15 +28,16 @@ import org.eclipse.paho.client.mqttv3.MqttCallback; |
28 | 28 | import org.eclipse.paho.client.mqttv3.MqttException; |
29 | 29 | import org.eclipse.paho.client.mqttv3.MqttMessage; |
30 | 30 | import org.junit.Assert; |
31 | +import org.thingsboard.common.util.JacksonUtil; | |
31 | 32 | import org.thingsboard.server.common.data.Device; |
32 | 33 | import org.thingsboard.server.common.data.TransportPayloadType; |
33 | 34 | import org.thingsboard.server.common.data.device.profile.MqttTopics; |
34 | -import org.thingsboard.common.util.JacksonUtil; | |
35 | 35 | import org.thingsboard.server.transport.mqtt.AbstractMqttIntegrationTest; |
36 | 36 | |
37 | 37 | import java.util.ArrayList; |
38 | 38 | import java.util.Arrays; |
39 | 39 | import java.util.List; |
40 | +import java.util.concurrent.CopyOnWriteArrayList; | |
40 | 41 | import java.util.concurrent.CountDownLatch; |
41 | 42 | import java.util.concurrent.TimeUnit; |
42 | 43 | |
... | ... | @@ -120,12 +121,13 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractM |
120 | 121 | } |
121 | 122 | |
122 | 123 | MqttAsyncClient client = getMqttAsyncClient(accessToken); |
124 | + client.setManualAcks(true); | |
123 | 125 | CountDownLatch latch = new CountDownLatch(10); |
124 | 126 | TestSequenceMqttCallback callback = new TestSequenceMqttCallback(client, latch, result); |
125 | 127 | client.setCallback(callback); |
126 | 128 | client.subscribe(MqttTopics.DEVICE_RPC_REQUESTS_SUB_TOPIC, 1); |
127 | 129 | |
128 | - latch.await(30, TimeUnit.SECONDS); | |
130 | + latch.await(10, TimeUnit.SECONDS); | |
129 | 131 | Assert.assertEquals(expected, result); |
130 | 132 | } |
131 | 133 | |
... | ... | @@ -246,8 +248,7 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractM |
246 | 248 | |
247 | 249 | private final MqttAsyncClient client; |
248 | 250 | private final CountDownLatch latch; |
249 | - private final List<String> expected; | |
250 | - private Integer qoS; | |
251 | + private final List<String> expected; | |
251 | 252 | |
252 | 253 | TestSequenceMqttCallback(MqttAsyncClient client, CountDownLatch latch, List<String> expected) { |
253 | 254 | this.client = client; |
... | ... | @@ -255,10 +256,6 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractM |
255 | 256 | this.expected = expected; |
256 | 257 | } |
257 | 258 | |
258 | - int getQoS() { | |
259 | - return qoS; | |
260 | - } | |
261 | - | |
262 | 259 | @Override |
263 | 260 | public void connectionLost(Throwable throwable) { |
264 | 261 | } |
... | ... | @@ -268,7 +265,9 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractM |
268 | 265 | log.info("Message Arrived: " + Arrays.toString(mqttMessage.getPayload())); |
269 | 266 | expected.add(new String(mqttMessage.getPayload())); |
270 | 267 | String responseTopic = requestTopic.replace("request", "response"); |
271 | - qoS = mqttMessage.getQos(); | |
268 | + var qoS = mqttMessage.getQos(); | |
269 | + | |
270 | + client.messageArrivedComplete(mqttMessage.getId(), qoS); | |
272 | 271 | client.publish(responseTopic, processMessageArrived(requestTopic, mqttMessage)); |
273 | 272 | latch.countDown(); |
274 | 273 | } | ... | ... |
... | ... | @@ -334,6 +334,7 @@ message ToDeviceRpcRequestMsg { |
334 | 334 | int64 requestIdLSB = 6; |
335 | 335 | bool oneway = 7; |
336 | 336 | bool persisted = 8; |
337 | + int64 timeout = 9; | |
337 | 338 | } |
338 | 339 | |
339 | 340 | message ToDeviceRpcResponseMsg { |
... | ... | @@ -346,7 +347,7 @@ message UplinkNotificationMsg { |
346 | 347 | int64 uplinkTs = 1; |
347 | 348 | } |
348 | 349 | |
349 | -message ToDevicePersistedRpcResponseMsg { | |
350 | +message ToDeviceRpcResponseStatusMsg { | |
350 | 351 | int32 requestId = 1; |
351 | 352 | int64 requestIdMSB = 2; |
352 | 353 | int64 requestIdLSB = 3; |
... | ... | @@ -456,7 +457,7 @@ message TransportToDeviceActorMsg { |
456 | 457 | SubscriptionInfoProto subscriptionInfo = 7; |
457 | 458 | ClaimDeviceMsg claimDevice = 8; |
458 | 459 | ProvisionDeviceRequestMsg provisionDevice = 9; |
459 | - ToDevicePersistedRpcResponseMsg persistedRpcResponseMsg = 10; | |
460 | + ToDeviceRpcResponseStatusMsg rpcResponseStatusMsg = 10; | |
460 | 461 | SendPendingRPCMsg sendPendingRPC = 11; |
461 | 462 | UplinkNotificationMsg uplinkNotificationMsg = 12; |
462 | 463 | } | ... | ... |
... | ... | @@ -36,6 +36,8 @@ public class DataConstants { |
36 | 36 | public static final String ALARM_CONDITION_REPEATS = "alarmConditionRepeats"; |
37 | 37 | public static final String ALARM_CONDITION_DURATION = "alarmConditionDuration"; |
38 | 38 | public static final String PERSISTENT = "persistent"; |
39 | + public static final String TIMEOUT = "timeout"; | |
40 | + public static final String EXPIRATION_TIME = "expirationTime"; | |
39 | 41 | public static final String ADDITIONAL_INFO = "additionalInfo"; |
40 | 42 | public static final String COAP_TRANSPORT_NAME = "COAP"; |
41 | 43 | public static final String LWM2M_TRANSPORT_NAME = "LWM2M"; | ... | ... |
... | ... | @@ -34,6 +34,7 @@ public class ToDeviceRpcRequest implements Serializable { |
34 | 34 | private final DeviceId deviceId; |
35 | 35 | private final boolean oneway; |
36 | 36 | private final long expirationTime; |
37 | + private final long timeout; | |
37 | 38 | private final ToDeviceRpcRequestBody body; |
38 | 39 | private final boolean persisted; |
39 | 40 | @JsonIgnore | ... | ... |
... | ... | @@ -525,17 +525,26 @@ public class DefaultCoapClientContext implements CoapClientContext { |
525 | 525 | Response response = state.getAdaptor().convertToPublish(conRequest, msg, state.getConfiguration().getRpcRequestDynamicMessageBuilder()); |
526 | 526 | int requestId = getNextMsgId(); |
527 | 527 | response.setMID(requestId); |
528 | - if (msg.getPersisted() && conRequest) { | |
528 | + if (conRequest) { | |
529 | 529 | transportContext.getRpcAwaitingAck().put(requestId, msg); |
530 | 530 | transportContext.getScheduler().schedule(() -> { |
531 | - transportContext.getRpcAwaitingAck().remove(requestId); | |
532 | - }, Math.max(0, msg.getExpirationTime() - System.currentTimeMillis()), TimeUnit.MILLISECONDS); | |
531 | + TransportProtos.ToDeviceRpcRequestMsg rpcRequestMsg = transportContext.getRpcAwaitingAck().remove(requestId); | |
532 | + if (rpcRequestMsg != null) { | |
533 | + transportService.process(state.getSession(), msg, RpcStatus.TIMEOUT, TransportServiceCallback.EMPTY); | |
534 | + } | |
535 | + }, Math.max(0, Math.min(msg.getTimeout(), msg.getExpirationTime() - System.currentTimeMillis())), TimeUnit.MILLISECONDS); | |
536 | + | |
533 | 537 | response.addMessageObserver(new TbCoapMessageObserver(requestId, id -> { |
534 | 538 | TransportProtos.ToDeviceRpcRequestMsg rpcRequestMsg = transportContext.getRpcAwaitingAck().remove(id); |
535 | 539 | if (rpcRequestMsg != null) { |
536 | 540 | transportService.process(state.getSession(), rpcRequestMsg, RpcStatus.DELIVERED, TransportServiceCallback.EMPTY); |
537 | 541 | } |
538 | - }, null)); | |
542 | + }, id -> { | |
543 | + TransportProtos.ToDeviceRpcRequestMsg rpcRequestMsg = transportContext.getRpcAwaitingAck().remove(id); | |
544 | + if (rpcRequestMsg != null) { | |
545 | + transportService.process(state.getSession(), msg, RpcStatus.TIMEOUT, TransportServiceCallback.EMPTY); | |
546 | + } | |
547 | + })); | |
539 | 548 | } |
540 | 549 | if (conRequest) { |
541 | 550 | response.addMessageObserver(new TbCoapMessageObserver(requestId, id -> awake(state), id -> asleep(state))); |
... | ... | @@ -554,11 +563,11 @@ public class DefaultCoapClientContext implements CoapClientContext { |
554 | 563 | transportService.process(state.getSession(), |
555 | 564 | TransportProtos.ToDeviceRpcResponseMsg.newBuilder() |
556 | 565 | .setRequestId(msg.getRequestId()).setError(error).build(), TransportServiceCallback.EMPTY); |
557 | - } else if (msg.getPersisted() && sent) { | |
558 | - if (conRequest) { | |
559 | - transportService.process(state.getSession(), msg, RpcStatus.SENT, TransportServiceCallback.EMPTY); | |
560 | - } else { | |
566 | + } else if (sent) { | |
567 | + if (!conRequest) { | |
561 | 568 | transportService.process(state.getSession(), msg, RpcStatus.DELIVERED, TransportServiceCallback.EMPTY); |
569 | + } else if (msg.getPersisted()) { | |
570 | + transportService.process(state.getSession(), msg, RpcStatus.SENT, TransportServiceCallback.EMPTY); | |
562 | 571 | } |
563 | 572 | } |
564 | 573 | } | ... | ... |
... | ... | @@ -850,24 +850,27 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement |
850 | 850 | try { |
851 | 851 | deviceSessionCtx.getPayloadAdaptor().convertToPublish(deviceSessionCtx, rpcRequest).ifPresent(payload -> { |
852 | 852 | int msgId = ((MqttPublishMessage) payload).variableHeader().packetId(); |
853 | - if (rpcRequest.getPersisted() && isAckExpected(payload)) { | |
853 | + if (isAckExpected(payload)) { | |
854 | 854 | rpcAwaitingAck.put(msgId, rpcRequest); |
855 | 855 | context.getScheduler().schedule(() -> { |
856 | - rpcAwaitingAck.remove(msgId); | |
857 | - }, Math.max(0, rpcRequest.getExpirationTime() - System.currentTimeMillis()), TimeUnit.MILLISECONDS); | |
856 | + TransportProtos.ToDeviceRpcRequestMsg msg = rpcAwaitingAck.remove(msgId); | |
857 | + if (msg != null) { | |
858 | + transportService.process(deviceSessionCtx.getSessionInfo(), rpcRequest, RpcStatus.TIMEOUT, TransportServiceCallback.EMPTY); | |
859 | + } | |
860 | + }, Math.max(0, Math.min(rpcRequest.getTimeout(), rpcRequest.getExpirationTime() - System.currentTimeMillis())), TimeUnit.MILLISECONDS); | |
858 | 861 | } |
859 | 862 | var cf = publish(payload, deviceSessionCtx); |
860 | - if (rpcRequest.getPersisted()) { | |
861 | - cf.addListener(result -> { | |
862 | - if (result.cause() == null) { | |
863 | - if (isAckExpected(payload)) { | |
864 | - transportService.process(deviceSessionCtx.getSessionInfo(), rpcRequest, RpcStatus.SENT, TransportServiceCallback.EMPTY); | |
865 | - } else { | |
866 | - transportService.process(deviceSessionCtx.getSessionInfo(), rpcRequest, RpcStatus.DELIVERED, TransportServiceCallback.EMPTY); | |
867 | - } | |
863 | + cf.addListener(result -> { | |
864 | + if (result.cause() == null) { | |
865 | + if (!isAckExpected(payload)) { | |
866 | + transportService.process(deviceSessionCtx.getSessionInfo(), rpcRequest, RpcStatus.DELIVERED, TransportServiceCallback.EMPTY); | |
867 | + } else if (rpcRequest.getPersisted()) { | |
868 | + transportService.process(deviceSessionCtx.getSessionInfo(), rpcRequest, RpcStatus.SENT, TransportServiceCallback.EMPTY); | |
868 | 869 | } |
869 | - }); | |
870 | - } | |
870 | + } else { | |
871 | + // TODO: send error | |
872 | + } | |
873 | + }); | |
871 | 874 | }); |
872 | 875 | } catch (Exception e) { |
873 | 876 | transportService.process(deviceSessionCtx.getSessionInfo(), | ... | ... |
... | ... | @@ -581,19 +581,17 @@ public class DefaultTransportService implements TransportService { |
581 | 581 | |
582 | 582 | @Override |
583 | 583 | public void process(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.ToDeviceRpcRequestMsg msg, RpcStatus rpcStatus, TransportServiceCallback<Void> callback) { |
584 | - if (msg.getPersisted()) { | |
585 | - TransportProtos.ToDevicePersistedRpcResponseMsg responseMsg = TransportProtos.ToDevicePersistedRpcResponseMsg.newBuilder() | |
586 | - .setRequestId(msg.getRequestId()) | |
587 | - .setRequestIdLSB(msg.getRequestIdLSB()) | |
588 | - .setRequestIdMSB(msg.getRequestIdMSB()) | |
589 | - .setStatus(rpcStatus.name()) | |
590 | - .build(); | |
591 | - | |
592 | - if (checkLimits(sessionInfo, responseMsg, callback)) { | |
593 | - reportActivityInternal(sessionInfo); | |
594 | - sendToDeviceActor(sessionInfo, TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo).setPersistedRpcResponseMsg(responseMsg).build(), | |
595 | - new ApiStatsProxyCallback<>(getTenantId(sessionInfo), getCustomerId(sessionInfo), 1, TransportServiceCallback.EMPTY)); | |
596 | - } | |
584 | + TransportProtos.ToDeviceRpcResponseStatusMsg responseMsg = TransportProtos.ToDeviceRpcResponseStatusMsg.newBuilder() | |
585 | + .setRequestId(msg.getRequestId()) | |
586 | + .setRequestIdLSB(msg.getRequestIdLSB()) | |
587 | + .setRequestIdMSB(msg.getRequestIdMSB()) | |
588 | + .setStatus(rpcStatus.name()) | |
589 | + .build(); | |
590 | + | |
591 | + if (checkLimits(sessionInfo, responseMsg, callback)) { | |
592 | + reportActivityInternal(sessionInfo); | |
593 | + sendToDeviceActor(sessionInfo, TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo).setRpcResponseStatusMsg(responseMsg).build(), | |
594 | + new ApiStatsProxyCallback<>(getTenantId(sessionInfo), getCustomerId(sessionInfo), 1, TransportServiceCallback.EMPTY)); | |
597 | 595 | } |
598 | 596 | } |
599 | 597 | ... | ... |
... | ... | @@ -39,6 +39,7 @@ public final class RuleEngineDeviceRpcRequest { |
39 | 39 | private final String method; |
40 | 40 | private final String body; |
41 | 41 | private final long expirationTime; |
42 | + private final long timeout; | |
42 | 43 | private final boolean restApiCall; |
43 | 44 | private final String additionalInfo; |
44 | 45 | ... | ... |
... | ... | @@ -89,9 +89,12 @@ public class TbSendRPCRequestNode implements TbNode { |
89 | 89 | tmp = msg.getMetaData().getValue("originServiceId"); |
90 | 90 | String originServiceId = !StringUtils.isEmpty(tmp) ? tmp : null; |
91 | 91 | |
92 | - tmp = msg.getMetaData().getValue("expirationTime"); | |
92 | + tmp = msg.getMetaData().getValue(DataConstants.EXPIRATION_TIME); | |
93 | 93 | long expirationTime = !StringUtils.isEmpty(tmp) ? Long.parseLong(tmp) : (System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(config.getTimeoutInSeconds())); |
94 | 94 | |
95 | + tmp = msg.getMetaData().getValue(DataConstants.TIMEOUT); | |
96 | + long timeout = !StringUtils.isEmpty(tmp) ? Long.parseLong(tmp) : TimeUnit.SECONDS.toMillis(config.getTimeoutInSeconds()); | |
97 | + | |
95 | 98 | String params; |
96 | 99 | JsonElement paramsEl = json.get("params"); |
97 | 100 | if (paramsEl.isJsonPrimitive()) { |
... | ... | @@ -112,6 +115,7 @@ public class TbSendRPCRequestNode implements TbNode { |
112 | 115 | .requestUUID(requestUUID) |
113 | 116 | .originServiceId(originServiceId) |
114 | 117 | .expirationTime(expirationTime) |
118 | + .timeout(timeout) | |
115 | 119 | .restApiCall(restApiCall) |
116 | 120 | .persisted(persisted) |
117 | 121 | .additionalInfo(additionalInfo) | ... | ... |