Implementation of statistics counters

This commit is contained in:
Andrii Shvaika 2020-04-14 08:27:44 +03:00
parent 2e122d8626
commit 63bac58ae8
23 changed files with 189 additions and 381 deletions

View File

@ -159,10 +159,6 @@ public class ActorSystemContext {
@Getter @Getter
private TbClusterService clusterService; private TbClusterService clusterService;
@Autowired
@Getter
private TbQueueProducerProvider producerProvider;
@Autowired @Autowired
@Getter @Getter
private TimeseriesService tsService; private TimeseriesService tsService;

View File

@ -17,10 +17,8 @@ package org.thingsboard.server.actors.ruleChain;
import akka.actor.ActorRef; import akka.actor.ActorRef;
import com.datastax.driver.core.ResultSetFuture; import com.datastax.driver.core.ResultSetFuture;
import com.datastax.driver.core.utils.UUIDs;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.netty.channel.EventLoopGroup; import io.netty.channel.EventLoopGroup;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
@ -36,7 +34,6 @@ import org.thingsboard.server.actors.ActorSystemContext;
import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.DataConstants;
import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo;
import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.Alarm;
import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.asset.Asset;
import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityId;
@ -45,8 +42,8 @@ import org.thingsboard.server.common.data.id.RuleNodeId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.rule.RuleNode; import org.thingsboard.server.common.data.rule.RuleNode;
import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.TbMsgDataType;
import org.thingsboard.server.common.msg.TbMsgMetaData; import org.thingsboard.server.common.msg.TbMsgMetaData;
import org.thingsboard.server.common.msg.queue.ServiceType;
import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; import org.thingsboard.server.common.msg.queue.TopicPartitionInfo;
import org.thingsboard.server.dao.alarm.AlarmService; import org.thingsboard.server.dao.alarm.AlarmService;
import org.thingsboard.server.dao.asset.AssetService; import org.thingsboard.server.dao.asset.AssetService;
@ -62,11 +59,9 @@ import org.thingsboard.server.dao.rule.RuleChainService;
import org.thingsboard.server.dao.tenant.TenantService; import org.thingsboard.server.dao.tenant.TenantService;
import org.thingsboard.server.dao.timeseries.TimeseriesService; import org.thingsboard.server.dao.timeseries.TimeseriesService;
import org.thingsboard.server.dao.user.UserService; import org.thingsboard.server.dao.user.UserService;
import org.thingsboard.server.common.msg.queue.ServiceType;
import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.queue.TbQueueCallback; import org.thingsboard.server.queue.TbQueueCallback;
import org.thingsboard.server.queue.TbQueueMsgMetadata; import org.thingsboard.server.queue.TbQueueMsgMetadata;
import org.thingsboard.server.queue.common.TbProtoQueueMsg;
import org.thingsboard.server.service.script.RuleNodeJsScriptEngine; import org.thingsboard.server.service.script.RuleNodeJsScriptEngine;
import scala.concurrent.duration.Duration; import scala.concurrent.duration.Duration;
@ -136,7 +131,7 @@ class DefaultTbContext implements TbContext {
.setTenantIdMSB(getTenantId().getId().getMostSignificantBits()) .setTenantIdMSB(getTenantId().getId().getMostSignificantBits())
.setTenantIdLSB(getTenantId().getId().getLeastSignificantBits()) .setTenantIdLSB(getTenantId().getId().getLeastSignificantBits())
.setTbMsg(TbMsg.toByteString(tbMsg)).build(); .setTbMsg(TbMsg.toByteString(tbMsg)).build();
mainCtx.getProducerProvider().getRuleEngineMsgProducer().send(tpi, new TbProtoQueueMsg<>(tbMsg.getId(), msg), new SimpleTbQueueCallback(onSuccess, onFailure)); mainCtx.getClusterService().pushMsgToRuleEngine(tpi, tbMsg.getId(), msg, new SimpleTbQueueCallback(onSuccess, onFailure));
} }
@Override @Override
@ -193,7 +188,7 @@ class DefaultTbContext implements TbContext {
if (failureMessage != null) { if (failureMessage != null) {
msg.setFailureMessage(failureMessage); msg.setFailureMessage(failureMessage);
} }
mainCtx.getProducerProvider().getRuleEngineMsgProducer().send(tpi, new TbProtoQueueMsg<>(tbMsg.getId(), msg.build()), new SimpleTbQueueCallback(onSuccess, onFailure)); mainCtx.getClusterService().pushMsgToRuleEngine(tpi, tbMsg.getId(), msg.build(), new SimpleTbQueueCallback(onSuccess, onFailure));
} }
@Override @Override

View File

@ -44,10 +44,9 @@ import org.thingsboard.server.common.msg.queue.TopicPartitionInfo;
import org.thingsboard.server.dao.rule.RuleChainService; import org.thingsboard.server.dao.rule.RuleChainService;
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg;
import org.thingsboard.server.queue.TbQueueCallback; import org.thingsboard.server.queue.TbQueueCallback;
import org.thingsboard.server.queue.TbQueueProducer;
import org.thingsboard.server.queue.common.MultipleTbQueueTbMsgCallbackWrapper; import org.thingsboard.server.queue.common.MultipleTbQueueTbMsgCallbackWrapper;
import org.thingsboard.server.queue.common.TbProtoQueueMsg;
import org.thingsboard.server.queue.common.TbQueueTbMsgCallbackWrapper; import org.thingsboard.server.queue.common.TbQueueTbMsgCallbackWrapper;
import org.thingsboard.server.service.queue.TbClusterService;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -68,7 +67,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
private final Map<RuleNodeId, RuleNodeCtx> nodeActors; private final Map<RuleNodeId, RuleNodeCtx> nodeActors;
private final Map<RuleNodeId, List<RuleNodeRelation>> nodeRoutes; private final Map<RuleNodeId, List<RuleNodeRelation>> nodeRoutes;
private final RuleChainService service; private final RuleChainService service;
private final TbQueueProducer<TbProtoQueueMsg<ToRuleEngineMsg>> producer; private final TbClusterService clusterService;
private String ruleChainName; private String ruleChainName;
private RuleNodeId firstId; private RuleNodeId firstId;
@ -84,7 +83,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
this.nodeActors = new HashMap<>(); this.nodeActors = new HashMap<>();
this.nodeRoutes = new HashMap<>(); this.nodeRoutes = new HashMap<>();
this.service = systemContext.getRuleChainService(); this.service = systemContext.getRuleChainService();
this.producer = systemContext.getProducerProvider().getRuleEngineMsgProducer(); this.clusterService = systemContext.getClusterService();
} }
@Override @Override
@ -255,7 +254,6 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
msg.getCallback().onFailure(new RuleNodeException(failureMessage, ruleChainName, ruleNodeCtx.getSelf())); msg.getCallback().onFailure(new RuleNodeException(failureMessage, ruleChainName, ruleNodeCtx.getSelf()));
} else { } else {
log.debug("[{}] Failure during message processing by Rule Node [{}]. Enable and see debug events for more info", entityId, originatorNodeId.getId()); log.debug("[{}] Failure during message processing by Rule Node [{}]. Enable and see debug events for more info", entityId, originatorNodeId.getId());
//TODO 2.5: Introduce our own RuleEngineFailureException to track what is wrong
msg.getCallback().onFailure(new RuleEngineException("Failure during message processing by Rule Node [" + originatorNodeId.getId().toString() + "]")); msg.getCallback().onFailure(new RuleEngineException("Failure during message processing by Rule Node [" + originatorNodeId.getId().toString() + "]"));
} }
} else { } else {
@ -311,7 +309,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
.setTenantIdLSB(tenantId.getId().getLeastSignificantBits()) .setTenantIdLSB(tenantId.getId().getLeastSignificantBits())
.setTbMsg(TbMsg.toByteString(newMsg)) .setTbMsg(TbMsg.toByteString(newMsg))
.build(); .build();
producer.send(tpi, new TbProtoQueueMsg<>(newMsg.getId(), toQueueMsg), callbackWrapper); clusterService.pushMsgToRuleEngine(tpi, newMsg.getId(), toQueueMsg, callbackWrapper);
} }
private boolean contains(Set<String> relationTypes, String type) { private boolean contains(Set<String> relationTypes, String type) {

View File

@ -97,96 +97,4 @@ public class DefaultActorService implements ActorService {
} }
} }
@Value("${cluster.stats.enabled:false}")
private boolean statsEnabled;
//TODO 2.5
private final AtomicInteger sentClusterMsgs = new AtomicInteger(0);
private final AtomicInteger receivedClusterMsgs = new AtomicInteger(0);
@Scheduled(fixedDelayString = "${cluster.stats.print_interval_ms}")
public void printStats() {
if (statsEnabled) {
int sent = sentClusterMsgs.getAndSet(0);
int received = receivedClusterMsgs.getAndSet(0);
if (sent > 0 || received > 0) {
log.info("Cluster msgs sent [{}] received [{}]", sent, received);
}
}
}
//TODO 2.5
// @Override
// public void onReceivedMsg(ServerAddress source, ClusterAPIProtos.ClusterMessage msg) {
// if (statsEnabled) {
// receivedClusterMsgs.incrementAndGet();
// }
// ServerAddress serverAddress = new ServerAddress(source.getHost(), source.getPort(), source.getServerType());
// if (log.isDebugEnabled()) {
// log.info("Received msg [{}] from [{}]", msg.getMessageType().name(), serverAddress);
// log.info("MSG: {}", msg);
// }
// switch (msg.getMessageType()) {
// case CLUSTER_ACTOR_MESSAGE:
// java.util.Optional<TbActorMsg> decodedMsg = actorContext.getEncodingService()
// .decode(msg.getPayload().toByteArray());
// if (decodedMsg.isPresent()) {
// appActor.tell(decodedMsg.get(), ActorRef.noSender());
// } else {
// log.error("Error during decoding cluster proto message");
// }
// break;
// case TO_ALL_NODES_MSG:
// //TODO
// break;
// case CLUSTER_TELEMETRY_SUBSCRIPTION_CREATE_MESSAGE:
// actorContext.getTsSubService().onNewRemoteSubscription(serverAddress, msg.getPayload().toByteArray());
// break;
// case CLUSTER_TELEMETRY_SUBSCRIPTION_UPDATE_MESSAGE:
// actorContext.getTsSubService().onRemoteSubscriptionUpdate(serverAddress, msg.getPayload().toByteArray());
// break;
// case CLUSTER_TELEMETRY_SUBSCRIPTION_CLOSE_MESSAGE:
// actorContext.getTsSubService().onRemoteSubscriptionClose(serverAddress, msg.getPayload().toByteArray());
// break;
// case CLUSTER_TELEMETRY_SESSION_CLOSE_MESSAGE:
// actorContext.getTsSubService().onRemoteSessionClose(serverAddress, msg.getPayload().toByteArray());
// break;
// case CLUSTER_TELEMETRY_ATTR_UPDATE_MESSAGE:
// actorContext.getTsSubService().onRemoteAttributesUpdate(serverAddress, msg.getPayload().toByteArray());
// break;
// case CLUSTER_TELEMETRY_TS_UPDATE_MESSAGE:
// actorContext.getTsSubService().onRemoteTsUpdate(serverAddress, msg.getPayload().toByteArray());
// break;
// case CLUSTER_RPC_FROM_DEVICE_RESPONSE_MESSAGE:
// actorContext.getDeviceRpcService().processResponseToServerSideRPCRequestFromRemoteServer(serverAddress, msg.getPayload().toByteArray());
// break;
// case CLUSTER_DEVICE_STATE_SERVICE_MESSAGE:
// actorContext.getDeviceStateService().onRemoteMsg(serverAddress, msg.getPayload().toByteArray());
// break;
// case CLUSTER_TRANSACTION_SERVICE_MESSAGE:
// actorContext.getRuleChainTransactionService().onRemoteTransactionMsg(serverAddress, msg.getPayload().toByteArray());
// break;
// }
// }
// @Override
// public void onSendMsg(ClusterAPIProtos.ClusterMessage msg) {
// if (statsEnabled) {
// sentClusterMsgs.incrementAndGet();
// }
// rpcManagerActor.tell(msg, ActorRef.noSender());
// }
//
// @Override
// public void onRpcSessionCreateRequestMsg(RpcSessionCreateRequestMsg msg) {
// if (statsEnabled) {
// sentClusterMsgs.incrementAndGet();
// }
// rpcManagerActor.tell(msg, ActorRef.noSender());
// }
// @Override
// public void onBroadcastMsg(RpcBroadcastMsg msg) {
// rpcManagerActor.tell(msg, ActorRef.noSender());
// }
} }

