15 changed files with 229 additions and 429 deletions
@ -1,161 +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.server.service.cluster.rpc; |
|||
|
|||
import com.google.protobuf.ByteString; |
|||
import io.grpc.Server; |
|||
import io.grpc.ServerBuilder; |
|||
import io.grpc.stub.StreamObserver; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Service; |
|||
import org.thingsboard.server.actors.rpc.RpcBroadcastMsg; |
|||
import org.thingsboard.server.actors.rpc.RpcSessionCreateRequestMsg; |
|||
import org.thingsboard.server.common.msg.TbActorMsg; |
|||
import org.thingsboard.server.common.msg.cluster.ServerAddress; |
|||
import org.thingsboard.server.gen.cluster.ClusterAPIProtos; |
|||
import org.thingsboard.server.gen.cluster.ClusterRpcServiceGrpc; |
|||
import org.thingsboard.server.service.cluster.discovery.ServerInstance; |
|||
import org.thingsboard.server.service.cluster.discovery.ServerInstanceService; |
|||
import org.thingsboard.server.service.encoding.DataDecodingEncodingService; |
|||
|
|||
import javax.annotation.PreDestroy; |
|||
import java.io.IOException; |
|||
import java.util.UUID; |
|||
import java.util.concurrent.ArrayBlockingQueue; |
|||
import java.util.concurrent.BlockingQueue; |
|||
import java.util.concurrent.ConcurrentHashMap; |
|||
import java.util.concurrent.ConcurrentMap; |
|||
|
|||
/** |
|||
* @author Andrew Shvayka |
|||
*/ |
|||
@Service |
|||
@Slf4j |
|||
public class ClusterGrpcService extends ClusterRpcServiceGrpc.ClusterRpcServiceImplBase implements ClusterRpcService { |
|||
|
|||
@Autowired |
|||
private ServerInstanceService instanceService; |
|||
|
|||
@Autowired |
|||
private DataDecodingEncodingService encodingService; |
|||
|
|||
private RpcMsgListener listener; |
|||
|
|||
private Server server; |
|||
|
|||
private ServerInstance instance; |
|||
|
|||
private ConcurrentMap<UUID, BlockingQueue<StreamObserver<ClusterAPIProtos.ClusterMessage>>> pendingSessionMap = |
|||
new ConcurrentHashMap<>(); |
|||
|
|||
public void init(RpcMsgListener listener) { |
|||
this.listener = listener; |
|||
log.info("Initializing RPC service!"); |
|||
instance = instanceService.getSelf(); |
|||
server = ServerBuilder.forPort(instance.getPort()).addService(this).build(); |
|||
log.info("Going to start RPC server using port: {}", instance.getPort()); |
|||
try { |
|||
server.start(); |
|||
} catch (IOException e) { |
|||
log.error("Failed to start RPC server!", e); |
|||
throw new RuntimeException("Failed to start RPC server!"); |
|||
} |
|||
log.info("RPC service initialized!"); |
|||
} |
|||
|
|||
@Override |
|||
public void onSessionCreated(UUID msgUid, StreamObserver<ClusterAPIProtos.ClusterMessage> inputStream) { |
|||
BlockingQueue<StreamObserver<ClusterAPIProtos.ClusterMessage>> queue = pendingSessionMap.remove(msgUid); |
|||
if (queue != null) { |
|||
try { |
|||
queue.put(inputStream); |
|||
} catch (InterruptedException e) { |
|||
log.warn("Failed to report created session!"); |
|||
Thread.currentThread().interrupt(); |
|||
} |
|||
} else { |
|||
log.warn("Failed to lookup pending session!"); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public StreamObserver<ClusterAPIProtos.ClusterMessage> handleMsgs( |
|||
StreamObserver<ClusterAPIProtos.ClusterMessage> responseObserver) { |
|||
log.info("Processing new session."); |
|||
return createSession(new RpcSessionCreateRequestMsg(UUID.randomUUID(), null, responseObserver)); |
|||
} |
|||
|
|||
|
|||
@PreDestroy |
|||
public void stop() { |
|||
if (server != null) { |
|||
log.info("Going to onStop RPC server"); |
|||
server.shutdownNow(); |
|||
try { |
|||
server.awaitTermination(); |
|||
log.info("RPC server stopped!"); |
|||
} catch (InterruptedException e) { |
|||
log.warn("Failed to onStop RPC server!"); |
|||
Thread.currentThread().interrupt(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
@Override |
|||
public void broadcast(RpcBroadcastMsg msg) { |
|||
listener.onBroadcastMsg(msg); |
|||
} |
|||
|
|||
private StreamObserver<ClusterAPIProtos.ClusterMessage> createSession(RpcSessionCreateRequestMsg msg) { |
|||
BlockingQueue<StreamObserver<ClusterAPIProtos.ClusterMessage>> queue = new ArrayBlockingQueue<>(1); |
|||
pendingSessionMap.put(msg.getMsgUid(), queue); |
|||
listener.onRpcSessionCreateRequestMsg(msg); |
|||
try { |
|||
StreamObserver<ClusterAPIProtos.ClusterMessage> observer = queue.take(); |
|||
log.info("Processed new session."); |
|||
return observer; |
|||
} catch (Exception e) { |
|||
log.info("Failed to process session.", e); |
|||
throw new RuntimeException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void tell(ClusterAPIProtos.ClusterMessage message) { |
|||
listener.onSendMsg(message); |
|||
} |
|||
|
|||
@Override |
|||
public void tell(ServerAddress serverAddress, TbActorMsg actorMsg) { |
|||
listener.onSendMsg(encodingService.convertToProtoDataMessage(serverAddress, actorMsg)); |
|||
} |
|||
|
|||
@Override |
|||
public void tell(ServerAddress serverAddress, ClusterAPIProtos.MessageType msgType, byte[] data) { |
|||
ClusterAPIProtos.ClusterMessage msg = ClusterAPIProtos.ClusterMessage |
|||
.newBuilder() |
|||
.setServerAddress(ClusterAPIProtos.ServerAddress |
|||
.newBuilder() |
|||
.setHost(serverAddress.getHost()) |
|||
.setPort(serverAddress.getPort()) |
|||
.build()) |
|||
.setMessageType(msgType) |
|||
.setPayload(ByteString.copyFrom(data)).build(); |
|||
listener.onSendMsg(msg); |
|||
} |
|||
} |
|||
@ -1,42 +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.server.service.cluster.rpc; |
|||
|
|||
import io.grpc.stub.StreamObserver; |
|||
import org.thingsboard.server.actors.rpc.RpcBroadcastMsg; |
|||
import org.thingsboard.server.common.msg.TbActorMsg; |
|||
import org.thingsboard.server.common.msg.cluster.ServerAddress; |
|||
import org.thingsboard.server.gen.cluster.ClusterAPIProtos; |
|||
|
|||
import java.util.UUID; |
|||
|
|||
/** |
|||
* @author Andrew Shvayka |
|||
*/ |
|||
public interface ClusterRpcService { |
|||
|
|||
void init(RpcMsgListener listener); |
|||
|
|||
void broadcast(RpcBroadcastMsg msg); |
|||
|
|||
void onSessionCreated(UUID msgUid, StreamObserver<ClusterAPIProtos.ClusterMessage> inputStream); |
|||
|
|||
void tell(ClusterAPIProtos.ClusterMessage message); |
|||
|
|||
void tell(ServerAddress serverAddress, TbActorMsg actorMsg); |
|||
|
|||
void tell(ServerAddress serverAddress, ClusterAPIProtos.MessageType msgType, byte[] data); |
|||
} |
|||
@ -1,125 +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.server.service.cluster.rpc; |
|||
|
|||
import io.grpc.Channel; |
|||
import io.grpc.ManagedChannel; |
|||
import io.grpc.stub.StreamObserver; |
|||
import lombok.Data; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.thingsboard.server.common.msg.cluster.ServerAddress; |
|||
import org.thingsboard.server.common.msg.cluster.ServerType; |
|||
import org.thingsboard.server.gen.cluster.ClusterAPIProtos; |
|||
|
|||
import java.io.Closeable; |
|||
import java.util.UUID; |
|||
|
|||
/** |
|||
* @author Andrew Shvayka |
|||
*/ |
|||
@Data |
|||
@Slf4j |
|||
public final class GrpcSession implements Closeable { |
|||
private final UUID sessionId; |
|||
private final boolean client; |
|||
private final GrpcSessionListener listener; |
|||
private final ManagedChannel channel; |
|||
private StreamObserver<ClusterAPIProtos.ClusterMessage> inputStream; |
|||
private StreamObserver<ClusterAPIProtos.ClusterMessage> outputStream; |
|||
|
|||
private boolean connected; |
|||
private ServerAddress remoteServer; |
|||
|
|||
public GrpcSession(GrpcSessionListener listener) { |
|||
this(null, listener, null); |
|||
} |
|||
|
|||
public GrpcSession(ServerAddress remoteServer, GrpcSessionListener listener, ManagedChannel channel) { |
|||
this.sessionId = UUID.randomUUID(); |
|||
this.listener = listener; |
|||
if (remoteServer != null) { |
|||
this.client = true; |
|||
this.connected = true; |
|||
this.remoteServer = remoteServer; |
|||
} else { |
|||
this.client = false; |
|||
} |
|||
this.channel = channel; |
|||
} |
|||
|
|||
public void initInputStream() { |
|||
this.inputStream = new StreamObserver<ClusterAPIProtos.ClusterMessage>() { |
|||
@Override |
|||
public void onNext(ClusterAPIProtos.ClusterMessage clusterMessage) { |
|||
if (!connected && clusterMessage.getMessageType() == ClusterAPIProtos.MessageType.CONNECT_RPC_MESSAGE) { |
|||
connected = true; |
|||
ServerAddress rpcAddress = new ServerAddress(clusterMessage.getServerAddress().getHost(), clusterMessage.getServerAddress().getPort(), ServerType.CORE); |
|||
remoteServer = new ServerAddress(rpcAddress.getHost(), rpcAddress.getPort(), ServerType.CORE); |
|||
listener.onConnected(GrpcSession.this); |
|||
} |
|||
if (connected) { |
|||
listener.onReceiveClusterGrpcMsg(GrpcSession.this, clusterMessage); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void onError(Throwable t) { |
|||
listener.onError(GrpcSession.this, t); |
|||
} |
|||
|
|||
@Override |
|||
public void onCompleted() { |
|||
outputStream.onCompleted(); |
|||
listener.onDisconnected(GrpcSession.this); |
|||
} |
|||
}; |
|||
} |
|||
|
|||
public void initOutputStream() { |
|||
if (client) { |
|||
listener.onConnected(GrpcSession.this); |
|||
} |
|||
} |
|||
|
|||
public void sendMsg(ClusterAPIProtos.ClusterMessage msg) { |
|||
if (connected) { |
|||
try { |
|||
outputStream.onNext(msg); |
|||
} catch (Throwable t) { |
|||
try { |
|||
outputStream.onError(t); |
|||
} catch (Throwable t2) { |
|||
} |
|||
listener.onError(GrpcSession.this, t); |
|||
} |
|||
} else { |
|||
log.warn("[{}] Failed to send message due to closed session!", sessionId); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void close() { |
|||
connected = false; |
|||
try { |
|||
outputStream.onCompleted(); |
|||
} catch (IllegalStateException e) { |
|||
log.debug("[{}] Failed to close output stream: {}", sessionId, e.getMessage()); |
|||
} |
|||
if (channel != null) { |
|||
channel.shutdownNow(); |
|||
} |
|||
} |
|||
} |
|||
@ -1,32 +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.server.service.cluster.rpc; |
|||
|
|||
import org.thingsboard.server.gen.cluster.ClusterAPIProtos; |
|||
|
|||
/** |
|||
* @author Andrew Shvayka |
|||
*/ |
|||
public interface GrpcSessionListener { |
|||
|
|||
void onConnected(GrpcSession session); |
|||
|
|||
void onDisconnected(GrpcSession session); |
|||
|
|||
void onReceiveClusterGrpcMsg(GrpcSession session, ClusterAPIProtos.ClusterMessage clusterMessage); |
|||
|
|||
void onError(GrpcSession session, Throwable t); |
|||
} |
|||
@ -1,32 +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.server.service.cluster.rpc; |
|||
|
|||
import org.thingsboard.server.actors.rpc.RpcBroadcastMsg; |
|||
import org.thingsboard.server.actors.rpc.RpcSessionCreateRequestMsg; |
|||
import org.thingsboard.server.common.msg.cluster.ServerAddress; |
|||
import org.thingsboard.server.gen.cluster.ClusterAPIProtos; |
|||
|
|||
/** |
|||
* @author Andrew Shvayka |
|||
*/ |
|||
|
|||
public interface RpcMsgListener { |
|||
void onReceivedMsg(ServerAddress remoteServer, ClusterAPIProtos.ClusterMessage msg); |
|||
void onSendMsg(ClusterAPIProtos.ClusterMessage msg); |
|||
void onRpcSessionCreateRequestMsg(RpcSessionCreateRequestMsg msg); |
|||
void onBroadcastMsg(RpcBroadcastMsg msg); |
|||
} |
|||
@ -0,0 +1,124 @@ |
|||
package org.thingsboard.server.service.queue; |
|||
|
|||
import akka.actor.ActorRef; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|||
import org.springframework.boot.context.event.ApplicationReadyEvent; |
|||
import org.springframework.context.event.EventListener; |
|||
import org.springframework.scheduling.annotation.Scheduled; |
|||
import org.springframework.stereotype.Service; |
|||
import org.thingsboard.common.util.ThingsBoardThreadFactory; |
|||
import org.thingsboard.server.TbQueueConsumer; |
|||
import org.thingsboard.server.actors.ActorSystemContext; |
|||
import org.thingsboard.server.common.TbProtoQueueMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos; |
|||
import org.thingsboard.server.provider.TbCoreQueueProvider; |
|||
import org.thingsboard.server.service.transport.msg.TransportToDeviceActorMsgWrapper; |
|||
|
|||
import javax.annotation.PostConstruct; |
|||
import javax.annotation.PreDestroy; |
|||
import java.util.List; |
|||
import java.util.UUID; |
|||
import java.util.concurrent.ConcurrentMap; |
|||
import java.util.concurrent.CountDownLatch; |
|||
import java.util.concurrent.ExecutorService; |
|||
import java.util.concurrent.Executors; |
|||
import java.util.concurrent.TimeUnit; |
|||
import java.util.function.Function; |
|||
import java.util.stream.Collectors; |
|||
|
|||
@Service |
|||
@ConditionalOnExpression("'${service.type:null}'=='monolith' || '${service.type:null}'=='tb-rule-engine')") |
|||
@Slf4j |
|||
public class DefaultTbRuleEngineConsumerService implements TbRuleEngineConsumerService { |
|||
|
|||
|
|||
@Value("${queue.rule-engine.poll_interval}") |
|||
private long pollDuration; |
|||
@Value("${queue.rule-engine.pack_processing_timeout}") |
|||
private long packProcessingTimeout; |
|||
@Value("${queue.rule-engine.stats.enabled:false}") |
|||
private boolean statsEnabled; |
|||
|
|||
private final ActorSystemContext actorContext; |
|||
private final TbQueueConsumer<TbProtoQueueMsg<TransportProtos.ToCoreMsg>> consumer; |
|||
private final TbCoreConsumerStats stats = new TbCoreConsumerStats(); |
|||
private volatile ExecutorService mainConsumerExecutor; |
|||
private volatile boolean stopped = false; |
|||
|
|||
public DefaultTbRuleEngineConsumerService(TbCoreQueueProvider tbCoreQueueProvider, ActorSystemContext actorContext) { |
|||
this.consumer = tbCoreQueueProvider.getToCoreMsgConsumer(); |
|||
this.actorContext = actorContext; |
|||
} |
|||
|
|||
@PostConstruct |
|||
public void init() { |
|||
this.consumer.subscribe(); |
|||
this.mainConsumerExecutor = Executors.newSingleThreadExecutor(ThingsBoardThreadFactory.forName("tb-core-consumer")); |
|||
} |
|||
|
|||
@EventListener(ApplicationReadyEvent.class) |
|||
public void onApplicationEvent(ApplicationReadyEvent event) { |
|||
mainConsumerExecutor.execute(() -> { |
|||
while (!stopped) { |
|||
try { |
|||
List<TbProtoQueueMsg<TransportProtos.ToCoreMsg>> msgs = consumer.poll(pollDuration); |
|||
ConcurrentMap<UUID, TbProtoQueueMsg<TransportProtos.ToCoreMsg>> ackMap = msgs.stream().collect( |
|||
Collectors.toConcurrentMap(s -> UUID.randomUUID(), Function.identity())); |
|||
CountDownLatch processingTimeoutLatch = new CountDownLatch(1); |
|||
ackMap.forEach((id, msg) -> { |
|||
TbMsgCallback callback = new MsgPackCallback<>(id, processingTimeoutLatch, ackMap); |
|||
try { |
|||
TransportProtos.ToCoreMsg toCoreMsg = msg.getValue(); |
|||
log.trace("Forwarding message to rule engine {}", toCoreMsg); |
|||
if (toCoreMsg.hasToDeviceActorMsg()) { |
|||
forwardToDeviceActor(toCoreMsg.getToDeviceActorMsg(), callback); |
|||
} else { |
|||
callback.onSuccess(); |
|||
} |
|||
} catch (Throwable e) { |
|||
callback.onFailure(e); |
|||
} |
|||
}); |
|||
if (!processingTimeoutLatch.await(packProcessingTimeout, TimeUnit.MILLISECONDS)) { |
|||
ackMap.forEach((id, msg) -> log.warn("[{}] Timeout to process message: {}", id, msg.getValue())); |
|||
} |
|||
consumer.commit(); |
|||
} catch (Exception e) { |
|||
log.warn("Failed to obtain messages from queue.", e); |
|||
try { |
|||
Thread.sleep(pollDuration); |
|||
} catch (InterruptedException e2) { |
|||
log.trace("Failed to wait until the server has capacity to handle new requests", e2); |
|||
} |
|||
} |
|||
} |
|||
}); |
|||
} |
|||
|
|||
private void forwardToDeviceActor(TransportProtos.TransportToDeviceActorMsg toDeviceActorMsg, TbMsgCallback callback) { |
|||
if (statsEnabled) { |
|||
stats.log(toDeviceActorMsg); |
|||
} |
|||
actorContext.getAppActor().tell(new TransportToDeviceActorMsgWrapper(toDeviceActorMsg, callback), ActorRef.noSender()); |
|||
} |
|||
|
|||
@Scheduled(fixedDelayString = "${queue.core.stats.print_interval_ms}") |
|||
public void printStats() { |
|||
if (statsEnabled) { |
|||
stats.printStats(); |
|||
} |
|||
} |
|||
|
|||
@PreDestroy |
|||
public void destroy() { |
|||
stopped = true; |
|||
if (consumer != null) { |
|||
consumer.unsubscribe(); |
|||
} |
|||
if (mainConsumerExecutor != null) { |
|||
mainConsumerExecutor.shutdownNow(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,70 @@ |
|||
/** |
|||
* 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.server.service.queue; |
|||
|
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.thingsboard.server.gen.transport.TransportProtos; |
|||
|
|||
import java.util.concurrent.atomic.AtomicInteger; |
|||
|
|||
@Slf4j |
|||
public class TbCoreConsumerStats { |
|||
|
|||
private final AtomicInteger totalCounter = new AtomicInteger(0); |
|||
private final AtomicInteger sessionEventCounter = new AtomicInteger(0); |
|||
private final AtomicInteger getAttributesCounter = new AtomicInteger(0); |
|||
private final AtomicInteger subscribeToAttributesCounter = new AtomicInteger(0); |
|||
private final AtomicInteger subscribeToRPCCounter = new AtomicInteger(0); |
|||
private final AtomicInteger toDeviceRPCCallResponseCounter = new AtomicInteger(0); |
|||
private final AtomicInteger subscriptionInfoCounter = new AtomicInteger(0); |
|||
private final AtomicInteger claimDeviceCounter = new AtomicInteger(0); |
|||
|
|||
public void log(TransportProtos.TransportToDeviceActorMsg msg) { |
|||
totalCounter.incrementAndGet(); |
|||
if (msg.hasSessionEvent()) { |
|||
sessionEventCounter.incrementAndGet(); |
|||
} |
|||
if (msg.hasGetAttributes()) { |
|||
getAttributesCounter.incrementAndGet(); |
|||
} |
|||
if (msg.hasSubscribeToAttributes()) { |
|||
subscribeToAttributesCounter.incrementAndGet(); |
|||
} |
|||
if (msg.hasSubscribeToRPC()) { |
|||
subscribeToRPCCounter.incrementAndGet(); |
|||
} |
|||
if (msg.hasToDeviceRPCCallResponse()) { |
|||
toDeviceRPCCallResponseCounter.incrementAndGet(); |
|||
} |
|||
if (msg.hasSubscriptionInfo()) { |
|||
subscriptionInfoCounter.incrementAndGet(); |
|||
} |
|||
if (msg.hasClaimDevice()) { |
|||
claimDeviceCounter.incrementAndGet(); |
|||
} |
|||
} |
|||
|
|||
public void printStats() { |
|||
int total = totalCounter.getAndSet(0); |
|||
if (total > 0) { |
|||
log.info("Transport total [{}] sessionEvents [{}] getAttr [{}] subToAttr [{}] subToRpc [{}] toDevRpc [{}] subInfo [{}] claimDevice [{}]", |
|||
total, sessionEventCounter.getAndSet(0), |
|||
getAttributesCounter.getAndSet(0), subscribeToAttributesCounter.getAndSet(0), |
|||
subscribeToRPCCounter.getAndSet(0), toDeviceRPCCallResponseCounter.getAndSet(0), |
|||
subscriptionInfoCounter.getAndSet(0), claimDeviceCounter.getAndSet(0)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,5 @@ |
|||
package org.thingsboard.server.service.queue; |
|||
|
|||
public interface TbRuleEngineConsumerService { |
|||
|
|||
} |
|||
Loading…
Reference in new issue