Showing
11 changed files
with
133 additions
and
49 deletions
@@ -39,6 +39,7 @@ import org.thingsboard.server.common.data.Tenant; | @@ -39,6 +39,7 @@ import org.thingsboard.server.common.data.Tenant; | ||
39 | import org.thingsboard.server.common.data.id.TenantId; | 39 | import org.thingsboard.server.common.data.id.TenantId; |
40 | import org.thingsboard.server.common.data.page.PageDataIterable; | 40 | import org.thingsboard.server.common.data.page.PageDataIterable; |
41 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; | 41 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; |
42 | +import org.thingsboard.server.common.msg.MsgType; | ||
42 | import org.thingsboard.server.common.msg.TbActorMsg; | 43 | import org.thingsboard.server.common.msg.TbActorMsg; |
43 | import org.thingsboard.server.common.msg.aware.TenantAwareMsg; | 44 | import org.thingsboard.server.common.msg.aware.TenantAwareMsg; |
44 | import org.thingsboard.server.common.msg.cluster.SendToClusterMsg; | 45 | import org.thingsboard.server.common.msg.cluster.SendToClusterMsg; |
@@ -58,6 +59,7 @@ public class AppActor extends RuleChainManagerActor { | @@ -58,6 +59,7 @@ public class AppActor extends RuleChainManagerActor { | ||
58 | private static final TenantId SYSTEM_TENANT = new TenantId(ModelConstants.NULL_UUID); | 59 | private static final TenantId SYSTEM_TENANT = new TenantId(ModelConstants.NULL_UUID); |
59 | private final TenantService tenantService; | 60 | private final TenantService tenantService; |
60 | private final BiMap<TenantId, ActorRef> tenantActors; | 61 | private final BiMap<TenantId, ActorRef> tenantActors; |
62 | + private boolean ruleChainsInitialized; | ||
61 | 63 | ||
62 | private AppActor(ActorSystemContext systemContext) { | 64 | private AppActor(ActorSystemContext systemContext) { |
63 | super(systemContext, new SystemRuleChainManager(systemContext)); | 65 | super(systemContext, new SystemRuleChainManager(systemContext)); |
@@ -72,26 +74,20 @@ public class AppActor extends RuleChainManagerActor { | @@ -72,26 +74,20 @@ public class AppActor extends RuleChainManagerActor { | ||
72 | 74 | ||
73 | @Override | 75 | @Override |
74 | public void preStart() { | 76 | public void preStart() { |
75 | - log.info("Starting main system actor."); | ||
76 | - try { | ||
77 | - initRuleChains(); | ||
78 | - if (systemContext.isTenantComponentsInitEnabled()) { | ||
79 | - PageDataIterable<Tenant> tenantIterator = new PageDataIterable<>(tenantService::findTenants, ENTITY_PACK_LIMIT); | ||
80 | - for (Tenant tenant : tenantIterator) { | ||
81 | - log.debug("[{}] Creating tenant actor", tenant.getId()); | ||
82 | - getOrCreateTenantActor(tenant.getId()); | ||
83 | - log.debug("Tenant actor created."); | ||
84 | - } | ||
85 | - } | ||
86 | - log.info("Main system actor started."); | ||
87 | - } catch (Exception e) { | ||
88 | - log.warn("Unknown failure", e); | ||
89 | - } | ||
90 | } | 77 | } |
91 | 78 | ||
92 | @Override | 79 | @Override |
93 | protected boolean process(TbActorMsg msg) { | 80 | protected boolean process(TbActorMsg msg) { |
81 | + if (!ruleChainsInitialized) { | ||
82 | + initRuleChainsAndTenantActors(); | ||
83 | + ruleChainsInitialized = true; | ||
84 | + if (msg.getMsgType() != MsgType.APP_INIT_MSG) { | ||
85 | + log.warn("Rule Chains initialized by unexpected message: {}", msg); | ||
86 | + } | ||
87 | + } | ||
94 | switch (msg.getMsgType()) { | 88 | switch (msg.getMsgType()) { |
89 | + case APP_INIT_MSG: | ||
90 | + break; | ||
95 | case SEND_TO_CLUSTER_MSG: | 91 | case SEND_TO_CLUSTER_MSG: |
96 | onPossibleClusterMsg((SendToClusterMsg) msg); | 92 | onPossibleClusterMsg((SendToClusterMsg) msg); |
97 | break; | 93 | break; |
@@ -119,6 +115,24 @@ public class AppActor extends RuleChainManagerActor { | @@ -119,6 +115,24 @@ public class AppActor extends RuleChainManagerActor { | ||
119 | return true; | 115 | return true; |
120 | } | 116 | } |
121 | 117 | ||
118 | + private void initRuleChainsAndTenantActors() { | ||
119 | + log.info("Starting main system actor."); | ||
120 | + try { | ||
121 | + initRuleChains(); | ||
122 | + if (systemContext.isTenantComponentsInitEnabled()) { | ||
123 | + PageDataIterable<Tenant> tenantIterator = new PageDataIterable<>(tenantService::findTenants, ENTITY_PACK_LIMIT); | ||
124 | + for (Tenant tenant : tenantIterator) { | ||
125 | + log.debug("[{}] Creating tenant actor", tenant.getId()); | ||
126 | + getOrCreateTenantActor(tenant.getId()); | ||
127 | + log.debug("Tenant actor created."); | ||
128 | + } | ||
129 | + } | ||
130 | + log.info("Main system actor started."); | ||
131 | + } catch (Exception e) { | ||
132 | + log.warn("Unknown failure", e); | ||
133 | + } | ||
134 | + } | ||
135 | + | ||
122 | private void onPossibleClusterMsg(SendToClusterMsg msg) { | 136 | private void onPossibleClusterMsg(SendToClusterMsg msg) { |
123 | Optional<ServerAddress> address = systemContext.getRoutingService().resolveById(msg.getEntityId()); | 137 | Optional<ServerAddress> address = systemContext.getRoutingService().resolveById(msg.getEntityId()); |
124 | if (address.isPresent()) { | 138 | if (address.isPresent()) { |
1 | +/** | ||
2 | + * Copyright © 2016-2018 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.actors.app; | ||
17 | + | ||
18 | +import org.thingsboard.server.common.msg.MsgType; | ||
19 | +import org.thingsboard.server.common.msg.TbActorMsg; | ||
20 | + | ||
21 | +public class AppInitMsg implements TbActorMsg { | ||
22 | + | ||
23 | + @Override | ||
24 | + public MsgType getMsgType() { | ||
25 | + return MsgType.APP_INIT_MSG; | ||
26 | + } | ||
27 | +} |
@@ -24,6 +24,7 @@ import com.google.common.util.concurrent.ListenableFuture; | @@ -24,6 +24,7 @@ import com.google.common.util.concurrent.ListenableFuture; | ||
24 | import com.google.gson.Gson; | 24 | import com.google.gson.Gson; |
25 | import com.google.gson.JsonObject; | 25 | import com.google.gson.JsonObject; |
26 | import com.google.gson.JsonParser; | 26 | import com.google.gson.JsonParser; |
27 | +import com.google.protobuf.InvalidProtocolBufferException; | ||
27 | import lombok.extern.slf4j.Slf4j; | 28 | import lombok.extern.slf4j.Slf4j; |
28 | import org.thingsboard.rule.engine.api.RpcError; | 29 | import org.thingsboard.rule.engine.api.RpcError; |
29 | import org.thingsboard.rule.engine.api.msg.DeviceAttributesEventNotificationMsg; | 30 | import org.thingsboard.rule.engine.api.msg.DeviceAttributesEventNotificationMsg; |
@@ -483,19 +484,19 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -483,19 +484,19 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
483 | } | 484 | } |
484 | } | 485 | } |
485 | 486 | ||
486 | - private void handleSessionActivity(ActorContext context, SessionInfoProto sessionInfo, TransportProtos.SubscriptionInfoProto subscriptionInfo) { | ||
487 | - UUID sessionId = getSessionId(sessionInfo); | ||
488 | - SessionInfoMetaData sessionMD = sessions.get(sessionId); | ||
489 | - if (sessionMD != null) { | ||
490 | - sessionMD.setLastActivityTime(subscriptionInfo.getLastActivityTime()); | ||
491 | - sessionMD.setSubscribedToAttributes(subscriptionInfo.getAttributeSubscription()); | ||
492 | - sessionMD.setSubscribedToRPC(subscriptionInfo.getRpcSubscription()); | ||
493 | - if (subscriptionInfo.getAttributeSubscription()) { | ||
494 | - attributeSubscriptions.putIfAbsent(sessionId, sessionMD.getSessionInfo()); | ||
495 | - } | ||
496 | - if (subscriptionInfo.getRpcSubscription()) { | ||
497 | - rpcSubscriptions.putIfAbsent(sessionId, sessionMD.getSessionInfo()); | ||
498 | - } | 487 | + private void handleSessionActivity(ActorContext context, SessionInfoProto sessionInfoProto, TransportProtos.SubscriptionInfoProto subscriptionInfo) { |
488 | + UUID sessionId = getSessionId(sessionInfoProto); | ||
489 | + SessionInfoMetaData sessionMD = sessions.computeIfAbsent(sessionId, | ||
490 | + id -> new SessionInfoMetaData(new SessionInfo(TransportProtos.SessionType.ASYNC, sessionInfoProto.getNodeId()), 0L)); | ||
491 | + | ||
492 | + sessionMD.setLastActivityTime(subscriptionInfo.getLastActivityTime()); | ||
493 | + sessionMD.setSubscribedToAttributes(subscriptionInfo.getAttributeSubscription()); | ||
494 | + sessionMD.setSubscribedToRPC(subscriptionInfo.getRpcSubscription()); | ||
495 | + if (subscriptionInfo.getAttributeSubscription()) { | ||
496 | + attributeSubscriptions.putIfAbsent(sessionId, sessionMD.getSessionInfo()); | ||
497 | + } | ||
498 | + if (subscriptionInfo.getRpcSubscription()) { | ||
499 | + rpcSubscriptions.putIfAbsent(sessionId, sessionMD.getSessionInfo()); | ||
499 | } | 500 | } |
500 | dumpSessions(); | 501 | dumpSessions(); |
501 | } | 502 | } |
@@ -629,8 +630,14 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -629,8 +630,14 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
629 | 630 | ||
630 | private void restoreSessions() { | 631 | private void restoreSessions() { |
631 | log.debug("[{}] Restoring sessions from cache", deviceId); | 632 | log.debug("[{}] Restoring sessions from cache", deviceId); |
632 | - TransportProtos.DeviceSessionsCacheEntry sessionsDump = systemContext.getDeviceSessionCacheService().get(deviceId); | ||
633 | - if (sessionsDump.getSerializedSize() == 0) { | 633 | + TransportProtos.DeviceSessionsCacheEntry sessionsDump = null; |
634 | + try { | ||
635 | + sessionsDump = TransportProtos.DeviceSessionsCacheEntry.parseFrom(systemContext.getDeviceSessionCacheService().get(deviceId)); | ||
636 | + } catch (InvalidProtocolBufferException e) { | ||
637 | + log.warn("[{}] Failed to decode device sessions from cache", deviceId); | ||
638 | + return; | ||
639 | + } | ||
640 | + if (sessionsDump.getSessionsCount() == 0) { | ||
634 | log.debug("[{}] No session information found", deviceId); | 641 | log.debug("[{}] No session information found", deviceId); |
635 | return; | 642 | return; |
636 | } | 643 | } |
@@ -677,7 +684,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -677,7 +684,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
677 | }); | 684 | }); |
678 | systemContext.getDeviceSessionCacheService() | 685 | systemContext.getDeviceSessionCacheService() |
679 | .put(deviceId, TransportProtos.DeviceSessionsCacheEntry.newBuilder() | 686 | .put(deviceId, TransportProtos.DeviceSessionsCacheEntry.newBuilder() |
680 | - .addAllSessions(sessionsList).build()); | 687 | + .addAllSessions(sessionsList).build().toByteArray()); |
681 | } | 688 | } |
682 | 689 | ||
683 | void initSessionTimeout(ActorContext context) { | 690 | void initSessionTimeout(ActorContext context) { |
@@ -22,11 +22,14 @@ import akka.actor.Terminated; | @@ -22,11 +22,14 @@ import akka.actor.Terminated; | ||
22 | import com.google.protobuf.ByteString; | 22 | import com.google.protobuf.ByteString; |
23 | import lombok.extern.slf4j.Slf4j; | 23 | import lombok.extern.slf4j.Slf4j; |
24 | import org.springframework.beans.factory.annotation.Autowired; | 24 | import org.springframework.beans.factory.annotation.Autowired; |
25 | +import org.springframework.boot.context.event.ApplicationReadyEvent; | ||
26 | +import org.springframework.context.event.EventListener; | ||
25 | import org.springframework.stereotype.Service; | 27 | import org.springframework.stereotype.Service; |
26 | import org.thingsboard.rule.engine.api.msg.DeviceCredentialsUpdateNotificationMsg; | 28 | import org.thingsboard.rule.engine.api.msg.DeviceCredentialsUpdateNotificationMsg; |
27 | import org.thingsboard.rule.engine.api.msg.DeviceNameOrTypeUpdateMsg; | 29 | import org.thingsboard.rule.engine.api.msg.DeviceNameOrTypeUpdateMsg; |
28 | import org.thingsboard.server.actors.ActorSystemContext; | 30 | import org.thingsboard.server.actors.ActorSystemContext; |
29 | import org.thingsboard.server.actors.app.AppActor; | 31 | import org.thingsboard.server.actors.app.AppActor; |
32 | +import org.thingsboard.server.actors.app.AppInitMsg; | ||
30 | import org.thingsboard.server.actors.rpc.RpcBroadcastMsg; | 33 | import org.thingsboard.server.actors.rpc.RpcBroadcastMsg; |
31 | import org.thingsboard.server.actors.rpc.RpcManagerActor; | 34 | import org.thingsboard.server.actors.rpc.RpcManagerActor; |
32 | import org.thingsboard.server.actors.rpc.RpcSessionCreateRequestMsg; | 35 | import org.thingsboard.server.actors.rpc.RpcSessionCreateRequestMsg; |
@@ -54,6 +57,12 @@ import scala.concurrent.duration.Duration; | @@ -54,6 +57,12 @@ import scala.concurrent.duration.Duration; | ||
54 | import javax.annotation.PostConstruct; | 57 | import javax.annotation.PostConstruct; |
55 | import javax.annotation.PreDestroy; | 58 | import javax.annotation.PreDestroy; |
56 | 59 | ||
60 | +import java.util.Arrays; | ||
61 | +import java.util.UUID; | ||
62 | +import java.util.concurrent.Executors; | ||
63 | +import java.util.concurrent.ScheduledExecutorService; | ||
64 | +import java.util.concurrent.TimeUnit; | ||
65 | + | ||
57 | import static org.thingsboard.server.gen.cluster.ClusterAPIProtos.MessageType.CLUSTER_ACTOR_MESSAGE; | 66 | import static org.thingsboard.server.gen.cluster.ClusterAPIProtos.MessageType.CLUSTER_ACTOR_MESSAGE; |
58 | 67 | ||
59 | @Service | 68 | @Service |
@@ -86,6 +95,8 @@ public class DefaultActorService implements ActorService { | @@ -86,6 +95,8 @@ public class DefaultActorService implements ActorService { | ||
86 | 95 | ||
87 | private ActorRef rpcManagerActor; | 96 | private ActorRef rpcManagerActor; |
88 | 97 | ||
98 | + private ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); | ||
99 | + | ||
89 | @PostConstruct | 100 | @PostConstruct |
90 | public void initActorSystem() { | 101 | public void initActorSystem() { |
91 | log.info("Initializing Actor system. {}", actorContext.getRuleChainService()); | 102 | log.info("Initializing Actor system. {}", actorContext.getRuleChainService()); |
@@ -106,6 +117,12 @@ public class DefaultActorService implements ActorService { | @@ -106,6 +117,12 @@ public class DefaultActorService implements ActorService { | ||
106 | log.info("Actor system initialized."); | 117 | log.info("Actor system initialized."); |
107 | } | 118 | } |
108 | 119 | ||
120 | + @EventListener(ApplicationReadyEvent.class) | ||
121 | + public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) { | ||
122 | + log.info("Received application ready event. Sending application init message to actor system"); | ||
123 | + appActor.tell(new AppInitMsg(), ActorRef.noSender()); | ||
124 | + } | ||
125 | + | ||
109 | @PreDestroy | 126 | @PreDestroy |
110 | public void stopActorSystem() { | 127 | public void stopActorSystem() { |
111 | Future<Terminated> status = system.terminate(); | 128 | Future<Terminated> status = system.terminate(); |
@@ -38,6 +38,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | @@ -38,6 +38,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | ||
38 | import org.springframework.boot.context.event.ApplicationReadyEvent; | 38 | import org.springframework.boot.context.event.ApplicationReadyEvent; |
39 | import org.springframework.context.ApplicationListener; | 39 | import org.springframework.context.ApplicationListener; |
40 | import org.springframework.context.annotation.Lazy; | 40 | import org.springframework.context.annotation.Lazy; |
41 | +import org.springframework.context.event.EventListener; | ||
41 | import org.springframework.stereotype.Service; | 42 | import org.springframework.stereotype.Service; |
42 | import org.springframework.util.Assert; | 43 | import org.springframework.util.Assert; |
43 | import org.thingsboard.server.actors.service.ActorService; | 44 | import org.thingsboard.server.actors.service.ActorService; |
@@ -61,7 +62,7 @@ import static org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent. | @@ -61,7 +62,7 @@ import static org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent. | ||
61 | @Service | 62 | @Service |
62 | @ConditionalOnProperty(prefix = "zk", value = "enabled", havingValue = "true", matchIfMissing = false) | 63 | @ConditionalOnProperty(prefix = "zk", value = "enabled", havingValue = "true", matchIfMissing = false) |
63 | @Slf4j | 64 | @Slf4j |
64 | -public class ZkDiscoveryService implements DiscoveryService, PathChildrenCacheListener, ApplicationListener<ApplicationReadyEvent> { | 65 | +public class ZkDiscoveryService implements DiscoveryService, PathChildrenCacheListener { |
65 | 66 | ||
66 | @Value("${zk.url}") | 67 | @Value("${zk.url}") |
67 | private String zkUrl; | 68 | private String zkUrl; |
@@ -232,8 +233,9 @@ public class ZkDiscoveryService implements DiscoveryService, PathChildrenCacheLi | @@ -232,8 +233,9 @@ public class ZkDiscoveryService implements DiscoveryService, PathChildrenCacheLi | ||
232 | .collect(Collectors.toList()); | 233 | .collect(Collectors.toList()); |
233 | } | 234 | } |
234 | 235 | ||
235 | - @Override | 236 | + @EventListener(ApplicationReadyEvent.class) |
236 | public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) { | 237 | public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) { |
238 | + log.info("Received application ready event. Starting current ZK node."); | ||
237 | if (stopped) { | 239 | if (stopped) { |
238 | log.debug("Ignoring application ready event. Service is stopped."); | 240 | log.debug("Ignoring application ready event. Service is stopped."); |
239 | return; | 241 | return; |
@@ -22,7 +22,6 @@ import org.springframework.stereotype.Service; | @@ -22,7 +22,6 @@ import org.springframework.stereotype.Service; | ||
22 | import org.thingsboard.server.common.data.id.DeviceId; | 22 | import org.thingsboard.server.common.data.id.DeviceId; |
23 | import org.thingsboard.server.gen.transport.TransportProtos.DeviceSessionsCacheEntry; | 23 | import org.thingsboard.server.gen.transport.TransportProtos.DeviceSessionsCacheEntry; |
24 | 24 | ||
25 | -import java.util.ArrayList; | ||
26 | import java.util.Collections; | 25 | import java.util.Collections; |
27 | 26 | ||
28 | import static org.thingsboard.server.common.data.CacheConstants.SESSIONS_CACHE; | 27 | import static org.thingsboard.server.common.data.CacheConstants.SESSIONS_CACHE; |
@@ -35,16 +34,17 @@ import static org.thingsboard.server.common.data.CacheConstants.SESSIONS_CACHE; | @@ -35,16 +34,17 @@ import static org.thingsboard.server.common.data.CacheConstants.SESSIONS_CACHE; | ||
35 | public class DefaultDeviceSessionCacheService implements DeviceSessionCacheService { | 34 | public class DefaultDeviceSessionCacheService implements DeviceSessionCacheService { |
36 | 35 | ||
37 | @Override | 36 | @Override |
38 | - @Cacheable(cacheNames = SESSIONS_CACHE, key = "#deviceId") | ||
39 | - public DeviceSessionsCacheEntry get(DeviceId deviceId) { | 37 | + @Cacheable(cacheNames = SESSIONS_CACHE, key = "#deviceId.toString()") |
38 | + public byte[] get(DeviceId deviceId) { | ||
40 | log.debug("[{}] Fetching session data from cache", deviceId); | 39 | log.debug("[{}] Fetching session data from cache", deviceId); |
41 | - return DeviceSessionsCacheEntry.newBuilder().addAllSessions(Collections.emptyList()).build(); | 40 | + return DeviceSessionsCacheEntry.newBuilder().addAllSessions(Collections.emptyList()).build().toByteArray(); |
42 | } | 41 | } |
43 | 42 | ||
44 | @Override | 43 | @Override |
45 | - @CachePut(cacheNames = SESSIONS_CACHE, key = "#deviceId") | ||
46 | - public DeviceSessionsCacheEntry put(DeviceId deviceId, DeviceSessionsCacheEntry sessions) { | ||
47 | - log.debug("[{}] Pushing session data from cache: {}", deviceId, sessions); | 44 | + @CachePut(cacheNames = SESSIONS_CACHE, key = "#deviceId.toString()") |
45 | + public byte[] put(DeviceId deviceId, byte[] sessions) { | ||
46 | + log.debug("[{}] Pushing session data to cache: {}", deviceId, sessions); | ||
48 | return sessions; | 47 | return sessions; |
49 | } | 48 | } |
49 | + | ||
50 | } | 50 | } |
@@ -23,8 +23,8 @@ import org.thingsboard.server.gen.transport.TransportProtos.DeviceSessionsCacheE | @@ -23,8 +23,8 @@ import org.thingsboard.server.gen.transport.TransportProtos.DeviceSessionsCacheE | ||
23 | */ | 23 | */ |
24 | public interface DeviceSessionCacheService { | 24 | public interface DeviceSessionCacheService { |
25 | 25 | ||
26 | - DeviceSessionsCacheEntry get(DeviceId deviceId); | 26 | + byte[] get(DeviceId deviceId); |
27 | 27 | ||
28 | - DeviceSessionsCacheEntry put(DeviceId deviceId, DeviceSessionsCacheEntry sessions); | 28 | + byte[] put(DeviceId deviceId, byte[] sessions); |
29 | 29 | ||
30 | } | 30 | } |
@@ -29,6 +29,9 @@ import org.apache.kafka.clients.producer.RecordMetadata; | @@ -29,6 +29,9 @@ import org.apache.kafka.clients.producer.RecordMetadata; | ||
29 | import org.springframework.beans.factory.annotation.Autowired; | 29 | import org.springframework.beans.factory.annotation.Autowired; |
30 | import org.springframework.beans.factory.annotation.Value; | 30 | import org.springframework.beans.factory.annotation.Value; |
31 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | 31 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
32 | +import org.springframework.boot.context.event.ApplicationReadyEvent; | ||
33 | +import org.springframework.context.event.ContextRefreshedEvent; | ||
34 | +import org.springframework.context.event.EventListener; | ||
32 | import org.springframework.stereotype.Service; | 35 | import org.springframework.stereotype.Service; |
33 | import org.thingsboard.server.actors.ActorSystemContext; | 36 | import org.thingsboard.server.actors.ActorSystemContext; |
34 | import org.thingsboard.server.actors.service.ActorService; | 37 | import org.thingsboard.server.actors.service.ActorService; |
@@ -127,7 +130,11 @@ public class RemoteRuleEngineTransportService implements RuleEngineTransportServ | @@ -127,7 +130,11 @@ public class RemoteRuleEngineTransportService implements RuleEngineTransportServ | ||
127 | 130 | ||
128 | ruleEngineConsumer = ruleEngineConsumerBuilder.build(); | 131 | ruleEngineConsumer = ruleEngineConsumerBuilder.build(); |
129 | ruleEngineConsumer.subscribe(); | 132 | ruleEngineConsumer.subscribe(); |
133 | + } | ||
130 | 134 | ||
135 | + @EventListener(ApplicationReadyEvent.class) | ||
136 | + public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) { | ||
137 | + log.info("Received application ready event. Starting polling for events."); | ||
131 | LocalBucketBuilder builder = Bucket4j.builder(); | 138 | LocalBucketBuilder builder = Bucket4j.builder(); |
132 | builder.addLimit(Bandwidth.simple(pollRecordsPerSecond, Duration.ofSeconds(1))); | 139 | builder.addLimit(Bandwidth.simple(pollRecordsPerSecond, Duration.ofSeconds(1))); |
133 | builder.addLimit(Bandwidth.simple(pollRecordsPerMinute, Duration.ofMinutes(1))); | 140 | builder.addLimit(Bandwidth.simple(pollRecordsPerMinute, Duration.ofMinutes(1))); |
@@ -19,6 +19,8 @@ import lombok.extern.slf4j.Slf4j; | @@ -19,6 +19,8 @@ import lombok.extern.slf4j.Slf4j; | ||
19 | import org.springframework.beans.factory.annotation.Autowired; | 19 | import org.springframework.beans.factory.annotation.Autowired; |
20 | import org.springframework.beans.factory.annotation.Value; | 20 | import org.springframework.beans.factory.annotation.Value; |
21 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | 21 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
22 | +import org.springframework.boot.context.event.ApplicationReadyEvent; | ||
23 | +import org.springframework.context.event.EventListener; | ||
22 | import org.springframework.stereotype.Component; | 24 | import org.springframework.stereotype.Component; |
23 | import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg; | 25 | import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg; |
24 | import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg; | 26 | import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg; |
@@ -93,6 +95,11 @@ public class RemoteTransportApiService { | @@ -93,6 +95,11 @@ public class RemoteTransportApiService { | ||
93 | builder.executor(transportCallbackExecutor); | 95 | builder.executor(transportCallbackExecutor); |
94 | builder.handler(transportApiService); | 96 | builder.handler(transportApiService); |
95 | transportApiTemplate = builder.build(); | 97 | transportApiTemplate = builder.build(); |
98 | + } | ||
99 | + | ||
100 | + @EventListener(ApplicationReadyEvent.class) | ||
101 | + public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) { | ||
102 | + log.info("Received application ready event. Starting polling for events."); | ||
96 | transportApiTemplate.init(); | 103 | transportApiTemplate.init(); |
97 | } | 104 | } |
98 | 105 |
@@ -141,7 +141,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement | @@ -141,7 +141,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement | ||
141 | processUnsubscribe(ctx, (MqttUnsubscribeMessage) msg); | 141 | processUnsubscribe(ctx, (MqttUnsubscribeMessage) msg); |
142 | break; | 142 | break; |
143 | case PINGREQ: | 143 | case PINGREQ: |
144 | - if (checkConnected(ctx)) { | 144 | + if (checkConnected(ctx, msg)) { |
145 | ctx.writeAndFlush(new MqttMessage(new MqttFixedHeader(PINGRESP, false, AT_MOST_ONCE, false, 0))); | 145 | ctx.writeAndFlush(new MqttMessage(new MqttFixedHeader(PINGRESP, false, AT_MOST_ONCE, false, 0))); |
146 | transportService.reportActivity(sessionInfo); | 146 | transportService.reportActivity(sessionInfo); |
147 | if (gatewaySessionHandler != null) { | 147 | if (gatewaySessionHandler != null) { |
@@ -150,7 +150,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement | @@ -150,7 +150,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement | ||
150 | } | 150 | } |
151 | break; | 151 | break; |
152 | case DISCONNECT: | 152 | case DISCONNECT: |
153 | - if (checkConnected(ctx)) { | 153 | + if (checkConnected(ctx, msg)) { |
154 | processDisconnect(ctx); | 154 | processDisconnect(ctx); |
155 | } | 155 | } |
156 | break; | 156 | break; |
@@ -161,7 +161,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement | @@ -161,7 +161,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement | ||
161 | } | 161 | } |
162 | 162 | ||
163 | private void processPublish(ChannelHandlerContext ctx, MqttPublishMessage mqttMsg) { | 163 | private void processPublish(ChannelHandlerContext ctx, MqttPublishMessage mqttMsg) { |
164 | - if (!checkConnected(ctx)) { | 164 | + if (!checkConnected(ctx, mqttMsg)) { |
165 | return; | 165 | return; |
166 | } | 166 | } |
167 | String topicName = mqttMsg.variableHeader().topicName(); | 167 | String topicName = mqttMsg.variableHeader().topicName(); |
@@ -248,7 +248,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement | @@ -248,7 +248,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement | ||
248 | } | 248 | } |
249 | 249 | ||
250 | private void processSubscribe(ChannelHandlerContext ctx, MqttSubscribeMessage mqttMsg) { | 250 | private void processSubscribe(ChannelHandlerContext ctx, MqttSubscribeMessage mqttMsg) { |
251 | - if (!checkConnected(ctx)) { | 251 | + if (!checkConnected(ctx, mqttMsg)) { |
252 | return; | 252 | return; |
253 | } | 253 | } |
254 | log.trace("[{}] Processing subscription [{}]!", sessionId, mqttMsg.variableHeader().messageId()); | 254 | log.trace("[{}] Processing subscription [{}]!", sessionId, mqttMsg.variableHeader().messageId()); |
@@ -293,7 +293,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement | @@ -293,7 +293,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement | ||
293 | } | 293 | } |
294 | 294 | ||
295 | private void processUnsubscribe(ChannelHandlerContext ctx, MqttUnsubscribeMessage mqttMsg) { | 295 | private void processUnsubscribe(ChannelHandlerContext ctx, MqttUnsubscribeMessage mqttMsg) { |
296 | - if (!checkConnected(ctx)) { | 296 | + if (!checkConnected(ctx, mqttMsg)) { |
297 | return; | 297 | return; |
298 | } | 298 | } |
299 | log.trace("[{}] Processing subscription [{}]!", sessionId, mqttMsg.variableHeader().messageId()); | 299 | log.trace("[{}] Processing subscription [{}]!", sessionId, mqttMsg.variableHeader().messageId()); |
@@ -444,11 +444,11 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement | @@ -444,11 +444,11 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement | ||
444 | return new MqttPubAckMessage(mqttFixedHeader, mqttMsgIdVariableHeader); | 444 | return new MqttPubAckMessage(mqttFixedHeader, mqttMsgIdVariableHeader); |
445 | } | 445 | } |
446 | 446 | ||
447 | - private boolean checkConnected(ChannelHandlerContext ctx) { | 447 | + private boolean checkConnected(ChannelHandlerContext ctx, MqttMessage msg) { |
448 | if (deviceSessionCtx.isConnected()) { | 448 | if (deviceSessionCtx.isConnected()) { |
449 | return true; | 449 | return true; |
450 | } else { | 450 | } else { |
451 | - log.info("[{}] Closing current session due to invalid msg order [{}][{}]", sessionId); | 451 | + log.info("[{}] Closing current session due to invalid msg order: {}", sessionId, msg); |
452 | ctx.close(); | 452 | ctx.close(); |
453 | return false; | 453 | return false; |
454 | } | 454 | } |
@@ -496,6 +496,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement | @@ -496,6 +496,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement | ||
496 | transportService.registerAsyncSession(sessionInfo, this); | 496 | transportService.registerAsyncSession(sessionInfo, this); |
497 | checkGatewaySession(); | 497 | checkGatewaySession(); |
498 | ctx.writeAndFlush(createMqttConnAckMsg(CONNECTION_ACCEPTED)); | 498 | ctx.writeAndFlush(createMqttConnAckMsg(CONNECTION_ACCEPTED)); |
499 | + log.info("[{}] Client connected!", sessionId); | ||
499 | } | 500 | } |
500 | } | 501 | } |
501 | 502 |