View File

@ -15,7 +15,6 @@
*/ */
package org.thingsboard.server.controller; package org.thingsboard.server.controller;
import com.datastax.driver.core.utils.UUIDs;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.ObjectNode;
@ -668,7 +667,7 @@ public abstract class BaseController {
} }
} }
TbMsg tbMsg = TbMsg.newMsg(msgType, entityId, metaData, TbMsgDataType.JSON, json.writeValueAsString(entityNode)); TbMsg tbMsg = TbMsg.newMsg(msgType, entityId, metaData, TbMsgDataType.JSON, json.writeValueAsString(entityNode));
tbClusterService.onToRuleEngineMsg(user.getTenantId(), entityId, tbMsg); tbClusterService.pushMsgToRuleEngine(user.getTenantId(), entityId, tbMsg, null);
} catch (Exception e) { } catch (Exception e) {
log.warn("[{}] Failed to push entity action to rule engine: {}", entityId, actionType, e); log.warn("[{}] Failed to push entity action to rule engine: {}", entityId, actionType, e);
} }

View File

@ -99,8 +99,8 @@ public class DeviceController extends BaseController {
Device savedDevice = checkNotNull(deviceService.saveDeviceWithAccessToken(device, accessToken)); Device savedDevice = checkNotNull(deviceService.saveDeviceWithAccessToken(device, accessToken));
tbClusterService.onToCoreMsg(new DeviceNameOrTypeUpdateMsg(savedDevice.getTenantId(), tbClusterService.pushMsgToCore(new DeviceNameOrTypeUpdateMsg(savedDevice.getTenantId(),
savedDevice.getId(), savedDevice.getName(), savedDevice.getType())); savedDevice.getId(), savedDevice.getName(), savedDevice.getType()), null);
logEntityAction(savedDevice.getId(), savedDevice, logEntityAction(savedDevice.getId(), savedDevice,
savedDevice.getCustomerId(), savedDevice.getCustomerId(),
@ -254,7 +254,7 @@ public class DeviceController extends BaseController {
Device device = checkDeviceId(deviceCredentials.getDeviceId(), Operation.WRITE_CREDENTIALS); Device device = checkDeviceId(deviceCredentials.getDeviceId(), Operation.WRITE_CREDENTIALS);
DeviceCredentials result = checkNotNull(deviceCredentialsService.updateDeviceCredentials(getCurrentUser().getTenantId(), deviceCredentials)); DeviceCredentials result = checkNotNull(deviceCredentialsService.updateDeviceCredentials(getCurrentUser().getTenantId(), deviceCredentials));
tbClusterService.onToCoreMsg(new DeviceCredentialsUpdateNotificationMsg(getCurrentUser().getTenantId(), deviceCredentials.getDeviceId())); tbClusterService.pushMsgToCore(new DeviceCredentialsUpdateNotificationMsg(getCurrentUser().getTenantId(), deviceCredentials.getDeviceId()), null);
logEntityAction(device.getId(), device, logEntityAction(device.getId(), device,
device.getCustomerId(), device.getCustomerId(),

View File

@ -364,8 +364,8 @@ public class TelemetryController extends BaseController {
DeviceId deviceId = new DeviceId(entityId.getId()); DeviceId deviceId = new DeviceId(entityId.getId());
Set<AttributeKey> keysToNotify = new HashSet<>(); Set<AttributeKey> keysToNotify = new HashSet<>();
keys.forEach(key -> keysToNotify.add(new AttributeKey(scope, key))); keys.forEach(key -> keysToNotify.add(new AttributeKey(scope, key)));
tbClusterService.onToCoreMsg(DeviceAttributesEventNotificationMsg.onDelete( tbClusterService.pushMsgToCore(DeviceAttributesEventNotificationMsg.onDelete(
user.getTenantId(), deviceId, keysToNotify)); user.getTenantId(), deviceId, keysToNotify), null);
} }
result.setResult(new ResponseEntity<>(HttpStatus.OK)); result.setResult(new ResponseEntity<>(HttpStatus.OK));
} }
@ -399,8 +399,8 @@ public class TelemetryController extends BaseController {
logAttributesUpdated(user, entityId, scope, attributes, null); logAttributesUpdated(user, entityId, scope, attributes, null);
if (entityId.getEntityType() == EntityType.DEVICE) { if (entityId.getEntityType() == EntityType.DEVICE) {
DeviceId deviceId = new DeviceId(entityId.getId()); DeviceId deviceId = new DeviceId(entityId.getId());
tbClusterService.onToCoreMsg(DeviceAttributesEventNotificationMsg.onUpdate( tbClusterService.pushMsgToCore(DeviceAttributesEventNotificationMsg.onUpdate(
user.getTenantId(), deviceId, scope, attributes)); user.getTenantId(), deviceId, scope, attributes), null);
} }
result.setResult(new ResponseEntity(HttpStatus.OK)); result.setResult(new ResponseEntity(HttpStatus.OK));
} }

View File

@ -17,6 +17,8 @@ package org.thingsboard.server.service.queue;
import com.google.protobuf.ByteString; import com.google.protobuf.ByteString;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.thingsboard.rule.engine.api.msg.ToDeviceActorNotificationMsg; import org.thingsboard.rule.engine.api.msg.ToDeviceActorNotificationMsg;
import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.EntityType;
@ -27,7 +29,13 @@ import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg;
import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.common.msg.queue.ServiceType;
import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; import org.thingsboard.server.common.msg.queue.TopicPartitionInfo;
import org.thingsboard.server.gen.transport.TransportProtos.*; import org.thingsboard.server.gen.transport.TransportProtos.FromDeviceRPCResponseProto;
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg;
import org.thingsboard.server.queue.TbQueueCallback;
import org.thingsboard.server.queue.TbQueueProducer; import org.thingsboard.server.queue.TbQueueProducer;
import org.thingsboard.server.queue.common.TbProtoQueueMsg; import org.thingsboard.server.queue.common.TbProtoQueueMsg;
import org.thingsboard.server.queue.discovery.PartitionService; import org.thingsboard.server.queue.discovery.PartitionService;
@ -38,12 +46,22 @@ import org.thingsboard.server.service.rpc.FromDeviceRpcResponse;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
@Service @Service
@Slf4j @Slf4j
public class DefaultTbClusterService implements TbClusterService { public class DefaultTbClusterService implements TbClusterService {
protected TbQueueProducerProvider producerProvider; @Value("${cluster.stats.enabled:false}")
private boolean statsEnabled;
private final AtomicInteger toCoreMsgs = new AtomicInteger(0);
private final AtomicInteger toCoreNfs = new AtomicInteger(0);
private final AtomicInteger toRuleEngineMsgs = new AtomicInteger(0);
private final AtomicInteger toRuleEngineNfs = new AtomicInteger(0);
private final AtomicInteger toTransportNfs = new AtomicInteger(0);
private final TbQueueProducerProvider producerProvider;
private final PartitionService partitionService; private final PartitionService partitionService;
private final DataDecodingEncodingService encodingService; private final DataDecodingEncodingService encodingService;
@ -54,7 +72,48 @@ public class DefaultTbClusterService implements TbClusterService {
} }
@Override @Override
public void onToRuleEngineMsg(TenantId tenantId, EntityId entityId, TbMsg tbMsg) { public void pushMsgToCore(TenantId tenantId, EntityId entityId, ToCoreMsg msg, TbQueueCallback callback) {
TopicPartitionInfo tpi = partitionService.resolve(ServiceType.TB_CORE, tenantId, entityId);
producerProvider.getTbCoreMsgProducer().send(tpi, new TbProtoQueueMsg<>(UUID.randomUUID(), msg), callback);
toCoreMsgs.incrementAndGet();
}
@Override
public void pushMsgToCore(TopicPartitionInfo tpi, UUID msgId, ToCoreMsg msg, TbQueueCallback callback) {
producerProvider.getTbCoreMsgProducer().send(tpi, new TbProtoQueueMsg<>(msgId, msg), callback);
toCoreMsgs.incrementAndGet();
}
@Override
public void pushMsgToCore(ToDeviceActorNotificationMsg msg, TbQueueCallback callback) {
TopicPartitionInfo tpi = partitionService.resolve(ServiceType.TB_CORE, msg.getTenantId(), msg.getDeviceId());
byte[] msgBytes = encodingService.encode(msg);
ToCoreMsg toCoreMsg = ToCoreMsg.newBuilder().setToDeviceActorNotificationMsg(ByteString.copyFrom(msgBytes)).build();
producerProvider.getTbCoreMsgProducer().send(tpi, new TbProtoQueueMsg<>(msg.getDeviceId().getId(), toCoreMsg), callback);
toCoreMsgs.incrementAndGet();
}
@Override
public void pushNotificationToCore(String serviceId, FromDeviceRpcResponse response, TbQueueCallback callback) {
TopicPartitionInfo tpi = partitionService.getNotificationsTopic(ServiceType.TB_CORE, serviceId);
FromDeviceRPCResponseProto.Builder builder = FromDeviceRPCResponseProto.newBuilder()
.setRequestIdMSB(response.getId().getMostSignificantBits())
.setRequestIdLSB(response.getId().getLeastSignificantBits())
.setError(response.getError().isPresent() ? response.getError().get().ordinal() : -1);
response.getResponse().ifPresent(builder::setResponse);
ToCoreNotificationMsg msg = ToCoreNotificationMsg.newBuilder().setFromDeviceRpcResponse(builder).build();
producerProvider.getTbCoreNotificationsMsgProducer().send(tpi, new TbProtoQueueMsg<>(response.getId(), msg), callback);
toCoreNfs.incrementAndGet();
}
@Override
public void pushMsgToRuleEngine(TopicPartitionInfo tpi, UUID msgId, ToRuleEngineMsg msg, TbQueueCallback callback) {
producerProvider.getRuleEngineMsgProducer().send(tpi, new TbProtoQueueMsg<>(msgId, msg), callback);
toRuleEngineMsgs.incrementAndGet();
}
@Override
public void pushMsgToRuleEngine(TenantId tenantId, EntityId entityId, TbMsg tbMsg, TbQueueCallback callback) {
if (tenantId.isNullUid()) { if (tenantId.isNullUid()) {
if (entityId.getEntityType().equals(EntityType.TENANT)) { if (entityId.getEntityType().equals(EntityType.TENANT)) {
tenantId = new TenantId(entityId.getId()); tenantId = new TenantId(entityId.getId());
@ -68,31 +127,12 @@ public class DefaultTbClusterService implements TbClusterService {
.setTenantIdMSB(tenantId.getId().getMostSignificantBits()) .setTenantIdMSB(tenantId.getId().getMostSignificantBits())
.setTenantIdLSB(tenantId.getId().getLeastSignificantBits()) .setTenantIdLSB(tenantId.getId().getLeastSignificantBits())
.setTbMsg(TbMsg.toByteString(tbMsg)).build(); .setTbMsg(TbMsg.toByteString(tbMsg)).build();
producerProvider.getRuleEngineMsgProducer().send(tpi, new TbProtoQueueMsg<>(tbMsg.getId(), msg), null); producerProvider.getRuleEngineMsgProducer().send(tpi, new TbProtoQueueMsg<>(tbMsg.getId(), msg), callback);
toRuleEngineMsgs.incrementAndGet();
} }
@Override @Override
public void onToCoreMsg(ToDeviceActorNotificationMsg msg) { public void pushNotificationToRuleEngine(String serviceId, FromDeviceRpcResponse response, TbQueueCallback callback) {
TopicPartitionInfo tpi = partitionService.resolve(ServiceType.TB_CORE, msg.getTenantId(), msg.getDeviceId());
byte[] msgBytes = encodingService.encode(msg);
ToCoreMsg toCoreMsg = ToCoreMsg.newBuilder().setToDeviceActorNotificationMsg(ByteString.copyFrom(msgBytes)).build();
producerProvider.getTbCoreMsgProducer().send(tpi, new TbProtoQueueMsg<>(msg.getDeviceId().getId(), toCoreMsg), null);
}
@Override
public void onToCoreMsg(String serviceId, FromDeviceRpcResponse response) {
TopicPartitionInfo tpi = partitionService.getNotificationsTopic(ServiceType.TB_CORE, serviceId);
FromDeviceRPCResponseProto.Builder builder = FromDeviceRPCResponseProto.newBuilder()
.setRequestIdMSB(response.getId().getMostSignificantBits())
.setRequestIdLSB(response.getId().getLeastSignificantBits())
.setError(response.getError().isPresent() ? response.getError().get().ordinal() : -1);
response.getResponse().ifPresent(builder::setResponse);
ToCoreNotificationMsg msg = ToCoreNotificationMsg.newBuilder().setFromDeviceRpcResponse(builder).build();
producerProvider.getTbCoreNotificationsMsgProducer().send(tpi, new TbProtoQueueMsg<>(response.getId(), msg), null);
}
@Override
public void onToRuleEngineMsg(String serviceId, FromDeviceRpcResponse response) {
TopicPartitionInfo tpi = partitionService.getNotificationsTopic(ServiceType.TB_RULE_ENGINE, serviceId); TopicPartitionInfo tpi = partitionService.getNotificationsTopic(ServiceType.TB_RULE_ENGINE, serviceId);
FromDeviceRPCResponseProto.Builder builder = FromDeviceRPCResponseProto.newBuilder() FromDeviceRPCResponseProto.Builder builder = FromDeviceRPCResponseProto.newBuilder()
.setRequestIdMSB(response.getId().getMostSignificantBits()) .setRequestIdMSB(response.getId().getMostSignificantBits())
@ -100,13 +140,15 @@ public class DefaultTbClusterService implements TbClusterService {
.setError(response.getError().isPresent() ? response.getError().get().ordinal() : -1); .setError(response.getError().isPresent() ? response.getError().get().ordinal() : -1);
response.getResponse().ifPresent(builder::setResponse); response.getResponse().ifPresent(builder::setResponse);
ToRuleEngineNotificationMsg msg = ToRuleEngineNotificationMsg.newBuilder().setFromDeviceRpcResponse(builder).build(); ToRuleEngineNotificationMsg msg = ToRuleEngineNotificationMsg.newBuilder().setFromDeviceRpcResponse(builder).build();
producerProvider.getRuleEngineNotificationsMsgProducer().send(tpi, new TbProtoQueueMsg<>(response.getId(), msg), null); producerProvider.getRuleEngineNotificationsMsgProducer().send(tpi, new TbProtoQueueMsg<>(response.getId(), msg), callback);
toRuleEngineNfs.incrementAndGet();
} }
@Override @Override
public void onToTransportMsg(String serviceId, ToTransportMsg response) { public void pushNotificationToTransport(String serviceId, ToTransportMsg response, TbQueueCallback callback) {
TopicPartitionInfo tpi = partitionService.getNotificationsTopic(ServiceType.TB_TRANSPORT, serviceId); TopicPartitionInfo tpi = partitionService.getNotificationsTopic(ServiceType.TB_TRANSPORT, serviceId);
producerProvider.getTransportNotificationsMsgProducer().send(tpi, new TbProtoQueueMsg<>(UUID.randomUUID(), response), null); producerProvider.getTransportNotificationsMsgProducer().send(tpi, new TbProtoQueueMsg<>(UUID.randomUUID(), response), callback);
toTransportNfs.incrementAndGet();
} }
@Override @Override
@ -120,12 +162,13 @@ public class DefaultTbClusterService implements TbClusterService {
TbQueueProducer<TbProtoQueueMsg<ToRuleEngineNotificationMsg>> toRuleEngineProducer = producerProvider.getRuleEngineNotificationsMsgProducer(); TbQueueProducer<TbProtoQueueMsg<ToRuleEngineNotificationMsg>> toRuleEngineProducer = producerProvider.getRuleEngineNotificationsMsgProducer();
Set<String> tbRuleEngineServices = new HashSet<>(partitionService.getAllServiceIds(ServiceType.TB_RULE_ENGINE)); Set<String> tbRuleEngineServices = new HashSet<>(partitionService.getAllServiceIds(ServiceType.TB_RULE_ENGINE));
if (msg.getEntityId().getEntityType().equals(EntityType.TENANT)) { if (msg.getEntityId().getEntityType().equals(EntityType.TENANT)) {
TbQueueProducer<TbProtoQueueMsg<ToCoreNotificationMsg>> toCoreProducer = producerProvider.getTbCoreNotificationsMsgProducer(); TbQueueProducer<TbProtoQueueMsg<ToCoreNotificationMsg>> toCoreNfProducer = producerProvider.getTbCoreNotificationsMsgProducer();
Set<String> tbCoreServices = partitionService.getAllServiceIds(ServiceType.TB_CORE); Set<String> tbCoreServices = partitionService.getAllServiceIds(ServiceType.TB_CORE);
for (String serviceId : tbCoreServices) { for (String serviceId : tbCoreServices) {
TopicPartitionInfo tpi = partitionService.getNotificationsTopic(ServiceType.TB_CORE, serviceId); TopicPartitionInfo tpi = partitionService.getNotificationsTopic(ServiceType.TB_CORE, serviceId);
ToCoreNotificationMsg toCoreMsg = ToCoreNotificationMsg.newBuilder().setComponentLifecycleMsg(ByteString.copyFrom(msgBytes)).build(); ToCoreNotificationMsg toCoreMsg = ToCoreNotificationMsg.newBuilder().setComponentLifecycleMsg(ByteString.copyFrom(msgBytes)).build();
toCoreProducer.send(tpi, new TbProtoQueueMsg<>(msg.getEntityId().getId(), toCoreMsg), null); toCoreNfProducer.send(tpi, new TbProtoQueueMsg<>(msg.getEntityId().getId(), toCoreMsg), null);
toCoreNfs.incrementAndGet();
} }
// No need to push notifications twice // No need to push notifications twice
tbRuleEngineServices.removeAll(tbCoreServices); tbRuleEngineServices.removeAll(tbCoreServices);
@ -134,6 +177,22 @@ public class DefaultTbClusterService implements TbClusterService {
TopicPartitionInfo tpi = partitionService.getNotificationsTopic(ServiceType.TB_RULE_ENGINE, serviceId); TopicPartitionInfo tpi = partitionService.getNotificationsTopic(ServiceType.TB_RULE_ENGINE, serviceId);
ToRuleEngineNotificationMsg toRuleEngineMsg = ToRuleEngineNotificationMsg.newBuilder().setComponentLifecycleMsg(ByteString.copyFrom(msgBytes)).build(); ToRuleEngineNotificationMsg toRuleEngineMsg = ToRuleEngineNotificationMsg.newBuilder().setComponentLifecycleMsg(ByteString.copyFrom(msgBytes)).build();
toRuleEngineProducer.send(tpi, new TbProtoQueueMsg<>(msg.getEntityId().getId(), toRuleEngineMsg), null); toRuleEngineProducer.send(tpi, new TbProtoQueueMsg<>(msg.getEntityId().getId(), toRuleEngineMsg), null);
toRuleEngineNfs.incrementAndGet();
}
}
@Scheduled(fixedDelayString = "${cluster.stats.print_interval_ms}")
public void printStats() {
if (statsEnabled) {
int toCoreMsgCnt = toCoreMsgs.getAndSet(0);
int toCoreNfsCnt = toCoreNfs.getAndSet(0);
int toRuleEngineMsgsCnt = toRuleEngineMsgs.getAndSet(0);
int toRuleEngineNfsCnt = toRuleEngineNfs.getAndSet(0);
int toTransportNfsCnt = toTransportNfs.getAndSet(0);
if (toCoreMsgCnt > 0 || toCoreNfsCnt > 0 || toRuleEngineMsgsCnt > 0 || toRuleEngineNfsCnt > 0 || toTransportNfsCnt > 0) {
log.info("To TbCore: [{}] messages [{}] notifications; To TbRuleEngine: [{}] messages [{}] notifications; To Transport: [{}] notifications",
toCoreMsgCnt, toCoreNfsCnt, toRuleEngineMsgsCnt, toRuleEngineNfsCnt, toTransportNfsCnt);
}
} }
} }
} }

View File

@ -183,21 +183,24 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore
@Override @Override
protected void handleNotification(UUID id, TbProtoQueueMsg<ToCoreNotificationMsg> msg, TbCallback callback) { protected void handleNotification(UUID id, TbProtoQueueMsg<ToCoreNotificationMsg> msg, TbCallback callback) {
ToCoreNotificationMsg toCoreMsg = msg.getValue(); ToCoreNotificationMsg toCoreNotification = msg.getValue();
if (toCoreMsg.hasToLocalSubscriptionServiceMsg()) { if (toCoreNotification.hasToLocalSubscriptionServiceMsg()) {
log.trace("[{}] Forwarding message to local subscription service {}", id, toCoreMsg.getToLocalSubscriptionServiceMsg()); log.trace("[{}] Forwarding message to local subscription service {}", id, toCoreNotification.getToLocalSubscriptionServiceMsg());
forwardToLocalSubMgrService(toCoreMsg.getToLocalSubscriptionServiceMsg(), callback); forwardToLocalSubMgrService(toCoreNotification.getToLocalSubscriptionServiceMsg(), callback);
} else if (toCoreMsg.hasFromDeviceRpcResponse()) { } else if (toCoreNotification.hasFromDeviceRpcResponse()) {
log.trace("[{}] Forwarding message to RPC service {}", id, toCoreMsg.getFromDeviceRpcResponse()); log.trace("[{}] Forwarding message to RPC service {}", id, toCoreNotification.getFromDeviceRpcResponse());
forwardToCoreRpcService(toCoreMsg.getFromDeviceRpcResponse(), callback); forwardToCoreRpcService(toCoreNotification.getFromDeviceRpcResponse(), callback);
} else if (toCoreMsg.getComponentLifecycleMsg() != null && !toCoreMsg.getComponentLifecycleMsg().isEmpty()) { } else if (toCoreNotification.getComponentLifecycleMsg() != null && !toCoreNotification.getComponentLifecycleMsg().isEmpty()) {
Optional<TbActorMsg> actorMsg = encodingService.decode(toCoreMsg.getComponentLifecycleMsg().toByteArray()); Optional<TbActorMsg> actorMsg = encodingService.decode(toCoreNotification.getComponentLifecycleMsg().toByteArray());
if (actorMsg.isPresent()) { if (actorMsg.isPresent()) {
log.trace("[{}] Forwarding message to App Actor {}", id, actorMsg.get()); log.trace("[{}] Forwarding message to App Actor {}", id, actorMsg.get());
actorContext.tell(actorMsg.get(), ActorRef.noSender()); actorContext.tell(actorMsg.get(), ActorRef.noSender());
} }
callback.onSuccess(); callback.onSuccess();
} }
if (statsEnabled) {
stats.log(toCoreNotification);
}
} }
private void forwardToCoreRpcService(FromDeviceRPCResponseProto proto, TbCallback callback) { private void forwardToCoreRpcService(FromDeviceRPCResponseProto proto, TbCallback callback) {
@ -246,6 +249,9 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore
} else { } else {
throwNotHandled(msg, callback); throwNotHandled(msg, callback);
} }
if (statsEnabled) {
stats.log(msg);
}
} }
private void forwardToStateService(DeviceStateServiceMsgProto deviceStateServiceMsg, TbCallback callback) { private void forwardToStateService(DeviceStateServiceMsgProto deviceStateServiceMsg, TbCallback callback) {

View File

@ -20,20 +20,32 @@ import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;
import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.queue.TopicPartitionInfo;
import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg;
import org.thingsboard.server.queue.TbQueueCallback;
import org.thingsboard.server.service.rpc.FromDeviceRpcResponse; import org.thingsboard.server.service.rpc.FromDeviceRpcResponse;
import java.util.UUID;
public interface TbClusterService { public interface TbClusterService {
void onToRuleEngineMsg(TenantId tenantId, EntityId entityId, TbMsg msg); void pushMsgToCore(TopicPartitionInfo tpi, UUID msgKey, ToCoreMsg msg, TbQueueCallback callback);
void onToCoreMsg(ToDeviceActorNotificationMsg msg); void pushMsgToCore(TenantId tenantId, EntityId entityId, ToCoreMsg msg, TbQueueCallback callback);
void onToCoreMsg(String targetServiceId, FromDeviceRpcResponse response); void pushMsgToCore(ToDeviceActorNotificationMsg msg, TbQueueCallback callback);
void onToRuleEngineMsg(String targetServiceId, FromDeviceRpcResponse response); void pushNotificationToCore(String targetServiceId, FromDeviceRpcResponse response, TbQueueCallback callback);
void onToTransportMsg(String targetServiceId, ToTransportMsg response); void pushMsgToRuleEngine(TopicPartitionInfo tpi, UUID msgId, TransportProtos.ToRuleEngineMsg msg, TbQueueCallback callback);
void pushMsgToRuleEngine(TenantId tenantId, EntityId entityId, TbMsg msg, TbQueueCallback callback);
void pushNotificationToRuleEngine(String targetServiceId, FromDeviceRpcResponse response, TbQueueCallback callback);
void pushNotificationToTransport(String targetServiceId, ToTransportMsg response, TbQueueCallback callback);
void onEntityStateChange(TenantId tenantId, EntityId entityId, ComponentLifecycleEvent state); void onEntityStateChange(TenantId tenantId, EntityId entityId, ComponentLifecycleEvent state);

View File

@ -32,6 +32,10 @@ public class TbCoreConsumerStats {
private final AtomicInteger subscriptionInfoCounter = new AtomicInteger(0); private final AtomicInteger subscriptionInfoCounter = new AtomicInteger(0);
private final AtomicInteger claimDeviceCounter = new AtomicInteger(0); private final AtomicInteger claimDeviceCounter = new AtomicInteger(0);
private final AtomicInteger deviceStateCounter = new AtomicInteger(0);
private final AtomicInteger subscriptionMsgCounter = new AtomicInteger(0);
private final AtomicInteger toCoreNotificationsCounter = new AtomicInteger(0);
public void log(TransportProtos.TransportToDeviceActorMsg msg) { public void log(TransportProtos.TransportToDeviceActorMsg msg) {
totalCounter.incrementAndGet(); totalCounter.incrementAndGet();
if (msg.hasSessionEvent()) { if (msg.hasSessionEvent()) {
@ -57,18 +61,31 @@ public class TbCoreConsumerStats {
} }
} }
public void log(TransportProtos.DeviceStateServiceMsgProto deviceStateServiceMsg) { public void log(TransportProtos.DeviceStateServiceMsgProto msg) {
//TODO 2.5 totalCounter.incrementAndGet();
deviceStateCounter.incrementAndGet();
}
public void log(TransportProtos.SubscriptionMgrMsgProto msg) {
totalCounter.incrementAndGet();
subscriptionMsgCounter.incrementAndGet();
}
public void log(TransportProtos.ToCoreNotificationMsg msg) {
totalCounter.incrementAndGet();
toCoreNotificationsCounter.incrementAndGet();
} }
public void printStats() { public void printStats() {
int total = totalCounter.getAndSet(0); int total = totalCounter.getAndSet(0);
if (total > 0) { if (total > 0) {
log.info("Transport total [{}] sessionEvents [{}] getAttr [{}] subToAttr [{}] subToRpc [{}] toDevRpc [{}] subInfo [{}] claimDevice [{}]", log.info("Transport total [{}] sessionEvents [{}] getAttr [{}] subToAttr [{}] subToRpc [{}] toDevRpc [{}] subInfo [{}] claimDevice [{}]" +
" deviceState [{}] subMgr [{}] coreNfs [{}]",
total, sessionEventCounter.getAndSet(0), total, sessionEventCounter.getAndSet(0),
getAttributesCounter.getAndSet(0), subscribeToAttributesCounter.getAndSet(0), getAttributesCounter.getAndSet(0), subscribeToAttributesCounter.getAndSet(0),
subscribeToRPCCounter.getAndSet(0), toDeviceRPCCallResponseCounter.getAndSet(0), subscribeToRPCCounter.getAndSet(0), toDeviceRPCCallResponseCounter.getAndSet(0),
subscriptionInfoCounter.getAndSet(0), claimDeviceCounter.getAndSet(0)); subscriptionInfoCounter.getAndSet(0), claimDeviceCounter.getAndSet(0)
, deviceStateCounter.getAndSet(0), subscriptionMsgCounter.getAndSet(0), toCoreNotificationsCounter.getAndSet(0));
} }
} }

View File

@ -16,7 +16,6 @@
package org.thingsboard.server.service.rpc; package org.thingsboard.server.service.rpc;
import akka.actor.ActorRef; import akka.actor.ActorRef;
import com.datastax.driver.core.utils.UUIDs;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.ObjectNode;
@ -147,7 +146,7 @@ public class DefaultTbCoreDeviceRpcService implements TbCoreDeviceRpcService {
log.warn("Failed to find tbCoreRpcService for local service. Possible duplication of serviceIds."); log.warn("Failed to find tbCoreRpcService for local service. Possible duplication of serviceIds.");
} }
} else { } else {
clusterService.onToRuleEngineMsg(originServiceId, response); clusterService.pushNotificationToRuleEngine(originServiceId, response, null);
} }
} }
@ -170,7 +169,7 @@ public class DefaultTbCoreDeviceRpcService implements TbCoreDeviceRpcService {
try { try {
TbMsg tbMsg = TbMsg.newMsg(DataConstants.RPC_CALL_FROM_SERVER_TO_DEVICE, msg.getDeviceId(), metaData, TbMsgDataType.JSON, json.writeValueAsString(entityNode)); TbMsg tbMsg = TbMsg.newMsg(DataConstants.RPC_CALL_FROM_SERVER_TO_DEVICE, msg.getDeviceId(), metaData, TbMsgDataType.JSON, json.writeValueAsString(entityNode));
clusterService.onToRuleEngineMsg(msg.getTenantId(), msg.getDeviceId(), tbMsg); clusterService.pushMsgToRuleEngine(msg.getTenantId(), msg.getDeviceId(), tbMsg, null);
} catch (JsonProcessingException e) { } catch (JsonProcessingException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }

View File

@ -22,7 +22,6 @@ import org.thingsboard.common.util.ThingsBoardThreadFactory;
import org.thingsboard.rule.engine.api.RpcError; import org.thingsboard.rule.engine.api.RpcError;
import org.thingsboard.rule.engine.api.RuleEngineDeviceRpcRequest; import org.thingsboard.rule.engine.api.RuleEngineDeviceRpcRequest;
import org.thingsboard.rule.engine.api.RuleEngineDeviceRpcResponse; import org.thingsboard.rule.engine.api.RuleEngineDeviceRpcResponse;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.rpc.ToDeviceRpcRequestBody; import org.thingsboard.server.common.data.rpc.ToDeviceRpcRequestBody;
import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.common.msg.queue.ServiceType;
import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; import org.thingsboard.server.common.msg.queue.TopicPartitionInfo;
@ -96,7 +95,7 @@ public class DefaultTbRuleEngineRpcService implements TbRuleEngineDeviceRpcServi
.setSessionIdLSB(sessionId.getLeastSignificantBits()) .setSessionIdLSB(sessionId.getLeastSignificantBits())
.setToServerResponse(responseMsg) .setToServerResponse(responseMsg)
.build(); .build();
clusterService.onToTransportMsg(serviceId, msg); clusterService.pushNotificationToTransport(serviceId, msg, null);
} }
@Override @Override
@ -148,7 +147,7 @@ public class DefaultTbRuleEngineRpcService implements TbRuleEngineDeviceRpcServi
} }
} else { } else {
log.trace("[{}] Forwarding msg {} to queue actor!", msg.getDeviceId(), msg); log.trace("[{}] Forwarding msg {} to queue actor!", msg.getDeviceId(), msg);
clusterService.onToCoreMsg(rpcMsg); clusterService.pushMsgToCore(rpcMsg, null);
} }
} }
@ -160,7 +159,7 @@ public class DefaultTbRuleEngineRpcService implements TbRuleEngineDeviceRpcServi
log.warn("Failed to find tbCoreRpcService for local service. Possible duplication of serviceIds."); log.warn("Failed to find tbCoreRpcService for local service. Possible duplication of serviceIds.");
} }
} else { } else {
clusterService.onToCoreMsg(originServiceId, response); clusterService.pushNotificationToCore(originServiceId, response, null);
} }
} }

View File

@ -29,7 +29,6 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.thingsboard.common.util.ThingsBoardThreadFactory; import org.thingsboard.common.util.ThingsBoardThreadFactory;
import org.thingsboard.server.queue.common.TbProtoQueueMsg;
import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.DataConstants;
import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.Tenant;
@ -56,8 +55,8 @@ import org.thingsboard.server.common.msg.queue.ServiceType;
import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; import org.thingsboard.server.common.msg.queue.TopicPartitionInfo;
import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.common.msg.queue.TbCallback; import org.thingsboard.server.common.msg.queue.TbCallback;
import org.thingsboard.server.queue.provider.TbQueueProducerProvider;
import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.queue.TbClusterService;
import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService; import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -106,7 +105,7 @@ public class DefaultDeviceStateService implements DeviceStateService {
private final DeviceService deviceService; private final DeviceService deviceService;
private final AttributesService attributesService; private final AttributesService attributesService;
private final TimeseriesService tsService; private final TimeseriesService tsService;
private final TbQueueProducerProvider producerProvider; private final TbClusterService clusterService;
private final PartitionService partitionService; private final PartitionService partitionService;
private TelemetrySubscriptionService tsSubService; private TelemetrySubscriptionService tsSubService;
@ -137,12 +136,12 @@ public class DefaultDeviceStateService implements DeviceStateService {
public DefaultDeviceStateService(TenantService tenantService, DeviceService deviceService, public DefaultDeviceStateService(TenantService tenantService, DeviceService deviceService,
AttributesService attributesService, TimeseriesService tsService, AttributesService attributesService, TimeseriesService tsService,
TbQueueProducerProvider producerProvider, PartitionService partitionService) { TbClusterService clusterService, PartitionService partitionService) {
this.tenantService = tenantService; this.tenantService = tenantService;
this.deviceService = deviceService; this.deviceService = deviceService;
this.attributesService = attributesService; this.attributesService = attributesService;
this.tsService = tsService; this.tsService = tsService;
this.producerProvider = producerProvider; this.clusterService = clusterService;
this.partitionService = partitionService; this.partitionService = partitionService;
} }
@ -413,8 +412,6 @@ public class DefaultDeviceStateService implements DeviceStateService {
} }
private void sendDeviceEvent(TenantId tenantId, DeviceId deviceId, boolean added, boolean updated, boolean deleted) { private void sendDeviceEvent(TenantId tenantId, DeviceId deviceId, boolean added, boolean updated, boolean deleted) {
TopicPartitionInfo tpi = partitionService.resolve(ServiceType.TB_CORE, tenantId, deviceId);
log.trace("[{}][{}] Device is monitored on partition: {}", tenantId, deviceId, tpi);
TransportProtos.DeviceStateServiceMsgProto.Builder builder = TransportProtos.DeviceStateServiceMsgProto.newBuilder(); TransportProtos.DeviceStateServiceMsgProto.Builder builder = TransportProtos.DeviceStateServiceMsgProto.newBuilder();
builder.setTenantIdMSB(tenantId.getId().getMostSignificantBits()); builder.setTenantIdMSB(tenantId.getId().getMostSignificantBits());
builder.setTenantIdLSB(tenantId.getId().getLeastSignificantBits()); builder.setTenantIdLSB(tenantId.getId().getLeastSignificantBits());
@ -424,8 +421,7 @@ public class DefaultDeviceStateService implements DeviceStateService {
builder.setUpdated(updated); builder.setUpdated(updated);
builder.setDeleted(deleted); builder.setDeleted(deleted);
TransportProtos.DeviceStateServiceMsgProto msg = builder.build(); TransportProtos.DeviceStateServiceMsgProto msg = builder.build();
producerProvider.getTbCoreMsgProducer().send(tpi, new TbProtoQueueMsg<>(deviceId.getId(), clusterService.pushMsgToCore(tenantId, deviceId, TransportProtos.ToCoreMsg.newBuilder().setDeviceStateServiceMsg(msg).build(), null);
TransportProtos.ToCoreMsg.newBuilder().setDeviceStateServiceMsg(msg).build()), null);
} }
private void onDeviceDeleted(TenantId tenantId, DeviceId deviceId) { private void onDeviceDeleted(TenantId tenantId, DeviceId deviceId) {
@ -497,12 +493,7 @@ public class DefaultDeviceStateService implements DeviceStateService {
try { try {
TbMsg tbMsg = TbMsg.newMsg(msgType, stateData.getDeviceId(), stateData.getMetaData().copy(), TbMsgDataType.JSON TbMsg tbMsg = TbMsg.newMsg(msgType, stateData.getDeviceId(), stateData.getMetaData().copy(), TbMsgDataType.JSON
, json.writeValueAsString(state)); , json.writeValueAsString(state));
TopicPartitionInfo tpi = partitionService.resolve(ServiceType.TB_RULE_ENGINE, stateData.getTenantId(), stateData.getDeviceId()); clusterService.pushMsgToRuleEngine(stateData.getTenantId(), stateData.getDeviceId(), tbMsg, null);
TransportProtos.ToRuleEngineMsg msg = TransportProtos.ToRuleEngineMsg.newBuilder()
.setTenantIdMSB(stateData.getTenantId().getId().getMostSignificantBits())
.setTenantIdLSB(stateData.getTenantId().getId().getLeastSignificantBits())
.setTbMsg(TbMsg.toByteString(tbMsg)).build();
producerProvider.getRuleEngineMsgProducer().send(tpi, new TbProtoQueueMsg<>(tbMsg.getId(), msg), null);
} catch (Exception e) { } catch (Exception e) {
log.warn("[{}] Failed to push inactivity alarm: {}", stateData.getDeviceId(), state, e); log.warn("[{}] Failed to push inactivity alarm: {}", stateData.getDeviceId(), state, e);
} }

View File

@ -245,8 +245,9 @@ public class DefaultSubscriptionManagerService implements SubscriptionManagerSer
} }
} }
} else if (TbAttributeSubscriptionScope.SHARED_SCOPE.name().equalsIgnoreCase(scope)) { } else if (TbAttributeSubscriptionScope.SHARED_SCOPE.name().equalsIgnoreCase(scope)) {
clusterService.onToCoreMsg(DeviceAttributesEventNotificationMsg.onUpdate(tenantId, clusterService.pushMsgToCore(DeviceAttributesEventNotificationMsg.onUpdate(tenantId,
new DeviceId(entityId.getId()), DataConstants.SHARED_SCOPE, new ArrayList<>(attributes))); new DeviceId(entityId.getId()), DataConstants.SHARED_SCOPE, new ArrayList<>(attributes))
, null);
} }
} }
callback.onSuccess(); callback.onSuccess();

View File

@ -28,16 +28,14 @@ import org.thingsboard.server.common.data.id.EntityViewId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.entityview.EntityViewService; import org.thingsboard.server.dao.entityview.EntityViewService;
import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.queue.TbQueueProducer;
import org.thingsboard.server.queue.common.TbProtoQueueMsg;
import org.thingsboard.server.queue.discovery.ClusterTopologyChangeEvent; import org.thingsboard.server.queue.discovery.ClusterTopologyChangeEvent;
import org.thingsboard.server.queue.discovery.PartitionChangeEvent; import org.thingsboard.server.queue.discovery.PartitionChangeEvent;
import org.thingsboard.server.queue.discovery.PartitionService; import org.thingsboard.server.queue.discovery.PartitionService;
import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.common.msg.queue.ServiceType;
import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; import org.thingsboard.server.common.msg.queue.TopicPartitionInfo;
import org.thingsboard.server.common.msg.queue.TbCallback; import org.thingsboard.server.common.msg.queue.TbCallback;
import org.thingsboard.server.queue.provider.TbQueueProducerProvider;
import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.queue.TbClusterService;
import org.thingsboard.server.service.telemetry.TelemetryWebSocketService; import org.thingsboard.server.service.telemetry.TelemetryWebSocketService;
import org.thingsboard.server.service.telemetry.sub.SubscriptionUpdate; import org.thingsboard.server.service.telemetry.sub.SubscriptionUpdate;
@ -70,19 +68,17 @@ public class DefaultTbLocalSubscriptionService implements TbLocalSubscriptionSer
private PartitionService partitionService; private PartitionService partitionService;
@Autowired @Autowired
private TbQueueProducerProvider producerProvider; private TbClusterService clusterService;
@Autowired @Autowired
@Lazy @Lazy
private SubscriptionManagerService subscriptionManagerService; private SubscriptionManagerService subscriptionManagerService;
private ExecutorService wsCallBackExecutor; private ExecutorService wsCallBackExecutor;
private TbQueueProducer<TbProtoQueueMsg<TransportProtos.ToCoreMsg>> toCoreProducer;
@PostConstruct @PostConstruct
public void initExecutor() { public void initExecutor() {
wsCallBackExecutor = Executors.newSingleThreadExecutor(ThingsBoardThreadFactory.forName("ws-sub-callback")); wsCallBackExecutor = Executors.newSingleThreadExecutor(ThingsBoardThreadFactory.forName("ws-sub-callback"));
toCoreProducer = producerProvider.getTbCoreMsgProducer();
} }
@PreDestroy @PreDestroy
@ -140,7 +136,7 @@ public class DefaultTbLocalSubscriptionService implements TbLocalSubscriptionSer
} else { } else {
// Push to the queue; // Push to the queue;
TransportProtos.ToCoreMsg toCoreMsg = TbSubscriptionUtils.toNewSubscriptionProto(subscription); TransportProtos.ToCoreMsg toCoreMsg = TbSubscriptionUtils.toNewSubscriptionProto(subscription);
toCoreProducer.send(tpi, new TbProtoQueueMsg<>(subscription.getEntityId().getId(), toCoreMsg), null); clusterService.pushMsgToCore(tpi, subscription.getEntityId().getId(), toCoreMsg, null);
} }
} }
@ -181,7 +177,7 @@ public class DefaultTbLocalSubscriptionService implements TbLocalSubscriptionSer
} else { } else {
// Push to the queue; // Push to the queue;
TransportProtos.ToCoreMsg toCoreMsg = TbSubscriptionUtils.toCloseSubscriptionProto(subscription); TransportProtos.ToCoreMsg toCoreMsg = TbSubscriptionUtils.toCloseSubscriptionProto(subscription);
toCoreProducer.send(tpi, new TbProtoQueueMsg<>(subscription.getEntityId().getId(), toCoreMsg), null); clusterService.pushMsgToCore(tpi, subscription.getEntityId().getId(), toCoreMsg, null);
} }
} else { } else {
log.debug("[{}][{}] Subscription not found!", sessionId, subscriptionId); log.debug("[{}][{}] Subscription not found!", sessionId, subscriptionId);

View File

@ -32,17 +32,15 @@ import org.thingsboard.server.common.data.kv.DoubleDataEntry;
import org.thingsboard.server.common.data.kv.LongDataEntry; import org.thingsboard.server.common.data.kv.LongDataEntry;
import org.thingsboard.server.common.data.kv.StringDataEntry; import org.thingsboard.server.common.data.kv.StringDataEntry;
import org.thingsboard.server.common.data.kv.TsKvEntry; import org.thingsboard.server.common.data.kv.TsKvEntry;
import org.thingsboard.server.common.msg.queue.ServiceType;
import org.thingsboard.server.common.msg.queue.TbCallback;
import org.thingsboard.server.common.msg.queue.TopicPartitionInfo;
import org.thingsboard.server.dao.attributes.AttributesService; import org.thingsboard.server.dao.attributes.AttributesService;
import org.thingsboard.server.dao.timeseries.TimeseriesService; import org.thingsboard.server.dao.timeseries.TimeseriesService;
import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.queue.TbQueueProducer;
import org.thingsboard.server.queue.common.TbProtoQueueMsg;
import org.thingsboard.server.queue.discovery.PartitionChangeEvent; import org.thingsboard.server.queue.discovery.PartitionChangeEvent;
import org.thingsboard.server.queue.discovery.PartitionService; import org.thingsboard.server.queue.discovery.PartitionService;
import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.service.queue.TbClusterService;
import org.thingsboard.server.common.msg.queue.TopicPartitionInfo;
import org.thingsboard.server.common.msg.queue.TbCallback;
import org.thingsboard.server.queue.provider.TbQueueProducerProvider;
import org.thingsboard.server.service.subscription.SubscriptionManagerService; import org.thingsboard.server.service.subscription.SubscriptionManagerService;
import org.thingsboard.server.service.subscription.TbSubscriptionUtils; import org.thingsboard.server.service.subscription.TbSubscriptionUtils;
@ -69,22 +67,20 @@ public class DefaultTelemetrySubscriptionService implements TelemetrySubscriptio
private final AttributesService attrService; private final AttributesService attrService;
private final TimeseriesService tsService; private final TimeseriesService tsService;
private final TbQueueProducerProvider producerProvider; private final TbClusterService clusterService;
private final PartitionService partitionService; private final PartitionService partitionService;
private Optional<SubscriptionManagerService> subscriptionManagerService; private Optional<SubscriptionManagerService> subscriptionManagerService;
private TbQueueProducer<TbProtoQueueMsg<TransportProtos.ToCoreMsg>> toCoreProducer;
private ExecutorService tsCallBackExecutor; private ExecutorService tsCallBackExecutor;
private ExecutorService wsCallBackExecutor; private ExecutorService wsCallBackExecutor;
public DefaultTelemetrySubscriptionService(AttributesService attrService, public DefaultTelemetrySubscriptionService(AttributesService attrService,
TimeseriesService tsService, TimeseriesService tsService,
TbQueueProducerProvider producerProvider, TbClusterService clusterService,
PartitionService partitionService) { PartitionService partitionService) {
this.attrService = attrService; this.attrService = attrService;
this.tsService = tsService; this.tsService = tsService;
this.producerProvider = producerProvider; this.clusterService = clusterService;
this.partitionService = partitionService; this.partitionService = partitionService;
} }
@ -97,7 +93,6 @@ public class DefaultTelemetrySubscriptionService implements TelemetrySubscriptio
public void initExecutor() { public void initExecutor() {
tsCallBackExecutor = Executors.newSingleThreadExecutor(ThingsBoardThreadFactory.forName("ts-service-ts-callback")); tsCallBackExecutor = Executors.newSingleThreadExecutor(ThingsBoardThreadFactory.forName("ts-service-ts-callback"));
wsCallBackExecutor = Executors.newSingleThreadExecutor(ThingsBoardThreadFactory.forName("ts-service-ws-callback")); wsCallBackExecutor = Executors.newSingleThreadExecutor(ThingsBoardThreadFactory.forName("ts-service-ws-callback"));
toCoreProducer = producerProvider.getTbCoreMsgProducer();
} }
@PreDestroy @PreDestroy
@ -172,7 +167,7 @@ public class DefaultTelemetrySubscriptionService implements TelemetrySubscriptio
} }
} else { } else {
TransportProtos.ToCoreMsg toCoreMsg = TbSubscriptionUtils.toAttributesUpdateProto(tenantId, entityId, scope, attributes); TransportProtos.ToCoreMsg toCoreMsg = TbSubscriptionUtils.toAttributesUpdateProto(tenantId, entityId, scope, attributes);
toCoreProducer.send(tpi, new TbProtoQueueMsg<>(entityId.getId(), toCoreMsg), null); clusterService.pushMsgToCore(tpi, entityId.getId(), toCoreMsg, null);
} }
} }
@ -186,7 +181,7 @@ public class DefaultTelemetrySubscriptionService implements TelemetrySubscriptio
} }
} else { } else {
TransportProtos.ToCoreMsg toCoreMsg = TbSubscriptionUtils.toTimeseriesUpdateProto(tenantId, entityId, ts); TransportProtos.ToCoreMsg toCoreMsg = TbSubscriptionUtils.toTimeseriesUpdateProto(tenantId, entityId, ts);
toCoreProducer.send(tpi, new TbProtoQueueMsg<>(entityId.getId(), toCoreMsg), null); clusterService.pushMsgToCore(tpi, entityId.getId(), toCoreMsg, null);
} }
} }

View File

@ -23,13 +23,11 @@ import org.thingsboard.server.queue.common.TbProtoQueueMsg;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
//TODO 2.5 Maybe remove this service if it is not used.
@Service @Service
@ConditionalOnExpression("'${service.type:null}'=='tb-transport'") @ConditionalOnExpression("'${service.type:null}'=='tb-transport'")
public class TbTransportQueueProducerProvider implements TbQueueProducerProvider { public class TbTransportQueueProducerProvider implements TbQueueProducerProvider {
private final TbTransportQueueFactory tbQueueProvider; private final TbTransportQueueFactory tbQueueProvider;
private TbQueueProducer<TbProtoQueueMsg<TransportProtos.ToTransportMsg>> toTransport;
private TbQueueProducer<TbProtoQueueMsg<TransportProtos.ToRuleEngineMsg>> toRuleEngine; private TbQueueProducer<TbProtoQueueMsg<TransportProtos.ToRuleEngineMsg>> toRuleEngine;
private TbQueueProducer<TbProtoQueueMsg<TransportProtos.ToCoreMsg>> toTbCore; private TbQueueProducer<TbProtoQueueMsg<TransportProtos.ToCoreMsg>> toTbCore;

View File

@ -211,7 +211,7 @@ public interface TbContext {
ResultSetFuture submitCassandraTask(CassandraStatementTask task); ResultSetFuture submitCassandraTask(CassandraStatementTask task);
//TODO 2.5: - need to remove this. @Deprecated
RedisTemplate<String, Object> getRedisTemplate(); RedisTemplate<String, Object> getRedisTemplate();
} }

View File

@ -75,7 +75,6 @@ public class TbMsgCountNode implements TbNode {
TbMsgMetaData metaData = new TbMsgMetaData(); TbMsgMetaData metaData = new TbMsgMetaData();
metaData.putValue("delta", Long.toString(System.currentTimeMillis() - lastScheduledTs + delay)); metaData.putValue("delta", Long.toString(System.currentTimeMillis() - lastScheduledTs + delay));
//TODO 2.5: Callback?
TbMsg tbMsg = TbMsg.newMsg(SessionMsgType.POST_TELEMETRY_REQUEST.name(), ctx.getTenantId(), metaData, gson.toJson(telemetryJson)); TbMsg tbMsg = TbMsg.newMsg(SessionMsgType.POST_TELEMETRY_REQUEST.name(), ctx.getTenantId(), metaData, gson.toJson(telemetryJson));
ctx.enqueueForTellNext(tbMsg, SUCCESS); ctx.enqueueForTellNext(tbMsg, SUCCESS);
scheduleTickMsg(ctx); scheduleTickMsg(ctx);

View File

@ -23,7 +23,6 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpEntity; import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.http.client.Netty4ClientHttpRequestFactory; import org.springframework.http.client.Netty4ClientHttpRequestFactory;
import org.springframework.util.concurrent.ListenableFuture; import org.springframework.util.concurrent.ListenableFuture;
@ -84,7 +83,7 @@ class TbHttpClient {
} }
} }
void processMessage(TbContext ctx, TbMsg msg, TbRedisQueueProcessor queueProcessor) { void processMessage(TbContext ctx, TbMsg msg) {
String endpointUrl = TbNodeUtils.processPattern(config.getRestEndpointUrlPattern(), msg.getMetaData()); String endpointUrl = TbNodeUtils.processPattern(config.getRestEndpointUrlPattern(), msg.getMetaData());
HttpHeaders headers = prepareHeaders(msg.getMetaData()); HttpHeaders headers = prepareHeaders(msg.getMetaData());
HttpMethod method = HttpMethod.valueOf(config.getRequestMethod()); HttpMethod method = HttpMethod.valueOf(config.getRequestMethod());
@ -95,13 +94,6 @@ class TbHttpClient {
future.addCallback(new ListenableFutureCallback<ResponseEntity<String>>() { future.addCallback(new ListenableFutureCallback<ResponseEntity<String>>() {
@Override @Override
public void onFailure(Throwable throwable) { public void onFailure(Throwable throwable) {
if (config.isUseRedisQueueForMsgPersistence()) {
if (throwable instanceof HttpClientErrorException) {
processHttpClientError(((HttpClientErrorException) throwable).getStatusCode(), msg, queueProcessor);
} else {
queueProcessor.pushOnFailure(msg);
}
}
TbMsg next = processException(ctx, msg, throwable); TbMsg next = processException(ctx, msg, throwable);
ctx.tellFailure(next, throwable); ctx.tellFailure(next, throwable);
} }
@ -109,15 +101,9 @@ class TbHttpClient {
@Override @Override
public void onSuccess(ResponseEntity<String> responseEntity) { public void onSuccess(ResponseEntity<String> responseEntity) {
if (responseEntity.getStatusCode().is2xxSuccessful()) { if (responseEntity.getStatusCode().is2xxSuccessful()) {
if (config.isUseRedisQueueForMsgPersistence()) {
queueProcessor.resetCounter();
}
TbMsg next = processResponse(ctx, msg, responseEntity); TbMsg next = processResponse(ctx, msg, responseEntity);
ctx.tellSuccess(next); ctx.tellSuccess(next);
} else { } else {
if (config.isUseRedisQueueForMsgPersistence()) {
processHttpClientError(responseEntity.getStatusCode(), msg, queueProcessor);
}
TbMsg next = processFailureResponse(ctx, msg, responseEntity); TbMsg next = processFailureResponse(ctx, msg, responseEntity);
ctx.tellNext(next, TbRelationTypes.FAILURE); ctx.tellNext(next, TbRelationTypes.FAILURE);
} }
@ -183,11 +169,4 @@ class TbHttpClient {
} }
} }
private void processHttpClientError(HttpStatus statusCode, TbMsg msg, TbRedisQueueProcessor queueProcessor) {
if (statusCode.is4xxClientError()) {
log.warn("[{}] Client error during message delivering!", msg);
} else {
queueProcessor.pushOnFailure(msg);
}
}
} }

View File

@ -1,126 +0,0 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.rule.engine.rest;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.ListOperations;
import org.thingsboard.rule.engine.api.TbContext;
import org.thingsboard.server.common.msg.TbMsg;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
@Data
@Slf4j
class TbRedisQueueProcessor {
private static final int MAX_QUEUE_SIZE = Integer.MAX_VALUE;
private final TbContext ctx;
private final TbHttpClient httpClient;
private final ExecutorService executor;
private final ListOperations<String, Object> listOperations;
private final String redisKey;
private final boolean trimQueue;
private final int maxQueueSize;
private AtomicInteger failuresCounter;
private Future future;
TbRedisQueueProcessor(TbContext ctx, TbHttpClient httpClient, boolean trimQueue, int maxQueueSize) {
this.ctx = ctx;
this.httpClient = httpClient;
this.executor = Executors.newSingleThreadExecutor();
this.listOperations = ctx.getRedisTemplate().opsForList();
this.redisKey = constructRedisKey();
this.trimQueue = trimQueue;
this.maxQueueSize = maxQueueSize;
init();
}
private void init() {
failuresCounter = new AtomicInteger(0);
future = executor.submit(() -> {
while (true) {
if (failuresCounter.get() != 0 && failuresCounter.get() % 50 == 0) {
sleep("Target HTTP server is down...", 3);
}
if (listOperations.size(redisKey) > 0) {
List<Object> list = listOperations.range(redisKey, -10, -1);
list.forEach(obj -> {
//TODO 2.5: Callback?
TbMsg msg = TbMsg.fromBytes((byte[]) obj, null);
log.debug("Trying to send the message: {}", msg);
listOperations.remove(redisKey, -1, obj);
httpClient.processMessage(ctx, msg, this);
});
} else {
sleep("Queue is empty, waiting for tasks!", 1);
}
}
});
}
void destroy() {
if (future != null) {
future.cancel(true);
}
if (executor != null) {
executor.shutdownNow();
}
}
void push(TbMsg msg) {
listOperations.leftPush(redisKey, TbMsg.toByteArray(msg));
if (trimQueue) {
listOperations.trim(redisKey, 0, validateMaxQueueSize());
}
}
void pushOnFailure(TbMsg msg) {
listOperations.rightPush(redisKey, TbMsg.toByteArray(msg));
failuresCounter.incrementAndGet();
}
void resetCounter() {
failuresCounter.set(0);
}
private String constructRedisKey() {
return ctx.getServiceId() + ctx.getSelfId();
}
private int validateMaxQueueSize() {
if (maxQueueSize != 0) {
return maxQueueSize;
}
return MAX_QUEUE_SIZE;
}
private void sleep(String logMessage, int sleepSeconds) {
try {
log.debug(logMessage);
TimeUnit.SECONDS.sleep(sleepSeconds);
} catch (InterruptedException e) {
throw new IllegalStateException("Thread interrupted!", e);
}
}
}

View File

@ -25,8 +25,6 @@ import org.thingsboard.rule.engine.api.util.TbNodeUtils;
import org.thingsboard.server.common.data.plugin.ComponentType; import org.thingsboard.server.common.data.plugin.ComponentType;
import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsg;
import java.util.concurrent.ExecutionException;
@Slf4j @Slf4j
@RuleNode( @RuleNode(
type = ComponentType.EXTERNAL, type = ComponentType.EXTERNAL,
@ -47,7 +45,6 @@ public class TbRestApiCallNode implements TbNode {
private boolean useRedisQueueForMsgPersistence; private boolean useRedisQueueForMsgPersistence;
private TbHttpClient httpClient; private TbHttpClient httpClient;
private TbRedisQueueProcessor queueProcessor;
@Override @Override
public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException { public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException {
@ -55,20 +52,13 @@ public class TbRestApiCallNode implements TbNode {
httpClient = new TbHttpClient(config); httpClient = new TbHttpClient(config);
useRedisQueueForMsgPersistence = config.isUseRedisQueueForMsgPersistence(); useRedisQueueForMsgPersistence = config.isUseRedisQueueForMsgPersistence();
if (useRedisQueueForMsgPersistence) { if (useRedisQueueForMsgPersistence) {
if (ctx.getRedisTemplate() == null) { log.warn("[{}][{}] Usage of Redis Template is deprecated starting 2.5 and will have no affect", ctx.getTenantId(), ctx.getSelfId());
throw new RuntimeException("Redis cache type must be used!");
}
queueProcessor = new TbRedisQueueProcessor(ctx, httpClient, config.isTrimQueue(), config.getMaxQueueSize());
} }
} }
@Override @Override
public void onMsg(TbContext ctx, TbMsg msg) throws ExecutionException, InterruptedException, TbNodeException { public void onMsg(TbContext ctx, TbMsg msg) {
if (useRedisQueueForMsgPersistence) { httpClient.processMessage(ctx, msg);
queueProcessor.push(msg);
} else {
httpClient.processMessage(ctx, msg, null);
}
} }
@Override @Override
@ -76,9 +66,6 @@ public class TbRestApiCallNode implements TbNode {
if (this.httpClient != null) { if (this.httpClient != null) {
this.httpClient.destroy(); this.httpClient.destroy();
} }
if (this.queueProcessor != null) {
this.queueProcessor.destroy();
}
} }
} }