Commit 21ee2aec11ae5bf0d0660001987cfeb4b8ba4cea
Merge remote-tracking branch 'upstream/develop/2.5.3' into feature/edge
Showing
88 changed files
with
2264 additions
and
742 deletions
Too many changes to show.
To preserve performance only 88 of 132 files are displayed.
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard</groupId> | 22 | <groupId>org.thingsboard</groupId> |
23 | - <version>2.5.1-SNAPSHOT</version> | 23 | + <version>2.5.3-SNAPSHOT</version> |
24 | <artifactId>thingsboard</artifactId> | 24 | <artifactId>thingsboard</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <artifactId>application</artifactId> | 26 | <artifactId>application</artifactId> |
@@ -59,6 +59,10 @@ | @@ -59,6 +59,10 @@ | ||
59 | </dependency> | 59 | </dependency> |
60 | <dependency> | 60 | <dependency> |
61 | <groupId>org.thingsboard.common</groupId> | 61 | <groupId>org.thingsboard.common</groupId> |
62 | + <artifactId>actor</artifactId> | ||
63 | + </dependency> | ||
64 | + <dependency> | ||
65 | + <groupId>org.thingsboard.common</groupId> | ||
62 | <artifactId>util</artifactId> | 66 | <artifactId>util</artifactId> |
63 | </dependency> | 67 | </dependency> |
64 | <dependency> | 68 | <dependency> |
@@ -178,14 +182,6 @@ | @@ -178,14 +182,6 @@ | ||
178 | <artifactId>spring-context-support</artifactId> | 182 | <artifactId>spring-context-support</artifactId> |
179 | </dependency> | 183 | </dependency> |
180 | <dependency> | 184 | <dependency> |
181 | - <groupId>com.typesafe.akka</groupId> | ||
182 | - <artifactId>akka-actor_${scala.version}</artifactId> | ||
183 | - </dependency> | ||
184 | - <dependency> | ||
185 | - <groupId>com.typesafe.akka</groupId> | ||
186 | - <artifactId>akka-slf4j_${scala.version}</artifactId> | ||
187 | - </dependency> | ||
188 | - <dependency> | ||
189 | <groupId>org.slf4j</groupId> | 185 | <groupId>org.slf4j</groupId> |
190 | <artifactId>slf4j-api</artifactId> | 186 | <artifactId>slf4j-api</artifactId> |
191 | </dependency> | 187 | </dependency> |
@@ -375,7 +371,7 @@ | @@ -375,7 +371,7 @@ | ||
375 | <repository> | 371 | <repository> |
376 | <id>jenkins</id> | 372 | <id>jenkins</id> |
377 | <name>Jenkins Repository</name> | 373 | <name>Jenkins Repository</name> |
378 | - <url>http://repo.jenkins-ci.org/releases</url> | 374 | + <url>https://repo.jenkins-ci.org/releases</url> |
379 | <snapshots> | 375 | <snapshots> |
380 | <enabled>false</enabled> | 376 | <enabled>false</enabled> |
381 | </snapshots> | 377 | </snapshots> |
@@ -35,7 +35,6 @@ | @@ -35,7 +35,6 @@ | ||
35 | </appender> | 35 | </appender> |
36 | 36 | ||
37 | <logger name="org.thingsboard.server" level="INFO" /> | 37 | <logger name="org.thingsboard.server" level="INFO" /> |
38 | - <logger name="akka" level="INFO" /> | ||
39 | <logger name="com.microsoft.azure.servicebus.primitives.CoreMessageReceiver" level="OFF" /> | 38 | <logger name="com.microsoft.azure.servicebus.primitives.CoreMessageReceiver" level="OFF" /> |
40 | 39 | ||
41 | <root level="INFO"> | 40 | <root level="INFO"> |
@@ -15,9 +15,6 @@ | @@ -15,9 +15,6 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.actors; | 16 | package org.thingsboard.server.actors; |
17 | 17 | ||
18 | -import akka.actor.ActorRef; | ||
19 | -import akka.actor.ActorSystem; | ||
20 | -import akka.actor.Scheduler; | ||
21 | import com.fasterxml.jackson.databind.JsonNode; | 18 | import com.fasterxml.jackson.databind.JsonNode; |
22 | import com.fasterxml.jackson.databind.ObjectMapper; | 19 | import com.fasterxml.jackson.databind.ObjectMapper; |
23 | import com.fasterxml.jackson.databind.node.ObjectNode; | 20 | import com.fasterxml.jackson.databind.node.ObjectNode; |
@@ -25,8 +22,6 @@ import com.google.common.util.concurrent.FutureCallback; | @@ -25,8 +22,6 @@ import com.google.common.util.concurrent.FutureCallback; | ||
25 | import com.google.common.util.concurrent.Futures; | 22 | import com.google.common.util.concurrent.Futures; |
26 | import com.google.common.util.concurrent.ListenableFuture; | 23 | import com.google.common.util.concurrent.ListenableFuture; |
27 | import com.google.common.util.concurrent.MoreExecutors; | 24 | import com.google.common.util.concurrent.MoreExecutors; |
28 | -import com.typesafe.config.Config; | ||
29 | -import com.typesafe.config.ConfigFactory; | ||
30 | import lombok.Getter; | 25 | import lombok.Getter; |
31 | import lombok.Setter; | 26 | import lombok.Setter; |
32 | import lombok.extern.slf4j.Slf4j; | 27 | import lombok.extern.slf4j.Slf4j; |
@@ -93,12 +88,13 @@ import java.io.StringWriter; | @@ -93,12 +88,13 @@ import java.io.StringWriter; | ||
93 | import java.util.Optional; | 88 | import java.util.Optional; |
94 | import java.util.concurrent.ConcurrentHashMap; | 89 | import java.util.concurrent.ConcurrentHashMap; |
95 | import java.util.concurrent.ConcurrentMap; | 90 | import java.util.concurrent.ConcurrentMap; |
91 | +import java.util.concurrent.ScheduledExecutorService; | ||
92 | +import java.util.concurrent.TimeUnit; | ||
96 | import java.util.concurrent.atomic.AtomicInteger; | 93 | import java.util.concurrent.atomic.AtomicInteger; |
97 | 94 | ||
98 | @Slf4j | 95 | @Slf4j |
99 | @Component | 96 | @Component |
100 | public class ActorSystemContext { | 97 | public class ActorSystemContext { |
101 | - private static final String AKKA_CONF_FILE_NAME = "actor-system.conf"; | ||
102 | 98 | ||
103 | protected final ObjectMapper mapper = new ObjectMapper(); | 99 | protected final ObjectMapper mapper = new ObjectMapper(); |
104 | 100 | ||
@@ -272,14 +268,6 @@ public class ActorSystemContext { | @@ -272,14 +268,6 @@ public class ActorSystemContext { | ||
272 | @Getter | 268 | @Getter |
273 | private long syncSessionTimeout; | 269 | private long syncSessionTimeout; |
274 | 270 | ||
275 | - @Value("${actors.queue.enabled}") | ||
276 | - @Getter | ||
277 | - private boolean queuePersistenceEnabled; | ||
278 | - | ||
279 | - @Value("${actors.queue.timeout}") | ||
280 | - @Getter | ||
281 | - private long queuePersistenceTimeout; | ||
282 | - | ||
283 | @Value("${actors.rule.chain.error_persist_frequency}") | 271 | @Value("${actors.rule.chain.error_persist_frequency}") |
284 | @Getter | 272 | @Getter |
285 | private long ruleChainErrorPersistFrequency; | 273 | private long ruleChainErrorPersistFrequency; |
@@ -339,17 +327,14 @@ public class ActorSystemContext { | @@ -339,17 +327,14 @@ public class ActorSystemContext { | ||
339 | 327 | ||
340 | @Getter | 328 | @Getter |
341 | @Setter | 329 | @Setter |
342 | - private ActorSystem actorSystem; | 330 | + private TbActorSystem actorSystem; |
343 | 331 | ||
344 | @Setter | 332 | @Setter |
345 | - private ActorRef appActor; | 333 | + private TbActorRef appActor; |
346 | 334 | ||
347 | @Getter | 335 | @Getter |
348 | @Setter | 336 | @Setter |
349 | - private ActorRef statsActor; | ||
350 | - | ||
351 | - @Getter | ||
352 | - private final Config config; | 337 | + private TbActorRef statsActor; |
353 | 338 | ||
354 | @Autowired(required = false) | 339 | @Autowired(required = false) |
355 | @Getter | 340 | @Getter |
@@ -363,14 +348,8 @@ public class ActorSystemContext { | @@ -363,14 +348,8 @@ public class ActorSystemContext { | ||
363 | @Getter | 348 | @Getter |
364 | private RedisTemplate<String, Object> redisTemplate; | 349 | private RedisTemplate<String, Object> redisTemplate; |
365 | 350 | ||
366 | - public ActorSystemContext() { | ||
367 | - config = ConfigFactory.parseResources(AKKA_CONF_FILE_NAME).withFallback(ConfigFactory.load()); | ||
368 | - } | ||
369 | - | ||
370 | - | ||
371 | - | ||
372 | - public Scheduler getScheduler() { | ||
373 | - return actorSystem.scheduler(); | 351 | + public ScheduledExecutorService getScheduler() { |
352 | + return actorSystem.getScheduler(); | ||
374 | } | 353 | } |
375 | 354 | ||
376 | public void persistError(TenantId tenantId, EntityId entityId, String method, Exception e) { | 355 | public void persistError(TenantId tenantId, EntityId entityId, String method, Exception e) { |
@@ -543,7 +522,21 @@ public class ActorSystemContext { | @@ -543,7 +522,21 @@ public class ActorSystemContext { | ||
543 | return Exception.class.isInstance(error) ? (Exception) error : new Exception(error); | 522 | return Exception.class.isInstance(error) ? (Exception) error : new Exception(error); |
544 | } | 523 | } |
545 | 524 | ||
546 | - public void tell(TbActorMsg tbActorMsg, ActorRef sender) { | ||
547 | - appActor.tell(tbActorMsg, sender); | 525 | + public void tell(TbActorMsg tbActorMsg) { |
526 | + appActor.tell(tbActorMsg); | ||
527 | + } | ||
528 | + | ||
529 | + public void tellWithHighPriority(TbActorMsg tbActorMsg) { | ||
530 | + appActor.tellWithHighPriority(tbActorMsg); | ||
531 | + } | ||
532 | + | ||
533 | + public void schedulePeriodicMsgWithDelay(TbActorRef ctx, TbActorMsg msg, long delayInMs, long periodInMs) { | ||
534 | + log.debug("Scheduling periodic msg {} every {} ms with delay {} ms", msg, periodInMs, delayInMs); | ||
535 | + getScheduler().scheduleWithFixedDelay(() -> ctx.tell(msg), delayInMs, periodInMs, TimeUnit.MILLISECONDS); | ||
536 | + } | ||
537 | + | ||
538 | + public void scheduleMsgWithDelay(TbActorRef ctx, TbActorMsg msg, long delayInMs) { | ||
539 | + log.debug("Scheduling msg {} with delay {} ms", msg, delayInMs); | ||
540 | + getScheduler().schedule(() -> ctx.tell(msg), delayInMs, TimeUnit.MILLISECONDS); | ||
548 | } | 541 | } |
549 | } | 542 | } |
application/src/main/java/org/thingsboard/server/actors/TbEntityTypeActorIdPredicate.java
0 → 100644
1 | +/** | ||
2 | + * Copyright © 2016-2020 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; | ||
17 | + | ||
18 | +import lombok.RequiredArgsConstructor; | ||
19 | +import org.thingsboard.server.common.data.EntityType; | ||
20 | +import org.thingsboard.server.common.data.id.EntityId; | ||
21 | + | ||
22 | +import java.util.function.Predicate; | ||
23 | + | ||
24 | +@RequiredArgsConstructor | ||
25 | +public class TbEntityTypeActorIdPredicate implements Predicate<TbActorId> { | ||
26 | + | ||
27 | + private final EntityType entityType; | ||
28 | + | ||
29 | + @Override | ||
30 | + public boolean test(TbActorId actorId) { | ||
31 | + return actorId instanceof TbEntityActorId && testEntityId(((TbEntityActorId) actorId).getEntityId()); | ||
32 | + } | ||
33 | + | ||
34 | + protected boolean testEntityId(EntityId entityId) { | ||
35 | + return entityId.getEntityType().equals(entityType); | ||
36 | + } | ||
37 | +} |
@@ -15,21 +15,19 @@ | @@ -15,21 +15,19 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.actors.app; | 16 | package org.thingsboard.server.actors.app; |
17 | 17 | ||
18 | -import akka.actor.ActorRef; | ||
19 | -import akka.actor.LocalActorRef; | ||
20 | -import akka.actor.OneForOneStrategy; | ||
21 | -import akka.actor.Props; | ||
22 | -import akka.actor.SupervisorStrategy; | ||
23 | -import akka.actor.Terminated; | ||
24 | -import com.google.common.collect.BiMap; | ||
25 | -import com.google.common.collect.HashBiMap; | 18 | +import lombok.extern.slf4j.Slf4j; |
26 | import org.thingsboard.server.actors.ActorSystemContext; | 19 | import org.thingsboard.server.actors.ActorSystemContext; |
20 | +import org.thingsboard.server.actors.TbActor; | ||
21 | +import org.thingsboard.server.actors.TbActorId; | ||
22 | +import org.thingsboard.server.actors.TbActorRef; | ||
23 | +import org.thingsboard.server.actors.TbEntityActorId; | ||
27 | import org.thingsboard.server.actors.service.ContextAwareActor; | 24 | import org.thingsboard.server.actors.service.ContextAwareActor; |
28 | import org.thingsboard.server.actors.service.ContextBasedCreator; | 25 | import org.thingsboard.server.actors.service.ContextBasedCreator; |
29 | import org.thingsboard.server.actors.service.DefaultActorService; | 26 | import org.thingsboard.server.actors.service.DefaultActorService; |
30 | import org.thingsboard.server.actors.tenant.TenantActor; | 27 | import org.thingsboard.server.actors.tenant.TenantActor; |
31 | import org.thingsboard.server.common.data.EntityType; | 28 | import org.thingsboard.server.common.data.EntityType; |
32 | import org.thingsboard.server.common.data.Tenant; | 29 | import org.thingsboard.server.common.data.Tenant; |
30 | +import org.thingsboard.server.common.data.id.EntityId; | ||
33 | import org.thingsboard.server.common.data.id.TenantId; | 31 | import org.thingsboard.server.common.data.id.TenantId; |
34 | import org.thingsboard.server.common.data.page.PageDataIterable; | 32 | import org.thingsboard.server.common.data.page.PageDataIterable; |
35 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; | 33 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; |
@@ -43,38 +41,27 @@ import org.thingsboard.server.common.msg.queue.ServiceType; | @@ -43,38 +41,27 @@ import org.thingsboard.server.common.msg.queue.ServiceType; | ||
43 | import org.thingsboard.server.dao.model.ModelConstants; | 41 | import org.thingsboard.server.dao.model.ModelConstants; |
44 | import org.thingsboard.server.dao.tenant.TenantService; | 42 | import org.thingsboard.server.dao.tenant.TenantService; |
45 | import org.thingsboard.server.service.transport.msg.TransportToDeviceActorMsgWrapper; | 43 | import org.thingsboard.server.service.transport.msg.TransportToDeviceActorMsgWrapper; |
46 | -import scala.concurrent.duration.Duration; | ||
47 | 44 | ||
48 | import java.util.HashSet; | 45 | import java.util.HashSet; |
49 | import java.util.Optional; | 46 | import java.util.Optional; |
50 | import java.util.Set; | 47 | import java.util.Set; |
51 | 48 | ||
49 | +@Slf4j | ||
52 | public class AppActor extends ContextAwareActor { | 50 | public class AppActor extends ContextAwareActor { |
53 | 51 | ||
54 | private static final TenantId SYSTEM_TENANT = new TenantId(ModelConstants.NULL_UUID); | 52 | private static final TenantId SYSTEM_TENANT = new TenantId(ModelConstants.NULL_UUID); |
55 | private final TenantService tenantService; | 53 | private final TenantService tenantService; |
56 | - private final BiMap<TenantId, ActorRef> tenantActors; | ||
57 | private final Set<TenantId> deletedTenants; | 54 | private final Set<TenantId> deletedTenants; |
58 | private boolean ruleChainsInitialized; | 55 | private boolean ruleChainsInitialized; |
59 | 56 | ||
60 | private AppActor(ActorSystemContext systemContext) { | 57 | private AppActor(ActorSystemContext systemContext) { |
61 | super(systemContext); | 58 | super(systemContext); |
62 | this.tenantService = systemContext.getTenantService(); | 59 | this.tenantService = systemContext.getTenantService(); |
63 | - this.tenantActors = HashBiMap.create(); | ||
64 | this.deletedTenants = new HashSet<>(); | 60 | this.deletedTenants = new HashSet<>(); |
65 | } | 61 | } |
66 | 62 | ||
67 | @Override | 63 | @Override |
68 | - public SupervisorStrategy supervisorStrategy() { | ||
69 | - return strategy; | ||
70 | - } | ||
71 | - | ||
72 | - @Override | ||
73 | - public void preStart() { | ||
74 | - } | ||
75 | - | ||
76 | - @Override | ||
77 | - protected boolean process(TbActorMsg msg) { | 64 | + protected boolean doProcess(TbActorMsg msg) { |
78 | if (!ruleChainsInitialized) { | 65 | if (!ruleChainsInitialized) { |
79 | initTenantActors(); | 66 | initTenantActors(); |
80 | ruleChainsInitialized = true; | 67 | ruleChainsInitialized = true; |
@@ -86,7 +73,7 @@ public class AppActor extends ContextAwareActor { | @@ -86,7 +73,7 @@ public class AppActor extends ContextAwareActor { | ||
86 | case APP_INIT_MSG: | 73 | case APP_INIT_MSG: |
87 | break; | 74 | break; |
88 | case PARTITION_CHANGE_MSG: | 75 | case PARTITION_CHANGE_MSG: |
89 | - broadcast(msg); | 76 | + ctx.broadcastToChildren(msg); |
90 | break; | 77 | break; |
91 | case COMPONENT_LIFE_CYCLE_MSG: | 78 | case COMPONENT_LIFE_CYCLE_MSG: |
92 | onComponentLifecycleMsg((ComponentLifecycleMsg) msg); | 79 | onComponentLifecycleMsg((ComponentLifecycleMsg) msg); |
@@ -95,12 +82,14 @@ public class AppActor extends ContextAwareActor { | @@ -95,12 +82,14 @@ public class AppActor extends ContextAwareActor { | ||
95 | onQueueToRuleEngineMsg((QueueToRuleEngineMsg) msg); | 82 | onQueueToRuleEngineMsg((QueueToRuleEngineMsg) msg); |
96 | break; | 83 | break; |
97 | case TRANSPORT_TO_DEVICE_ACTOR_MSG: | 84 | case TRANSPORT_TO_DEVICE_ACTOR_MSG: |
85 | + onToDeviceActorMsg((TenantAwareMsg) msg, false); | ||
86 | + break; | ||
98 | case DEVICE_ATTRIBUTES_UPDATE_TO_DEVICE_ACTOR_MSG: | 87 | case DEVICE_ATTRIBUTES_UPDATE_TO_DEVICE_ACTOR_MSG: |
99 | case DEVICE_CREDENTIALS_UPDATE_TO_DEVICE_ACTOR_MSG: | 88 | case DEVICE_CREDENTIALS_UPDATE_TO_DEVICE_ACTOR_MSG: |
100 | case DEVICE_NAME_OR_TYPE_UPDATE_TO_DEVICE_ACTOR_MSG: | 89 | case DEVICE_NAME_OR_TYPE_UPDATE_TO_DEVICE_ACTOR_MSG: |
101 | case DEVICE_RPC_REQUEST_TO_DEVICE_ACTOR_MSG: | 90 | case DEVICE_RPC_REQUEST_TO_DEVICE_ACTOR_MSG: |
102 | case SERVER_RPC_RESPONSE_TO_DEVICE_ACTOR_MSG: | 91 | case SERVER_RPC_RESPONSE_TO_DEVICE_ACTOR_MSG: |
103 | - onToDeviceActorMsg((TenantAwareMsg) msg); | 92 | + onToDeviceActorMsg((TenantAwareMsg) msg, true); |
104 | break; | 93 | break; |
105 | default: | 94 | default: |
106 | return false; | 95 | return false; |
@@ -145,19 +134,15 @@ public class AppActor extends ContextAwareActor { | @@ -145,19 +134,15 @@ public class AppActor extends ContextAwareActor { | ||
145 | msg.getTbMsg().getCallback().onFailure(new RuleEngineException("Message has system tenant id!")); | 134 | msg.getTbMsg().getCallback().onFailure(new RuleEngineException("Message has system tenant id!")); |
146 | } else { | 135 | } else { |
147 | if (!deletedTenants.contains(msg.getTenantId())) { | 136 | if (!deletedTenants.contains(msg.getTenantId())) { |
148 | - getOrCreateTenantActor(msg.getTenantId()).tell(msg, self()); | 137 | + getOrCreateTenantActor(msg.getTenantId()).tell(msg); |
149 | } else { | 138 | } else { |
150 | msg.getTbMsg().getCallback().onSuccess(); | 139 | msg.getTbMsg().getCallback().onSuccess(); |
151 | } | 140 | } |
152 | } | 141 | } |
153 | } | 142 | } |
154 | 143 | ||
155 | - protected void broadcast(Object msg) { | ||
156 | - tenantActors.values().forEach(actorRef -> actorRef.tell(msg, ActorRef.noSender())); | ||
157 | - } | ||
158 | - | ||
159 | private void onComponentLifecycleMsg(ComponentLifecycleMsg msg) { | 144 | private void onComponentLifecycleMsg(ComponentLifecycleMsg msg) { |
160 | - ActorRef target = null; | 145 | + TbActorRef target = null; |
161 | if (SYSTEM_TENANT.equals(msg.getTenantId())) { | 146 | if (SYSTEM_TENANT.equals(msg.getTenantId())) { |
162 | log.warn("Message has system tenant id: {}", msg); | 147 | log.warn("Message has system tenant id: {}", msg); |
163 | } else { | 148 | } else { |
@@ -166,25 +151,26 @@ public class AppActor extends ContextAwareActor { | @@ -166,25 +151,26 @@ public class AppActor extends ContextAwareActor { | ||
166 | log.info("[{}] Handling tenant deleted notification: {}", msg.getTenantId(), msg); | 151 | log.info("[{}] Handling tenant deleted notification: {}", msg.getTenantId(), msg); |
167 | TenantId tenantId = new TenantId(msg.getEntityId().getId()); | 152 | TenantId tenantId = new TenantId(msg.getEntityId().getId()); |
168 | deletedTenants.add(tenantId); | 153 | deletedTenants.add(tenantId); |
169 | - ActorRef tenantActor = tenantActors.get(tenantId); | ||
170 | - if (tenantActor != null) { | ||
171 | - log.debug("[{}] Deleting tenant actor: {}", msg.getTenantId(), tenantActor); | ||
172 | - context().stop(tenantActor); | ||
173 | - } | 154 | + ctx.stop(new TbEntityActorId(tenantId)); |
174 | } else { | 155 | } else { |
175 | target = getOrCreateTenantActor(msg.getTenantId()); | 156 | target = getOrCreateTenantActor(msg.getTenantId()); |
176 | } | 157 | } |
177 | } | 158 | } |
178 | if (target != null) { | 159 | if (target != null) { |
179 | - target.tell(msg, ActorRef.noSender()); | 160 | + target.tellWithHighPriority(msg); |
180 | } else { | 161 | } else { |
181 | log.debug("[{}] Invalid component lifecycle msg: {}", msg.getTenantId(), msg); | 162 | log.debug("[{}] Invalid component lifecycle msg: {}", msg.getTenantId(), msg); |
182 | } | 163 | } |
183 | } | 164 | } |
184 | 165 | ||
185 | - private void onToDeviceActorMsg(TenantAwareMsg msg) { | 166 | + private void onToDeviceActorMsg(TenantAwareMsg msg, boolean priority) { |
186 | if (!deletedTenants.contains(msg.getTenantId())) { | 167 | if (!deletedTenants.contains(msg.getTenantId())) { |
187 | - getOrCreateTenantActor(msg.getTenantId()).tell(msg, ActorRef.noSender()); | 168 | + TbActorRef tenantActor = getOrCreateTenantActor(msg.getTenantId()); |
169 | + if (priority) { | ||
170 | + tenantActor.tellWithHighPriority(msg); | ||
171 | + } else { | ||
172 | + tenantActor.tell(msg); | ||
173 | + } | ||
188 | } else { | 174 | } else { |
189 | if (msg instanceof TransportToDeviceActorMsgWrapper) { | 175 | if (msg instanceof TransportToDeviceActorMsgWrapper) { |
190 | ((TransportToDeviceActorMsgWrapper) msg).getCallback().onSuccess(); | 176 | ((TransportToDeviceActorMsgWrapper) msg).getCallback().onSuccess(); |
@@ -192,49 +178,27 @@ public class AppActor extends ContextAwareActor { | @@ -192,49 +178,27 @@ public class AppActor extends ContextAwareActor { | ||
192 | } | 178 | } |
193 | } | 179 | } |
194 | 180 | ||
195 | - private ActorRef getOrCreateTenantActor(TenantId tenantId) { | ||
196 | - return tenantActors.computeIfAbsent(tenantId, k -> { | ||
197 | - log.info("[{}] Creating tenant actor.", tenantId); | ||
198 | - ActorRef tenantActor = context().actorOf(Props.create(new TenantActor.ActorCreator(systemContext, tenantId)) | ||
199 | - .withDispatcher(DefaultActorService.CORE_DISPATCHER_NAME), tenantId.toString()); | ||
200 | - context().watch(tenantActor); | ||
201 | - log.info("[{}] Created tenant actor: {}.", tenantId, tenantActor); | ||
202 | - return tenantActor; | ||
203 | - }); | 181 | + private TbActorRef getOrCreateTenantActor(TenantId tenantId) { |
182 | + return ctx.getOrCreateChildActor(new TbEntityActorId(tenantId), | ||
183 | + () -> DefaultActorService.TENANT_DISPATCHER_NAME, | ||
184 | + () -> new TenantActor.ActorCreator(systemContext, tenantId)); | ||
204 | } | 185 | } |
205 | 186 | ||
206 | - @Override | ||
207 | - protected void processTermination(Terminated message) { | ||
208 | - ActorRef terminated = message.actor(); | ||
209 | - if (terminated instanceof LocalActorRef) { | ||
210 | - boolean removed = tenantActors.inverse().remove(terminated) != null; | ||
211 | - if (removed) { | ||
212 | - log.debug("[{}] Removed actor:", terminated); | ||
213 | - } | ||
214 | - } else { | ||
215 | - throw new IllegalStateException("Remote actors are not supported!"); | ||
216 | - } | ||
217 | - } | ||
218 | - | ||
219 | - public static class ActorCreator extends ContextBasedCreator<AppActor> { | ||
220 | - private static final long serialVersionUID = 1L; | 187 | + public static class ActorCreator extends ContextBasedCreator { |
221 | 188 | ||
222 | public ActorCreator(ActorSystemContext context) { | 189 | public ActorCreator(ActorSystemContext context) { |
223 | super(context); | 190 | super(context); |
224 | } | 191 | } |
225 | 192 | ||
226 | @Override | 193 | @Override |
227 | - public AppActor create() { | 194 | + public TbActorId createActorId() { |
195 | + return new TbEntityActorId(new TenantId(EntityId.NULL_UUID)); | ||
196 | + } | ||
197 | + | ||
198 | + @Override | ||
199 | + public TbActor createActor() { | ||
228 | return new AppActor(context); | 200 | return new AppActor(context); |
229 | } | 201 | } |
230 | } | 202 | } |
231 | 203 | ||
232 | - private final SupervisorStrategy strategy = new OneForOneStrategy(3, Duration.create("1 minute"), t -> { | ||
233 | - log.warn("Unknown failure", t); | ||
234 | - if (t instanceof RuntimeException) { | ||
235 | - return SupervisorStrategy.restart(); | ||
236 | - } else { | ||
237 | - return SupervisorStrategy.stop(); | ||
238 | - } | ||
239 | - }); | ||
240 | } | 204 | } |
@@ -15,9 +15,12 @@ | @@ -15,9 +15,12 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.actors.device; | 16 | package org.thingsboard.server.actors.device; |
17 | 17 | ||
18 | +import lombok.extern.slf4j.Slf4j; | ||
18 | import org.thingsboard.rule.engine.api.msg.DeviceAttributesEventNotificationMsg; | 19 | import org.thingsboard.rule.engine.api.msg.DeviceAttributesEventNotificationMsg; |
19 | import org.thingsboard.rule.engine.api.msg.DeviceNameOrTypeUpdateMsg; | 20 | import org.thingsboard.rule.engine.api.msg.DeviceNameOrTypeUpdateMsg; |
20 | import org.thingsboard.server.actors.ActorSystemContext; | 21 | import org.thingsboard.server.actors.ActorSystemContext; |
22 | +import org.thingsboard.server.actors.TbActorCtx; | ||
23 | +import org.thingsboard.server.actors.TbActorException; | ||
21 | import org.thingsboard.server.actors.service.ContextAwareActor; | 24 | import org.thingsboard.server.actors.service.ContextAwareActor; |
22 | import org.thingsboard.server.common.data.id.DeviceId; | 25 | import org.thingsboard.server.common.data.id.DeviceId; |
23 | import org.thingsboard.server.common.data.id.TenantId; | 26 | import org.thingsboard.server.common.data.id.TenantId; |
@@ -26,6 +29,7 @@ import org.thingsboard.server.common.msg.timeout.DeviceActorServerSideRpcTimeout | @@ -26,6 +29,7 @@ import org.thingsboard.server.common.msg.timeout.DeviceActorServerSideRpcTimeout | ||
26 | import org.thingsboard.server.service.rpc.ToDeviceRpcRequestActorMsg; | 29 | import org.thingsboard.server.service.rpc.ToDeviceRpcRequestActorMsg; |
27 | import org.thingsboard.server.service.transport.msg.TransportToDeviceActorMsgWrapper; | 30 | import org.thingsboard.server.service.transport.msg.TransportToDeviceActorMsgWrapper; |
28 | 31 | ||
32 | +@Slf4j | ||
29 | public class DeviceActor extends ContextAwareActor { | 33 | public class DeviceActor extends ContextAwareActor { |
30 | 34 | ||
31 | private final DeviceActorMessageProcessor processor; | 35 | private final DeviceActorMessageProcessor processor; |
@@ -36,29 +40,26 @@ public class DeviceActor extends ContextAwareActor { | @@ -36,29 +40,26 @@ public class DeviceActor extends ContextAwareActor { | ||
36 | } | 40 | } |
37 | 41 | ||
38 | @Override | 42 | @Override |
39 | - public void preStart() { | 43 | + public void init(TbActorCtx ctx) throws TbActorException { |
44 | + super.init(ctx); | ||
40 | log.debug("[{}][{}] Starting device actor.", processor.tenantId, processor.deviceId); | 45 | log.debug("[{}][{}] Starting device actor.", processor.tenantId, processor.deviceId); |
41 | try { | 46 | try { |
42 | - processor.initSessionTimeout(context()); | 47 | + processor.initSessionTimeout(ctx); |
43 | log.debug("[{}][{}] Device actor started.", processor.tenantId, processor.deviceId); | 48 | log.debug("[{}][{}] Device actor started.", processor.tenantId, processor.deviceId); |
44 | } catch (Exception e) { | 49 | } catch (Exception e) { |
45 | log.warn("[{}][{}] Unknown failure", processor.tenantId, processor.deviceId, e); | 50 | log.warn("[{}][{}] Unknown failure", processor.tenantId, processor.deviceId, e); |
51 | + throw new TbActorException("Failed to initialize device actor", e); | ||
46 | } | 52 | } |
47 | } | 53 | } |
48 | 54 | ||
49 | @Override | 55 | @Override |
50 | - public void postStop() { | ||
51 | - | ||
52 | - } | ||
53 | - | ||
54 | - @Override | ||
55 | - protected boolean process(TbActorMsg msg) { | 56 | + protected boolean doProcess(TbActorMsg msg) { |
56 | switch (msg.getMsgType()) { | 57 | switch (msg.getMsgType()) { |
57 | case TRANSPORT_TO_DEVICE_ACTOR_MSG: | 58 | case TRANSPORT_TO_DEVICE_ACTOR_MSG: |
58 | - processor.process(context(), (TransportToDeviceActorMsgWrapper) msg); | 59 | + processor.process(ctx, (TransportToDeviceActorMsgWrapper) msg); |
59 | break; | 60 | break; |
60 | case DEVICE_ATTRIBUTES_UPDATE_TO_DEVICE_ACTOR_MSG: | 61 | case DEVICE_ATTRIBUTES_UPDATE_TO_DEVICE_ACTOR_MSG: |
61 | - processor.processAttributesUpdate(context(), (DeviceAttributesEventNotificationMsg) msg); | 62 | + processor.processAttributesUpdate(ctx, (DeviceAttributesEventNotificationMsg) msg); |
62 | break; | 63 | break; |
63 | case DEVICE_CREDENTIALS_UPDATE_TO_DEVICE_ACTOR_MSG: | 64 | case DEVICE_CREDENTIALS_UPDATE_TO_DEVICE_ACTOR_MSG: |
64 | processor.processCredentialsUpdate(); | 65 | processor.processCredentialsUpdate(); |
@@ -67,10 +68,10 @@ public class DeviceActor extends ContextAwareActor { | @@ -67,10 +68,10 @@ public class DeviceActor extends ContextAwareActor { | ||
67 | processor.processNameOrTypeUpdate((DeviceNameOrTypeUpdateMsg) msg); | 68 | processor.processNameOrTypeUpdate((DeviceNameOrTypeUpdateMsg) msg); |
68 | break; | 69 | break; |
69 | case DEVICE_RPC_REQUEST_TO_DEVICE_ACTOR_MSG: | 70 | case DEVICE_RPC_REQUEST_TO_DEVICE_ACTOR_MSG: |
70 | - processor.processRpcRequest(context(), (ToDeviceRpcRequestActorMsg) msg); | 71 | + processor.processRpcRequest(ctx, (ToDeviceRpcRequestActorMsg) msg); |
71 | break; | 72 | break; |
72 | case DEVICE_ACTOR_SERVER_SIDE_RPC_TIMEOUT_MSG: | 73 | case DEVICE_ACTOR_SERVER_SIDE_RPC_TIMEOUT_MSG: |
73 | - processor.processServerSideRpcTimeout(context(), (DeviceActorServerSideRpcTimeoutMsg) msg); | 74 | + processor.processServerSideRpcTimeout(ctx, (DeviceActorServerSideRpcTimeoutMsg) msg); |
74 | break; | 75 | break; |
75 | case SESSION_TIMEOUT_MSG: | 76 | case SESSION_TIMEOUT_MSG: |
76 | processor.checkSessionsTimeout(); | 77 | processor.checkSessionsTimeout(); |
@@ -16,12 +16,14 @@ | @@ -16,12 +16,14 @@ | ||
16 | package org.thingsboard.server.actors.device; | 16 | package org.thingsboard.server.actors.device; |
17 | 17 | ||
18 | import org.thingsboard.server.actors.ActorSystemContext; | 18 | import org.thingsboard.server.actors.ActorSystemContext; |
19 | +import org.thingsboard.server.actors.TbActor; | ||
20 | +import org.thingsboard.server.actors.TbActorId; | ||
21 | +import org.thingsboard.server.actors.TbEntityActorId; | ||
19 | import org.thingsboard.server.actors.service.ContextBasedCreator; | 22 | import org.thingsboard.server.actors.service.ContextBasedCreator; |
20 | import org.thingsboard.server.common.data.id.DeviceId; | 23 | import org.thingsboard.server.common.data.id.DeviceId; |
21 | import org.thingsboard.server.common.data.id.TenantId; | 24 | import org.thingsboard.server.common.data.id.TenantId; |
22 | 25 | ||
23 | -public class DeviceActorCreator extends ContextBasedCreator<DeviceActor> { | ||
24 | - private static final long serialVersionUID = 1L; | 26 | +public class DeviceActorCreator extends ContextBasedCreator { |
25 | 27 | ||
26 | private final TenantId tenantId; | 28 | private final TenantId tenantId; |
27 | private final DeviceId deviceId; | 29 | private final DeviceId deviceId; |
@@ -33,7 +35,13 @@ public class DeviceActorCreator extends ContextBasedCreator<DeviceActor> { | @@ -33,7 +35,13 @@ public class DeviceActorCreator extends ContextBasedCreator<DeviceActor> { | ||
33 | } | 35 | } |
34 | 36 | ||
35 | @Override | 37 | @Override |
36 | - public DeviceActor create() { | 38 | + public TbActorId createActorId() { |
39 | + return new TbEntityActorId(deviceId); | ||
40 | + } | ||
41 | + | ||
42 | + @Override | ||
43 | + public TbActor createActor() { | ||
37 | return new DeviceActor(context, tenantId, deviceId); | 44 | return new DeviceActor(context, tenantId, deviceId); |
38 | } | 45 | } |
46 | + | ||
39 | } | 47 | } |
@@ -15,7 +15,6 @@ | @@ -15,7 +15,6 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.actors.device; | 16 | package org.thingsboard.server.actors.device; |
17 | 17 | ||
18 | -import akka.actor.ActorContext; | ||
19 | import com.google.common.util.concurrent.FutureCallback; | 18 | import com.google.common.util.concurrent.FutureCallback; |
20 | import com.google.common.util.concurrent.Futures; | 19 | import com.google.common.util.concurrent.Futures; |
21 | import com.google.common.util.concurrent.ListenableFuture; | 20 | import com.google.common.util.concurrent.ListenableFuture; |
@@ -27,6 +26,7 @@ import org.thingsboard.rule.engine.api.RpcError; | @@ -27,6 +26,7 @@ import org.thingsboard.rule.engine.api.RpcError; | ||
27 | import org.thingsboard.rule.engine.api.msg.DeviceAttributesEventNotificationMsg; | 26 | import org.thingsboard.rule.engine.api.msg.DeviceAttributesEventNotificationMsg; |
28 | import org.thingsboard.rule.engine.api.msg.DeviceNameOrTypeUpdateMsg; | 27 | import org.thingsboard.rule.engine.api.msg.DeviceNameOrTypeUpdateMsg; |
29 | import org.thingsboard.server.actors.ActorSystemContext; | 28 | import org.thingsboard.server.actors.ActorSystemContext; |
29 | +import org.thingsboard.server.actors.TbActorCtx; | ||
30 | import org.thingsboard.server.actors.shared.AbstractContextAwareMsgProcessor; | 30 | import org.thingsboard.server.actors.shared.AbstractContextAwareMsgProcessor; |
31 | import org.thingsboard.server.common.data.Device; | 31 | import org.thingsboard.server.common.data.Device; |
32 | import org.thingsboard.server.common.data.id.DeviceId; | 32 | import org.thingsboard.server.common.data.id.DeviceId; |
@@ -127,7 +127,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -127,7 +127,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
127 | } | 127 | } |
128 | } | 128 | } |
129 | 129 | ||
130 | - void processRpcRequest(ActorContext context, ToDeviceRpcRequestActorMsg msg) { | 130 | + void processRpcRequest(TbActorCtx context, ToDeviceRpcRequestActorMsg msg) { |
131 | ToDeviceRpcRequest request = msg.getMsg(); | 131 | ToDeviceRpcRequest request = msg.getMsg(); |
132 | ToDeviceRpcRequestBody body = request.getBody(); | 132 | ToDeviceRpcRequestBody body = request.getBody(); |
133 | ToDeviceRpcRequestMsg rpcRequest = ToDeviceRpcRequestMsg.newBuilder().setRequestId( | 133 | ToDeviceRpcRequestMsg rpcRequest = ToDeviceRpcRequestMsg.newBuilder().setRequestId( |
@@ -162,13 +162,13 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -162,13 +162,13 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
162 | } | 162 | } |
163 | } | 163 | } |
164 | 164 | ||
165 | - private void registerPendingRpcRequest(ActorContext context, ToDeviceRpcRequestActorMsg msg, boolean sent, ToDeviceRpcRequestMsg rpcRequest, long timeout) { | 165 | + private void registerPendingRpcRequest(TbActorCtx context, ToDeviceRpcRequestActorMsg msg, boolean sent, ToDeviceRpcRequestMsg rpcRequest, long timeout) { |
166 | toDeviceRpcPendingMap.put(rpcRequest.getRequestId(), new ToDeviceRpcRequestMetadata(msg, sent)); | 166 | toDeviceRpcPendingMap.put(rpcRequest.getRequestId(), new ToDeviceRpcRequestMetadata(msg, sent)); |
167 | DeviceActorServerSideRpcTimeoutMsg timeoutMsg = new DeviceActorServerSideRpcTimeoutMsg(rpcRequest.getRequestId(), timeout); | 167 | DeviceActorServerSideRpcTimeoutMsg timeoutMsg = new DeviceActorServerSideRpcTimeoutMsg(rpcRequest.getRequestId(), timeout); |
168 | scheduleMsgWithDelay(context, timeoutMsg, timeoutMsg.getTimeout()); | 168 | scheduleMsgWithDelay(context, timeoutMsg, timeoutMsg.getTimeout()); |
169 | } | 169 | } |
170 | 170 | ||
171 | - void processServerSideRpcTimeout(ActorContext context, DeviceActorServerSideRpcTimeoutMsg msg) { | 171 | + void processServerSideRpcTimeout(TbActorCtx context, DeviceActorServerSideRpcTimeoutMsg msg) { |
172 | ToDeviceRpcRequestMetadata requestMd = toDeviceRpcPendingMap.remove(msg.getId()); | 172 | ToDeviceRpcRequestMetadata requestMd = toDeviceRpcPendingMap.remove(msg.getId()); |
173 | if (requestMd != null) { | 173 | if (requestMd != null) { |
174 | log.debug("[{}] RPC request [{}] timeout detected!", deviceId, msg.getId()); | 174 | log.debug("[{}] RPC request [{}] timeout detected!", deviceId, msg.getId()); |
@@ -177,7 +177,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -177,7 +177,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
177 | } | 177 | } |
178 | } | 178 | } |
179 | 179 | ||
180 | - private void sendPendingRequests(ActorContext context, UUID sessionId, SessionInfoProto sessionInfo) { | 180 | + private void sendPendingRequests(TbActorCtx context, UUID sessionId, SessionInfoProto sessionInfo) { |
181 | SessionType sessionType = getSessionType(sessionId); | 181 | SessionType sessionType = getSessionType(sessionId); |
182 | if (!toDeviceRpcPendingMap.isEmpty()) { | 182 | if (!toDeviceRpcPendingMap.isEmpty()) { |
183 | log.debug("[{}] Pushing {} pending RPC messages to new async session [{}]", deviceId, toDeviceRpcPendingMap.size(), sessionId); | 183 | log.debug("[{}] Pushing {} pending RPC messages to new async session [{}]", deviceId, toDeviceRpcPendingMap.size(), sessionId); |
@@ -198,7 +198,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -198,7 +198,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
198 | sentOneWayIds.forEach(toDeviceRpcPendingMap::remove); | 198 | sentOneWayIds.forEach(toDeviceRpcPendingMap::remove); |
199 | } | 199 | } |
200 | 200 | ||
201 | - private Consumer<Map.Entry<Integer, ToDeviceRpcRequestMetadata>> processPendingRpc(ActorContext context, UUID sessionId, String nodeId, Set<Integer> sentOneWayIds) { | 201 | + private Consumer<Map.Entry<Integer, ToDeviceRpcRequestMetadata>> processPendingRpc(TbActorCtx context, UUID sessionId, String nodeId, Set<Integer> sentOneWayIds) { |
202 | return entry -> { | 202 | return entry -> { |
203 | ToDeviceRpcRequest request = entry.getValue().getMsg().getMsg(); | 203 | ToDeviceRpcRequest request = entry.getValue().getMsg().getMsg(); |
204 | ToDeviceRpcRequestBody body = request.getBody(); | 204 | ToDeviceRpcRequestBody body = request.getBody(); |
@@ -212,7 +212,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -212,7 +212,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
212 | }; | 212 | }; |
213 | } | 213 | } |
214 | 214 | ||
215 | - void process(ActorContext context, TransportToDeviceActorMsgWrapper wrapper) { | 215 | + void process(TbActorCtx context, TransportToDeviceActorMsgWrapper wrapper) { |
216 | TransportToDeviceActorMsg msg = wrapper.getMsg(); | 216 | TransportToDeviceActorMsg msg = wrapper.getMsg(); |
217 | TbCallback callback = wrapper.getCallback(); | 217 | TbCallback callback = wrapper.getCallback(); |
218 | if (msg.hasSessionEvent()) { | 218 | if (msg.hasSessionEvent()) { |
@@ -239,7 +239,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -239,7 +239,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
239 | callback.onSuccess(); | 239 | callback.onSuccess(); |
240 | } | 240 | } |
241 | 241 | ||
242 | - private void handleClaimDeviceMsg(ActorContext context, SessionInfoProto sessionInfo, TransportProtos.ClaimDeviceMsg msg) { | 242 | + private void handleClaimDeviceMsg(TbActorCtx context, SessionInfoProto sessionInfo, TransportProtos.ClaimDeviceMsg msg) { |
243 | DeviceId deviceId = new DeviceId(new UUID(msg.getDeviceIdMSB(), msg.getDeviceIdLSB())); | 243 | DeviceId deviceId = new DeviceId(new UUID(msg.getDeviceIdMSB(), msg.getDeviceIdLSB())); |
244 | systemContext.getClaimDevicesService().registerClaimingInfo(tenantId, deviceId, msg.getSecretKey(), msg.getDurationMs()); | 244 | systemContext.getClaimDevicesService().registerClaimingInfo(tenantId, deviceId, msg.getSecretKey(), msg.getDurationMs()); |
245 | } | 245 | } |
@@ -252,7 +252,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -252,7 +252,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
252 | systemContext.getDeviceStateService().onDeviceDisconnect(deviceId); | 252 | systemContext.getDeviceStateService().onDeviceDisconnect(deviceId); |
253 | } | 253 | } |
254 | 254 | ||
255 | - private void handleGetAttributesRequest(ActorContext context, SessionInfoProto sessionInfo, GetAttributeRequestMsg request) { | 255 | + private void handleGetAttributesRequest(TbActorCtx context, SessionInfoProto sessionInfo, GetAttributeRequestMsg request) { |
256 | int requestId = request.getRequestId(); | 256 | int requestId = request.getRequestId(); |
257 | Futures.addCallback(getAttributesKvEntries(request), new FutureCallback<List<List<AttributeKvEntry>>>() { | 257 | Futures.addCallback(getAttributesKvEntries(request), new FutureCallback<List<List<AttributeKvEntry>>>() { |
258 | @Override | 258 | @Override |
@@ -310,7 +310,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -310,7 +310,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
310 | return sessions.containsKey(sessionId) ? SessionType.ASYNC : SessionType.SYNC; | 310 | return sessions.containsKey(sessionId) ? SessionType.ASYNC : SessionType.SYNC; |
311 | } | 311 | } |
312 | 312 | ||
313 | - void processAttributesUpdate(ActorContext context, DeviceAttributesEventNotificationMsg msg) { | 313 | + void processAttributesUpdate(TbActorCtx context, DeviceAttributesEventNotificationMsg msg) { |
314 | if (attributeSubscriptions.size() > 0) { | 314 | if (attributeSubscriptions.size() > 0) { |
315 | boolean hasNotificationData = false; | 315 | boolean hasNotificationData = false; |
316 | AttributeUpdateNotificationMsg.Builder notification = AttributeUpdateNotificationMsg.newBuilder(); | 316 | AttributeUpdateNotificationMsg.Builder notification = AttributeUpdateNotificationMsg.newBuilder(); |
@@ -349,7 +349,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -349,7 +349,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
349 | } | 349 | } |
350 | } | 350 | } |
351 | 351 | ||
352 | - private void processRpcResponses(ActorContext context, SessionInfoProto sessionInfo, ToDeviceRpcResponseMsg responseMsg) { | 352 | + private void processRpcResponses(TbActorCtx context, SessionInfoProto sessionInfo, ToDeviceRpcResponseMsg responseMsg) { |
353 | UUID sessionId = getSessionId(sessionInfo); | 353 | UUID sessionId = getSessionId(sessionInfo); |
354 | log.debug("[{}] Processing rpc command response [{}]", deviceId, sessionId); | 354 | log.debug("[{}] Processing rpc command response [{}]", deviceId, sessionId); |
355 | ToDeviceRpcRequestMetadata requestMd = toDeviceRpcPendingMap.remove(responseMsg.getRequestId()); | 355 | ToDeviceRpcRequestMetadata requestMd = toDeviceRpcPendingMap.remove(responseMsg.getRequestId()); |
@@ -362,7 +362,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -362,7 +362,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
362 | } | 362 | } |
363 | } | 363 | } |
364 | 364 | ||
365 | - private void processSubscriptionCommands(ActorContext context, SessionInfoProto sessionInfo, SubscribeToAttributeUpdatesMsg subscribeCmd) { | 365 | + private void processSubscriptionCommands(TbActorCtx context, SessionInfoProto sessionInfo, SubscribeToAttributeUpdatesMsg subscribeCmd) { |
366 | UUID sessionId = getSessionId(sessionInfo); | 366 | UUID sessionId = getSessionId(sessionInfo); |
367 | if (subscribeCmd.getUnsubscribe()) { | 367 | if (subscribeCmd.getUnsubscribe()) { |
368 | log.debug("[{}] Canceling attributes subscription for session [{}]", deviceId, sessionId); | 368 | log.debug("[{}] Canceling attributes subscription for session [{}]", deviceId, sessionId); |
@@ -383,7 +383,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -383,7 +383,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
383 | return new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()); | 383 | return new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()); |
384 | } | 384 | } |
385 | 385 | ||
386 | - private void processSubscriptionCommands(ActorContext context, SessionInfoProto sessionInfo, SubscribeToRPCMsg subscribeCmd) { | 386 | + private void processSubscriptionCommands(TbActorCtx context, SessionInfoProto sessionInfo, SubscribeToRPCMsg subscribeCmd) { |
387 | UUID sessionId = getSessionId(sessionInfo); | 387 | UUID sessionId = getSessionId(sessionInfo); |
388 | if (subscribeCmd.getUnsubscribe()) { | 388 | if (subscribeCmd.getUnsubscribe()) { |
389 | log.debug("[{}] Canceling rpc subscription for session [{}]", deviceId, sessionId); | 389 | log.debug("[{}] Canceling rpc subscription for session [{}]", deviceId, sessionId); |
@@ -433,7 +433,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -433,7 +433,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
433 | } | 433 | } |
434 | } | 434 | } |
435 | 435 | ||
436 | - private void handleSessionActivity(ActorContext context, SessionInfoProto sessionInfoProto, SubscriptionInfoProto subscriptionInfo) { | 436 | + private void handleSessionActivity(TbActorCtx context, SessionInfoProto sessionInfoProto, SubscriptionInfoProto subscriptionInfo) { |
437 | UUID sessionId = getSessionId(sessionInfoProto); | 437 | UUID sessionId = getSessionId(sessionInfoProto); |
438 | SessionInfoMetaData sessionMD = sessions.computeIfAbsent(sessionId, | 438 | SessionInfoMetaData sessionMD = sessions.computeIfAbsent(sessionId, |
439 | id -> new SessionInfoMetaData(new SessionInfo(SessionType.ASYNC, sessionInfoProto.getNodeId()), 0L)); | 439 | id -> new SessionInfoMetaData(new SessionInfo(SessionType.ASYNC, sessionInfoProto.getNodeId()), 0L)); |
@@ -612,8 +612,8 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -612,8 +612,8 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
612 | .addAllSessions(sessionsList).build().toByteArray()); | 612 | .addAllSessions(sessionsList).build().toByteArray()); |
613 | } | 613 | } |
614 | 614 | ||
615 | - void initSessionTimeout(ActorContext context) { | ||
616 | - schedulePeriodicMsgWithDelay(context, SessionTimeoutCheckMsg.instance(), systemContext.getSessionInactivityTimeout(), systemContext.getSessionInactivityTimeout()); | 615 | + void initSessionTimeout(TbActorCtx ctx) { |
616 | + schedulePeriodicMsgWithDelay(ctx, SessionTimeoutCheckMsg.instance(), systemContext.getSessionInactivityTimeout(), systemContext.getSessionInactivityTimeout()); | ||
617 | } | 617 | } |
618 | 618 | ||
619 | void checkSessionsTimeout() { | 619 | void checkSessionsTimeout() { |
@@ -15,7 +15,6 @@ | @@ -15,7 +15,6 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.actors.ruleChain; | 16 | package org.thingsboard.server.actors.ruleChain; |
17 | 17 | ||
18 | -import akka.actor.ActorRef; | ||
19 | import com.datastax.driver.core.ResultSetFuture; | 18 | import com.datastax.driver.core.ResultSetFuture; |
20 | import com.fasterxml.jackson.core.JsonProcessingException; | 19 | import com.fasterxml.jackson.core.JsonProcessingException; |
21 | import com.fasterxml.jackson.databind.ObjectMapper; | 20 | import com.fasterxml.jackson.databind.ObjectMapper; |
@@ -30,6 +29,7 @@ import org.thingsboard.rule.engine.api.ScriptEngine; | @@ -30,6 +29,7 @@ import org.thingsboard.rule.engine.api.ScriptEngine; | ||
30 | import org.thingsboard.rule.engine.api.TbContext; | 29 | import org.thingsboard.rule.engine.api.TbContext; |
31 | import org.thingsboard.rule.engine.api.TbRelationTypes; | 30 | import org.thingsboard.rule.engine.api.TbRelationTypes; |
32 | import org.thingsboard.server.actors.ActorSystemContext; | 31 | import org.thingsboard.server.actors.ActorSystemContext; |
32 | +import org.thingsboard.server.actors.TbActorRef; | ||
33 | import org.thingsboard.server.common.data.Customer; | 33 | import org.thingsboard.server.common.data.Customer; |
34 | import org.thingsboard.server.common.data.DataConstants; | 34 | import org.thingsboard.server.common.data.DataConstants; |
35 | import org.thingsboard.server.common.data.Device; | 35 | import org.thingsboard.server.common.data.Device; |
@@ -40,6 +40,7 @@ import org.thingsboard.server.common.data.id.RuleChainId; | @@ -40,6 +40,7 @@ import org.thingsboard.server.common.data.id.RuleChainId; | ||
40 | import org.thingsboard.server.common.data.id.RuleNodeId; | 40 | import org.thingsboard.server.common.data.id.RuleNodeId; |
41 | import org.thingsboard.server.common.data.id.TenantId; | 41 | import org.thingsboard.server.common.data.id.TenantId; |
42 | import org.thingsboard.server.common.data.rule.RuleNode; | 42 | import org.thingsboard.server.common.data.rule.RuleNode; |
43 | +import org.thingsboard.server.common.msg.TbActorMsg; | ||
43 | import org.thingsboard.server.common.msg.TbMsg; | 44 | import org.thingsboard.server.common.msg.TbMsg; |
44 | import org.thingsboard.server.common.msg.TbMsgMetaData; | 45 | import org.thingsboard.server.common.msg.TbMsgMetaData; |
45 | import org.thingsboard.server.common.msg.queue.ServiceType; | 46 | import org.thingsboard.server.common.msg.queue.ServiceType; |
@@ -64,7 +65,6 @@ import org.thingsboard.server.gen.transport.TransportProtos; | @@ -64,7 +65,6 @@ import org.thingsboard.server.gen.transport.TransportProtos; | ||
64 | import org.thingsboard.server.queue.TbQueueCallback; | 65 | import org.thingsboard.server.queue.TbQueueCallback; |
65 | import org.thingsboard.server.queue.TbQueueMsgMetadata; | 66 | import org.thingsboard.server.queue.TbQueueMsgMetadata; |
66 | import org.thingsboard.server.service.script.RuleNodeJsScriptEngine; | 67 | import org.thingsboard.server.service.script.RuleNodeJsScriptEngine; |
67 | -import scala.concurrent.duration.Duration; | ||
68 | 68 | ||
69 | import java.util.Collections; | 69 | import java.util.Collections; |
70 | import java.util.Set; | 70 | import java.util.Set; |
@@ -106,7 +106,7 @@ class DefaultTbContext implements TbContext { | @@ -106,7 +106,7 @@ class DefaultTbContext implements TbContext { | ||
106 | if (nodeCtx.getSelf().isDebugMode()) { | 106 | if (nodeCtx.getSelf().isDebugMode()) { |
107 | relationTypes.forEach(relationType -> mainCtx.persistDebugOutput(nodeCtx.getTenantId(), nodeCtx.getSelf().getId(), msg, relationType, th)); | 107 | relationTypes.forEach(relationType -> mainCtx.persistDebugOutput(nodeCtx.getTenantId(), nodeCtx.getSelf().getId(), msg, relationType, th)); |
108 | } | 108 | } |
109 | - nodeCtx.getChainActor().tell(new RuleNodeToRuleChainTellNextMsg(nodeCtx.getSelf().getId(), relationTypes, msg, th != null ? th.getMessage() : null), nodeCtx.getSelfActor()); | 109 | + nodeCtx.getChainActor().tell(new RuleNodeToRuleChainTellNextMsg(nodeCtx.getSelf().getId(), relationTypes, msg, th != null ? th.getMessage() : null)); |
110 | } | 110 | } |
111 | 111 | ||
112 | @Override | 112 | @Override |
@@ -132,7 +132,7 @@ class DefaultTbContext implements TbContext { | @@ -132,7 +132,7 @@ class DefaultTbContext implements TbContext { | ||
132 | .setTenantIdMSB(getTenantId().getId().getMostSignificantBits()) | 132 | .setTenantIdMSB(getTenantId().getId().getMostSignificantBits()) |
133 | .setTenantIdLSB(getTenantId().getId().getLeastSignificantBits()) | 133 | .setTenantIdLSB(getTenantId().getId().getLeastSignificantBits()) |
134 | .setTbMsg(TbMsg.toByteString(tbMsg)).build(); | 134 | .setTbMsg(TbMsg.toByteString(tbMsg)).build(); |
135 | - mainCtx.getClusterService().pushMsgToRuleEngine(tpi, tbMsg.getId(), msg, new SimpleTbQueueCallback(onSuccess, onFailure)); | 135 | + mainCtx.getClusterService().pushMsgToRuleEngine(tpi, tbMsg.getId(), msg, new SimpleTbQueueCallback(onSuccess, onFailure)); |
136 | } | 136 | } |
137 | 137 | ||
138 | @Override | 138 | @Override |
@@ -189,7 +189,7 @@ class DefaultTbContext implements TbContext { | @@ -189,7 +189,7 @@ class DefaultTbContext implements TbContext { | ||
189 | if (failureMessage != null) { | 189 | if (failureMessage != null) { |
190 | msg.setFailureMessage(failureMessage); | 190 | msg.setFailureMessage(failureMessage); |
191 | } | 191 | } |
192 | - mainCtx.getClusterService().pushMsgToRuleEngine(tpi, tbMsg.getId(), msg.build(), new SimpleTbQueueCallback(onSuccess, onFailure)); | 192 | + mainCtx.getClusterService().pushMsgToRuleEngine(tpi, tbMsg.getId(), msg.build(), new SimpleTbQueueCallback(onSuccess, onFailure)); |
193 | } | 193 | } |
194 | 194 | ||
195 | @Override | 195 | @Override |
@@ -205,8 +205,8 @@ class DefaultTbContext implements TbContext { | @@ -205,8 +205,8 @@ class DefaultTbContext implements TbContext { | ||
205 | return mainCtx.resolve(ServiceType.TB_RULE_ENGINE, getTenantId(), entityId).isMyPartition(); | 205 | return mainCtx.resolve(ServiceType.TB_RULE_ENGINE, getTenantId(), entityId).isMyPartition(); |
206 | } | 206 | } |
207 | 207 | ||
208 | - private void scheduleMsgWithDelay(Object msg, long delayInMs, ActorRef target) { | ||
209 | - mainCtx.getScheduler().scheduleOnce(Duration.create(delayInMs, TimeUnit.MILLISECONDS), target, msg, mainCtx.getActorSystem().dispatcher(), nodeCtx.getSelfActor()); | 208 | + private void scheduleMsgWithDelay(TbActorMsg msg, long delayInMs, TbActorRef target) { |
209 | + mainCtx.scheduleMsgWithDelay(target, msg, delayInMs); | ||
210 | } | 210 | } |
211 | 211 | ||
212 | @Override | 212 | @Override |
@@ -215,7 +215,7 @@ class DefaultTbContext implements TbContext { | @@ -215,7 +215,7 @@ class DefaultTbContext implements TbContext { | ||
215 | mainCtx.persistDebugOutput(nodeCtx.getTenantId(), nodeCtx.getSelf().getId(), msg, TbRelationTypes.FAILURE, th); | 215 | mainCtx.persistDebugOutput(nodeCtx.getTenantId(), nodeCtx.getSelf().getId(), msg, TbRelationTypes.FAILURE, th); |
216 | } | 216 | } |
217 | nodeCtx.getChainActor().tell(new RuleNodeToRuleChainTellNextMsg(nodeCtx.getSelf().getId(), Collections.singleton(TbRelationTypes.FAILURE), | 217 | nodeCtx.getChainActor().tell(new RuleNodeToRuleChainTellNextMsg(nodeCtx.getSelf().getId(), Collections.singleton(TbRelationTypes.FAILURE), |
218 | - msg, th != null ? th.getMessage() : null), nodeCtx.getSelfActor()); | 218 | + msg, th != null ? th.getMessage() : null)); |
219 | } | 219 | } |
220 | 220 | ||
221 | public void updateSelf(RuleNode self) { | 221 | public void updateSelf(RuleNode self) { |
@@ -223,8 +223,8 @@ class DefaultTbContext implements TbContext { | @@ -223,8 +223,8 @@ class DefaultTbContext implements TbContext { | ||
223 | } | 223 | } |
224 | 224 | ||
225 | @Override | 225 | @Override |
226 | - public TbMsg newMsg(String type, EntityId originator, TbMsgMetaData metaData, String data) { | ||
227 | - return TbMsg.newMsg(type, originator, metaData, data, nodeCtx.getSelf().getRuleChainId(), nodeCtx.getSelf().getId()); | 226 | + public TbMsg newMsg(String queueName, String type, EntityId originator, TbMsgMetaData metaData, String data) { |
227 | + return TbMsg.newMsg(queueName, type, originator, metaData, data, nodeCtx.getSelf().getRuleChainId(), nodeCtx.getSelf().getId()); | ||
228 | } | 228 | } |
229 | 229 | ||
230 | @Override | 230 | @Override |
@@ -15,9 +15,11 @@ | @@ -15,9 +15,11 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.actors.ruleChain; | 16 | package org.thingsboard.server.actors.ruleChain; |
17 | 17 | ||
18 | -import akka.actor.OneForOneStrategy; | ||
19 | -import akka.actor.SupervisorStrategy; | ||
20 | import org.thingsboard.server.actors.ActorSystemContext; | 18 | import org.thingsboard.server.actors.ActorSystemContext; |
19 | +import org.thingsboard.server.actors.TbActor; | ||
20 | +import org.thingsboard.server.actors.TbActorCtx; | ||
21 | +import org.thingsboard.server.actors.TbActorId; | ||
22 | +import org.thingsboard.server.actors.TbEntityActorId; | ||
21 | import org.thingsboard.server.actors.service.ComponentActor; | 23 | import org.thingsboard.server.actors.service.ComponentActor; |
22 | import org.thingsboard.server.actors.service.ContextBasedCreator; | 24 | import org.thingsboard.server.actors.service.ContextBasedCreator; |
23 | import org.thingsboard.server.common.data.id.RuleChainId; | 25 | import org.thingsboard.server.common.data.id.RuleChainId; |
@@ -27,18 +29,24 @@ import org.thingsboard.server.common.msg.TbActorMsg; | @@ -27,18 +29,24 @@ import org.thingsboard.server.common.msg.TbActorMsg; | ||
27 | import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; | 29 | import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; |
28 | import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; | 30 | import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; |
29 | import org.thingsboard.server.common.msg.queue.QueueToRuleEngineMsg; | 31 | import org.thingsboard.server.common.msg.queue.QueueToRuleEngineMsg; |
30 | -import scala.concurrent.duration.Duration; | ||
31 | 32 | ||
32 | public class RuleChainActor extends ComponentActor<RuleChainId, RuleChainActorMessageProcessor> { | 33 | public class RuleChainActor extends ComponentActor<RuleChainId, RuleChainActorMessageProcessor> { |
33 | 34 | ||
35 | + private final RuleChain ruleChain; | ||
36 | + | ||
34 | private RuleChainActor(ActorSystemContext systemContext, TenantId tenantId, RuleChain ruleChain) { | 37 | private RuleChainActor(ActorSystemContext systemContext, TenantId tenantId, RuleChain ruleChain) { |
35 | super(systemContext, tenantId, ruleChain.getId()); | 38 | super(systemContext, tenantId, ruleChain.getId()); |
36 | - setProcessor(new RuleChainActorMessageProcessor(tenantId, ruleChain, systemContext, | ||
37 | - context().parent(), context().self())); | 39 | + this.ruleChain = ruleChain; |
38 | } | 40 | } |
39 | 41 | ||
40 | @Override | 42 | @Override |
41 | - protected boolean process(TbActorMsg msg) { | 43 | + protected RuleChainActorMessageProcessor createProcessor(TbActorCtx ctx) { |
44 | + return new RuleChainActorMessageProcessor(tenantId, ruleChain, systemContext, | ||
45 | + ctx.getParentRef(), ctx); | ||
46 | + } | ||
47 | + | ||
48 | + @Override | ||
49 | + protected boolean doProcess(TbActorMsg msg) { | ||
42 | switch (msg.getMsgType()) { | 50 | switch (msg.getMsgType()) { |
43 | case COMPONENT_LIFE_CYCLE_MSG: | 51 | case COMPONENT_LIFE_CYCLE_MSG: |
44 | onComponentLifecycleMsg((ComponentLifecycleMsg) msg); | 52 | onComponentLifecycleMsg((ComponentLifecycleMsg) msg); |
@@ -64,7 +72,7 @@ public class RuleChainActor extends ComponentActor<RuleChainId, RuleChainActorMe | @@ -64,7 +72,7 @@ public class RuleChainActor extends ComponentActor<RuleChainId, RuleChainActorMe | ||
64 | return true; | 72 | return true; |
65 | } | 73 | } |
66 | 74 | ||
67 | - public static class ActorCreator extends ContextBasedCreator<RuleChainActor> { | 75 | + public static class ActorCreator extends ContextBasedCreator { |
68 | private static final long serialVersionUID = 1L; | 76 | private static final long serialVersionUID = 1L; |
69 | 77 | ||
70 | private final TenantId tenantId; | 78 | private final TenantId tenantId; |
@@ -77,7 +85,12 @@ public class RuleChainActor extends ComponentActor<RuleChainId, RuleChainActorMe | @@ -77,7 +85,12 @@ public class RuleChainActor extends ComponentActor<RuleChainId, RuleChainActorMe | ||
77 | } | 85 | } |
78 | 86 | ||
79 | @Override | 87 | @Override |
80 | - public RuleChainActor create() { | 88 | + public TbActorId createActorId() { |
89 | + return new TbEntityActorId(ruleChain.getId()); | ||
90 | + } | ||
91 | + | ||
92 | + @Override | ||
93 | + public TbActor createActor() { | ||
81 | return new RuleChainActor(context, tenantId, ruleChain); | 94 | return new RuleChainActor(context, tenantId, ruleChain); |
82 | } | 95 | } |
83 | } | 96 | } |
@@ -87,13 +100,4 @@ public class RuleChainActor extends ComponentActor<RuleChainId, RuleChainActorMe | @@ -87,13 +100,4 @@ public class RuleChainActor extends ComponentActor<RuleChainId, RuleChainActorMe | ||
87 | return systemContext.getRuleChainErrorPersistFrequency(); | 100 | return systemContext.getRuleChainErrorPersistFrequency(); |
88 | } | 101 | } |
89 | 102 | ||
90 | - @Override | ||
91 | - public SupervisorStrategy supervisorStrategy() { | ||
92 | - return strategy; | ||
93 | - } | ||
94 | - | ||
95 | - private final SupervisorStrategy strategy = new OneForOneStrategy(3, Duration.create("1 minute"), t -> { | ||
96 | - logAndPersist("Unknown Failure", ActorSystemContext.toException(t)); | ||
97 | - return SupervisorStrategy.resume(); | ||
98 | - }); | ||
99 | } | 103 | } |
@@ -15,12 +15,12 @@ | @@ -15,12 +15,12 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.actors.ruleChain; | 16 | package org.thingsboard.server.actors.ruleChain; |
17 | 17 | ||
18 | -import akka.actor.ActorContext; | ||
19 | -import akka.actor.ActorRef; | ||
20 | -import akka.actor.Props; | ||
21 | import lombok.extern.slf4j.Slf4j; | 18 | import lombok.extern.slf4j.Slf4j; |
22 | import org.thingsboard.rule.engine.api.TbRelationTypes; | 19 | import org.thingsboard.rule.engine.api.TbRelationTypes; |
23 | import org.thingsboard.server.actors.ActorSystemContext; | 20 | import org.thingsboard.server.actors.ActorSystemContext; |
21 | +import org.thingsboard.server.actors.TbActorCtx; | ||
22 | +import org.thingsboard.server.actors.TbActorRef; | ||
23 | +import org.thingsboard.server.actors.TbEntityActorId; | ||
24 | import org.thingsboard.server.actors.service.DefaultActorService; | 24 | import org.thingsboard.server.actors.service.DefaultActorService; |
25 | import org.thingsboard.server.actors.shared.ComponentMsgProcessor; | 25 | import org.thingsboard.server.actors.shared.ComponentMsgProcessor; |
26 | import org.thingsboard.server.common.data.EntityType; | 26 | import org.thingsboard.server.common.data.EntityType; |
@@ -64,20 +64,21 @@ import java.util.stream.Collectors; | @@ -64,20 +64,21 @@ import java.util.stream.Collectors; | ||
64 | @Slf4j | 64 | @Slf4j |
65 | public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleChainId> { | 65 | public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleChainId> { |
66 | 66 | ||
67 | - private final ActorRef parent; | ||
68 | - private final ActorRef self; | 67 | + private final TbActorRef parent; |
68 | + private final TbActorRef self; | ||
69 | private final Map<RuleNodeId, RuleNodeCtx> nodeActors; | 69 | private final Map<RuleNodeId, RuleNodeCtx> nodeActors; |
70 | private final Map<RuleNodeId, List<RuleNodeRelation>> nodeRoutes; | 70 | private final Map<RuleNodeId, List<RuleNodeRelation>> nodeRoutes; |
71 | private final RuleChainService service; | 71 | private final RuleChainService service; |
72 | private final TbClusterService clusterService; | 72 | private final TbClusterService clusterService; |
73 | private final EdgeService edgeService; | 73 | private final EdgeService edgeService; |
74 | private String ruleChainName; | 74 | private String ruleChainName; |
75 | + | ||
75 | private RuleNodeId firstId; | 76 | private RuleNodeId firstId; |
76 | private RuleNodeCtx firstNode; | 77 | private RuleNodeCtx firstNode; |
77 | private boolean started; | 78 | private boolean started; |
78 | 79 | ||
79 | RuleChainActorMessageProcessor(TenantId tenantId, RuleChain ruleChain, ActorSystemContext systemContext | 80 | RuleChainActorMessageProcessor(TenantId tenantId, RuleChain ruleChain, ActorSystemContext systemContext |
80 | - , ActorRef parent, ActorRef self) { | 81 | + , TbActorRef parent, TbActorRef self) { |
81 | super(systemContext, tenantId, ruleChain.getId()); | 82 | super(systemContext, tenantId, ruleChain.getId()); |
82 | this.ruleChainName = ruleChain.getName(); | 83 | this.ruleChainName = ruleChain.getName(); |
83 | this.parent = parent; | 84 | this.parent = parent; |
@@ -95,7 +96,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh | @@ -95,7 +96,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh | ||
95 | } | 96 | } |
96 | 97 | ||
97 | @Override | 98 | @Override |
98 | - public void start(ActorContext context) { | 99 | + public void start(TbActorCtx context) { |
99 | if (!started) { | 100 | if (!started) { |
100 | RuleChain ruleChain = service.findRuleChainById(tenantId, entityId); | 101 | RuleChain ruleChain = service.findRuleChainById(tenantId, entityId); |
101 | if (ruleChain != null) { | 102 | if (ruleChain != null) { |
@@ -105,7 +106,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh | @@ -105,7 +106,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh | ||
105 | // Creating and starting the actors; | 106 | // Creating and starting the actors; |
106 | for (RuleNode ruleNode : ruleNodeList) { | 107 | for (RuleNode ruleNode : ruleNodeList) { |
107 | log.trace("[{}][{}] Creating rule node [{}]: {}", entityId, ruleNode.getId(), ruleNode.getName(), ruleNode); | 108 | log.trace("[{}][{}] Creating rule node [{}]: {}", entityId, ruleNode.getId(), ruleNode.getName(), ruleNode); |
108 | - ActorRef ruleNodeActor = createRuleNodeActor(context, ruleNode); | 109 | + TbActorRef ruleNodeActor = createRuleNodeActor(context, ruleNode); |
109 | nodeActors.put(ruleNode.getId(), new RuleNodeCtx(tenantId, self, ruleNodeActor, ruleNode)); | 110 | nodeActors.put(ruleNode.getId(), new RuleNodeCtx(tenantId, self, ruleNodeActor, ruleNode)); |
110 | } | 111 | } |
111 | initRoutes(ruleChain, ruleNodeList); | 112 | initRoutes(ruleChain, ruleNodeList); |
@@ -118,7 +119,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh | @@ -118,7 +119,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh | ||
118 | } | 119 | } |
119 | 120 | ||
120 | @Override | 121 | @Override |
121 | - public void onUpdate(ActorContext context) { | 122 | + public void onUpdate(TbActorCtx context) { |
122 | RuleChain ruleChain = service.findRuleChainById(tenantId, entityId); | 123 | RuleChain ruleChain = service.findRuleChainById(tenantId, entityId); |
123 | if (ruleChain != null) { | 124 | if (ruleChain != null) { |
124 | if (ruleChain.getType().equals(RuleChainType.CORE)) { | 125 | if (ruleChain.getType().equals(RuleChainType.CORE)) { |
@@ -129,22 +130,22 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh | @@ -129,22 +130,22 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh | ||
129 | RuleNodeCtx existing = nodeActors.get(ruleNode.getId()); | 130 | RuleNodeCtx existing = nodeActors.get(ruleNode.getId()); |
130 | if (existing == null) { | 131 | if (existing == null) { |
131 | log.trace("[{}][{}] Creating rule node [{}]: {}", entityId, ruleNode.getId(), ruleNode.getName(), ruleNode); | 132 | log.trace("[{}][{}] Creating rule node [{}]: {}", entityId, ruleNode.getId(), ruleNode.getName(), ruleNode); |
132 | - ActorRef ruleNodeActor = createRuleNodeActor(context, ruleNode); | 133 | + TbActorRef ruleNodeActor = createRuleNodeActor(context, ruleNode); |
133 | nodeActors.put(ruleNode.getId(), new RuleNodeCtx(tenantId, self, ruleNodeActor, ruleNode)); | 134 | nodeActors.put(ruleNode.getId(), new RuleNodeCtx(tenantId, self, ruleNodeActor, ruleNode)); |
134 | } else { | 135 | } else { |
135 | log.trace("[{}][{}] Updating rule node [{}]: {}", entityId, ruleNode.getId(), ruleNode.getName(), ruleNode); | 136 | log.trace("[{}][{}] Updating rule node [{}]: {}", entityId, ruleNode.getId(), ruleNode.getName(), ruleNode); |
136 | existing.setSelf(ruleNode); | 137 | existing.setSelf(ruleNode); |
137 | - existing.getSelfActor().tell(new ComponentLifecycleMsg(tenantId, existing.getSelf().getId(), ComponentLifecycleEvent.UPDATED), self); | 138 | + existing.getSelfActor().tellWithHighPriority(new ComponentLifecycleMsg(tenantId, existing.getSelf().getId(), ComponentLifecycleEvent.UPDATED)); |
138 | } | 139 | } |
139 | } | 140 | } |
140 | 141 | ||
141 | - Set<RuleNodeId> existingNodes = ruleNodeList.stream().map(RuleNode::getId).collect(Collectors.toSet()); | ||
142 | - List<RuleNodeId> removedRules = nodeActors.keySet().stream().filter(node -> !existingNodes.contains(node)).collect(Collectors.toList()); | ||
143 | - removedRules.forEach(ruleNodeId -> { | ||
144 | - log.trace("[{}][{}] Removing rule node [{}]", tenantId, entityId, ruleNodeId); | ||
145 | - RuleNodeCtx removed = nodeActors.remove(ruleNodeId); | ||
146 | - removed.getSelfActor().tell(new ComponentLifecycleMsg(tenantId, removed.getSelf().getId(), ComponentLifecycleEvent.DELETED), self); | ||
147 | - }); | 142 | + Set<RuleNodeId> existingNodes = ruleNodeList.stream().map(RuleNode::getId).collect(Collectors.toSet()); |
143 | + List<RuleNodeId> removedRules = nodeActors.keySet().stream().filter(node -> !existingNodes.contains(node)).collect(Collectors.toList()); | ||
144 | + removedRules.forEach(ruleNodeId -> { | ||
145 | + log.trace("[{}][{}] Removing rule node [{}]", tenantId, entityId, ruleNodeId); | ||
146 | + RuleNodeCtx removed = nodeActors.remove(ruleNodeId); | ||
147 | + removed.getSelfActor().tellWithHighPriority(new ComponentLifecycleMsg(tenantId, removed.getSelf().getId(), ComponentLifecycleEvent.DELETED)); | ||
148 | + }); | ||
148 | 149 | ||
149 | initRoutes(ruleChain, ruleNodeList); | 150 | initRoutes(ruleChain, ruleNodeList); |
150 | } else if (ruleChain.getType().equals(RuleChainType.EDGE)) { | 151 | } else if (ruleChain.getType().equals(RuleChainType.EDGE)) { |
@@ -154,26 +155,23 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh | @@ -154,26 +155,23 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh | ||
154 | } | 155 | } |
155 | 156 | ||
156 | @Override | 157 | @Override |
157 | - public void stop(ActorContext context) { | 158 | + public void stop(TbActorCtx ctx) { |
158 | log.trace("[{}][{}] Stopping rule chain with {} nodes", tenantId, entityId, nodeActors.size()); | 159 | log.trace("[{}][{}] Stopping rule chain with {} nodes", tenantId, entityId, nodeActors.size()); |
159 | - nodeActors.values().stream().map(RuleNodeCtx::getSelfActor).forEach(context::stop); | 160 | + nodeActors.values().stream().map(RuleNodeCtx::getSelfActor).map(TbActorRef::getActorId).forEach(ctx::stop); |
160 | nodeActors.clear(); | 161 | nodeActors.clear(); |
161 | nodeRoutes.clear(); | 162 | nodeRoutes.clear(); |
162 | - context.stop(self); | ||
163 | started = false; | 163 | started = false; |
164 | } | 164 | } |
165 | 165 | ||
166 | @Override | 166 | @Override |
167 | public void onPartitionChangeMsg(PartitionChangeMsg msg) { | 167 | public void onPartitionChangeMsg(PartitionChangeMsg msg) { |
168 | - nodeActors.values().stream().map(RuleNodeCtx::getSelfActor).forEach(actorRef -> actorRef.tell(msg, self)); | 168 | + nodeActors.values().stream().map(RuleNodeCtx::getSelfActor).forEach(actorRef -> actorRef.tellWithHighPriority(msg)); |
169 | } | 169 | } |
170 | 170 | ||
171 | - private ActorRef createRuleNodeActor(ActorContext context, RuleNode ruleNode) { | ||
172 | - String dispatcherName = tenantId.getId().equals(EntityId.NULL_UUID) ? | ||
173 | - DefaultActorService.SYSTEM_RULE_DISPATCHER_NAME : DefaultActorService.TENANT_RULE_DISPATCHER_NAME; | ||
174 | - return context.actorOf( | ||
175 | - Props.create(new RuleNodeActor.ActorCreator(systemContext, tenantId, entityId, ruleNode.getName(), ruleNode.getId())) | ||
176 | - .withDispatcher(dispatcherName), ruleNode.getId().toString()); | 171 | + private TbActorRef createRuleNodeActor(TbActorCtx ctx, RuleNode ruleNode) { |
172 | + return ctx.getOrCreateChildActor(new TbEntityActorId(ruleNode.getId()), | ||
173 | + () -> DefaultActorService.RULE_DISPATCHER_NAME, | ||
174 | + () -> new RuleNodeActor.ActorCreator(systemContext, tenantId, entityId, ruleNode.getName(), ruleNode.getId())); | ||
177 | } | 175 | } |
178 | 176 | ||
179 | private void initRoutes(RuleChain ruleChain, List<RuleNode> ruleNodeList) { | 177 | private void initRoutes(RuleChain ruleChain, List<RuleNode> ruleNodeList) { |
@@ -256,7 +254,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh | @@ -256,7 +254,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh | ||
256 | try { | 254 | try { |
257 | checkActive(msg); | 255 | checkActive(msg); |
258 | EntityId entityId = msg.getOriginator(); | 256 | EntityId entityId = msg.getOriginator(); |
259 | - TopicPartitionInfo tpi = systemContext.resolve(ServiceType.TB_RULE_ENGINE, tenantId, entityId); | 257 | + TopicPartitionInfo tpi = systemContext.resolve(ServiceType.TB_RULE_ENGINE, msg.getQueueName(), tenantId, entityId); |
260 | List<RuleNodeRelation> relations = nodeRoutes.get(originatorNodeId).stream() | 258 | List<RuleNodeRelation> relations = nodeRoutes.get(originatorNodeId).stream() |
261 | .filter(r -> contains(relationTypes, r.getType())) | 259 | .filter(r -> contains(relationTypes, r.getType())) |
262 | .collect(Collectors.toList()); | 260 | .collect(Collectors.toList()); |
@@ -312,7 +310,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh | @@ -312,7 +310,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh | ||
312 | pushMsgToNode(nodeActors.get(new RuleNodeId(target.getId())), msg, fromRelationType); | 310 | pushMsgToNode(nodeActors.get(new RuleNodeId(target.getId())), msg, fromRelationType); |
313 | break; | 311 | break; |
314 | case RULE_CHAIN: | 312 | case RULE_CHAIN: |
315 | - parent.tell(new RuleChainToRuleChainMsg(new RuleChainId(target.getId()), entityId, msg, fromRelationType), self); | 313 | + parent.tell(new RuleChainToRuleChainMsg(new RuleChainId(target.getId()), entityId, msg, fromRelationType)); |
316 | break; | 314 | break; |
317 | } | 315 | } |
318 | } else { | 316 | } else { |
@@ -343,7 +341,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh | @@ -343,7 +341,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh | ||
343 | 341 | ||
344 | private void pushMsgToNode(RuleNodeCtx nodeCtx, TbMsg msg, String fromRelationType) { | 342 | private void pushMsgToNode(RuleNodeCtx nodeCtx, TbMsg msg, String fromRelationType) { |
345 | if (nodeCtx != null) { | 343 | if (nodeCtx != null) { |
346 | - nodeCtx.getSelfActor().tell(new RuleChainToRuleNodeMsg(new DefaultTbContext(systemContext, nodeCtx), msg, fromRelationType), self); | 344 | + nodeCtx.getSelfActor().tell(new RuleChainToRuleNodeMsg(new DefaultTbContext(systemContext, nodeCtx), msg, fromRelationType)); |
347 | } else { | 345 | } else { |
348 | log.error("[{}][{}] RuleNodeCtx is empty", entityId, ruleChainName); | 346 | log.error("[{}][{}] RuleNodeCtx is empty", entityId, ruleChainName); |
349 | msg.getCallback().onFailure(new RuleEngineException("Rule Node CTX is empty")); | 347 | msg.getCallback().onFailure(new RuleEngineException("Rule Node CTX is empty")); |
@@ -15,21 +15,22 @@ | @@ -15,21 +15,22 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.actors.ruleChain; | 16 | package org.thingsboard.server.actors.ruleChain; |
17 | 17 | ||
18 | -import akka.actor.ActorContext; | ||
19 | -import akka.actor.ActorRef; | ||
20 | -import akka.actor.Props; | ||
21 | -import com.google.common.collect.BiMap; | ||
22 | -import com.google.common.collect.HashBiMap; | ||
23 | import lombok.Getter; | 18 | import lombok.Getter; |
19 | +import lombok.extern.slf4j.Slf4j; | ||
24 | import org.thingsboard.server.actors.ActorSystemContext; | 20 | import org.thingsboard.server.actors.ActorSystemContext; |
21 | +import org.thingsboard.server.actors.TbActorRef; | ||
22 | +import org.thingsboard.server.actors.TbEntityActorId; | ||
23 | +import org.thingsboard.server.actors.TbEntityTypeActorIdPredicate; | ||
25 | import org.thingsboard.server.actors.service.ContextAwareActor; | 24 | import org.thingsboard.server.actors.service.ContextAwareActor; |
26 | import org.thingsboard.server.actors.service.DefaultActorService; | 25 | import org.thingsboard.server.actors.service.DefaultActorService; |
26 | +import org.thingsboard.server.actors.tenant.TenantActor; | ||
27 | import org.thingsboard.server.common.data.EntityType; | 27 | import org.thingsboard.server.common.data.EntityType; |
28 | import org.thingsboard.server.common.data.id.EntityId; | 28 | import org.thingsboard.server.common.data.id.EntityId; |
29 | import org.thingsboard.server.common.data.id.RuleChainId; | 29 | import org.thingsboard.server.common.data.id.RuleChainId; |
30 | import org.thingsboard.server.common.data.id.TenantId; | 30 | import org.thingsboard.server.common.data.id.TenantId; |
31 | import org.thingsboard.server.common.data.page.PageDataIterable; | 31 | import org.thingsboard.server.common.data.page.PageDataIterable; |
32 | import org.thingsboard.server.common.data.rule.RuleChain; | 32 | import org.thingsboard.server.common.data.rule.RuleChain; |
33 | +import org.thingsboard.server.common.msg.TbActorMsg; | ||
33 | import org.thingsboard.server.common.data.rule.RuleChainType; | 34 | import org.thingsboard.server.common.data.rule.RuleChainType; |
34 | import org.thingsboard.server.dao.rule.RuleChainService; | 35 | import org.thingsboard.server.dao.rule.RuleChainService; |
35 | 36 | ||
@@ -38,20 +39,19 @@ import java.util.function.Function; | @@ -38,20 +39,19 @@ import java.util.function.Function; | ||
38 | /** | 39 | /** |
39 | * Created by ashvayka on 15.03.18. | 40 | * Created by ashvayka on 15.03.18. |
40 | */ | 41 | */ |
42 | +@Slf4j | ||
41 | public abstract class RuleChainManagerActor extends ContextAwareActor { | 43 | public abstract class RuleChainManagerActor extends ContextAwareActor { |
42 | 44 | ||
43 | protected final TenantId tenantId; | 45 | protected final TenantId tenantId; |
44 | private final RuleChainService ruleChainService; | 46 | private final RuleChainService ruleChainService; |
45 | - private final BiMap<RuleChainId, ActorRef> actors; | ||
46 | @Getter | 47 | @Getter |
47 | protected RuleChain rootChain; | 48 | protected RuleChain rootChain; |
48 | @Getter | 49 | @Getter |
49 | - protected ActorRef rootChainActor; | 50 | + protected TbActorRef rootChainActor; |
50 | 51 | ||
51 | public RuleChainManagerActor(ActorSystemContext systemContext, TenantId tenantId) { | 52 | public RuleChainManagerActor(ActorSystemContext systemContext, TenantId tenantId) { |
52 | super(systemContext); | 53 | super(systemContext); |
53 | this.tenantId = tenantId; | 54 | this.tenantId = tenantId; |
54 | - this.actors = HashBiMap.create(); | ||
55 | this.ruleChainService = systemContext.getRuleChainService(); | 55 | this.ruleChainService = systemContext.getRuleChainService(); |
56 | } | 56 | } |
57 | 57 | ||
@@ -59,46 +59,41 @@ public abstract class RuleChainManagerActor extends ContextAwareActor { | @@ -59,46 +59,41 @@ public abstract class RuleChainManagerActor extends ContextAwareActor { | ||
59 | for (RuleChain ruleChain : new PageDataIterable<>(link -> ruleChainService.findTenantRuleChainsByType(tenantId, RuleChainType.CORE, link), ContextAwareActor.ENTITY_PACK_LIMIT)) { | 59 | for (RuleChain ruleChain : new PageDataIterable<>(link -> ruleChainService.findTenantRuleChainsByType(tenantId, RuleChainType.CORE, link), ContextAwareActor.ENTITY_PACK_LIMIT)) { |
60 | RuleChainId ruleChainId = ruleChain.getId(); | 60 | RuleChainId ruleChainId = ruleChain.getId(); |
61 | log.debug("[{}|{}] Creating rule chain actor", ruleChainId.getEntityType(), ruleChain.getId()); | 61 | log.debug("[{}|{}] Creating rule chain actor", ruleChainId.getEntityType(), ruleChain.getId()); |
62 | - //TODO: remove this cast making UUIDBased subclass of EntityId an interface and vice versa. | ||
63 | - ActorRef actorRef = getOrCreateActor(this.context(), ruleChainId, id -> ruleChain); | 62 | + TbActorRef actorRef = getOrCreateActor(ruleChainId, id -> ruleChain); |
64 | visit(ruleChain, actorRef); | 63 | visit(ruleChain, actorRef); |
65 | log.debug("[{}|{}] Rule Chain actor created.", ruleChainId.getEntityType(), ruleChainId.getId()); | 64 | log.debug("[{}|{}] Rule Chain actor created.", ruleChainId.getEntityType(), ruleChainId.getId()); |
66 | } | 65 | } |
67 | } | 66 | } |
68 | 67 | ||
69 | - protected void visit(RuleChain entity, ActorRef actorRef) { | 68 | + protected void visit(RuleChain entity, TbActorRef actorRef) { |
70 | if (entity != null && entity.isRoot() && entity.getType().equals(RuleChainType.CORE)) { | 69 | if (entity != null && entity.isRoot() && entity.getType().equals(RuleChainType.CORE)) { |
71 | rootChain = entity; | 70 | rootChain = entity; |
72 | rootChainActor = actorRef; | 71 | rootChainActor = actorRef; |
73 | } | 72 | } |
74 | } | 73 | } |
75 | 74 | ||
76 | - public ActorRef getOrCreateActor(akka.actor.ActorContext context, RuleChainId ruleChainId) { | ||
77 | - return getOrCreateActor(context, ruleChainId, eId -> ruleChainService.findRuleChainById(TenantId.SYS_TENANT_ID, eId)); | 75 | + protected TbActorRef getOrCreateActor(RuleChainId ruleChainId) { |
76 | + return getOrCreateActor(ruleChainId, eId -> ruleChainService.findRuleChainById(TenantId.SYS_TENANT_ID, eId)); | ||
78 | } | 77 | } |
79 | 78 | ||
80 | - public ActorRef getOrCreateActor(akka.actor.ActorContext context, RuleChainId ruleChainId, Function<RuleChainId, RuleChain> provider) { | ||
81 | - return actors.computeIfAbsent(ruleChainId, eId -> { | ||
82 | - RuleChain ruleChain = provider.apply(eId); | ||
83 | - return context.actorOf(Props.create(new RuleChainActor.ActorCreator(systemContext, tenantId, ruleChain)) | ||
84 | - .withDispatcher(DefaultActorService.TENANT_RULE_DISPATCHER_NAME), eId.toString()); | ||
85 | - }); | 79 | + protected TbActorRef getOrCreateActor(RuleChainId ruleChainId, Function<RuleChainId, RuleChain> provider) { |
80 | + return ctx.getOrCreateChildActor(new TbEntityActorId(ruleChainId), | ||
81 | + () -> DefaultActorService.RULE_DISPATCHER_NAME, | ||
82 | + () -> { | ||
83 | + RuleChain ruleChain = provider.apply(ruleChainId); | ||
84 | + return new RuleChainActor.ActorCreator(systemContext, tenantId, ruleChain); | ||
85 | + }); | ||
86 | } | 86 | } |
87 | 87 | ||
88 | - protected ActorRef getEntityActorRef(EntityId entityId) { | ||
89 | - ActorRef target = null; | 88 | + protected TbActorRef getEntityActorRef(EntityId entityId) { |
89 | + TbActorRef target = null; | ||
90 | if (entityId.getEntityType() == EntityType.RULE_CHAIN) { | 90 | if (entityId.getEntityType() == EntityType.RULE_CHAIN) { |
91 | - target = getOrCreateActor(this.context(), (RuleChainId) entityId); | 91 | + target = getOrCreateActor((RuleChainId) entityId); |
92 | } | 92 | } |
93 | return target; | 93 | return target; |
94 | } | 94 | } |
95 | 95 | ||
96 | - protected void broadcast(Object msg) { | ||
97 | - actors.values().forEach(actorRef -> actorRef.tell(msg, ActorRef.noSender())); | 96 | + protected void broadcast(TbActorMsg msg) { |
97 | + ctx.broadcastToChildren(msg, new TbEntityTypeActorIdPredicate(EntityType.RULE_CHAIN)); | ||
98 | } | 98 | } |
99 | - | ||
100 | - public ActorRef get(RuleChainId id) { | ||
101 | - return actors.get(id); | ||
102 | - } | ||
103 | - | ||
104 | } | 99 | } |
@@ -15,31 +15,43 @@ | @@ -15,31 +15,43 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.actors.ruleChain; | 16 | package org.thingsboard.server.actors.ruleChain; |
17 | 17 | ||
18 | +import lombok.extern.slf4j.Slf4j; | ||
18 | import org.thingsboard.server.actors.ActorSystemContext; | 19 | import org.thingsboard.server.actors.ActorSystemContext; |
20 | +import org.thingsboard.server.actors.TbActor; | ||
21 | +import org.thingsboard.server.actors.TbActorCtx; | ||
22 | +import org.thingsboard.server.actors.TbActorId; | ||
23 | +import org.thingsboard.server.actors.TbEntityActorId; | ||
19 | import org.thingsboard.server.actors.service.ComponentActor; | 24 | import org.thingsboard.server.actors.service.ComponentActor; |
20 | import org.thingsboard.server.actors.service.ContextBasedCreator; | 25 | import org.thingsboard.server.actors.service.ContextBasedCreator; |
21 | import org.thingsboard.server.common.data.id.RuleChainId; | 26 | import org.thingsboard.server.common.data.id.RuleChainId; |
22 | import org.thingsboard.server.common.data.id.RuleNodeId; | 27 | import org.thingsboard.server.common.data.id.RuleNodeId; |
23 | import org.thingsboard.server.common.data.id.TenantId; | 28 | import org.thingsboard.server.common.data.id.TenantId; |
29 | +import org.thingsboard.server.common.data.rule.RuleChain; | ||
24 | import org.thingsboard.server.common.msg.TbActorMsg; | 30 | import org.thingsboard.server.common.msg.TbActorMsg; |
25 | import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; | 31 | import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; |
26 | import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; | 32 | import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; |
27 | 33 | ||
34 | +@Slf4j | ||
28 | public class RuleNodeActor extends ComponentActor<RuleNodeId, RuleNodeActorMessageProcessor> { | 35 | public class RuleNodeActor extends ComponentActor<RuleNodeId, RuleNodeActorMessageProcessor> { |
29 | 36 | ||
30 | private final String ruleChainName; | 37 | private final String ruleChainName; |
31 | private final RuleChainId ruleChainId; | 38 | private final RuleChainId ruleChainId; |
39 | + private final RuleNodeId ruleNodeId; | ||
32 | 40 | ||
33 | private RuleNodeActor(ActorSystemContext systemContext, TenantId tenantId, RuleChainId ruleChainId, String ruleChainName, RuleNodeId ruleNodeId) { | 41 | private RuleNodeActor(ActorSystemContext systemContext, TenantId tenantId, RuleChainId ruleChainId, String ruleChainName, RuleNodeId ruleNodeId) { |
34 | super(systemContext, tenantId, ruleNodeId); | 42 | super(systemContext, tenantId, ruleNodeId); |
35 | this.ruleChainName = ruleChainName; | 43 | this.ruleChainName = ruleChainName; |
36 | this.ruleChainId = ruleChainId; | 44 | this.ruleChainId = ruleChainId; |
37 | - setProcessor(new RuleNodeActorMessageProcessor(tenantId, this.ruleChainName, ruleNodeId, systemContext, | ||
38 | - context().parent(), context().self())); | 45 | + this.ruleNodeId = ruleNodeId; |
39 | } | 46 | } |
40 | 47 | ||
41 | @Override | 48 | @Override |
42 | - protected boolean process(TbActorMsg msg) { | 49 | + protected RuleNodeActorMessageProcessor createProcessor(TbActorCtx ctx) { |
50 | + return new RuleNodeActorMessageProcessor(tenantId, this.ruleChainName, ruleNodeId, systemContext, ctx.getParentRef(), ctx); | ||
51 | + } | ||
52 | + | ||
53 | + @Override | ||
54 | + protected boolean doProcess(TbActorMsg msg) { | ||
43 | switch (msg.getMsgType()) { | 55 | switch (msg.getMsgType()) { |
44 | case COMPONENT_LIFE_CYCLE_MSG: | 56 | case COMPONENT_LIFE_CYCLE_MSG: |
45 | onComponentLifecycleMsg((ComponentLifecycleMsg) msg); | 57 | onComponentLifecycleMsg((ComponentLifecycleMsg) msg); |
@@ -93,8 +105,7 @@ public class RuleNodeActor extends ComponentActor<RuleNodeId, RuleNodeActorMessa | @@ -93,8 +105,7 @@ public class RuleNodeActor extends ComponentActor<RuleNodeId, RuleNodeActorMessa | ||
93 | logAndPersist("onRuleMsg", ActorSystemContext.toException(msg.getError())); | 105 | logAndPersist("onRuleMsg", ActorSystemContext.toException(msg.getError())); |
94 | } | 106 | } |
95 | 107 | ||
96 | - public static class ActorCreator extends ContextBasedCreator<RuleNodeActor> { | ||
97 | - private static final long serialVersionUID = 1L; | 108 | + public static class ActorCreator extends ContextBasedCreator { |
98 | 109 | ||
99 | private final TenantId tenantId; | 110 | private final TenantId tenantId; |
100 | private final RuleChainId ruleChainId; | 111 | private final RuleChainId ruleChainId; |
@@ -111,7 +122,12 @@ public class RuleNodeActor extends ComponentActor<RuleNodeId, RuleNodeActorMessa | @@ -111,7 +122,12 @@ public class RuleNodeActor extends ComponentActor<RuleNodeId, RuleNodeActorMessa | ||
111 | } | 122 | } |
112 | 123 | ||
113 | @Override | 124 | @Override |
114 | - public RuleNodeActor create() throws Exception { | 125 | + public TbActorId createActorId() { |
126 | + return new TbEntityActorId(ruleNodeId); | ||
127 | + } | ||
128 | + | ||
129 | + @Override | ||
130 | + public TbActor createActor() { | ||
115 | return new RuleNodeActor(context, tenantId, ruleChainId, ruleChainName, ruleNodeId); | 131 | return new RuleNodeActor(context, tenantId, ruleChainId, ruleChainName, ruleNodeId); |
116 | } | 132 | } |
117 | } | 133 | } |
application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeActorMessageProcessor.java
@@ -15,11 +15,11 @@ | @@ -15,11 +15,11 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.actors.ruleChain; | 16 | package org.thingsboard.server.actors.ruleChain; |
17 | 17 | ||
18 | -import akka.actor.ActorContext; | ||
19 | -import akka.actor.ActorRef; | ||
20 | import org.thingsboard.rule.engine.api.TbNode; | 18 | import org.thingsboard.rule.engine.api.TbNode; |
21 | import org.thingsboard.rule.engine.api.TbNodeConfiguration; | 19 | import org.thingsboard.rule.engine.api.TbNodeConfiguration; |
22 | import org.thingsboard.server.actors.ActorSystemContext; | 20 | import org.thingsboard.server.actors.ActorSystemContext; |
21 | +import org.thingsboard.server.actors.TbActorCtx; | ||
22 | +import org.thingsboard.server.actors.TbActorRef; | ||
23 | import org.thingsboard.server.actors.shared.ComponentMsgProcessor; | 23 | import org.thingsboard.server.actors.shared.ComponentMsgProcessor; |
24 | import org.thingsboard.server.common.data.id.RuleNodeId; | 24 | import org.thingsboard.server.common.data.id.RuleNodeId; |
25 | import org.thingsboard.server.common.data.id.TenantId; | 25 | import org.thingsboard.server.common.data.id.TenantId; |
@@ -34,13 +34,13 @@ import org.thingsboard.server.common.msg.queue.RuleNodeException; | @@ -34,13 +34,13 @@ import org.thingsboard.server.common.msg.queue.RuleNodeException; | ||
34 | public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor<RuleNodeId> { | 34 | public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor<RuleNodeId> { |
35 | 35 | ||
36 | private final String ruleChainName; | 36 | private final String ruleChainName; |
37 | - private final ActorRef self; | 37 | + private final TbActorRef self; |
38 | private RuleNode ruleNode; | 38 | private RuleNode ruleNode; |
39 | private TbNode tbNode; | 39 | private TbNode tbNode; |
40 | private DefaultTbContext defaultCtx; | 40 | private DefaultTbContext defaultCtx; |
41 | 41 | ||
42 | RuleNodeActorMessageProcessor(TenantId tenantId, String ruleChainName, RuleNodeId ruleNodeId, ActorSystemContext systemContext | 42 | RuleNodeActorMessageProcessor(TenantId tenantId, String ruleChainName, RuleNodeId ruleNodeId, ActorSystemContext systemContext |
43 | - , ActorRef parent, ActorRef self) { | 43 | + , TbActorRef parent, TbActorRef self) { |
44 | super(systemContext, tenantId, ruleNodeId); | 44 | super(systemContext, tenantId, ruleNodeId); |
45 | this.ruleChainName = ruleChainName; | 45 | this.ruleChainName = ruleChainName; |
46 | this.self = self; | 46 | this.self = self; |
@@ -49,7 +49,7 @@ public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor<RuleNod | @@ -49,7 +49,7 @@ public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor<RuleNod | ||
49 | } | 49 | } |
50 | 50 | ||
51 | @Override | 51 | @Override |
52 | - public void start(ActorContext context) throws Exception { | 52 | + public void start(TbActorCtx context) throws Exception { |
53 | tbNode = initComponent(ruleNode); | 53 | tbNode = initComponent(ruleNode); |
54 | if (tbNode != null) { | 54 | if (tbNode != null) { |
55 | state = ComponentLifecycleState.ACTIVE; | 55 | state = ComponentLifecycleState.ACTIVE; |
@@ -57,7 +57,7 @@ public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor<RuleNod | @@ -57,7 +57,7 @@ public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor<RuleNod | ||
57 | } | 57 | } |
58 | 58 | ||
59 | @Override | 59 | @Override |
60 | - public void onUpdate(ActorContext context) throws Exception { | 60 | + public void onUpdate(TbActorCtx context) throws Exception { |
61 | RuleNode newRuleNode = systemContext.getRuleChainService().findRuleNodeById(tenantId, entityId); | 61 | RuleNode newRuleNode = systemContext.getRuleChainService().findRuleNodeById(tenantId, entityId); |
62 | boolean restartRequired = state != ComponentLifecycleState.ACTIVE || | 62 | boolean restartRequired = state != ComponentLifecycleState.ACTIVE || |
63 | !(ruleNode.getType().equals(newRuleNode.getType()) && ruleNode.getConfiguration().equals(newRuleNode.getConfiguration())); | 63 | !(ruleNode.getType().equals(newRuleNode.getType()) && ruleNode.getConfiguration().equals(newRuleNode.getConfiguration())); |
@@ -72,11 +72,11 @@ public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor<RuleNod | @@ -72,11 +72,11 @@ public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor<RuleNod | ||
72 | } | 72 | } |
73 | 73 | ||
74 | @Override | 74 | @Override |
75 | - public void stop(ActorContext context) { | 75 | + public void stop(TbActorCtx context) { |
76 | if (tbNode != null) { | 76 | if (tbNode != null) { |
77 | tbNode.destroy(); | 77 | tbNode.destroy(); |
78 | + state = ComponentLifecycleState.SUSPENDED; | ||
78 | } | 79 | } |
79 | - context.stop(self); | ||
80 | } | 80 | } |
81 | 81 | ||
82 | @Override | 82 | @Override |
@@ -15,9 +15,9 @@ | @@ -15,9 +15,9 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.actors.ruleChain; | 16 | package org.thingsboard.server.actors.ruleChain; |
17 | 17 | ||
18 | -import akka.actor.ActorRef; | ||
19 | import lombok.AllArgsConstructor; | 18 | import lombok.AllArgsConstructor; |
20 | import lombok.Data; | 19 | import lombok.Data; |
20 | +import org.thingsboard.server.actors.TbActorRef; | ||
21 | import org.thingsboard.server.common.data.id.TenantId; | 21 | import org.thingsboard.server.common.data.id.TenantId; |
22 | import org.thingsboard.server.common.data.rule.RuleNode; | 22 | import org.thingsboard.server.common.data.rule.RuleNode; |
23 | 23 | ||
@@ -28,7 +28,7 @@ import org.thingsboard.server.common.data.rule.RuleNode; | @@ -28,7 +28,7 @@ import org.thingsboard.server.common.data.rule.RuleNode; | ||
28 | @AllArgsConstructor | 28 | @AllArgsConstructor |
29 | final class RuleNodeCtx { | 29 | final class RuleNodeCtx { |
30 | private final TenantId tenantId; | 30 | private final TenantId tenantId; |
31 | - private final ActorRef chainActor; | ||
32 | - private final ActorRef selfActor; | 31 | + private final TbActorRef chainActor; |
32 | + private final TbActorRef selfActor; | ||
33 | private RuleNode self; | 33 | private RuleNode self; |
34 | } | 34 | } |
@@ -15,19 +15,23 @@ | @@ -15,19 +15,23 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.actors.service; | 16 | package org.thingsboard.server.actors.service; |
17 | 17 | ||
18 | -import akka.actor.ActorRef; | 18 | +import lombok.extern.slf4j.Slf4j; |
19 | import org.thingsboard.server.actors.ActorSystemContext; | 19 | import org.thingsboard.server.actors.ActorSystemContext; |
20 | +import org.thingsboard.server.actors.TbActor; | ||
21 | +import org.thingsboard.server.actors.TbActorCtx; | ||
22 | +import org.thingsboard.server.actors.TbActorException; | ||
20 | import org.thingsboard.server.actors.shared.ComponentMsgProcessor; | 23 | import org.thingsboard.server.actors.shared.ComponentMsgProcessor; |
21 | import org.thingsboard.server.actors.stats.StatsPersistMsg; | 24 | import org.thingsboard.server.actors.stats.StatsPersistMsg; |
22 | import org.thingsboard.server.common.data.id.EntityId; | 25 | import org.thingsboard.server.common.data.id.EntityId; |
23 | import org.thingsboard.server.common.data.id.TenantId; | 26 | import org.thingsboard.server.common.data.id.TenantId; |
24 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; | 27 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; |
25 | -import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; | ||
26 | import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; | 28 | import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; |
29 | +import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; | ||
27 | 30 | ||
28 | /** | 31 | /** |
29 | * @author Andrew Shvayka | 32 | * @author Andrew Shvayka |
30 | */ | 33 | */ |
34 | +@Slf4j | ||
31 | public abstract class ComponentActor<T extends EntityId, P extends ComponentMsgProcessor<T>> extends ContextAwareActor { | 35 | public abstract class ComponentActor<T extends EntityId, P extends ComponentMsgProcessor<T>> extends ContextAwareActor { |
32 | 36 | ||
33 | private long lastPersistedErrorTs = 0L; | 37 | private long lastPersistedErrorTs = 0L; |
@@ -43,30 +47,34 @@ public abstract class ComponentActor<T extends EntityId, P extends ComponentMsgP | @@ -43,30 +47,34 @@ public abstract class ComponentActor<T extends EntityId, P extends ComponentMsgP | ||
43 | this.id = id; | 47 | this.id = id; |
44 | } | 48 | } |
45 | 49 | ||
46 | - protected void setProcessor(P processor) { | ||
47 | - this.processor = processor; | ||
48 | - } | 50 | + abstract protected P createProcessor(TbActorCtx ctx); |
49 | 51 | ||
50 | @Override | 52 | @Override |
51 | - public void preStart() { | 53 | + public void init(TbActorCtx ctx) throws TbActorException { |
54 | + super.init(ctx); | ||
55 | + this.processor = createProcessor(ctx); | ||
56 | + initProcessor(ctx); | ||
57 | + } | ||
58 | + | ||
59 | + protected void initProcessor(TbActorCtx ctx) throws TbActorException { | ||
52 | try { | 60 | try { |
53 | log.debug("[{}][{}][{}] Starting processor.", tenantId, id, id.getEntityType()); | 61 | log.debug("[{}][{}][{}] Starting processor.", tenantId, id, id.getEntityType()); |
54 | - processor.start(context()); | 62 | + processor.start(ctx); |
55 | logLifecycleEvent(ComponentLifecycleEvent.STARTED); | 63 | logLifecycleEvent(ComponentLifecycleEvent.STARTED); |
56 | if (systemContext.isStatisticsEnabled()) { | 64 | if (systemContext.isStatisticsEnabled()) { |
57 | scheduleStatsPersistTick(); | 65 | scheduleStatsPersistTick(); |
58 | } | 66 | } |
59 | } catch (Exception e) { | 67 | } catch (Exception e) { |
60 | - log.warn("[{}][{}] Failed to start {} processor.", tenantId, id, id.getEntityType()); | ||
61 | - log.warn("Error:", e); | 68 | + log.debug("[{}][{}] Failed to start {} processor.", tenantId, id, id.getEntityType(), e); |
62 | logAndPersist("OnStart", e, true); | 69 | logAndPersist("OnStart", e, true); |
63 | logLifecycleEvent(ComponentLifecycleEvent.STARTED, e); | 70 | logLifecycleEvent(ComponentLifecycleEvent.STARTED, e); |
71 | + throw new TbActorException("Failed to init actor", e); | ||
64 | } | 72 | } |
65 | } | 73 | } |
66 | 74 | ||
67 | private void scheduleStatsPersistTick() { | 75 | private void scheduleStatsPersistTick() { |
68 | try { | 76 | try { |
69 | - processor.scheduleStatsPersistTick(context(), systemContext.getStatisticsPersistFrequency()); | 77 | + processor.scheduleStatsPersistTick(ctx, systemContext.getStatisticsPersistFrequency()); |
70 | } catch (Exception e) { | 78 | } catch (Exception e) { |
71 | log.error("[{}][{}] Failed to schedule statistics store message. No statistics is going to be stored: {}", tenantId, id, e.getMessage()); | 79 | log.error("[{}][{}] Failed to schedule statistics store message. No statistics is going to be stored: {}", tenantId, id, e.getMessage()); |
72 | logAndPersist("onScheduleStatsPersistMsg", e); | 80 | logAndPersist("onScheduleStatsPersistMsg", e); |
@@ -74,10 +82,12 @@ public abstract class ComponentActor<T extends EntityId, P extends ComponentMsgP | @@ -74,10 +82,12 @@ public abstract class ComponentActor<T extends EntityId, P extends ComponentMsgP | ||
74 | } | 82 | } |
75 | 83 | ||
76 | @Override | 84 | @Override |
77 | - public void postStop() { | 85 | + public void destroy() { |
78 | try { | 86 | try { |
79 | - log.debug("[{}][{}] Stopping processor.", tenantId, id, id.getEntityType()); | ||
80 | - processor.stop(context()); | 87 | + log.debug("[{}][{}][{}] Stopping processor.", tenantId, id, id.getEntityType()); |
88 | + if (processor != null) { | ||
89 | + processor.stop(ctx); | ||
90 | + } | ||
81 | logLifecycleEvent(ComponentLifecycleEvent.STOPPED); | 91 | logLifecycleEvent(ComponentLifecycleEvent.STOPPED); |
82 | } catch (Exception e) { | 92 | } catch (Exception e) { |
83 | log.warn("[{}][{}] Failed to stop {} processor: {}", tenantId, id, id.getEntityType(), e.getMessage()); | 93 | log.warn("[{}][{}] Failed to stop {} processor: {}", tenantId, id, id.getEntityType(), e.getMessage()); |
@@ -91,19 +101,20 @@ public abstract class ComponentActor<T extends EntityId, P extends ComponentMsgP | @@ -91,19 +101,20 @@ public abstract class ComponentActor<T extends EntityId, P extends ComponentMsgP | ||
91 | try { | 101 | try { |
92 | switch (msg.getEvent()) { | 102 | switch (msg.getEvent()) { |
93 | case CREATED: | 103 | case CREATED: |
94 | - processor.onCreated(context()); | 104 | + processor.onCreated(ctx); |
95 | break; | 105 | break; |
96 | case UPDATED: | 106 | case UPDATED: |
97 | - processor.onUpdate(context()); | 107 | + processor.onUpdate(ctx); |
98 | break; | 108 | break; |
99 | case ACTIVATED: | 109 | case ACTIVATED: |
100 | - processor.onActivate(context()); | 110 | + processor.onActivate(ctx); |
101 | break; | 111 | break; |
102 | case SUSPENDED: | 112 | case SUSPENDED: |
103 | - processor.onSuspend(context()); | 113 | + processor.onSuspend(ctx); |
104 | break; | 114 | break; |
105 | case DELETED: | 115 | case DELETED: |
106 | - processor.onStop(context()); | 116 | + processor.onStop(ctx); |
117 | + ctx.stop(ctx.getSelf()); | ||
107 | break; | 118 | break; |
108 | default: | 119 | default: |
109 | break; | 120 | break; |
@@ -125,7 +136,7 @@ public abstract class ComponentActor<T extends EntityId, P extends ComponentMsgP | @@ -125,7 +136,7 @@ public abstract class ComponentActor<T extends EntityId, P extends ComponentMsgP | ||
125 | 136 | ||
126 | protected void onStatsPersistTick(EntityId entityId) { | 137 | protected void onStatsPersistTick(EntityId entityId) { |
127 | try { | 138 | try { |
128 | - systemContext.getStatsActor().tell(new StatsPersistMsg(messagesProcessed, errorsOccurred, tenantId, entityId), ActorRef.noSender()); | 139 | + systemContext.getStatsActor().tell(new StatsPersistMsg(messagesProcessed, errorsOccurred, tenantId, entityId)); |
129 | resetStatsCounters(); | 140 | resetStatsCounters(); |
130 | } catch (Exception e) { | 141 | } catch (Exception e) { |
131 | logAndPersist("onStatsPersistTick", e); | 142 | logAndPersist("onStatsPersistTick", e); |
@@ -149,11 +160,11 @@ public abstract class ComponentActor<T extends EntityId, P extends ComponentMsgP | @@ -149,11 +160,11 @@ public abstract class ComponentActor<T extends EntityId, P extends ComponentMsgP | ||
149 | errorsOccurred++; | 160 | errorsOccurred++; |
150 | String componentName = processor != null ? processor.getComponentName() : "Unknown"; | 161 | String componentName = processor != null ? processor.getComponentName() : "Unknown"; |
151 | if (critical) { | 162 | if (critical) { |
152 | - log.warn("[{}][{}][{}] Failed to process {} msg: {}", id, tenantId, componentName, method); | ||
153 | - log.warn("Critical Error: ", e); | 163 | + log.debug("[{}][{}][{}] Failed to process method: {}", id, tenantId, componentName, method); |
164 | + log.debug("Critical Error: ", e); | ||
154 | } else { | 165 | } else { |
155 | - log.debug("[{}][{}][{}] Failed to process {} msg: {}", id, tenantId, componentName, method); | ||
156 | - log.debug("Debug Error: ", e); | 166 | + log.trace("[{}][{}][{}] Failed to process method: {}", id, tenantId, componentName, method); |
167 | + log.trace("Debug Error: ", e); | ||
157 | } | 168 | } |
158 | long ts = System.currentTimeMillis(); | 169 | long ts = System.currentTimeMillis(); |
159 | if (ts - lastPersistedErrorTs > getErrorPersistFrequency()) { | 170 | if (ts - lastPersistedErrorTs > getErrorPersistFrequency()) { |
@@ -15,17 +15,18 @@ | @@ -15,17 +15,18 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.actors.service; | 16 | package org.thingsboard.server.actors.service; |
17 | 17 | ||
18 | -import akka.actor.Terminated; | ||
19 | -import akka.actor.UntypedAbstractActor; | 18 | +import lombok.extern.slf4j.Slf4j; |
20 | import org.slf4j.Logger; | 19 | import org.slf4j.Logger; |
21 | import org.slf4j.LoggerFactory; | 20 | import org.slf4j.LoggerFactory; |
21 | +import org.thingsboard.server.actors.AbstractTbActor; | ||
22 | import org.thingsboard.server.actors.ActorSystemContext; | 22 | import org.thingsboard.server.actors.ActorSystemContext; |
23 | +import org.thingsboard.server.actors.ProcessFailureStrategy; | ||
24 | +import org.thingsboard.server.actors.TbActor; | ||
25 | +import org.thingsboard.server.actors.TbActorCtx; | ||
23 | import org.thingsboard.server.common.msg.TbActorMsg; | 26 | import org.thingsboard.server.common.msg.TbActorMsg; |
24 | 27 | ||
25 | - | ||
26 | -public abstract class ContextAwareActor extends UntypedAbstractActor { | ||
27 | - | ||
28 | - protected final Logger log = LoggerFactory.getLogger(getClass()); | 28 | +@Slf4j |
29 | +public abstract class ContextAwareActor extends AbstractTbActor { | ||
29 | 30 | ||
30 | public static final int ENTITY_PACK_LIMIT = 1024; | 31 | public static final int ENTITY_PACK_LIMIT = 1024; |
31 | 32 | ||
@@ -37,27 +38,29 @@ public abstract class ContextAwareActor extends UntypedAbstractActor { | @@ -37,27 +38,29 @@ public abstract class ContextAwareActor extends UntypedAbstractActor { | ||
37 | } | 38 | } |
38 | 39 | ||
39 | @Override | 40 | @Override |
40 | - public void onReceive(Object msg) { | 41 | + public boolean process(TbActorMsg msg) { |
41 | if (log.isDebugEnabled()) { | 42 | if (log.isDebugEnabled()) { |
42 | log.debug("Processing msg: {}", msg); | 43 | log.debug("Processing msg: {}", msg); |
43 | } | 44 | } |
44 | - if (msg instanceof TbActorMsg) { | ||
45 | - try { | ||
46 | - if (!process((TbActorMsg) msg)) { | ||
47 | - log.warn("Unknown message: {}!", msg); | ||
48 | - } | ||
49 | - } catch (Exception e) { | ||
50 | - throw e; | ||
51 | - } | ||
52 | - } else if (msg instanceof Terminated) { | ||
53 | - processTermination((Terminated) msg); | ||
54 | - } else { | ||
55 | - log.warn("Unknown message: {}!", msg); | 45 | + if (!doProcess(msg)) { |
46 | + log.warn("Unprocessed message: {}!", msg); | ||
56 | } | 47 | } |
48 | + return false; | ||
57 | } | 49 | } |
58 | 50 | ||
59 | - protected void processTermination(Terminated msg) { | 51 | + protected abstract boolean doProcess(TbActorMsg msg); |
52 | + | ||
53 | + @Override | ||
54 | + public ProcessFailureStrategy onProcessFailure(Throwable t) { | ||
55 | + log.debug("[{}] Processing failure: ", getActorRef().getActorId(), t); | ||
56 | + return doProcessFailure(t); | ||
60 | } | 57 | } |
61 | 58 | ||
62 | - protected abstract boolean process(TbActorMsg msg); | 59 | + protected ProcessFailureStrategy doProcessFailure(Throwable t) { |
60 | + if (t instanceof Error) { | ||
61 | + return ProcessFailureStrategy.stop(); | ||
62 | + } else { | ||
63 | + return ProcessFailureStrategy.resume(); | ||
64 | + } | ||
65 | + } | ||
63 | } | 66 | } |
@@ -15,12 +15,10 @@ | @@ -15,12 +15,10 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.actors.service; | 16 | package org.thingsboard.server.actors.service; |
17 | 17 | ||
18 | -import akka.japi.Creator; | ||
19 | import org.thingsboard.server.actors.ActorSystemContext; | 18 | import org.thingsboard.server.actors.ActorSystemContext; |
19 | +import org.thingsboard.server.actors.TbActorCreator; | ||
20 | 20 | ||
21 | -public abstract class ContextBasedCreator<T> implements Creator<T> { | ||
22 | - | ||
23 | - private static final long serialVersionUID = 1L; | 21 | +public abstract class ContextBasedCreator implements TbActorCreator { |
24 | 22 | ||
25 | protected final transient ActorSystemContext context; | 23 | protected final transient ActorSystemContext context; |
26 | 24 |
@@ -15,85 +15,121 @@ | @@ -15,85 +15,121 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.actors.service; | 16 | package org.thingsboard.server.actors.service; |
17 | 17 | ||
18 | -import akka.actor.ActorRef; | ||
19 | -import akka.actor.ActorSystem; | ||
20 | -import akka.actor.Props; | ||
21 | -import akka.actor.Terminated; | ||
22 | import lombok.extern.slf4j.Slf4j; | 18 | import lombok.extern.slf4j.Slf4j; |
23 | import org.springframework.beans.factory.annotation.Autowired; | 19 | import org.springframework.beans.factory.annotation.Autowired; |
24 | import org.springframework.beans.factory.annotation.Value; | 20 | import org.springframework.beans.factory.annotation.Value; |
25 | import org.springframework.boot.context.event.ApplicationReadyEvent; | 21 | import org.springframework.boot.context.event.ApplicationReadyEvent; |
26 | import org.springframework.context.event.EventListener; | 22 | import org.springframework.context.event.EventListener; |
27 | -import org.springframework.scheduling.annotation.Scheduled; | ||
28 | import org.springframework.stereotype.Service; | 23 | import org.springframework.stereotype.Service; |
24 | +import org.thingsboard.common.util.ThingsBoardThreadFactory; | ||
29 | import org.thingsboard.server.actors.ActorSystemContext; | 25 | import org.thingsboard.server.actors.ActorSystemContext; |
26 | +import org.thingsboard.server.actors.DefaultTbActorSystem; | ||
27 | +import org.thingsboard.server.actors.TbActorId; | ||
28 | +import org.thingsboard.server.actors.TbActorRef; | ||
29 | +import org.thingsboard.server.actors.TbActorSystem; | ||
30 | +import org.thingsboard.server.actors.TbActorSystemSettings; | ||
30 | import org.thingsboard.server.actors.app.AppActor; | 31 | import org.thingsboard.server.actors.app.AppActor; |
31 | import org.thingsboard.server.actors.app.AppInitMsg; | 32 | import org.thingsboard.server.actors.app.AppInitMsg; |
32 | import org.thingsboard.server.actors.stats.StatsActor; | 33 | import org.thingsboard.server.actors.stats.StatsActor; |
33 | import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; | 34 | import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; |
34 | import org.thingsboard.server.queue.discovery.PartitionChangeEvent; | 35 | import org.thingsboard.server.queue.discovery.PartitionChangeEvent; |
35 | -import scala.concurrent.Await; | ||
36 | -import scala.concurrent.Future; | ||
37 | -import scala.concurrent.duration.Duration; | ||
38 | 36 | ||
39 | import javax.annotation.PostConstruct; | 37 | import javax.annotation.PostConstruct; |
40 | import javax.annotation.PreDestroy; | 38 | import javax.annotation.PreDestroy; |
41 | -import java.util.concurrent.atomic.AtomicInteger; | 39 | +import java.util.concurrent.ExecutorService; |
40 | +import java.util.concurrent.Executors; | ||
41 | +import java.util.concurrent.ScheduledExecutorService; | ||
42 | 42 | ||
43 | @Service | 43 | @Service |
44 | @Slf4j | 44 | @Slf4j |
45 | public class DefaultActorService implements ActorService { | 45 | public class DefaultActorService implements ActorService { |
46 | 46 | ||
47 | - private static final String ACTOR_SYSTEM_NAME = "Akka"; | ||
48 | - | ||
49 | public static final String APP_DISPATCHER_NAME = "app-dispatcher"; | 47 | public static final String APP_DISPATCHER_NAME = "app-dispatcher"; |
50 | - public static final String CORE_DISPATCHER_NAME = "core-dispatcher"; | ||
51 | - public static final String SYSTEM_RULE_DISPATCHER_NAME = "system-rule-dispatcher"; | ||
52 | - public static final String TENANT_RULE_DISPATCHER_NAME = "rule-dispatcher"; | 48 | + public static final String TENANT_DISPATCHER_NAME = "tenant-dispatcher"; |
49 | + public static final String DEVICE_DISPATCHER_NAME = "device-dispatcher"; | ||
50 | + public static final String RULE_DISPATCHER_NAME = "rule-dispatcher"; | ||
53 | 51 | ||
54 | @Autowired | 52 | @Autowired |
55 | private ActorSystemContext actorContext; | 53 | private ActorSystemContext actorContext; |
56 | 54 | ||
57 | - private ActorSystem system; | 55 | + private TbActorSystem system; |
56 | + | ||
57 | + private TbActorRef appActor; | ||
58 | + | ||
59 | + @Value("${actors.system.throughput:5}") | ||
60 | + private int actorThroughput; | ||
61 | + | ||
62 | + @Value("${actors.system.max_actor_init_attempts:10}") | ||
63 | + private int maxActorInitAttempts; | ||
64 | + | ||
65 | + @Value("${actors.system.scheduler_pool_size:1}") | ||
66 | + private int schedulerPoolSize; | ||
67 | + | ||
68 | + @Value("${actors.system.app_dispatcher_pool_size:1}") | ||
69 | + private int appDispatcherSize; | ||
70 | + | ||
71 | + @Value("${actors.system.tenant_dispatcher_pool_size:2}") | ||
72 | + private int tenantDispatcherSize; | ||
58 | 73 | ||
59 | - private ActorRef appActor; | 74 | + @Value("${actors.system.device_dispatcher_pool_size:4}") |
75 | + private int deviceDispatcherSize; | ||
76 | + | ||
77 | + @Value("${actors.system.rule_dispatcher_pool_size:4}") | ||
78 | + private int ruleDispatcherSize; | ||
60 | 79 | ||
61 | @PostConstruct | 80 | @PostConstruct |
62 | public void initActorSystem() { | 81 | public void initActorSystem() { |
63 | - log.info("Initializing Actor system."); | 82 | + log.info("Initializing actor system."); |
64 | actorContext.setActorService(this); | 83 | actorContext.setActorService(this); |
65 | - system = ActorSystem.create(ACTOR_SYSTEM_NAME, actorContext.getConfig()); | 84 | + TbActorSystemSettings settings = new TbActorSystemSettings(actorThroughput, schedulerPoolSize, maxActorInitAttempts); |
85 | + system = new DefaultTbActorSystem(settings); | ||
86 | + | ||
87 | + system.createDispatcher(APP_DISPATCHER_NAME, initDispatcherExecutor(APP_DISPATCHER_NAME, appDispatcherSize)); | ||
88 | + system.createDispatcher(TENANT_DISPATCHER_NAME, initDispatcherExecutor(TENANT_DISPATCHER_NAME, tenantDispatcherSize)); | ||
89 | + system.createDispatcher(DEVICE_DISPATCHER_NAME, initDispatcherExecutor(DEVICE_DISPATCHER_NAME, deviceDispatcherSize)); | ||
90 | + system.createDispatcher(RULE_DISPATCHER_NAME, initDispatcherExecutor(RULE_DISPATCHER_NAME, ruleDispatcherSize)); | ||
91 | + | ||
66 | actorContext.setActorSystem(system); | 92 | actorContext.setActorSystem(system); |
67 | 93 | ||
68 | - appActor = system.actorOf(Props.create(new AppActor.ActorCreator(actorContext)).withDispatcher(APP_DISPATCHER_NAME), "appActor"); | 94 | + appActor = system.createRootActor(APP_DISPATCHER_NAME, new AppActor.ActorCreator(actorContext)); |
69 | actorContext.setAppActor(appActor); | 95 | actorContext.setAppActor(appActor); |
70 | 96 | ||
71 | - ActorRef statsActor = system.actorOf(Props.create(new StatsActor.ActorCreator(actorContext)).withDispatcher(CORE_DISPATCHER_NAME), "statsActor"); | 97 | + TbActorRef statsActor = system.createRootActor(TENANT_DISPATCHER_NAME, new StatsActor.ActorCreator(actorContext, "StatsActor")); |
72 | actorContext.setStatsActor(statsActor); | 98 | actorContext.setStatsActor(statsActor); |
73 | 99 | ||
74 | log.info("Actor system initialized."); | 100 | log.info("Actor system initialized."); |
75 | } | 101 | } |
76 | 102 | ||
103 | + private ExecutorService initDispatcherExecutor(String dispatcherName, int poolSize) { | ||
104 | + if (poolSize == 0) { | ||
105 | + int cores = Runtime.getRuntime().availableProcessors(); | ||
106 | + poolSize = Math.max(1, cores / 2); | ||
107 | + } | ||
108 | + if (poolSize == 1) { | ||
109 | + return Executors.newSingleThreadExecutor(ThingsBoardThreadFactory.forName(dispatcherName)); | ||
110 | + } else { | ||
111 | + return Executors.newWorkStealingPool(poolSize); | ||
112 | + } | ||
113 | + } | ||
114 | + | ||
77 | @EventListener(ApplicationReadyEvent.class) | 115 | @EventListener(ApplicationReadyEvent.class) |
78 | public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) { | 116 | public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) { |
79 | log.info("Received application ready event. Sending application init message to actor system"); | 117 | log.info("Received application ready event. Sending application init message to actor system"); |
80 | - appActor.tell(new AppInitMsg(), ActorRef.noSender()); | 118 | + appActor.tellWithHighPriority(new AppInitMsg()); |
81 | } | 119 | } |
82 | 120 | ||
83 | @EventListener(PartitionChangeEvent.class) | 121 | @EventListener(PartitionChangeEvent.class) |
84 | public void onApplicationEvent(PartitionChangeEvent partitionChangeEvent) { | 122 | public void onApplicationEvent(PartitionChangeEvent partitionChangeEvent) { |
85 | log.info("Received partition change event."); | 123 | log.info("Received partition change event."); |
86 | - this.appActor.tell(new PartitionChangeMsg(partitionChangeEvent.getServiceQueueKey(), partitionChangeEvent.getPartitions()), ActorRef.noSender()); | 124 | + this.appActor.tellWithHighPriority(new PartitionChangeMsg(partitionChangeEvent.getServiceQueueKey(), partitionChangeEvent.getPartitions())); |
87 | } | 125 | } |
88 | 126 | ||
89 | @PreDestroy | 127 | @PreDestroy |
90 | public void stopActorSystem() { | 128 | public void stopActorSystem() { |
91 | - Future<Terminated> status = system.terminate(); | ||
92 | - try { | ||
93 | - Terminated terminated = Await.result(status, Duration.Inf()); | ||
94 | - log.info("Actor system terminated: {}", terminated); | ||
95 | - } catch (Exception e) { | ||
96 | - log.error("Failed to terminate actor system.", e); | 129 | + if (system != null) { |
130 | + log.info("Stopping actor system."); | ||
131 | + system.stop(); | ||
132 | + log.info("Actor system stopped."); | ||
97 | } | 133 | } |
98 | } | 134 | } |
99 | 135 |
application/src/main/java/org/thingsboard/server/actors/shared/AbstractContextAwareMsgProcessor.java
@@ -15,18 +15,13 @@ | @@ -15,18 +15,13 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.actors.shared; | 16 | package org.thingsboard.server.actors.shared; |
17 | 17 | ||
18 | -import akka.actor.ActorContext; | ||
19 | -import akka.actor.ActorRef; | ||
20 | -import akka.actor.Scheduler; | ||
21 | -import akka.event.LoggingAdapter; | ||
22 | import com.fasterxml.jackson.databind.ObjectMapper; | 18 | import com.fasterxml.jackson.databind.ObjectMapper; |
23 | -import lombok.AllArgsConstructor; | ||
24 | -import lombok.Data; | ||
25 | import lombok.extern.slf4j.Slf4j; | 19 | import lombok.extern.slf4j.Slf4j; |
26 | import org.thingsboard.server.actors.ActorSystemContext; | 20 | import org.thingsboard.server.actors.ActorSystemContext; |
27 | -import scala.concurrent.ExecutionContextExecutor; | ||
28 | -import scala.concurrent.duration.Duration; | 21 | +import org.thingsboard.server.actors.TbActorCtx; |
22 | +import org.thingsboard.server.common.msg.TbActorMsg; | ||
29 | 23 | ||
24 | +import java.util.concurrent.ScheduledExecutorService; | ||
30 | import java.util.concurrent.TimeUnit; | 25 | import java.util.concurrent.TimeUnit; |
31 | 26 | ||
32 | @Slf4j | 27 | @Slf4j |
@@ -40,31 +35,16 @@ public abstract class AbstractContextAwareMsgProcessor { | @@ -40,31 +35,16 @@ public abstract class AbstractContextAwareMsgProcessor { | ||
40 | this.systemContext = systemContext; | 35 | this.systemContext = systemContext; |
41 | } | 36 | } |
42 | 37 | ||
43 | - private Scheduler getScheduler() { | 38 | + private ScheduledExecutorService getScheduler() { |
44 | return systemContext.getScheduler(); | 39 | return systemContext.getScheduler(); |
45 | } | 40 | } |
46 | 41 | ||
47 | - private ExecutionContextExecutor getSystemDispatcher() { | ||
48 | - return systemContext.getActorSystem().dispatcher(); | 42 | + protected void schedulePeriodicMsgWithDelay(TbActorCtx ctx, TbActorMsg msg, long delayInMs, long periodInMs) { |
43 | + systemContext.schedulePeriodicMsgWithDelay(ctx, msg, delayInMs, periodInMs); | ||
49 | } | 44 | } |
50 | 45 | ||
51 | - protected void schedulePeriodicMsgWithDelay(ActorContext ctx, Object msg, long delayInMs, long periodInMs) { | ||
52 | - schedulePeriodicMsgWithDelay(msg, delayInMs, periodInMs, ctx.self()); | 46 | + protected void scheduleMsgWithDelay(TbActorCtx ctx, TbActorMsg msg, long delayInMs) { |
47 | + systemContext.scheduleMsgWithDelay(ctx, msg, delayInMs); | ||
53 | } | 48 | } |
54 | 49 | ||
55 | - private void schedulePeriodicMsgWithDelay(Object msg, long delayInMs, long periodInMs, ActorRef target) { | ||
56 | - log.debug("Scheduling periodic msg {} every {} ms with delay {} ms", msg, periodInMs, delayInMs); | ||
57 | - getScheduler().schedule(Duration.create(delayInMs, TimeUnit.MILLISECONDS), Duration.create(periodInMs, TimeUnit.MILLISECONDS), target, msg, getSystemDispatcher(), null); | ||
58 | - } | ||
59 | - | ||
60 | - protected void scheduleMsgWithDelay(ActorContext ctx, Object msg, long delayInMs) { | ||
61 | - scheduleMsgWithDelay(msg, delayInMs, ctx.self()); | ||
62 | - } | ||
63 | - | ||
64 | - private void scheduleMsgWithDelay(Object msg, long delayInMs, ActorRef target) { | ||
65 | - log.debug("Scheduling msg {} with delay {} ms", msg, delayInMs); | ||
66 | - getScheduler().scheduleOnce(Duration.create(delayInMs, TimeUnit.MILLISECONDS), target, msg, getSystemDispatcher(), null); | ||
67 | - } | ||
68 | - | ||
69 | - | ||
70 | } | 50 | } |
@@ -15,16 +15,15 @@ | @@ -15,16 +15,15 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.actors.shared; | 16 | package org.thingsboard.server.actors.shared; |
17 | 17 | ||
18 | -import akka.actor.ActorContext; | ||
19 | import lombok.extern.slf4j.Slf4j; | 18 | import lombok.extern.slf4j.Slf4j; |
20 | import org.thingsboard.server.actors.ActorSystemContext; | 19 | import org.thingsboard.server.actors.ActorSystemContext; |
20 | +import org.thingsboard.server.actors.TbActorCtx; | ||
21 | import org.thingsboard.server.actors.stats.StatsPersistTick; | 21 | import org.thingsboard.server.actors.stats.StatsPersistTick; |
22 | import org.thingsboard.server.common.data.id.EntityId; | 22 | import org.thingsboard.server.common.data.id.EntityId; |
23 | import org.thingsboard.server.common.data.id.TenantId; | 23 | import org.thingsboard.server.common.data.id.TenantId; |
24 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleState; | 24 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleState; |
25 | import org.thingsboard.server.common.msg.TbMsg; | 25 | import org.thingsboard.server.common.msg.TbMsg; |
26 | import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; | 26 | import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; |
27 | -import org.thingsboard.server.common.msg.queue.RuleEngineException; | ||
28 | import org.thingsboard.server.common.msg.queue.RuleNodeException; | 27 | import org.thingsboard.server.common.msg.queue.RuleNodeException; |
29 | 28 | ||
30 | @Slf4j | 29 | @Slf4j |
@@ -42,38 +41,38 @@ public abstract class ComponentMsgProcessor<T extends EntityId> extends Abstract | @@ -42,38 +41,38 @@ public abstract class ComponentMsgProcessor<T extends EntityId> extends Abstract | ||
42 | 41 | ||
43 | public abstract String getComponentName(); | 42 | public abstract String getComponentName(); |
44 | 43 | ||
45 | - public abstract void start(ActorContext context) throws Exception; | 44 | + public abstract void start(TbActorCtx context) throws Exception; |
46 | 45 | ||
47 | - public abstract void stop(ActorContext context) throws Exception; | 46 | + public abstract void stop(TbActorCtx context) throws Exception; |
48 | 47 | ||
49 | public abstract void onPartitionChangeMsg(PartitionChangeMsg msg) throws Exception; | 48 | public abstract void onPartitionChangeMsg(PartitionChangeMsg msg) throws Exception; |
50 | 49 | ||
51 | - public void onCreated(ActorContext context) throws Exception { | 50 | + public void onCreated(TbActorCtx context) throws Exception { |
52 | start(context); | 51 | start(context); |
53 | } | 52 | } |
54 | 53 | ||
55 | - public void onUpdate(ActorContext context) throws Exception { | 54 | + public void onUpdate(TbActorCtx context) throws Exception { |
56 | restart(context); | 55 | restart(context); |
57 | } | 56 | } |
58 | 57 | ||
59 | - public void onActivate(ActorContext context) throws Exception { | 58 | + public void onActivate(TbActorCtx context) throws Exception { |
60 | restart(context); | 59 | restart(context); |
61 | } | 60 | } |
62 | 61 | ||
63 | - public void onSuspend(ActorContext context) throws Exception { | 62 | + public void onSuspend(TbActorCtx context) throws Exception { |
64 | stop(context); | 63 | stop(context); |
65 | } | 64 | } |
66 | 65 | ||
67 | - public void onStop(ActorContext context) throws Exception { | 66 | + public void onStop(TbActorCtx context) throws Exception { |
68 | stop(context); | 67 | stop(context); |
69 | } | 68 | } |
70 | 69 | ||
71 | - private void restart(ActorContext context) throws Exception { | 70 | + private void restart(TbActorCtx context) throws Exception { |
72 | stop(context); | 71 | stop(context); |
73 | start(context); | 72 | start(context); |
74 | } | 73 | } |
75 | 74 | ||
76 | - public void scheduleStatsPersistTick(ActorContext context, long statsPersistFrequency) { | 75 | + public void scheduleStatsPersistTick(TbActorCtx context, long statsPersistFrequency) { |
77 | schedulePeriodicMsgWithDelay(context, new StatsPersistTick(), statsPersistFrequency, statsPersistFrequency); | 76 | schedulePeriodicMsgWithDelay(context, new StatsPersistTick(), statsPersistFrequency, statsPersistFrequency); |
78 | } | 77 | } |
79 | 78 |
@@ -19,10 +19,15 @@ import com.fasterxml.jackson.databind.JsonNode; | @@ -19,10 +19,15 @@ import com.fasterxml.jackson.databind.JsonNode; | ||
19 | import com.fasterxml.jackson.databind.ObjectMapper; | 19 | import com.fasterxml.jackson.databind.ObjectMapper; |
20 | import lombok.extern.slf4j.Slf4j; | 20 | import lombok.extern.slf4j.Slf4j; |
21 | import org.thingsboard.server.actors.ActorSystemContext; | 21 | import org.thingsboard.server.actors.ActorSystemContext; |
22 | +import org.thingsboard.server.actors.TbActor; | ||
23 | +import org.thingsboard.server.actors.TbActorCtx; | ||
24 | +import org.thingsboard.server.actors.TbActorId; | ||
25 | +import org.thingsboard.server.actors.TbStringActorId; | ||
22 | import org.thingsboard.server.actors.service.ContextAwareActor; | 26 | import org.thingsboard.server.actors.service.ContextAwareActor; |
23 | import org.thingsboard.server.actors.service.ContextBasedCreator; | 27 | import org.thingsboard.server.actors.service.ContextBasedCreator; |
24 | import org.thingsboard.server.common.data.DataConstants; | 28 | import org.thingsboard.server.common.data.DataConstants; |
25 | import org.thingsboard.server.common.data.Event; | 29 | import org.thingsboard.server.common.data.Event; |
30 | +import org.thingsboard.server.common.msg.MsgType; | ||
26 | import org.thingsboard.server.common.msg.TbActorMsg; | 31 | import org.thingsboard.server.common.msg.TbActorMsg; |
27 | 32 | ||
28 | @Slf4j | 33 | @Slf4j |
@@ -35,24 +40,17 @@ public class StatsActor extends ContextAwareActor { | @@ -35,24 +40,17 @@ public class StatsActor extends ContextAwareActor { | ||
35 | } | 40 | } |
36 | 41 | ||
37 | @Override | 42 | @Override |
38 | - protected boolean process(TbActorMsg msg) { | ||
39 | - //TODO Move everything here, to work with TbActorMsg\ | ||
40 | - return false; | ||
41 | - } | ||
42 | - | ||
43 | - @Override | ||
44 | - public void onReceive(Object msg) { | 43 | + protected boolean doProcess(TbActorMsg msg) { |
45 | log.debug("Received message: {}", msg); | 44 | log.debug("Received message: {}", msg); |
46 | - if (msg instanceof StatsPersistMsg) { | ||
47 | - try { | ||
48 | - onStatsPersistMsg((StatsPersistMsg) msg); | ||
49 | - } catch (Exception e) { | ||
50 | - log.warn("Failed to persist statistics: {}", msg, e); | ||
51 | - } | 45 | + if (msg.getMsgType().equals(MsgType.STATS_PERSIST_MSG)) { |
46 | + onStatsPersistMsg((StatsPersistMsg) msg); | ||
47 | + return true; | ||
48 | + } else { | ||
49 | + return false; | ||
52 | } | 50 | } |
53 | } | 51 | } |
54 | 52 | ||
55 | - public void onStatsPersistMsg(StatsPersistMsg msg) throws Exception { | 53 | + public void onStatsPersistMsg(StatsPersistMsg msg) { |
56 | Event event = new Event(); | 54 | Event event = new Event(); |
57 | event.setEntityId(msg.getEntityId()); | 55 | event.setEntityId(msg.getEntityId()); |
58 | event.setTenantId(msg.getTenantId()); | 56 | event.setTenantId(msg.getTenantId()); |
@@ -65,15 +63,21 @@ public class StatsActor extends ContextAwareActor { | @@ -65,15 +63,21 @@ public class StatsActor extends ContextAwareActor { | ||
65 | return mapper.createObjectNode().put("server", serviceId).put("messagesProcessed", messagesProcessed).put("errorsOccurred", errorsOccurred); | 63 | return mapper.createObjectNode().put("server", serviceId).put("messagesProcessed", messagesProcessed).put("errorsOccurred", errorsOccurred); |
66 | } | 64 | } |
67 | 65 | ||
68 | - public static class ActorCreator extends ContextBasedCreator<StatsActor> { | ||
69 | - private static final long serialVersionUID = 1L; | 66 | + public static class ActorCreator extends ContextBasedCreator { |
67 | + private final String actorId; | ||
70 | 68 | ||
71 | - public ActorCreator(ActorSystemContext context) { | 69 | + public ActorCreator(ActorSystemContext context, String actorId) { |
72 | super(context); | 70 | super(context); |
71 | + this.actorId = actorId; | ||
72 | + } | ||
73 | + | ||
74 | + @Override | ||
75 | + public TbActorId createActorId() { | ||
76 | + return new TbStringActorId(actorId); | ||
73 | } | 77 | } |
74 | 78 | ||
75 | @Override | 79 | @Override |
76 | - public StatsActor create() { | 80 | + public TbActor createActor() { |
77 | return new StatsActor(context); | 81 | return new StatsActor(context); |
78 | } | 82 | } |
79 | } | 83 | } |
@@ -20,13 +20,21 @@ import lombok.Getter; | @@ -20,13 +20,21 @@ import lombok.Getter; | ||
20 | import lombok.ToString; | 20 | import lombok.ToString; |
21 | import org.thingsboard.server.common.data.id.EntityId; | 21 | import org.thingsboard.server.common.data.id.EntityId; |
22 | import org.thingsboard.server.common.data.id.TenantId; | 22 | import org.thingsboard.server.common.data.id.TenantId; |
23 | +import org.thingsboard.server.common.msg.MsgType; | ||
24 | +import org.thingsboard.server.common.msg.TbActorMsg; | ||
23 | 25 | ||
24 | @AllArgsConstructor | 26 | @AllArgsConstructor |
25 | @Getter | 27 | @Getter |
26 | @ToString | 28 | @ToString |
27 | -public final class StatsPersistMsg { | 29 | +public final class StatsPersistMsg implements TbActorMsg { |
30 | + | ||
28 | private long messagesProcessed; | 31 | private long messagesProcessed; |
29 | private long errorsOccurred; | 32 | private long errorsOccurred; |
30 | private TenantId tenantId; | 33 | private TenantId tenantId; |
31 | private EntityId entityId; | 34 | private EntityId entityId; |
35 | + | ||
36 | + @Override | ||
37 | + public MsgType getMsgType() { | ||
38 | + return MsgType.STATS_PERSIST_MSG; | ||
39 | + } | ||
32 | } | 40 | } |
@@ -15,16 +15,16 @@ | @@ -15,16 +15,16 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.actors.tenant; | 16 | package org.thingsboard.server.actors.tenant; |
17 | 17 | ||
18 | -import akka.actor.ActorInitializationException; | ||
19 | -import akka.actor.ActorRef; | ||
20 | -import akka.actor.LocalActorRef; | ||
21 | -import akka.actor.OneForOneStrategy; | ||
22 | -import akka.actor.Props; | ||
23 | -import akka.actor.SupervisorStrategy; | ||
24 | -import akka.actor.Terminated; | ||
25 | -import com.google.common.collect.BiMap; | ||
26 | -import com.google.common.collect.HashBiMap; | 18 | +import lombok.extern.slf4j.Slf4j; |
27 | import org.thingsboard.server.actors.ActorSystemContext; | 19 | import org.thingsboard.server.actors.ActorSystemContext; |
20 | +import org.thingsboard.server.actors.TbActor; | ||
21 | +import org.thingsboard.server.actors.TbActorCtx; | ||
22 | +import org.thingsboard.server.actors.TbActorException; | ||
23 | +import org.thingsboard.server.actors.TbActorId; | ||
24 | +import org.thingsboard.server.actors.TbActorNotRegisteredException; | ||
25 | +import org.thingsboard.server.actors.TbActorRef; | ||
26 | +import org.thingsboard.server.actors.TbEntityActorId; | ||
27 | +import org.thingsboard.server.actors.TbEntityTypeActorIdPredicate; | ||
28 | import org.thingsboard.server.actors.device.DeviceActorCreator; | 28 | import org.thingsboard.server.actors.device.DeviceActorCreator; |
29 | import org.thingsboard.server.actors.ruleChain.RuleChainManagerActor; | 29 | import org.thingsboard.server.actors.ruleChain.RuleChainManagerActor; |
30 | import org.thingsboard.server.actors.service.ContextBasedCreator; | 30 | import org.thingsboard.server.actors.service.ContextBasedCreator; |
@@ -32,6 +32,7 @@ import org.thingsboard.server.actors.service.DefaultActorService; | @@ -32,6 +32,7 @@ import org.thingsboard.server.actors.service.DefaultActorService; | ||
32 | import org.thingsboard.server.common.data.EntityType; | 32 | import org.thingsboard.server.common.data.EntityType; |
33 | import org.thingsboard.server.common.data.Tenant; | 33 | import org.thingsboard.server.common.data.Tenant; |
34 | import org.thingsboard.server.common.data.id.DeviceId; | 34 | import org.thingsboard.server.common.data.id.DeviceId; |
35 | +import org.thingsboard.server.common.data.id.EntityId; | ||
35 | import org.thingsboard.server.common.data.id.RuleChainId; | 36 | import org.thingsboard.server.common.data.id.RuleChainId; |
36 | import org.thingsboard.server.common.data.id.TenantId; | 37 | import org.thingsboard.server.common.data.id.TenantId; |
37 | import org.thingsboard.server.common.data.rule.RuleChain; | 38 | import org.thingsboard.server.common.data.rule.RuleChain; |
@@ -46,32 +47,25 @@ import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; | @@ -46,32 +47,25 @@ import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; | ||
46 | import org.thingsboard.server.common.msg.queue.QueueToRuleEngineMsg; | 47 | import org.thingsboard.server.common.msg.queue.QueueToRuleEngineMsg; |
47 | import org.thingsboard.server.common.msg.queue.RuleEngineException; | 48 | import org.thingsboard.server.common.msg.queue.RuleEngineException; |
48 | import org.thingsboard.server.common.msg.queue.ServiceType; | 49 | import org.thingsboard.server.common.msg.queue.ServiceType; |
49 | -import scala.concurrent.duration.Duration; | ||
50 | 50 | ||
51 | import java.util.List; | 51 | import java.util.List; |
52 | import java.util.Optional; | 52 | import java.util.Optional; |
53 | -import java.util.stream.Collectors; | ||
54 | 53 | ||
54 | +@Slf4j | ||
55 | public class TenantActor extends RuleChainManagerActor { | 55 | public class TenantActor extends RuleChainManagerActor { |
56 | 56 | ||
57 | - private final BiMap<DeviceId, ActorRef> deviceActors; | ||
58 | private boolean isRuleEngineForCurrentTenant; | 57 | private boolean isRuleEngineForCurrentTenant; |
59 | private boolean isCore; | 58 | private boolean isCore; |
60 | 59 | ||
61 | private TenantActor(ActorSystemContext systemContext, TenantId tenantId) { | 60 | private TenantActor(ActorSystemContext systemContext, TenantId tenantId) { |
62 | super(systemContext, tenantId); | 61 | super(systemContext, tenantId); |
63 | - this.deviceActors = HashBiMap.create(); | ||
64 | - } | ||
65 | - | ||
66 | - @Override | ||
67 | - public SupervisorStrategy supervisorStrategy() { | ||
68 | - return strategy; | ||
69 | } | 62 | } |
70 | 63 | ||
71 | boolean cantFindTenant = false; | 64 | boolean cantFindTenant = false; |
72 | 65 | ||
73 | @Override | 66 | @Override |
74 | - public void preStart() { | 67 | + public void init(TbActorCtx ctx) throws TbActorException { |
68 | + super.init(ctx); | ||
75 | log.info("[{}] Starting tenant actor.", tenantId); | 69 | log.info("[{}] Starting tenant actor.", tenantId); |
76 | try { | 70 | try { |
77 | Tenant tenant = systemContext.getTenantService().findTenantById(tenantId); | 71 | Tenant tenant = systemContext.getTenantService().findTenantById(tenantId); |
@@ -101,16 +95,18 @@ public class TenantActor extends RuleChainManagerActor { | @@ -101,16 +95,18 @@ public class TenantActor extends RuleChainManagerActor { | ||
101 | } | 95 | } |
102 | } catch (Exception e) { | 96 | } catch (Exception e) { |
103 | log.warn("[{}] Unknown failure", tenantId, e); | 97 | log.warn("[{}] Unknown failure", tenantId, e); |
98 | +// TODO: throw this in 3.1? | ||
99 | +// throw new TbActorException("Failed to init actor", e); | ||
104 | } | 100 | } |
105 | } | 101 | } |
106 | 102 | ||
107 | @Override | 103 | @Override |
108 | - public void postStop() { | 104 | + public void destroy() { |
109 | log.info("[{}] Stopping tenant actor.", tenantId); | 105 | log.info("[{}] Stopping tenant actor.", tenantId); |
110 | } | 106 | } |
111 | 107 | ||
112 | @Override | 108 | @Override |
113 | - protected boolean process(TbActorMsg msg) { | 109 | + protected boolean doProcess(TbActorMsg msg) { |
114 | if (cantFindTenant) { | 110 | if (cantFindTenant) { |
115 | log.info("[{}] Processing missing Tenant msg: {}", tenantId, msg); | 111 | log.info("[{}] Processing missing Tenant msg: {}", tenantId, msg); |
116 | if (msg.getMsgType().equals(MsgType.QUEUE_TO_RULE_ENGINE_MSG)) { | 112 | if (msg.getMsgType().equals(MsgType.QUEUE_TO_RULE_ENGINE_MSG)) { |
@@ -127,13 +123,13 @@ public class TenantActor extends RuleChainManagerActor { | @@ -127,13 +123,13 @@ public class TenantActor extends RuleChainManagerActor { | ||
127 | //To Rule Chain Actors | 123 | //To Rule Chain Actors |
128 | broadcast(msg); | 124 | broadcast(msg); |
129 | } else if (ServiceType.TB_CORE.equals(serviceType)) { | 125 | } else if (ServiceType.TB_CORE.equals(serviceType)) { |
130 | - //To Device Actors | ||
131 | - List<DeviceId> repartitionedDevices = | ||
132 | - deviceActors.keySet().stream().filter(deviceId -> !isMyPartition(deviceId)).collect(Collectors.toList()); | ||
133 | - for (DeviceId deviceId : repartitionedDevices) { | ||
134 | - ActorRef deviceActor = deviceActors.remove(deviceId); | ||
135 | - context().stop(deviceActor); | ||
136 | - } | 126 | + List<TbActorId> deviceActorIds = ctx.filterChildren(new TbEntityTypeActorIdPredicate(EntityType.DEVICE) { |
127 | + @Override | ||
128 | + protected boolean testEntityId(EntityId entityId) { | ||
129 | + return super.testEntityId(entityId) && !isMyPartition(entityId); | ||
130 | + } | ||
131 | + }); | ||
132 | + deviceActorIds.forEach(id -> ctx.stop(id)); | ||
137 | } | 133 | } |
138 | break; | 134 | break; |
139 | case COMPONENT_LIFE_CYCLE_MSG: | 135 | case COMPONENT_LIFE_CYCLE_MSG: |
@@ -143,12 +139,14 @@ public class TenantActor extends RuleChainManagerActor { | @@ -143,12 +139,14 @@ public class TenantActor extends RuleChainManagerActor { | ||
143 | onQueueToRuleEngineMsg((QueueToRuleEngineMsg) msg); | 139 | onQueueToRuleEngineMsg((QueueToRuleEngineMsg) msg); |
144 | break; | 140 | break; |
145 | case TRANSPORT_TO_DEVICE_ACTOR_MSG: | 141 | case TRANSPORT_TO_DEVICE_ACTOR_MSG: |
142 | + onToDeviceActorMsg((DeviceAwareMsg) msg, false); | ||
143 | + break; | ||
146 | case DEVICE_ATTRIBUTES_UPDATE_TO_DEVICE_ACTOR_MSG: | 144 | case DEVICE_ATTRIBUTES_UPDATE_TO_DEVICE_ACTOR_MSG: |
147 | case DEVICE_CREDENTIALS_UPDATE_TO_DEVICE_ACTOR_MSG: | 145 | case DEVICE_CREDENTIALS_UPDATE_TO_DEVICE_ACTOR_MSG: |
148 | case DEVICE_NAME_OR_TYPE_UPDATE_TO_DEVICE_ACTOR_MSG: | 146 | case DEVICE_NAME_OR_TYPE_UPDATE_TO_DEVICE_ACTOR_MSG: |
149 | case DEVICE_RPC_REQUEST_TO_DEVICE_ACTOR_MSG: | 147 | case DEVICE_RPC_REQUEST_TO_DEVICE_ACTOR_MSG: |
150 | case SERVER_RPC_RESPONSE_TO_DEVICE_ACTOR_MSG: | 148 | case SERVER_RPC_RESPONSE_TO_DEVICE_ACTOR_MSG: |
151 | - onToDeviceActorMsg((DeviceAwareMsg) msg); | 149 | + onToDeviceActorMsg((DeviceAwareMsg) msg, true); |
152 | break; | 150 | break; |
153 | case RULE_CHAIN_TO_RULE_CHAIN_MSG: | 151 | case RULE_CHAIN_TO_RULE_CHAIN_MSG: |
154 | onRuleChainMsg((RuleChainAwareMsg) msg); | 152 | onRuleChainMsg((RuleChainAwareMsg) msg); |
@@ -159,8 +157,8 @@ public class TenantActor extends RuleChainManagerActor { | @@ -159,8 +157,8 @@ public class TenantActor extends RuleChainManagerActor { | ||
159 | return true; | 157 | return true; |
160 | } | 158 | } |
161 | 159 | ||
162 | - private boolean isMyPartition(DeviceId deviceId) { | ||
163 | - return systemContext.resolve(ServiceType.TB_CORE, tenantId, deviceId).isMyPartition(); | 160 | + private boolean isMyPartition(EntityId entityId) { |
161 | + return systemContext.resolve(ServiceType.TB_CORE, tenantId, entityId).isMyPartition(); | ||
164 | } | 162 | } |
165 | 163 | ||
166 | private void onQueueToRuleEngineMsg(QueueToRuleEngineMsg msg) { | 164 | private void onQueueToRuleEngineMsg(QueueToRuleEngineMsg msg) { |
@@ -171,16 +169,15 @@ public class TenantActor extends RuleChainManagerActor { | @@ -171,16 +169,15 @@ public class TenantActor extends RuleChainManagerActor { | ||
171 | TbMsg tbMsg = msg.getTbMsg(); | 169 | TbMsg tbMsg = msg.getTbMsg(); |
172 | if (tbMsg.getRuleChainId() == null) { | 170 | if (tbMsg.getRuleChainId() == null) { |
173 | if (getRootChainActor() != null) { | 171 | if (getRootChainActor() != null) { |
174 | - getRootChainActor().tell(msg, self()); | 172 | + getRootChainActor().tell(msg); |
175 | } else { | 173 | } else { |
176 | tbMsg.getCallback().onFailure(new RuleEngineException("No Root Rule Chain available!")); | 174 | tbMsg.getCallback().onFailure(new RuleEngineException("No Root Rule Chain available!")); |
177 | log.info("[{}] No Root Chain: {}", tenantId, msg); | 175 | log.info("[{}] No Root Chain: {}", tenantId, msg); |
178 | } | 176 | } |
179 | } else { | 177 | } else { |
180 | - ActorRef ruleChainActor = get(tbMsg.getRuleChainId()); | ||
181 | - if (ruleChainActor != null) { | ||
182 | - ruleChainActor.tell(msg, self()); | ||
183 | - } else { | 178 | + try { |
179 | + ctx.tell(new TbEntityActorId(tbMsg.getRuleChainId()), msg); | ||
180 | + } catch (TbActorNotRegisteredException ex) { | ||
184 | log.trace("Received message for non-existing rule chain: [{}]", tbMsg.getRuleChainId()); | 181 | log.trace("Received message for non-existing rule chain: [{}]", tbMsg.getRuleChainId()); |
185 | //TODO: 3.1 Log it to dead letters queue; | 182 | //TODO: 3.1 Log it to dead letters queue; |
186 | tbMsg.getCallback().onSuccess(); | 183 | tbMsg.getCallback().onSuccess(); |
@@ -189,19 +186,24 @@ public class TenantActor extends RuleChainManagerActor { | @@ -189,19 +186,24 @@ public class TenantActor extends RuleChainManagerActor { | ||
189 | } | 186 | } |
190 | 187 | ||
191 | private void onRuleChainMsg(RuleChainAwareMsg msg) { | 188 | private void onRuleChainMsg(RuleChainAwareMsg msg) { |
192 | - getOrCreateActor(context(), msg.getRuleChainId()).tell(msg, self()); | 189 | + getOrCreateActor(msg.getRuleChainId()).tell(msg); |
193 | } | 190 | } |
194 | 191 | ||
195 | - private void onToDeviceActorMsg(DeviceAwareMsg msg) { | 192 | + private void onToDeviceActorMsg(DeviceAwareMsg msg, boolean priority) { |
196 | if (!isCore) { | 193 | if (!isCore) { |
197 | log.warn("RECEIVED INVALID MESSAGE: {}", msg); | 194 | log.warn("RECEIVED INVALID MESSAGE: {}", msg); |
198 | } | 195 | } |
199 | - getOrCreateDeviceActor(msg.getDeviceId()).tell(msg, ActorRef.noSender()); | 196 | + TbActorRef deviceActor = getOrCreateDeviceActor(msg.getDeviceId()); |
197 | + if (priority) { | ||
198 | + deviceActor.tellWithHighPriority(msg); | ||
199 | + } else { | ||
200 | + deviceActor.tell(msg); | ||
201 | + } | ||
200 | } | 202 | } |
201 | 203 | ||
202 | private void onComponentLifecycleMsg(ComponentLifecycleMsg msg) { | 204 | private void onComponentLifecycleMsg(ComponentLifecycleMsg msg) { |
203 | if (isRuleEngineForCurrentTenant) { | 205 | if (isRuleEngineForCurrentTenant) { |
204 | - ActorRef target = getEntityActorRef(msg.getEntityId()); | 206 | + TbActorRef target = getEntityActorRef(msg.getEntityId()); |
205 | if (target != null) { | 207 | if (target != null) { |
206 | if (msg.getEntityId().getEntityType() == EntityType.RULE_CHAIN) { | 208 | if (msg.getEntityId().getEntityType() == EntityType.RULE_CHAIN) { |
207 | RuleChain ruleChain = systemContext.getRuleChainService(). | 209 | RuleChain ruleChain = systemContext.getRuleChainService(). |
@@ -210,42 +212,20 @@ public class TenantActor extends RuleChainManagerActor { | @@ -210,42 +212,20 @@ public class TenantActor extends RuleChainManagerActor { | ||
210 | visit(ruleChain, target); | 212 | visit(ruleChain, target); |
211 | } | 213 | } |
212 | } | 214 | } |
213 | - target.tell(msg, ActorRef.noSender()); | 215 | + target.tellWithHighPriority(msg); |
214 | } else { | 216 | } else { |
215 | log.debug("[{}] Invalid component lifecycle msg: {}", tenantId, msg); | 217 | log.debug("[{}] Invalid component lifecycle msg: {}", tenantId, msg); |
216 | } | 218 | } |
217 | } | 219 | } |
218 | } | 220 | } |
219 | 221 | ||
220 | - private ActorRef getOrCreateDeviceActor(DeviceId deviceId) { | ||
221 | - return deviceActors.computeIfAbsent(deviceId, k -> { | ||
222 | - log.debug("[{}][{}] Creating device actor.", tenantId, deviceId); | ||
223 | - ActorRef deviceActor = context().actorOf(Props.create(new DeviceActorCreator(systemContext, tenantId, deviceId)) | ||
224 | - .withDispatcher(DefaultActorService.CORE_DISPATCHER_NAME) | ||
225 | - , deviceId.toString()); | ||
226 | - context().watch(deviceActor); | ||
227 | - log.debug("[{}][{}] Created device actor: {}.", tenantId, deviceId, deviceActor); | ||
228 | - return deviceActor; | ||
229 | - }); | ||
230 | - } | ||
231 | - | ||
232 | - @Override | ||
233 | - protected void processTermination(Terminated message) { | ||
234 | - ActorRef terminated = message.actor(); | ||
235 | - if (terminated instanceof LocalActorRef) { | ||
236 | - boolean removed = deviceActors.inverse().remove(terminated) != null; | ||
237 | - if (removed) { | ||
238 | - log.debug("[{}] Removed actor:", terminated); | ||
239 | - } else { | ||
240 | - log.debug("Removed actor was not found in the device map!"); | ||
241 | - } | ||
242 | - } else { | ||
243 | - throw new IllegalStateException("Remote actors are not supported!"); | ||
244 | - } | 222 | + private TbActorRef getOrCreateDeviceActor(DeviceId deviceId) { |
223 | + return ctx.getOrCreateChildActor(new TbEntityActorId(deviceId), | ||
224 | + () -> DefaultActorService.DEVICE_DISPATCHER_NAME, | ||
225 | + () -> new DeviceActorCreator(systemContext, tenantId, deviceId)); | ||
245 | } | 226 | } |
246 | 227 | ||
247 | - public static class ActorCreator extends ContextBasedCreator<TenantActor> { | ||
248 | - private static final long serialVersionUID = 1L; | 228 | + public static class ActorCreator extends ContextBasedCreator { |
249 | 229 | ||
250 | private final TenantId tenantId; | 230 | private final TenantId tenantId; |
251 | 231 | ||
@@ -255,18 +235,14 @@ public class TenantActor extends RuleChainManagerActor { | @@ -255,18 +235,14 @@ public class TenantActor extends RuleChainManagerActor { | ||
255 | } | 235 | } |
256 | 236 | ||
257 | @Override | 237 | @Override |
258 | - public TenantActor create() { | ||
259 | - return new TenantActor(context, tenantId); | 238 | + public TbActorId createActorId() { |
239 | + return new TbEntityActorId(tenantId); | ||
260 | } | 240 | } |
261 | - } | ||
262 | 241 | ||
263 | - private final SupervisorStrategy strategy = new OneForOneStrategy(3, Duration.create("1 minute"), t -> { | ||
264 | - log.warn("[{}] Unknown failure", tenantId, t); | ||
265 | - if (t instanceof ActorInitializationException) { | ||
266 | - return SupervisorStrategy.stop(); | ||
267 | - } else { | ||
268 | - return SupervisorStrategy.resume(); | 242 | + @Override |
243 | + public TbActor createActor() { | ||
244 | + return new TenantActor(context, tenantId); | ||
269 | } | 245 | } |
270 | - }); | 246 | + } |
271 | 247 | ||
272 | } | 248 | } |
@@ -15,7 +15,6 @@ | @@ -15,7 +15,6 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.service.queue; | 16 | package org.thingsboard.server.service.queue; |
17 | 17 | ||
18 | -import akka.actor.ActorRef; | ||
19 | import lombok.extern.slf4j.Slf4j; | 18 | import lombok.extern.slf4j.Slf4j; |
20 | import org.springframework.beans.factory.annotation.Value; | 19 | import org.springframework.beans.factory.annotation.Value; |
21 | import org.springframework.scheduling.annotation.Scheduled; | 20 | import org.springframework.scheduling.annotation.Scheduled; |
@@ -157,7 +156,7 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore | @@ -157,7 +156,7 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore | ||
157 | tbCoreDeviceRpcService.forwardRpcRequestToDeviceActor((ToDeviceRpcRequestActorMsg) tbActorMsg); | 156 | tbCoreDeviceRpcService.forwardRpcRequestToDeviceActor((ToDeviceRpcRequestActorMsg) tbActorMsg); |
158 | } else { | 157 | } else { |
159 | log.trace("[{}] Forwarding message to App Actor {}", id, actorMsg.get()); | 158 | log.trace("[{}] Forwarding message to App Actor {}", id, actorMsg.get()); |
160 | - actorContext.tell(actorMsg.get(), ActorRef.noSender()); | 159 | + actorContext.tell(actorMsg.get()); |
161 | } | 160 | } |
162 | } | 161 | } |
163 | callback.onSuccess(); | 162 | callback.onSuccess(); |
@@ -168,7 +167,7 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore | @@ -168,7 +167,7 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore | ||
168 | } | 167 | } |
169 | }); | 168 | }); |
170 | if (!processingTimeoutLatch.await(packProcessingTimeout, TimeUnit.MILLISECONDS)) { | 169 | if (!processingTimeoutLatch.await(packProcessingTimeout, TimeUnit.MILLISECONDS)) { |
171 | - ctx.getAckMap().forEach((id, msg) -> log.warn("[{}] Timeout to process message: {}", id, msg.getValue())); | 170 | + ctx.getAckMap().forEach((id, msg) -> log.debug("[{}] Timeout to process message: {}", id, msg.getValue())); |
172 | ctx.getFailedMap().forEach((id, msg) -> log.warn("[{}] Failed to process message: {}", id, msg.getValue())); | 171 | ctx.getFailedMap().forEach((id, msg) -> log.warn("[{}] Failed to process message: {}", id, msg.getValue())); |
173 | } | 172 | } |
174 | mainConsumer.commit(); | 173 | mainConsumer.commit(); |
@@ -215,7 +214,7 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore | @@ -215,7 +214,7 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore | ||
215 | Optional<TbActorMsg> actorMsg = encodingService.decode(toCoreNotification.getComponentLifecycleMsg().toByteArray()); | 214 | Optional<TbActorMsg> actorMsg = encodingService.decode(toCoreNotification.getComponentLifecycleMsg().toByteArray()); |
216 | if (actorMsg.isPresent()) { | 215 | if (actorMsg.isPresent()) { |
217 | log.trace("[{}] Forwarding message to App Actor {}", id, actorMsg.get()); | 216 | log.trace("[{}] Forwarding message to App Actor {}", id, actorMsg.get()); |
218 | - actorContext.tell(actorMsg.get(), ActorRef.noSender()); | 217 | + actorContext.tellWithHighPriority(actorMsg.get()); |
219 | } | 218 | } |
220 | callback.onSuccess(); | 219 | callback.onSuccess(); |
221 | } | 220 | } |
@@ -293,7 +292,7 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore | @@ -293,7 +292,7 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore | ||
293 | if (statsEnabled) { | 292 | if (statsEnabled) { |
294 | stats.log(toDeviceActorMsg); | 293 | stats.log(toDeviceActorMsg); |
295 | } | 294 | } |
296 | - actorContext.tell(new TransportToDeviceActorMsgWrapper(toDeviceActorMsg, callback), ActorRef.noSender()); | 295 | + actorContext.tell(new TransportToDeviceActorMsgWrapper(toDeviceActorMsg, callback)); |
297 | } | 296 | } |
298 | 297 | ||
299 | private void throwNotHandled(Object msg, TbCallback callback) { | 298 | private void throwNotHandled(Object msg, TbCallback callback) { |
@@ -15,7 +15,6 @@ | @@ -15,7 +15,6 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.service.queue; | 16 | package org.thingsboard.server.service.queue; |
17 | 17 | ||
18 | -import akka.actor.ActorRef; | ||
19 | import com.google.protobuf.ProtocolStringList; | 18 | import com.google.protobuf.ProtocolStringList; |
20 | import lombok.extern.slf4j.Slf4j; | 19 | import lombok.extern.slf4j.Slf4j; |
21 | import org.springframework.beans.factory.annotation.Value; | 20 | import org.springframework.beans.factory.annotation.Value; |
@@ -51,7 +50,6 @@ import org.thingsboard.server.service.queue.processing.TbRuleEngineProcessingStr | @@ -51,7 +50,6 @@ import org.thingsboard.server.service.queue.processing.TbRuleEngineProcessingStr | ||
51 | import org.thingsboard.server.service.queue.processing.TbRuleEngineSubmitStrategy; | 50 | import org.thingsboard.server.service.queue.processing.TbRuleEngineSubmitStrategy; |
52 | import org.thingsboard.server.service.queue.processing.TbRuleEngineSubmitStrategyFactory; | 51 | import org.thingsboard.server.service.queue.processing.TbRuleEngineSubmitStrategyFactory; |
53 | import org.thingsboard.server.service.rpc.FromDeviceRpcResponse; | 52 | import org.thingsboard.server.service.rpc.FromDeviceRpcResponse; |
54 | -import org.thingsboard.server.service.rpc.TbCoreDeviceRpcService; | ||
55 | import org.thingsboard.server.service.rpc.TbRuleEngineDeviceRpcService; | 53 | import org.thingsboard.server.service.rpc.TbRuleEngineDeviceRpcService; |
56 | import org.thingsboard.server.service.stats.RuleEngineStatisticsService; | 54 | import org.thingsboard.server.service.stats.RuleEngineStatisticsService; |
57 | 55 | ||
@@ -168,7 +166,7 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService< | @@ -168,7 +166,7 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService< | ||
168 | TbMsgCallback callback = new TbMsgPackCallback(id, tenantId, ctx); | 166 | TbMsgCallback callback = new TbMsgPackCallback(id, tenantId, ctx); |
169 | try { | 167 | try { |
170 | if (toRuleEngineMsg.getTbMsg() != null && !toRuleEngineMsg.getTbMsg().isEmpty()) { | 168 | if (toRuleEngineMsg.getTbMsg() != null && !toRuleEngineMsg.getTbMsg().isEmpty()) { |
171 | - forwardToRuleEngineActor(tenantId, toRuleEngineMsg, callback); | 169 | + forwardToRuleEngineActor(configuration.getName(), tenantId, toRuleEngineMsg, callback); |
172 | } else { | 170 | } else { |
173 | callback.onSuccess(); | 171 | callback.onSuccess(); |
174 | } | 172 | } |
@@ -182,7 +180,7 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService< | @@ -182,7 +180,7 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService< | ||
182 | timeout = true; | 180 | timeout = true; |
183 | } | 181 | } |
184 | 182 | ||
185 | - TbRuleEngineProcessingResult result = new TbRuleEngineProcessingResult(timeout, ctx); | 183 | + TbRuleEngineProcessingResult result = new TbRuleEngineProcessingResult(configuration.getName(), timeout, ctx); |
186 | TbRuleEngineProcessingDecision decision = ackStrategy.analyze(result); | 184 | TbRuleEngineProcessingDecision decision = ackStrategy.analyze(result); |
187 | if (statsEnabled) { | 185 | if (statsEnabled) { |
188 | stats.log(result, decision.isCommit()); | 186 | stats.log(result, decision.isCommit()); |
@@ -232,7 +230,7 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService< | @@ -232,7 +230,7 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService< | ||
232 | Optional<TbActorMsg> actorMsg = encodingService.decode(nfMsg.getComponentLifecycleMsg().toByteArray()); | 230 | Optional<TbActorMsg> actorMsg = encodingService.decode(nfMsg.getComponentLifecycleMsg().toByteArray()); |
233 | if (actorMsg.isPresent()) { | 231 | if (actorMsg.isPresent()) { |
234 | log.trace("[{}] Forwarding message to App Actor {}", id, actorMsg.get()); | 232 | log.trace("[{}] Forwarding message to App Actor {}", id, actorMsg.get()); |
235 | - actorContext.tell(actorMsg.get(), ActorRef.noSender()); | 233 | + actorContext.tellWithHighPriority(actorMsg.get()); |
236 | } | 234 | } |
237 | callback.onSuccess(); | 235 | callback.onSuccess(); |
238 | } else if (nfMsg.hasFromDeviceRpcResponse()) { | 236 | } else if (nfMsg.hasFromDeviceRpcResponse()) { |
@@ -248,8 +246,8 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService< | @@ -248,8 +246,8 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService< | ||
248 | } | 246 | } |
249 | } | 247 | } |
250 | 248 | ||
251 | - private void forwardToRuleEngineActor(TenantId tenantId, ToRuleEngineMsg toRuleEngineMsg, TbMsgCallback callback) { | ||
252 | - TbMsg tbMsg = TbMsg.fromBytes(toRuleEngineMsg.getTbMsg().toByteArray(), callback); | 249 | + private void forwardToRuleEngineActor(String queueName, TenantId tenantId, ToRuleEngineMsg toRuleEngineMsg, TbMsgCallback callback) { |
250 | + TbMsg tbMsg = TbMsg.fromBytes(queueName, toRuleEngineMsg.getTbMsg().toByteArray(), callback); | ||
253 | QueueToRuleEngineMsg msg; | 251 | QueueToRuleEngineMsg msg; |
254 | ProtocolStringList relationTypesList = toRuleEngineMsg.getRelationTypesList(); | 252 | ProtocolStringList relationTypesList = toRuleEngineMsg.getRelationTypesList(); |
255 | Set<String> relationTypes = null; | 253 | Set<String> relationTypes = null; |
@@ -261,7 +259,7 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService< | @@ -261,7 +259,7 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService< | ||
261 | } | 259 | } |
262 | } | 260 | } |
263 | msg = new QueueToRuleEngineMsg(tenantId, tbMsg, relationTypes, toRuleEngineMsg.getFailureMessage()); | 261 | msg = new QueueToRuleEngineMsg(tenantId, tbMsg, relationTypes, toRuleEngineMsg.getFailureMessage()); |
264 | - actorContext.tell(msg, ActorRef.noSender()); | 262 | + actorContext.tell(msg); |
265 | } | 263 | } |
266 | 264 | ||
267 | @Scheduled(fixedDelayString = "${queue.rule-engine.stats.print-interval-ms}") | 265 | @Scheduled(fixedDelayString = "${queue.rule-engine.stats.print-interval-ms}") |
@@ -28,13 +28,16 @@ import java.util.concurrent.ConcurrentMap; | @@ -28,13 +28,16 @@ import java.util.concurrent.ConcurrentMap; | ||
28 | public class TbRuleEngineProcessingResult { | 28 | public class TbRuleEngineProcessingResult { |
29 | 29 | ||
30 | @Getter | 30 | @Getter |
31 | + private final String queueName; | ||
32 | + @Getter | ||
31 | private final boolean success; | 33 | private final boolean success; |
32 | @Getter | 34 | @Getter |
33 | private final boolean timeout; | 35 | private final boolean timeout; |
34 | @Getter | 36 | @Getter |
35 | private final TbMsgPackProcessingContext ctx; | 37 | private final TbMsgPackProcessingContext ctx; |
36 | 38 | ||
37 | - public TbRuleEngineProcessingResult(boolean timeout, TbMsgPackProcessingContext ctx) { | 39 | + public TbRuleEngineProcessingResult(String queueName, boolean timeout, TbMsgPackProcessingContext ctx) { |
40 | + this.queueName = queueName; | ||
38 | this.timeout = timeout; | 41 | this.timeout = timeout; |
39 | this.ctx = ctx; | 42 | this.ctx = ctx; |
40 | this.success = !timeout && ctx.getPendingMap().isEmpty() && ctx.getFailedMap().isEmpty(); | 43 | this.success = !timeout && ctx.getPendingMap().isEmpty() && ctx.getFailedMap().isEmpty(); |
@@ -100,7 +100,7 @@ public class TbRuleEngineProcessingStrategyFactory { | @@ -100,7 +100,7 @@ public class TbRuleEngineProcessingStrategyFactory { | ||
100 | } | 100 | } |
101 | log.debug("[{}] Going to reprocess {} messages", queueName, toReprocess.size()); | 101 | log.debug("[{}] Going to reprocess {} messages", queueName, toReprocess.size()); |
102 | if (log.isTraceEnabled()) { | 102 | if (log.isTraceEnabled()) { |
103 | - toReprocess.forEach((id, msg) -> log.trace("Going to reprocess [{}]: {}", id, TbMsg.fromBytes(msg.getValue().getTbMsg().toByteArray(), TbMsgCallback.EMPTY))); | 103 | + toReprocess.forEach((id, msg) -> log.trace("Going to reprocess [{}]: {}", id, TbMsg.fromBytes(result.getQueueName(), msg.getValue().getTbMsg().toByteArray(), TbMsgCallback.EMPTY))); |
104 | } | 104 | } |
105 | if (pauseBetweenRetries > 0) { | 105 | if (pauseBetweenRetries > 0) { |
106 | try { | 106 | try { |
@@ -129,10 +129,10 @@ public class TbRuleEngineProcessingStrategyFactory { | @@ -129,10 +129,10 @@ public class TbRuleEngineProcessingStrategyFactory { | ||
129 | log.debug("[{}] Reprocessing skipped for {} failed and {} timeout messages", queueName, result.getFailedMap().size(), result.getPendingMap().size()); | 129 | log.debug("[{}] Reprocessing skipped for {} failed and {} timeout messages", queueName, result.getFailedMap().size(), result.getPendingMap().size()); |
130 | } | 130 | } |
131 | if (log.isTraceEnabled()) { | 131 | if (log.isTraceEnabled()) { |
132 | - result.getFailedMap().forEach((id, msg) -> log.trace("Failed messages [{}]: {}", id, TbMsg.fromBytes(msg.getValue().getTbMsg().toByteArray(), TbMsgCallback.EMPTY))); | 132 | + result.getFailedMap().forEach((id, msg) -> log.trace("Failed messages [{}]: {}", id, TbMsg.fromBytes(result.getQueueName(), msg.getValue().getTbMsg().toByteArray(), TbMsgCallback.EMPTY))); |
133 | } | 133 | } |
134 | if (log.isTraceEnabled()) { | 134 | if (log.isTraceEnabled()) { |
135 | - result.getPendingMap().forEach((id, msg) -> log.trace("Timeout messages [{}]: {}", id, TbMsg.fromBytes(msg.getValue().getTbMsg().toByteArray(), TbMsgCallback.EMPTY))); | 135 | + result.getPendingMap().forEach((id, msg) -> log.trace("Timeout messages [{}]: {}", id, TbMsg.fromBytes(result.getQueueName(), msg.getValue().getTbMsg().toByteArray(), TbMsgCallback.EMPTY))); |
136 | } | 136 | } |
137 | return new TbRuleEngineProcessingDecision(true, null); | 137 | return new TbRuleEngineProcessingDecision(true, null); |
138 | } | 138 | } |
@@ -15,7 +15,6 @@ | @@ -15,7 +15,6 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.service.rpc; | 16 | package org.thingsboard.server.service.rpc; |
17 | 17 | ||
18 | -import akka.actor.ActorRef; | ||
19 | import com.fasterxml.jackson.core.JsonProcessingException; | 18 | import com.fasterxml.jackson.core.JsonProcessingException; |
20 | import com.fasterxml.jackson.databind.ObjectMapper; | 19 | import com.fasterxml.jackson.databind.ObjectMapper; |
21 | import com.fasterxml.jackson.databind.node.ObjectNode; | 20 | import com.fasterxml.jackson.databind.node.ObjectNode; |
@@ -122,7 +121,7 @@ public class DefaultTbCoreDeviceRpcService implements TbCoreDeviceRpcService { | @@ -122,7 +121,7 @@ public class DefaultTbCoreDeviceRpcService implements TbCoreDeviceRpcService { | ||
122 | log.trace("[{}][{}] Processing local rpc call to device actor [{}]", request.getTenantId(), request.getId(), request.getDeviceId()); | 121 | log.trace("[{}][{}] Processing local rpc call to device actor [{}]", request.getTenantId(), request.getId(), request.getDeviceId()); |
123 | UUID requestId = request.getId(); | 122 | UUID requestId = request.getId(); |
124 | localToDeviceRpcRequests.put(requestId, rpcMsg); | 123 | localToDeviceRpcRequests.put(requestId, rpcMsg); |
125 | - actorContext.tell(rpcMsg, ActorRef.noSender()); | 124 | + actorContext.tellWithHighPriority(rpcMsg); |
126 | scheduleToDeviceTimeout(request, requestId); | 125 | scheduleToDeviceTimeout(request, requestId); |
127 | } | 126 | } |
128 | 127 | ||
@@ -176,7 +175,7 @@ public class DefaultTbCoreDeviceRpcService implements TbCoreDeviceRpcService { | @@ -176,7 +175,7 @@ public class DefaultTbCoreDeviceRpcService implements TbCoreDeviceRpcService { | ||
176 | } | 175 | } |
177 | 176 | ||
178 | private void scheduleToRuleEngineTimeout(ToDeviceRpcRequest request, UUID requestId) { | 177 | private void scheduleToRuleEngineTimeout(ToDeviceRpcRequest request, UUID requestId) { |
179 | - long timeout = Math.max(0, request.getExpirationTime() - System.currentTimeMillis()); | 178 | + long timeout = Math.max(0, request.getExpirationTime() - System.currentTimeMillis()) + TimeUnit.SECONDS.toMillis(1); |
180 | log.trace("[{}] processing to rule engine request.", requestId); | 179 | log.trace("[{}] processing to rule engine request.", requestId); |
181 | scheduler.schedule(() -> { | 180 | scheduler.schedule(() -> { |
182 | log.trace("[{}] timeout for processing to rule engine request.", requestId); | 181 | log.trace("[{}] timeout for processing to rule engine request.", requestId); |
@@ -188,7 +187,7 @@ public class DefaultTbCoreDeviceRpcService implements TbCoreDeviceRpcService { | @@ -188,7 +187,7 @@ public class DefaultTbCoreDeviceRpcService implements TbCoreDeviceRpcService { | ||
188 | } | 187 | } |
189 | 188 | ||
190 | private void scheduleToDeviceTimeout(ToDeviceRpcRequest request, UUID requestId) { | 189 | private void scheduleToDeviceTimeout(ToDeviceRpcRequest request, UUID requestId) { |
191 | - long timeout = Math.max(0, request.getExpirationTime() - System.currentTimeMillis()); | 190 | + long timeout = Math.max(0, request.getExpirationTime() - System.currentTimeMillis()) + TimeUnit.SECONDS.toMillis(1); |
192 | log.trace("[{}] processing to device request.", requestId); | 191 | log.trace("[{}] processing to device request.", requestId); |
193 | scheduler.schedule(() -> { | 192 | scheduler.schedule(() -> { |
194 | log.trace("[{}] timeout for to device request.", requestId); | 193 | log.trace("[{}] timeout for to device request.", requestId); |
@@ -164,7 +164,7 @@ public class DefaultTbRuleEngineRpcService implements TbRuleEngineDeviceRpcServi | @@ -164,7 +164,7 @@ public class DefaultTbRuleEngineRpcService implements TbRuleEngineDeviceRpcServi | ||
164 | } | 164 | } |
165 | 165 | ||
166 | private void scheduleTimeout(ToDeviceRpcRequest request, UUID requestId) { | 166 | private void scheduleTimeout(ToDeviceRpcRequest request, UUID requestId) { |
167 | - long timeout = Math.max(0, request.getExpirationTime() - System.currentTimeMillis()); | 167 | + long timeout = Math.max(0, request.getExpirationTime() - System.currentTimeMillis()) + TimeUnit.SECONDS.toMillis(1); |
168 | log.trace("[{}] processing the request: [{}]", this.hashCode(), requestId); | 168 | log.trace("[{}] processing the request: [{}]", this.hashCode(), requestId); |
169 | scheduler.schedule(() -> { | 169 | scheduler.schedule(() -> { |
170 | log.trace("[{}] timeout the request: [{}]", this.hashCode(), requestId); | 170 | log.trace("[{}] timeout the request: [{}]", this.hashCode(), requestId); |
@@ -126,7 +126,7 @@ public abstract class AbstractNashornJsInvokeService extends AbstractJsInvokeSer | @@ -126,7 +126,7 @@ public abstract class AbstractNashornJsInvokeService extends AbstractJsInvokeSer | ||
126 | scriptIdToNameMap.put(scriptId, functionName); | 126 | scriptIdToNameMap.put(scriptId, functionName); |
127 | return scriptId; | 127 | return scriptId; |
128 | } catch (Exception e) { | 128 | } catch (Exception e) { |
129 | - log.warn("Failed to compile JS script: {}", e.getMessage(), e); | 129 | + log.debug("Failed to compile JS script: {}", e.getMessage(), e); |
130 | throw new ExecutionException(e); | 130 | throw new ExecutionException(e); |
131 | } | 131 | } |
132 | }); | 132 | }); |
application/src/main/resources/actor-system.conf
deleted
100644 → 0
1 | -# | ||
2 | -# Copyright © 2016-2020 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 | - | ||
17 | - | ||
18 | -akka { | ||
19 | - # JVM shutdown, System.exit(-1), in case of a fatal error, | ||
20 | - # such as OutOfMemoryError | ||
21 | - jvm-exit-on-fatal-error = off | ||
22 | - loglevel = "INFO" | ||
23 | - loggers = ["akka.event.slf4j.Slf4jLogger"] | ||
24 | -} | ||
25 | - | ||
26 | -# This dispatcher is used for app | ||
27 | -app-dispatcher { | ||
28 | - type = Dispatcher | ||
29 | - executor = "fork-join-executor" | ||
30 | - fork-join-executor { | ||
31 | - # Min number of threads to cap factor-based parallelism number to | ||
32 | - parallelism-min = 1 | ||
33 | - # Max number of threads to cap factor-based parallelism number to | ||
34 | - parallelism-max = 1 | ||
35 | - | ||
36 | - # The parallelism factor is used to determine thread pool size using the | ||
37 | - # following formula: ceil(available processors * factor). Resulting size | ||
38 | - # is then bounded by the parallelism-min and parallelism-max values. | ||
39 | - parallelism-factor = 1.0 | ||
40 | - } | ||
41 | - # How long time the dispatcher will wait for new actors until it shuts down | ||
42 | - shutdown-timeout = 1s | ||
43 | - | ||
44 | - # Throughput defines the number of messages that are processed in a batch | ||
45 | - # before the thread is returned to the pool. Set to 1 for as fair as possible. | ||
46 | - throughput = 5 | ||
47 | -} | ||
48 | - | ||
49 | -# This dispatcher is used for rpc actors | ||
50 | -rpc-dispatcher { | ||
51 | - type = Dispatcher | ||
52 | - executor = "fork-join-executor" | ||
53 | - fork-join-executor { | ||
54 | - # Min number of threads to cap factor-based parallelism number to | ||
55 | - parallelism-min = 2 | ||
56 | - # Max number of threads to cap factor-based parallelism number to | ||
57 | - parallelism-max = 8 | ||
58 | - | ||
59 | - # The parallelism factor is used to determine thread pool size using the | ||
60 | - # following formula: ceil(available processors * factor). Resulting size | ||
61 | - # is then bounded by the parallelism-min and parallelism-max values. | ||
62 | - parallelism-factor = 0.5 | ||
63 | - } | ||
64 | - # How long time the dispatcher will wait for new actors until it shuts down | ||
65 | - shutdown-timeout = 1s | ||
66 | - | ||
67 | - # Throughput defines the number of messages that are processed in a batch | ||
68 | - # before the thread is returned to the pool. Set to 1 for as fair as possible. | ||
69 | - throughput = 5 | ||
70 | -} | ||
71 | - | ||
72 | -# This dispatcher is used for auth | ||
73 | -core-dispatcher { | ||
74 | - type = Dispatcher | ||
75 | - executor = "fork-join-executor" | ||
76 | - fork-join-executor { | ||
77 | - # Min number of threads to cap factor-based parallelism number to | ||
78 | - parallelism-min = 2 | ||
79 | - # Max number of threads to cap factor-based parallelism number to | ||
80 | - parallelism-max = 12 | ||
81 | - | ||
82 | - # The parallelism factor is used to determine thread pool size using the | ||
83 | - # following formula: ceil(available processors * factor). Resulting size | ||
84 | - # is then bounded by the parallelism-min and parallelism-max values. | ||
85 | - parallelism-factor = 0.25 | ||
86 | - } | ||
87 | - # How long time the dispatcher will wait for new actors until it shuts down | ||
88 | - shutdown-timeout = 1s | ||
89 | - | ||
90 | - # Throughput defines the number of messages that are processed in a batch | ||
91 | - # before the thread is returned to the pool. Set to 1 for as fair as possible. | ||
92 | - throughput = 5 | ||
93 | -} | ||
94 | - | ||
95 | -# This dispatcher is used for system rule chains and rule node actors | ||
96 | -system-rule-dispatcher { | ||
97 | - type = Dispatcher | ||
98 | - executor = "fork-join-executor" | ||
99 | - fork-join-executor { | ||
100 | - # Min number of threads to cap factor-based parallelism number to | ||
101 | - parallelism-min = 2 | ||
102 | - # Max number of threads to cap factor-based parallelism number to | ||
103 | - parallelism-max = 12 | ||
104 | - | ||
105 | - # The parallelism factor is used to determine thread pool size using the | ||
106 | - # following formula: ceil(available processors * factor). Resulting size | ||
107 | - # is then bounded by the parallelism-min and parallelism-max values. | ||
108 | - parallelism-factor = 0.25 | ||
109 | - } | ||
110 | - # How long time the dispatcher will wait for new actors until it shuts down | ||
111 | - shutdown-timeout = 1s | ||
112 | - | ||
113 | - # Throughput defines the number of messages that are processed in a batch | ||
114 | - # before the thread is returned to the pool. Set to 1 for as fair as possible. | ||
115 | - throughput = 5 | ||
116 | -} | ||
117 | - | ||
118 | -# This dispatcher is used for tenant rule chains and rule node actors | ||
119 | -rule-dispatcher { | ||
120 | - type = Dispatcher | ||
121 | - executor = "fork-join-executor" | ||
122 | - fork-join-executor { | ||
123 | - # Min number of threads to cap factor-based parallelism number to | ||
124 | - parallelism-min = 2 | ||
125 | - # Max number of threads to cap factor-based parallelism number to | ||
126 | - parallelism-max = 12 | ||
127 | - | ||
128 | - # The parallelism factor is used to determine thread pool size using the | ||
129 | - # following formula: ceil(available processors * factor). Resulting size | ||
130 | - # is then bounded by the parallelism-min and parallelism-max values. | ||
131 | - parallelism-factor = 0.25 | ||
132 | - } | ||
133 | - # How long time the dispatcher will wait for new actors until it shuts down | ||
134 | - shutdown-timeout = 1s | ||
135 | - | ||
136 | - # Throughput defines the number of messages that are processed in a batch | ||
137 | - # before the thread is returned to the pool. Set to 1 for as fair as possible. | ||
138 | - throughput = 5 | ||
139 | -} |
@@ -27,7 +27,6 @@ | @@ -27,7 +27,6 @@ | ||
27 | 27 | ||
28 | <logger name="org.thingsboard.server" level="INFO" /> | 28 | <logger name="org.thingsboard.server" level="INFO" /> |
29 | <logger name="org.thingsboard.server.service.edge" level="TRACE" /> | 29 | <logger name="org.thingsboard.server.service.edge" level="TRACE" /> |
30 | - <logger name="akka" level="INFO" /> | ||
31 | 30 | ||
32 | <!-- <logger name="org.thingsboard.server.service.queue" level="TRACE" />--> | 31 | <!-- <logger name="org.thingsboard.server.service.queue" level="TRACE" />--> |
33 | <!-- <logger name="org.thingsboard.server.service.transport" level="TRACE" />--> | 32 | <!-- <logger name="org.thingsboard.server.service.transport" level="TRACE" />--> |
@@ -281,6 +281,14 @@ sql: | @@ -281,6 +281,14 @@ sql: | ||
281 | 281 | ||
282 | # Actor system parameters | 282 | # Actor system parameters |
283 | actors: | 283 | actors: |
284 | + system: | ||
285 | + throughput: "${ACTORS_SYSTEM_THROUGHPUT:5}" | ||
286 | + scheduler_pool_size: "${ACTORS_SYSTEM_SCHEDULER_POOL_SIZE:1}" | ||
287 | + max_actor_init_attempts: "${ACTORS_SYSTEM_MAX_ACTOR_INIT_ATTEMPTS:10}" | ||
288 | + app_dispatcher_pool_size: "${ACTORS_SYSTEM_APP_DISPATCHER_POOL_SIZE:1}" | ||
289 | + tenant_dispatcher_pool_size: "${ACTORS_SYSTEM_TENANT_DISPATCHER_POOL_SIZE:2}" | ||
290 | + device_dispatcher_pool_size: "${ACTORS_SYSTEM_DEVICE_DISPATCHER_POOL_SIZE:4}" | ||
291 | + rule_dispatcher_pool_size: "${ACTORS_SYSTEM_RULE_DISPATCHER_POOL_SIZE:4}" | ||
284 | tenant: | 292 | tenant: |
285 | create_components_on_init: "${ACTORS_TENANT_CREATE_COMPONENTS_ON_INIT:true}" | 293 | create_components_on_init: "${ACTORS_TENANT_CREATE_COMPONENTS_ON_INIT:true}" |
286 | session: | 294 | session: |
@@ -318,11 +326,6 @@ actors: | @@ -318,11 +326,6 @@ actors: | ||
318 | enabled: "${ACTORS_STATISTICS_ENABLED:true}" | 326 | enabled: "${ACTORS_STATISTICS_ENABLED:true}" |
319 | js_print_interval_ms: "${ACTORS_JS_STATISTICS_PRINT_INTERVAL_MS:10000}" | 327 | js_print_interval_ms: "${ACTORS_JS_STATISTICS_PRINT_INTERVAL_MS:10000}" |
320 | persist_frequency: "${ACTORS_STATISTICS_PERSIST_FREQUENCY:3600000}" | 328 | persist_frequency: "${ACTORS_STATISTICS_PERSIST_FREQUENCY:3600000}" |
321 | - queue: | ||
322 | - # Enable/disable persistence of un-processed messages to the queue | ||
323 | - enabled: "${ACTORS_QUEUE_ENABLED:true}" | ||
324 | - # Maximum allowed timeout for persistence into the queue | ||
325 | - timeout: "${ACTORS_QUEUE_PERSISTENCE_TIMEOUT:30000}" | ||
326 | 329 | ||
327 | cache: | 330 | cache: |
328 | # caffeine or redis | 331 | # caffeine or redis |
@@ -26,7 +26,9 @@ import java.util.Arrays; | @@ -26,7 +26,9 @@ import java.util.Arrays; | ||
26 | 26 | ||
27 | @RunWith(ClasspathSuite.class) | 27 | @RunWith(ClasspathSuite.class) |
28 | @ClasspathSuite.ClassnameFilters({ | 28 | @ClasspathSuite.ClassnameFilters({ |
29 | - "org.thingsboard.server.mqtt.rpc.sql.*Test", "org.thingsboard.server.mqtt.telemetry.sql.*Test"}) | 29 | + "org.thingsboard.server.mqtt.rpc.sql.*Test", |
30 | + "org.thingsboard.server.mqtt.telemetry.sql.*Test" | ||
31 | +}) | ||
30 | public class MqttSqlTestSuite { | 32 | public class MqttSqlTestSuite { |
31 | 33 | ||
32 | @ClassRule | 34 | @ClassRule |
@@ -136,7 +136,7 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractC | @@ -136,7 +136,7 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractC | ||
136 | String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"24\",\"value\": 1},\"timeout\": 6000}"; | 136 | String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"24\",\"value\": 1},\"timeout\": 6000}"; |
137 | String deviceId = savedDevice.getId().getId().toString(); | 137 | String deviceId = savedDevice.getId().getId().toString(); |
138 | 138 | ||
139 | - doPostAsync("/api/plugins/rpc/oneway/" + deviceId, setGpioRequest, String.class, status().isRequestTimeout(), | 139 | + doPostAsync("/api/plugins/rpc/oneway/" + deviceId, setGpioRequest, String.class, status().is(409), |
140 | asyncContextTimeoutToUseRpcPlugin); | 140 | asyncContextTimeoutToUseRpcPlugin); |
141 | } | 141 | } |
142 | 142 | ||
@@ -193,7 +193,7 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractC | @@ -193,7 +193,7 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractC | ||
193 | String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"27\",\"value\": 1},\"timeout\": 6000}"; | 193 | String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"27\",\"value\": 1},\"timeout\": 6000}"; |
194 | String deviceId = savedDevice.getId().getId().toString(); | 194 | String deviceId = savedDevice.getId().getId().toString(); |
195 | 195 | ||
196 | - doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().isRequestTimeout(), | 196 | + doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().is(409), |
197 | asyncContextTimeoutToUseRpcPlugin); | 197 | asyncContextTimeoutToUseRpcPlugin); |
198 | } | 198 | } |
199 | 199 |
@@ -15,8 +15,6 @@ | @@ -15,8 +15,6 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.rules.flow; | 16 | package org.thingsboard.server.rules.flow; |
17 | 17 | ||
18 | -import akka.actor.ActorRef; | ||
19 | -import com.datastax.driver.core.utils.UUIDs; | ||
20 | import lombok.extern.slf4j.Slf4j; | 18 | import lombok.extern.slf4j.Slf4j; |
21 | import org.junit.After; | 19 | import org.junit.After; |
22 | import org.junit.Assert; | 20 | import org.junit.Assert; |
@@ -26,7 +24,6 @@ import org.mockito.Mockito; | @@ -26,7 +24,6 @@ import org.mockito.Mockito; | ||
26 | import org.springframework.beans.factory.annotation.Autowired; | 24 | import org.springframework.beans.factory.annotation.Autowired; |
27 | import org.thingsboard.rule.engine.metadata.TbGetAttributesNodeConfiguration; | 25 | import org.thingsboard.rule.engine.metadata.TbGetAttributesNodeConfiguration; |
28 | import org.thingsboard.server.actors.ActorSystemContext; | 26 | import org.thingsboard.server.actors.ActorSystemContext; |
29 | -import org.thingsboard.server.actors.service.ActorService; | ||
30 | import org.thingsboard.server.common.data.*; | 27 | import org.thingsboard.server.common.data.*; |
31 | import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; | 28 | import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; |
32 | import org.thingsboard.server.common.data.kv.StringDataEntry; | 29 | import org.thingsboard.server.common.data.kv.StringDataEntry; |
@@ -36,7 +33,6 @@ import org.thingsboard.server.common.data.rule.RuleChainMetaData; | @@ -36,7 +33,6 @@ import org.thingsboard.server.common.data.rule.RuleChainMetaData; | ||
36 | import org.thingsboard.server.common.data.rule.RuleNode; | 33 | import org.thingsboard.server.common.data.rule.RuleNode; |
37 | import org.thingsboard.server.common.data.security.Authority; | 34 | import org.thingsboard.server.common.data.security.Authority; |
38 | import org.thingsboard.server.common.msg.TbMsg; | 35 | import org.thingsboard.server.common.msg.TbMsg; |
39 | -import org.thingsboard.server.common.msg.TbMsgDataType; | ||
40 | import org.thingsboard.server.common.msg.TbMsgMetaData; | 36 | import org.thingsboard.server.common.msg.TbMsgMetaData; |
41 | import org.thingsboard.server.common.msg.queue.QueueToRuleEngineMsg; | 37 | import org.thingsboard.server.common.msg.queue.QueueToRuleEngineMsg; |
42 | import org.thingsboard.server.common.msg.queue.TbMsgCallback; | 38 | import org.thingsboard.server.common.msg.queue.TbMsgCallback; |
@@ -151,7 +147,7 @@ public abstract class AbstractRuleEngineFlowIntegrationTest extends AbstractRule | @@ -151,7 +147,7 @@ public abstract class AbstractRuleEngineFlowIntegrationTest extends AbstractRule | ||
151 | TbMsg tbMsg = TbMsg.newMsg("CUSTOM", device.getId(), new TbMsgMetaData(), "{}", tbMsgCallback); | 147 | TbMsg tbMsg = TbMsg.newMsg("CUSTOM", device.getId(), new TbMsgMetaData(), "{}", tbMsgCallback); |
152 | QueueToRuleEngineMsg qMsg = new QueueToRuleEngineMsg(savedTenant.getId(), tbMsg, null, null); | 148 | QueueToRuleEngineMsg qMsg = new QueueToRuleEngineMsg(savedTenant.getId(), tbMsg, null, null); |
153 | // Pushing Message to the system | 149 | // Pushing Message to the system |
154 | - actorSystem.tell(qMsg, ActorRef.noSender()); | 150 | + actorSystem.tell(qMsg); |
155 | Mockito.verify(tbMsgCallback, Mockito.timeout(10000)).onSuccess(); | 151 | Mockito.verify(tbMsgCallback, Mockito.timeout(10000)).onSuccess(); |
156 | 152 | ||
157 | TimePageData<Event> eventsPage = getDebugEvents(savedTenant.getId(), ruleChain.getFirstRuleNodeId(), 1000); | 153 | TimePageData<Event> eventsPage = getDebugEvents(savedTenant.getId(), ruleChain.getFirstRuleNodeId(), 1000); |
@@ -263,7 +259,7 @@ public abstract class AbstractRuleEngineFlowIntegrationTest extends AbstractRule | @@ -263,7 +259,7 @@ public abstract class AbstractRuleEngineFlowIntegrationTest extends AbstractRule | ||
263 | TbMsg tbMsg = TbMsg.newMsg("CUSTOM", device.getId(), new TbMsgMetaData(), "{}", tbMsgCallback); | 259 | TbMsg tbMsg = TbMsg.newMsg("CUSTOM", device.getId(), new TbMsgMetaData(), "{}", tbMsgCallback); |
264 | QueueToRuleEngineMsg qMsg = new QueueToRuleEngineMsg(savedTenant.getId(), tbMsg, null, null); | 260 | QueueToRuleEngineMsg qMsg = new QueueToRuleEngineMsg(savedTenant.getId(), tbMsg, null, null); |
265 | // Pushing Message to the system | 261 | // Pushing Message to the system |
266 | - actorSystem.tell(qMsg, ActorRef.noSender()); | 262 | + actorSystem.tell(qMsg); |
267 | 263 | ||
268 | Mockito.verify(tbMsgCallback, Mockito.timeout(10000)).onSuccess(); | 264 | Mockito.verify(tbMsgCallback, Mockito.timeout(10000)).onSuccess(); |
269 | 265 |
@@ -15,8 +15,6 @@ | @@ -15,8 +15,6 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.rules.lifecycle; | 16 | package org.thingsboard.server.rules.lifecycle; |
17 | 17 | ||
18 | -import akka.actor.ActorRef; | ||
19 | -import com.datastax.driver.core.utils.UUIDs; | ||
20 | import lombok.extern.slf4j.Slf4j; | 18 | import lombok.extern.slf4j.Slf4j; |
21 | import org.junit.After; | 19 | import org.junit.After; |
22 | import org.junit.Assert; | 20 | import org.junit.Assert; |
@@ -26,7 +24,6 @@ import org.mockito.Mockito; | @@ -26,7 +24,6 @@ import org.mockito.Mockito; | ||
26 | import org.springframework.beans.factory.annotation.Autowired; | 24 | import org.springframework.beans.factory.annotation.Autowired; |
27 | import org.thingsboard.rule.engine.metadata.TbGetAttributesNodeConfiguration; | 25 | import org.thingsboard.rule.engine.metadata.TbGetAttributesNodeConfiguration; |
28 | import org.thingsboard.server.actors.ActorSystemContext; | 26 | import org.thingsboard.server.actors.ActorSystemContext; |
29 | -import org.thingsboard.server.actors.service.ActorService; | ||
30 | import org.thingsboard.server.common.data.DataConstants; | 27 | import org.thingsboard.server.common.data.DataConstants; |
31 | import org.thingsboard.server.common.data.Device; | 28 | import org.thingsboard.server.common.data.Device; |
32 | import org.thingsboard.server.common.data.Event; | 29 | import org.thingsboard.server.common.data.Event; |
@@ -40,7 +37,6 @@ import org.thingsboard.server.common.data.rule.RuleChainMetaData; | @@ -40,7 +37,6 @@ import org.thingsboard.server.common.data.rule.RuleChainMetaData; | ||
40 | import org.thingsboard.server.common.data.rule.RuleNode; | 37 | import org.thingsboard.server.common.data.rule.RuleNode; |
41 | import org.thingsboard.server.common.data.security.Authority; | 38 | import org.thingsboard.server.common.data.security.Authority; |
42 | import org.thingsboard.server.common.msg.TbMsg; | 39 | import org.thingsboard.server.common.msg.TbMsg; |
43 | -import org.thingsboard.server.common.msg.TbMsgDataType; | ||
44 | import org.thingsboard.server.common.msg.TbMsgMetaData; | 40 | import org.thingsboard.server.common.msg.TbMsgMetaData; |
45 | import org.thingsboard.server.common.msg.queue.QueueToRuleEngineMsg; | 41 | import org.thingsboard.server.common.msg.queue.QueueToRuleEngineMsg; |
46 | import org.thingsboard.server.common.msg.queue.TbMsgCallback; | 42 | import org.thingsboard.server.common.msg.queue.TbMsgCallback; |
@@ -142,7 +138,7 @@ public abstract class AbstractRuleEngineLifecycleIntegrationTest extends Abstrac | @@ -142,7 +138,7 @@ public abstract class AbstractRuleEngineLifecycleIntegrationTest extends Abstrac | ||
142 | TbMsg tbMsg = TbMsg.newMsg("CUSTOM", device.getId(), new TbMsgMetaData(), "{}", tbMsgCallback); | 138 | TbMsg tbMsg = TbMsg.newMsg("CUSTOM", device.getId(), new TbMsgMetaData(), "{}", tbMsgCallback); |
143 | QueueToRuleEngineMsg qMsg = new QueueToRuleEngineMsg(savedTenant.getId(), tbMsg, null, null); | 139 | QueueToRuleEngineMsg qMsg = new QueueToRuleEngineMsg(savedTenant.getId(), tbMsg, null, null); |
144 | // Pushing Message to the system | 140 | // Pushing Message to the system |
145 | - actorSystem.tell(qMsg, ActorRef.noSender()); | 141 | + actorSystem.tell(qMsg); |
146 | Mockito.verify(tbMsgCallback, Mockito.timeout(3000)).onSuccess(); | 142 | Mockito.verify(tbMsgCallback, Mockito.timeout(3000)).onSuccess(); |
147 | 143 | ||
148 | 144 |
@@ -13,8 +13,6 @@ | @@ -13,8 +13,6 @@ | ||
13 | <logger name="org.apache.cassandra" level="WARN"/> | 13 | <logger name="org.apache.cassandra" level="WARN"/> |
14 | <logger name="org.cassandraunit" level="INFO"/> | 14 | <logger name="org.cassandraunit" level="INFO"/> |
15 | 15 | ||
16 | - <logger name="akka" level="INFO" /> | ||
17 | - | ||
18 | <root level="WARN"> | 16 | <root level="WARN"> |
19 | <appender-ref ref="console"/> | 17 | <appender-ref ref="console"/> |
20 | </root> | 18 | </root> |
common/actor/pom.xml
0 → 100644
1 | +<!-- | ||
2 | + | ||
3 | + Copyright © 2016-2020 The Thingsboard Authors | ||
4 | + | ||
5 | + Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | + you may not use this file except in compliance with the License. | ||
7 | + You may obtain a copy of the License at | ||
8 | + | ||
9 | + http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | + | ||
11 | + Unless required by applicable law or agreed to in writing, software | ||
12 | + distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | + See the License for the specific language governing permissions and | ||
15 | + limitations under the License. | ||
16 | + | ||
17 | +--> | ||
18 | +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
19 | + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
20 | + <modelVersion>4.0.0</modelVersion> | ||
21 | + <parent> | ||
22 | + <groupId>org.thingsboard</groupId> | ||
23 | + <version>2.5.3-SNAPSHOT</version> | ||
24 | + <artifactId>common</artifactId> | ||
25 | + </parent> | ||
26 | + <groupId>org.thingsboard.common</groupId> | ||
27 | + <artifactId>actor</artifactId> | ||
28 | + <packaging>jar</packaging> | ||
29 | + | ||
30 | + <name>Thingsboard Actor system</name> | ||
31 | + <url>https://thingsboard.io</url> | ||
32 | + | ||
33 | + <properties> | ||
34 | + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
35 | + <main.dir>${basedir}/../..</main.dir> | ||
36 | + </properties> | ||
37 | + | ||
38 | + <dependencies> | ||
39 | + <dependency> | ||
40 | + <groupId>org.thingsboard.common</groupId> | ||
41 | + <artifactId>util</artifactId> | ||
42 | + </dependency> | ||
43 | + <dependency> | ||
44 | + <groupId>org.thingsboard.common</groupId> | ||
45 | + <artifactId>message</artifactId> | ||
46 | + </dependency> | ||
47 | + <dependency> | ||
48 | + <groupId>org.slf4j</groupId> | ||
49 | + <artifactId>slf4j-api</artifactId> | ||
50 | + </dependency> | ||
51 | + <dependency> | ||
52 | + <groupId>org.slf4j</groupId> | ||
53 | + <artifactId>log4j-over-slf4j</artifactId> | ||
54 | + </dependency> | ||
55 | + <dependency> | ||
56 | + <groupId>ch.qos.logback</groupId> | ||
57 | + <artifactId>logback-core</artifactId> | ||
58 | + </dependency> | ||
59 | + <dependency> | ||
60 | + <groupId>ch.qos.logback</groupId> | ||
61 | + <artifactId>logback-classic</artifactId> | ||
62 | + </dependency> | ||
63 | + <dependency> | ||
64 | + <groupId>junit</groupId> | ||
65 | + <artifactId>junit</artifactId> | ||
66 | + <scope>test</scope> | ||
67 | + </dependency> | ||
68 | + <dependency> | ||
69 | + <groupId>org.mockito</groupId> | ||
70 | + <artifactId>mockito-all</artifactId> | ||
71 | + <scope>test</scope> | ||
72 | + </dependency> | ||
73 | + </dependencies> | ||
74 | + | ||
75 | +</project> |
1 | +/** | ||
2 | + * Copyright © 2016-2020 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; | ||
17 | + | ||
18 | +import lombok.Getter; | ||
19 | + | ||
20 | +public abstract class AbstractTbActor implements TbActor { | ||
21 | + | ||
22 | + @Getter | ||
23 | + protected TbActorCtx ctx; | ||
24 | + | ||
25 | + @Override | ||
26 | + public void init(TbActorCtx ctx) throws TbActorException { | ||
27 | + this.ctx = ctx; | ||
28 | + } | ||
29 | + | ||
30 | + @Override | ||
31 | + public TbActorRef getActorRef() { | ||
32 | + return ctx; | ||
33 | + } | ||
34 | +} |
1 | +/** | ||
2 | + * Copyright © 2016-2020 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; | ||
17 | + | ||
18 | +import lombok.Data; | ||
19 | +import lombok.Getter; | ||
20 | +import lombok.extern.slf4j.Slf4j; | ||
21 | +import org.thingsboard.common.util.ThingsBoardThreadFactory; | ||
22 | +import org.thingsboard.server.common.msg.TbActorMsg; | ||
23 | + | ||
24 | +import java.util.Collections; | ||
25 | +import java.util.List; | ||
26 | +import java.util.Set; | ||
27 | +import java.util.concurrent.ConcurrentHashMap; | ||
28 | +import java.util.concurrent.ConcurrentMap; | ||
29 | +import java.util.concurrent.ExecutorService; | ||
30 | +import java.util.concurrent.Executors; | ||
31 | +import java.util.concurrent.ScheduledExecutorService; | ||
32 | +import java.util.concurrent.TimeUnit; | ||
33 | +import java.util.concurrent.locks.Lock; | ||
34 | +import java.util.concurrent.locks.ReentrantLock; | ||
35 | +import java.util.function.Predicate; | ||
36 | +import java.util.stream.Collectors; | ||
37 | + | ||
38 | +@Slf4j | ||
39 | +@Data | ||
40 | +public class DefaultTbActorSystem implements TbActorSystem { | ||
41 | + | ||
42 | + private final ConcurrentMap<String, Dispatcher> dispatchers = new ConcurrentHashMap<>(); | ||
43 | + private final ConcurrentMap<TbActorId, TbActorMailbox> actors = new ConcurrentHashMap<>(); | ||
44 | + private final ConcurrentMap<TbActorId, ReentrantLock> actorCreationLocks = new ConcurrentHashMap<>(); | ||
45 | + private final ConcurrentMap<TbActorId, Set<TbActorId>> parentChildMap = new ConcurrentHashMap<>(); | ||
46 | + | ||
47 | + @Getter | ||
48 | + private final TbActorSystemSettings settings; | ||
49 | + @Getter | ||
50 | + private final ScheduledExecutorService scheduler; | ||
51 | + | ||
52 | + public DefaultTbActorSystem(TbActorSystemSettings settings) { | ||
53 | + this.settings = settings; | ||
54 | + this.scheduler = Executors.newScheduledThreadPool(settings.getSchedulerPoolSize(), ThingsBoardThreadFactory.forName("actor-system-scheduler")); | ||
55 | + } | ||
56 | + | ||
57 | + @Override | ||
58 | + public void createDispatcher(String dispatcherId, ExecutorService executor) { | ||
59 | + Dispatcher current = dispatchers.putIfAbsent(dispatcherId, new Dispatcher(dispatcherId, executor)); | ||
60 | + if (current != null) { | ||
61 | + throw new RuntimeException("Dispatcher with id [" + dispatcherId + "] is already registered!"); | ||
62 | + } | ||
63 | + } | ||
64 | + | ||
65 | + @Override | ||
66 | + public void destroyDispatcher(String dispatcherId) { | ||
67 | + Dispatcher dispatcher = dispatchers.remove(dispatcherId); | ||
68 | + if (dispatcher != null) { | ||
69 | + dispatcher.getExecutor().shutdownNow(); | ||
70 | + } else { | ||
71 | + throw new RuntimeException("Dispatcher with id [" + dispatcherId + "] is not registered!"); | ||
72 | + } | ||
73 | + } | ||
74 | + | ||
75 | + @Override | ||
76 | + public TbActorRef getActor(TbActorId actorId) { | ||
77 | + return actors.get(actorId); | ||
78 | + } | ||
79 | + | ||
80 | + @Override | ||
81 | + public TbActorRef createRootActor(String dispatcherId, TbActorCreator creator) { | ||
82 | + return createActor(dispatcherId, creator, null); | ||
83 | + } | ||
84 | + | ||
85 | + @Override | ||
86 | + public TbActorRef createChildActor(String dispatcherId, TbActorCreator creator, TbActorId parent) { | ||
87 | + return createActor(dispatcherId, creator, parent); | ||
88 | + } | ||
89 | + | ||
90 | + private TbActorRef createActor(String dispatcherId, TbActorCreator creator, TbActorId parent) { | ||
91 | + Dispatcher dispatcher = dispatchers.get(dispatcherId); | ||
92 | + if (dispatcher == null) { | ||
93 | + log.warn("Dispatcher with id [{}] is not registered!", dispatcherId); | ||
94 | + throw new RuntimeException("Dispatcher with id [" + dispatcherId + "] is not registered!"); | ||
95 | + } | ||
96 | + | ||
97 | + TbActorId actorId = creator.createActorId(); | ||
98 | + TbActorMailbox actorMailbox = actors.get(actorId); | ||
99 | + if (actorMailbox != null) { | ||
100 | + log.debug("Actor with id [{}] is already registered!", actorId); | ||
101 | + } else { | ||
102 | + Lock actorCreationLock = actorCreationLocks.computeIfAbsent(actorId, id -> new ReentrantLock()); | ||
103 | + actorCreationLock.lock(); | ||
104 | + try { | ||
105 | + actorMailbox = actors.get(actorId); | ||
106 | + if (actorMailbox == null) { | ||
107 | + log.debug("Creating actor with id [{}]!", actorId); | ||
108 | + TbActor actor = creator.createActor(); | ||
109 | + TbActorRef parentRef = null; | ||
110 | + if (parent != null) { | ||
111 | + parentRef = getActor(parent); | ||
112 | + if (parentRef == null) { | ||
113 | + throw new TbActorNotRegisteredException(parent, "Parent Actor with id [" + parent + "] is not registered!"); | ||
114 | + } | ||
115 | + } | ||
116 | + TbActorMailbox mailbox = new TbActorMailbox(this, settings, actorId, parentRef, actor, dispatcher); | ||
117 | + actors.put(actorId, mailbox); | ||
118 | + mailbox.initActor(); | ||
119 | + actorMailbox = mailbox; | ||
120 | + if (parent != null) { | ||
121 | + parentChildMap.computeIfAbsent(parent, id -> ConcurrentHashMap.newKeySet()).add(actorId); | ||
122 | + } | ||
123 | + } else { | ||
124 | + log.debug("Actor with id [{}] is already registered!", actorId); | ||
125 | + } | ||
126 | + } finally { | ||
127 | + actorCreationLock.unlock(); | ||
128 | + actorCreationLocks.remove(actorId); | ||
129 | + } | ||
130 | + } | ||
131 | + return actorMailbox; | ||
132 | + } | ||
133 | + | ||
134 | + @Override | ||
135 | + public void tellWithHighPriority(TbActorId target, TbActorMsg actorMsg) { | ||
136 | + tell(target, actorMsg, true); | ||
137 | + } | ||
138 | + | ||
139 | + @Override | ||
140 | + public void tell(TbActorId target, TbActorMsg actorMsg) { | ||
141 | + tell(target, actorMsg, false); | ||
142 | + } | ||
143 | + | ||
144 | + private void tell(TbActorId target, TbActorMsg actorMsg, boolean highPriority) { | ||
145 | + TbActorMailbox mailbox = actors.get(target); | ||
146 | + if (mailbox == null) { | ||
147 | + throw new TbActorNotRegisteredException(target, "Actor with id [" + target + "] is not registered!"); | ||
148 | + } | ||
149 | + if (highPriority) { | ||
150 | + mailbox.tellWithHighPriority(actorMsg); | ||
151 | + } else { | ||
152 | + mailbox.tell(actorMsg); | ||
153 | + } | ||
154 | + } | ||
155 | + | ||
156 | + | ||
157 | + @Override | ||
158 | + public void broadcastToChildren(TbActorId parent, TbActorMsg msg) { | ||
159 | + broadcastToChildren(parent, id -> true, msg); | ||
160 | + } | ||
161 | + | ||
162 | + @Override | ||
163 | + public void broadcastToChildren(TbActorId parent, Predicate<TbActorId> childFilter, TbActorMsg msg) { | ||
164 | + Set<TbActorId> children = parentChildMap.get(parent); | ||
165 | + if (children != null) { | ||
166 | + children.stream().filter(childFilter).forEach(id -> tell(id, msg)); | ||
167 | + } | ||
168 | + } | ||
169 | + | ||
170 | + @Override | ||
171 | + public List<TbActorId> filterChildren(TbActorId parent, Predicate<TbActorId> childFilter) { | ||
172 | + Set<TbActorId> children = parentChildMap.get(parent); | ||
173 | + if (children != null) { | ||
174 | + return children.stream().filter(childFilter).collect(Collectors.toList()); | ||
175 | + } else { | ||
176 | + return Collections.emptyList(); | ||
177 | + } | ||
178 | + } | ||
179 | + | ||
180 | + @Override | ||
181 | + public void stop(TbActorRef actorRef) { | ||
182 | + stop(actorRef.getActorId()); | ||
183 | + } | ||
184 | + | ||
185 | + @Override | ||
186 | + public void stop(TbActorId actorId) { | ||
187 | + Set<TbActorId> children = parentChildMap.remove(actorId); | ||
188 | + if (children != null) { | ||
189 | + for (TbActorId child : children) { | ||
190 | + stop(child); | ||
191 | + } | ||
192 | + } | ||
193 | + TbActorMailbox mailbox = actors.remove(actorId); | ||
194 | + if (mailbox != null) { | ||
195 | + mailbox.destroy(); | ||
196 | + } | ||
197 | + } | ||
198 | + | ||
199 | + @Override | ||
200 | + public void stop() { | ||
201 | + dispatchers.values().forEach(dispatcher -> { | ||
202 | + dispatcher.getExecutor().shutdown(); | ||
203 | + try { | ||
204 | + dispatcher.getExecutor().awaitTermination(3, TimeUnit.SECONDS); | ||
205 | + } catch (InterruptedException e) { | ||
206 | + log.warn("[{}] Failed to stop dispatcher", dispatcher.getDispatcherId(), e); | ||
207 | + } | ||
208 | + }); | ||
209 | + if (scheduler != null) { | ||
210 | + scheduler.shutdownNow(); | ||
211 | + } | ||
212 | + actors.clear(); | ||
213 | + } | ||
214 | + | ||
215 | +} |
1 | +/** | ||
2 | + * Copyright © 2016-2020 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; | ||
17 | + | ||
18 | +import lombok.Data; | ||
19 | + | ||
20 | +import java.util.concurrent.ExecutorService; | ||
21 | + | ||
22 | +@Data | ||
23 | +class Dispatcher { | ||
24 | + | ||
25 | + private final String dispatcherId; | ||
26 | + private final ExecutorService executor; | ||
27 | + | ||
28 | +} |
1 | +/** | ||
2 | + * Copyright © 2016-2020 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; | ||
17 | + | ||
18 | +import lombok.Getter; | ||
19 | +import lombok.ToString; | ||
20 | + | ||
21 | +@ToString | ||
22 | +public class InitFailureStrategy { | ||
23 | + | ||
24 | + @Getter | ||
25 | + private boolean stop; | ||
26 | + @Getter | ||
27 | + private long retryDelay; | ||
28 | + | ||
29 | + private InitFailureStrategy(boolean stop, long retryDelay) { | ||
30 | + this.stop = stop; | ||
31 | + this.retryDelay = retryDelay; | ||
32 | + } | ||
33 | + | ||
34 | + public static InitFailureStrategy retryImmediately() { | ||
35 | + return new InitFailureStrategy(false, 0); | ||
36 | + } | ||
37 | + | ||
38 | + public static InitFailureStrategy retryWithDelay(long ms) { | ||
39 | + return new InitFailureStrategy(false, ms); | ||
40 | + } | ||
41 | + | ||
42 | + public static InitFailureStrategy stop() { | ||
43 | + return new InitFailureStrategy(true, 0); | ||
44 | + } | ||
45 | +} |
1 | +/** | ||
2 | + * Copyright © 2016-2020 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; | ||
17 | + | ||
18 | +import lombok.Getter; | ||
19 | +import lombok.ToString; | ||
20 | + | ||
21 | +@ToString | ||
22 | +public class ProcessFailureStrategy { | ||
23 | + | ||
24 | + @Getter | ||
25 | + private boolean stop; | ||
26 | + | ||
27 | + private ProcessFailureStrategy(boolean stop) { | ||
28 | + this.stop = stop; | ||
29 | + } | ||
30 | + | ||
31 | + public static ProcessFailureStrategy stop() { | ||
32 | + return new ProcessFailureStrategy(true); | ||
33 | + } | ||
34 | + | ||
35 | + public static ProcessFailureStrategy resume() { | ||
36 | + return new ProcessFailureStrategy(false); | ||
37 | + } | ||
38 | +} |
1 | +/** | ||
2 | + * Copyright © 2016-2020 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; | ||
17 | + | ||
18 | +import org.thingsboard.server.common.msg.TbActorMsg; | ||
19 | + | ||
20 | +public interface TbActor { | ||
21 | + | ||
22 | + boolean process(TbActorMsg msg); | ||
23 | + | ||
24 | + TbActorRef getActorRef(); | ||
25 | + | ||
26 | + default void init(TbActorCtx ctx) throws TbActorException { | ||
27 | + } | ||
28 | + | ||
29 | + default void destroy() throws TbActorException { | ||
30 | + } | ||
31 | + | ||
32 | + default InitFailureStrategy onInitFailure(int attempt, Throwable t) { | ||
33 | + return InitFailureStrategy.retryWithDelay(5000 * attempt); | ||
34 | + } | ||
35 | + | ||
36 | + default ProcessFailureStrategy onProcessFailure(Throwable t) { | ||
37 | + if (t instanceof Error) { | ||
38 | + return ProcessFailureStrategy.stop(); | ||
39 | + } else { | ||
40 | + return ProcessFailureStrategy.resume(); | ||
41 | + } | ||
42 | + } | ||
43 | +} |
1 | +/** | ||
2 | + * Copyright © 2016-2020 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; | ||
17 | + | ||
18 | +public interface TbActorCreator { | ||
19 | + | ||
20 | + TbActorId createActorId(); | ||
21 | + | ||
22 | + TbActor createActor(); | ||
23 | + | ||
24 | +} |
1 | +/** | ||
2 | + * Copyright © 2016-2020 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; | ||
17 | + | ||
18 | +import org.thingsboard.server.common.msg.TbActorMsg; | ||
19 | + | ||
20 | +import java.util.List; | ||
21 | +import java.util.function.Predicate; | ||
22 | +import java.util.function.Supplier; | ||
23 | + | ||
24 | +public interface TbActorCtx extends TbActorRef { | ||
25 | + | ||
26 | + TbActorId getSelf(); | ||
27 | + | ||
28 | + TbActorRef getParentRef(); | ||
29 | + | ||
30 | + void tell(TbActorId target, TbActorMsg msg); | ||
31 | + | ||
32 | + void stop(TbActorId target); | ||
33 | + | ||
34 | + TbActorRef getOrCreateChildActor(TbActorId actorId, Supplier<String> dispatcher, Supplier<TbActorCreator> creator); | ||
35 | + | ||
36 | + void broadcastToChildren(TbActorMsg msg); | ||
37 | + | ||
38 | + void broadcastToChildren(TbActorMsg msg, Predicate<TbActorId> childFilter); | ||
39 | + | ||
40 | + List<TbActorId> filterChildren(Predicate<TbActorId> childFilter); | ||
41 | +} |
1 | +/** | ||
2 | + * Copyright © 2016-2020 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; | ||
17 | + | ||
18 | +public class TbActorException extends Exception { | ||
19 | + | ||
20 | + public TbActorException(String message, Throwable cause) { | ||
21 | + super(message, cause); | ||
22 | + } | ||
23 | +} |
1 | +/** | ||
2 | + * Copyright © 2016-2020 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; | ||
17 | + | ||
18 | +public interface TbActorId { | ||
19 | + | ||
20 | +} |
1 | +/** | ||
2 | + * Copyright © 2016-2020 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; | ||
17 | + | ||
18 | +import lombok.Data; | ||
19 | +import lombok.extern.slf4j.Slf4j; | ||
20 | +import org.thingsboard.server.common.msg.TbActorMsg; | ||
21 | + | ||
22 | +import java.util.List; | ||
23 | +import java.util.concurrent.ConcurrentLinkedQueue; | ||
24 | +import java.util.concurrent.TimeUnit; | ||
25 | +import java.util.concurrent.atomic.AtomicBoolean; | ||
26 | +import java.util.function.Predicate; | ||
27 | +import java.util.function.Supplier; | ||
28 | + | ||
29 | +@Slf4j | ||
30 | +@Data | ||
31 | +public final class TbActorMailbox implements TbActorCtx { | ||
32 | + private static final boolean HIGH_PRIORITY = true; | ||
33 | + private static final boolean NORMAL_PRIORITY = false; | ||
34 | + | ||
35 | + private static final boolean FREE = false; | ||
36 | + private static final boolean BUSY = true; | ||
37 | + | ||
38 | + private static final boolean NOT_READY = false; | ||
39 | + private static final boolean READY = true; | ||
40 | + | ||
41 | + private final TbActorSystem system; | ||
42 | + private final TbActorSystemSettings settings; | ||
43 | + private final TbActorId selfId; | ||
44 | + private final TbActorRef parentRef; | ||
45 | + private final TbActor actor; | ||
46 | + private final Dispatcher dispatcher; | ||
47 | + private final ConcurrentLinkedQueue<TbActorMsg> highPriorityMsgs = new ConcurrentLinkedQueue<>(); | ||
48 | + private final ConcurrentLinkedQueue<TbActorMsg> normalPriorityMsgs = new ConcurrentLinkedQueue<>(); | ||
49 | + private final AtomicBoolean busy = new AtomicBoolean(FREE); | ||
50 | + private final AtomicBoolean ready = new AtomicBoolean(NOT_READY); | ||
51 | + private final AtomicBoolean destroyInProgress = new AtomicBoolean(); | ||
52 | + | ||
53 | + public void initActor() { | ||
54 | + dispatcher.getExecutor().execute(() -> tryInit(1)); | ||
55 | + } | ||
56 | + | ||
57 | + private void tryInit(int attempt) { | ||
58 | + try { | ||
59 | + log.debug("[{}] Trying to init actor, attempt: {}", selfId, attempt); | ||
60 | + if (!destroyInProgress.get()) { | ||
61 | + actor.init(this); | ||
62 | + if (!destroyInProgress.get()) { | ||
63 | + ready.set(READY); | ||
64 | + tryProcessQueue(false); | ||
65 | + } | ||
66 | + } | ||
67 | + } catch (Throwable t) { | ||
68 | + log.debug("[{}] Failed to init actor, attempt: {}", selfId, attempt, t); | ||
69 | + int attemptIdx = attempt + 1; | ||
70 | + InitFailureStrategy strategy = actor.onInitFailure(attempt, t); | ||
71 | + if (strategy.isStop() || (settings.getMaxActorInitAttempts() > 0 && attemptIdx > settings.getMaxActorInitAttempts())) { | ||
72 | + log.info("[{}] Failed to init actor, attempt {}, going to stop attempts.", selfId, attempt, t); | ||
73 | + system.stop(selfId); | ||
74 | + } else if (strategy.getRetryDelay() > 0) { | ||
75 | + log.info("[{}] Failed to init actor, attempt {}, going to retry in attempts in {}ms", selfId, attempt, strategy.getRetryDelay()); | ||
76 | + log.debug("[{}] Error", selfId, t); | ||
77 | + system.getScheduler().schedule(() -> dispatcher.getExecutor().execute(() -> tryInit(attemptIdx)), strategy.getRetryDelay(), TimeUnit.MILLISECONDS); | ||
78 | + } else { | ||
79 | + log.info("[{}] Failed to init actor, attempt {}, going to retry immediately", selfId, attempt); | ||
80 | + log.debug("[{}] Error", selfId, t); | ||
81 | + dispatcher.getExecutor().execute(() -> tryInit(attemptIdx)); | ||
82 | + } | ||
83 | + } | ||
84 | + } | ||
85 | + | ||
86 | + private void enqueue(TbActorMsg msg, boolean highPriority) { | ||
87 | + if (highPriority) { | ||
88 | + highPriorityMsgs.add(msg); | ||
89 | + } else { | ||
90 | + normalPriorityMsgs.add(msg); | ||
91 | + } | ||
92 | + tryProcessQueue(true); | ||
93 | + } | ||
94 | + | ||
95 | + private void tryProcessQueue(boolean newMsg) { | ||
96 | + if (ready.get() == READY) { | ||
97 | + if (newMsg || !highPriorityMsgs.isEmpty() || !normalPriorityMsgs.isEmpty()) { | ||
98 | + if (busy.compareAndSet(FREE, BUSY)) { | ||
99 | + dispatcher.getExecutor().execute(this::processMailbox); | ||
100 | + } else { | ||
101 | + log.trace("[{}] MessageBox is busy, new msg: {}", selfId, newMsg); | ||
102 | + } | ||
103 | + } else { | ||
104 | + log.trace("[{}] MessageBox is empty, new msg: {}", selfId, newMsg); | ||
105 | + } | ||
106 | + } else { | ||
107 | + log.trace("[{}] MessageBox is not ready, new msg: {}", selfId, newMsg); | ||
108 | + } | ||
109 | + } | ||
110 | + | ||
111 | + private void processMailbox() { | ||
112 | + boolean noMoreElements = false; | ||
113 | + for (int i = 0; i < settings.getActorThroughput(); i++) { | ||
114 | + TbActorMsg msg = highPriorityMsgs.poll(); | ||
115 | + if (msg == null) { | ||
116 | + msg = normalPriorityMsgs.poll(); | ||
117 | + } | ||
118 | + if (msg != null) { | ||
119 | + try { | ||
120 | + log.debug("[{}] Going to process message: {}", selfId, msg); | ||
121 | + actor.process(msg); | ||
122 | + } catch (Throwable t) { | ||
123 | + log.debug("[{}] Failed to process message: {}", selfId, msg, t); | ||
124 | + ProcessFailureStrategy strategy = actor.onProcessFailure(t); | ||
125 | + if (strategy.isStop()) { | ||
126 | + system.stop(selfId); | ||
127 | + } | ||
128 | + } | ||
129 | + } else { | ||
130 | + noMoreElements = true; | ||
131 | + break; | ||
132 | + } | ||
133 | + } | ||
134 | + if (noMoreElements) { | ||
135 | + busy.set(FREE); | ||
136 | + dispatcher.getExecutor().execute(() -> tryProcessQueue(false)); | ||
137 | + } else { | ||
138 | + dispatcher.getExecutor().execute(this::processMailbox); | ||
139 | + } | ||
140 | + } | ||
141 | + | ||
142 | + @Override | ||
143 | + public TbActorId getSelf() { | ||
144 | + return selfId; | ||
145 | + } | ||
146 | + | ||
147 | + @Override | ||
148 | + public void tell(TbActorId target, TbActorMsg actorMsg) { | ||
149 | + system.tell(target, actorMsg); | ||
150 | + } | ||
151 | + | ||
152 | + @Override | ||
153 | + public void broadcastToChildren(TbActorMsg msg) { | ||
154 | + system.broadcastToChildren(selfId, msg); | ||
155 | + } | ||
156 | + | ||
157 | + @Override | ||
158 | + public void broadcastToChildren(TbActorMsg msg, Predicate<TbActorId> childFilter) { | ||
159 | + system.broadcastToChildren(selfId, childFilter, msg); | ||
160 | + } | ||
161 | + | ||
162 | + @Override | ||
163 | + public List<TbActorId> filterChildren(Predicate<TbActorId> childFilter) { | ||
164 | + return system.filterChildren(selfId, childFilter); | ||
165 | + } | ||
166 | + | ||
167 | + @Override | ||
168 | + public void stop(TbActorId target) { | ||
169 | + system.stop(target); | ||
170 | + } | ||
171 | + | ||
172 | + @Override | ||
173 | + public TbActorRef getOrCreateChildActor(TbActorId actorId, Supplier<String> dispatcher, Supplier<TbActorCreator> creator) { | ||
174 | + TbActorRef actorRef = system.getActor(actorId); | ||
175 | + if (actorRef == null) { | ||
176 | + return system.createChildActor(dispatcher.get(), creator.get(), selfId); | ||
177 | + } else { | ||
178 | + return actorRef; | ||
179 | + } | ||
180 | + } | ||
181 | + | ||
182 | + public void destroy() { | ||
183 | + destroyInProgress.set(true); | ||
184 | + dispatcher.getExecutor().execute(() -> { | ||
185 | + try { | ||
186 | + ready.set(NOT_READY); | ||
187 | + actor.destroy(); | ||
188 | + } catch (Throwable t) { | ||
189 | + log.warn("[{}] Failed to destroy actor: {}", selfId, t); | ||
190 | + } | ||
191 | + }); | ||
192 | + } | ||
193 | + | ||
194 | + @Override | ||
195 | + public TbActorId getActorId() { | ||
196 | + return selfId; | ||
197 | + } | ||
198 | + | ||
199 | + @Override | ||
200 | + public void tell(TbActorMsg actorMsg) { | ||
201 | + enqueue(actorMsg, NORMAL_PRIORITY); | ||
202 | + } | ||
203 | + | ||
204 | + @Override | ||
205 | + public void tellWithHighPriority(TbActorMsg actorMsg) { | ||
206 | + enqueue(actorMsg, HIGH_PRIORITY); | ||
207 | + } | ||
208 | + | ||
209 | +} |
common/actor/src/main/java/org/thingsboard/server/actors/TbActorNotRegisteredException.java
0 → 100644
1 | +/** | ||
2 | + * Copyright © 2016-2020 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; | ||
17 | + | ||
18 | +import lombok.Getter; | ||
19 | + | ||
20 | +public class TbActorNotRegisteredException extends RuntimeException { | ||
21 | + | ||
22 | + @Getter | ||
23 | + private TbActorId target; | ||
24 | + | ||
25 | + public TbActorNotRegisteredException(TbActorId target, String message) { | ||
26 | + super(message); | ||
27 | + this.target = target; | ||
28 | + } | ||
29 | +} |
1 | +/** | ||
2 | + * Copyright © 2016-2020 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; | ||
17 | + | ||
18 | +import org.thingsboard.server.common.msg.TbActorMsg; | ||
19 | + | ||
20 | +public interface TbActorRef { | ||
21 | + | ||
22 | + TbActorId getActorId(); | ||
23 | + | ||
24 | + void tell(TbActorMsg actorMsg); | ||
25 | + | ||
26 | + void tellWithHighPriority(TbActorMsg actorMsg); | ||
27 | + | ||
28 | +} |
1 | +/** | ||
2 | + * Copyright © 2016-2020 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; | ||
17 | + | ||
18 | +import org.thingsboard.server.common.msg.TbActorMsg; | ||
19 | + | ||
20 | +import java.util.List; | ||
21 | +import java.util.concurrent.ExecutorService; | ||
22 | +import java.util.concurrent.ScheduledExecutorService; | ||
23 | +import java.util.function.Predicate; | ||
24 | + | ||
25 | +public interface TbActorSystem { | ||
26 | + | ||
27 | + ScheduledExecutorService getScheduler(); | ||
28 | + | ||
29 | + void createDispatcher(String dispatcherId, ExecutorService executor); | ||
30 | + | ||
31 | + void destroyDispatcher(String dispatcherId); | ||
32 | + | ||
33 | + TbActorRef getActor(TbActorId actorId); | ||
34 | + | ||
35 | + TbActorRef createRootActor(String dispatcherId, TbActorCreator creator); | ||
36 | + | ||
37 | + TbActorRef createChildActor(String dispatcherId, TbActorCreator creator, TbActorId parent); | ||
38 | + | ||
39 | + void tell(TbActorId target, TbActorMsg actorMsg); | ||
40 | + | ||
41 | + void tellWithHighPriority(TbActorId target, TbActorMsg actorMsg); | ||
42 | + | ||
43 | + void stop(TbActorRef actorRef); | ||
44 | + | ||
45 | + void stop(TbActorId actorId); | ||
46 | + | ||
47 | + void stop(); | ||
48 | + | ||
49 | + void broadcastToChildren(TbActorId parent, TbActorMsg msg); | ||
50 | + | ||
51 | + void broadcastToChildren(TbActorId parent, Predicate<TbActorId> childFilter, TbActorMsg msg); | ||
52 | + | ||
53 | + List<TbActorId> filterChildren(TbActorId parent, Predicate<TbActorId> childFilter); | ||
54 | +} |
1 | +/** | ||
2 | + * Copyright © 2016-2020 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; | ||
17 | + | ||
18 | +import lombok.Data; | ||
19 | + | ||
20 | +@Data | ||
21 | +public class TbActorSystemSettings { | ||
22 | + | ||
23 | + private final int actorThroughput; | ||
24 | + private final int schedulerPoolSize; | ||
25 | + private final int maxActorInitAttempts; | ||
26 | + | ||
27 | +} |
1 | +/** | ||
2 | + * Copyright © 2016-2020 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; | ||
17 | + | ||
18 | +import lombok.Getter; | ||
19 | +import org.thingsboard.server.common.data.id.EntityId; | ||
20 | + | ||
21 | +import java.util.Objects; | ||
22 | + | ||
23 | +public class TbEntityActorId implements TbActorId { | ||
24 | + | ||
25 | + @Getter | ||
26 | + private final EntityId entityId; | ||
27 | + | ||
28 | + public TbEntityActorId(EntityId entityId) { | ||
29 | + this.entityId = entityId; | ||
30 | + } | ||
31 | + | ||
32 | + @Override | ||
33 | + public String toString() { | ||
34 | + return entityId.getEntityType() + "|" + entityId.getId(); | ||
35 | + } | ||
36 | + | ||
37 | + @Override | ||
38 | + public boolean equals(Object o) { | ||
39 | + if (this == o) return true; | ||
40 | + if (o == null || getClass() != o.getClass()) return false; | ||
41 | + TbEntityActorId that = (TbEntityActorId) o; | ||
42 | + return entityId.equals(that.entityId); | ||
43 | + } | ||
44 | + | ||
45 | + @Override | ||
46 | + public int hashCode() { | ||
47 | + return Objects.hash(entityId); | ||
48 | + } | ||
49 | +} |
1 | +/** | ||
2 | + * Copyright © 2016-2020 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; | ||
17 | + | ||
18 | +import java.util.Objects; | ||
19 | + | ||
20 | +public class TbStringActorId implements TbActorId { | ||
21 | + | ||
22 | + private final String id; | ||
23 | + | ||
24 | + public TbStringActorId(String id) { | ||
25 | + this.id = id; | ||
26 | + } | ||
27 | + | ||
28 | + @Override | ||
29 | + public String toString() { | ||
30 | + return id; | ||
31 | + } | ||
32 | + | ||
33 | + @Override | ||
34 | + public boolean equals(Object o) { | ||
35 | + if (this == o) return true; | ||
36 | + if (o == null || getClass() != o.getClass()) return false; | ||
37 | + TbStringActorId that = (TbStringActorId) o; | ||
38 | + return id.equals(that.id); | ||
39 | + } | ||
40 | + | ||
41 | + @Override | ||
42 | + public int hashCode() { | ||
43 | + return Objects.hash(id); | ||
44 | + } | ||
45 | +} |
1 | +/** | ||
2 | + * Copyright © 2016-2020 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; | ||
17 | + | ||
18 | +import lombok.extern.slf4j.Slf4j; | ||
19 | +import org.junit.After; | ||
20 | +import org.junit.Assert; | ||
21 | +import org.junit.Before; | ||
22 | +import org.junit.Test; | ||
23 | +import org.junit.runner.RunWith; | ||
24 | +import org.mockito.runners.MockitoJUnitRunner; | ||
25 | +import org.thingsboard.server.common.data.id.DeviceId; | ||
26 | + | ||
27 | +import java.util.ArrayList; | ||
28 | +import java.util.List; | ||
29 | +import java.util.Random; | ||
30 | +import java.util.UUID; | ||
31 | +import java.util.concurrent.CountDownLatch; | ||
32 | +import java.util.concurrent.ExecutorService; | ||
33 | +import java.util.concurrent.Executors; | ||
34 | +import java.util.concurrent.TimeUnit; | ||
35 | +import java.util.concurrent.atomic.AtomicInteger; | ||
36 | +import java.util.concurrent.atomic.AtomicLong; | ||
37 | + | ||
38 | +@Slf4j | ||
39 | +@RunWith(MockitoJUnitRunner.class) | ||
40 | +public class ActorSystemTest { | ||
41 | + | ||
42 | + public static final String ROOT_DISPATCHER = "root-dispatcher"; | ||
43 | + private static final int _100K = 100 * 1024; | ||
44 | + | ||
45 | + private volatile TbActorSystem actorSystem; | ||
46 | + private volatile ExecutorService submitPool; | ||
47 | + private int parallelism; | ||
48 | + | ||
49 | + @Before | ||
50 | + public void initActorSystem() { | ||
51 | + int cores = Runtime.getRuntime().availableProcessors(); | ||
52 | + parallelism = Math.max(2, cores / 2); | ||
53 | + TbActorSystemSettings settings = new TbActorSystemSettings(5, parallelism, 42); | ||
54 | + actorSystem = new DefaultTbActorSystem(settings); | ||
55 | + submitPool = Executors.newWorkStealingPool(parallelism); | ||
56 | + } | ||
57 | + | ||
58 | + @After | ||
59 | + public void shutdownActorSystem() { | ||
60 | + actorSystem.stop(); | ||
61 | + submitPool.shutdownNow(); | ||
62 | + } | ||
63 | + | ||
64 | + @Test | ||
65 | + public void test1actorsAnd100KMessages() throws InterruptedException { | ||
66 | + actorSystem.createDispatcher(ROOT_DISPATCHER, Executors.newWorkStealingPool(parallelism)); | ||
67 | + testActorsAndMessages(1, _100K, 1); | ||
68 | + } | ||
69 | + | ||
70 | + @Test | ||
71 | + public void test10actorsAnd100KMessages() throws InterruptedException { | ||
72 | + actorSystem.createDispatcher(ROOT_DISPATCHER, Executors.newWorkStealingPool(parallelism)); | ||
73 | + testActorsAndMessages(10, _100K, 1); | ||
74 | + } | ||
75 | + | ||
76 | + @Test | ||
77 | + public void test100KActorsAnd1Messages5timesSingleThread() throws InterruptedException { | ||
78 | + actorSystem.createDispatcher(ROOT_DISPATCHER, Executors.newSingleThreadExecutor()); | ||
79 | + testActorsAndMessages(_100K, 1, 5); | ||
80 | + } | ||
81 | + | ||
82 | + @Test | ||
83 | + public void test100KActorsAnd1Messages5times() throws InterruptedException { | ||
84 | + actorSystem.createDispatcher(ROOT_DISPATCHER, Executors.newWorkStealingPool(parallelism)); | ||
85 | + testActorsAndMessages(_100K, 1, 5); | ||
86 | + } | ||
87 | + | ||
88 | + @Test | ||
89 | + public void test100KActorsAnd10Messages() throws InterruptedException { | ||
90 | + actorSystem.createDispatcher(ROOT_DISPATCHER, Executors.newWorkStealingPool(parallelism)); | ||
91 | + testActorsAndMessages(_100K, 10, 1); | ||
92 | + } | ||
93 | + | ||
94 | + @Test | ||
95 | + public void test1KActorsAnd1KMessages() throws InterruptedException { | ||
96 | + actorSystem.createDispatcher(ROOT_DISPATCHER, Executors.newWorkStealingPool(parallelism)); | ||
97 | + testActorsAndMessages(1000, 1000, 10); | ||
98 | + } | ||
99 | + | ||
100 | + @Test | ||
101 | + public void testNoMessagesAfterDestroy() throws InterruptedException { | ||
102 | + actorSystem.createDispatcher(ROOT_DISPATCHER, Executors.newWorkStealingPool(parallelism)); | ||
103 | + ActorTestCtx testCtx1 = getActorTestCtx(1); | ||
104 | + ActorTestCtx testCtx2 = getActorTestCtx(1); | ||
105 | + | ||
106 | + TbActorRef actorId1 = actorSystem.createRootActor(ROOT_DISPATCHER, new SlowInitActor.SlowInitActorCreator( | ||
107 | + new TbEntityActorId(new DeviceId(UUID.randomUUID())), testCtx1)); | ||
108 | + TbActorRef actorId2 = actorSystem.createRootActor(ROOT_DISPATCHER, new SlowInitActor.SlowInitActorCreator( | ||
109 | + new TbEntityActorId(new DeviceId(UUID.randomUUID())), testCtx2)); | ||
110 | + | ||
111 | + actorId1.tell(new IntTbActorMsg(42)); | ||
112 | + actorId2.tell(new IntTbActorMsg(42)); | ||
113 | + actorSystem.stop(actorId1); | ||
114 | + | ||
115 | + Assert.assertTrue(testCtx2.getLatch().await(1, TimeUnit.SECONDS)); | ||
116 | + Assert.assertFalse(testCtx1.getLatch().await(1, TimeUnit.SECONDS)); | ||
117 | + } | ||
118 | + | ||
119 | + @Test | ||
120 | + public void testOneActorCreated() throws InterruptedException { | ||
121 | + actorSystem.createDispatcher(ROOT_DISPATCHER, Executors.newWorkStealingPool(parallelism)); | ||
122 | + ActorTestCtx testCtx1 = getActorTestCtx(1); | ||
123 | + ActorTestCtx testCtx2 = getActorTestCtx(1); | ||
124 | + TbActorId actorId = new TbEntityActorId(new DeviceId(UUID.randomUUID())); | ||
125 | + submitPool.submit(() -> actorSystem.createRootActor(ROOT_DISPATCHER, new SlowCreateActor.SlowCreateActorCreator(actorId, testCtx1))); | ||
126 | + submitPool.submit(() -> actorSystem.createRootActor(ROOT_DISPATCHER, new SlowCreateActor.SlowCreateActorCreator(actorId, testCtx2))); | ||
127 | + | ||
128 | + Thread.sleep(1000); | ||
129 | + actorSystem.tell(actorId, new IntTbActorMsg(42)); | ||
130 | + | ||
131 | + Assert.assertTrue(testCtx1.getLatch().await(1, TimeUnit.SECONDS)); | ||
132 | + Assert.assertFalse(testCtx2.getLatch().await(1, TimeUnit.SECONDS)); | ||
133 | + } | ||
134 | + | ||
135 | + @Test | ||
136 | + public void testActorCreatorCalledOnce() throws InterruptedException { | ||
137 | + actorSystem.createDispatcher(ROOT_DISPATCHER, Executors.newWorkStealingPool(parallelism)); | ||
138 | + ActorTestCtx testCtx = getActorTestCtx(1); | ||
139 | + TbActorId actorId = new TbEntityActorId(new DeviceId(UUID.randomUUID())); | ||
140 | + for (int i = 0; i < 1000; i++) { | ||
141 | + submitPool.submit(() -> actorSystem.createRootActor(ROOT_DISPATCHER, new SlowCreateActor.SlowCreateActorCreator(actorId, testCtx))); | ||
142 | + } | ||
143 | + Thread.sleep(1000); | ||
144 | + actorSystem.tell(actorId, new IntTbActorMsg(42)); | ||
145 | + | ||
146 | + Assert.assertTrue(testCtx.getLatch().await(1, TimeUnit.SECONDS)); | ||
147 | + //One for creation and one for message | ||
148 | + Assert.assertEquals(2, testCtx.getInvocationCount().get()); | ||
149 | + } | ||
150 | + | ||
151 | + @Test | ||
152 | + public void testFailedInit() throws InterruptedException { | ||
153 | + actorSystem.createDispatcher(ROOT_DISPATCHER, Executors.newWorkStealingPool(parallelism)); | ||
154 | + ActorTestCtx testCtx1 = getActorTestCtx(1); | ||
155 | + ActorTestCtx testCtx2 = getActorTestCtx(1); | ||
156 | + | ||
157 | + TbActorRef actorId1 = actorSystem.createRootActor(ROOT_DISPATCHER, new FailedToInitActor.FailedToInitActorCreator( | ||
158 | + new TbEntityActorId(new DeviceId(UUID.randomUUID())), testCtx1, 1, 3000)); | ||
159 | + TbActorRef actorId2 = actorSystem.createRootActor(ROOT_DISPATCHER, new FailedToInitActor.FailedToInitActorCreator( | ||
160 | + new TbEntityActorId(new DeviceId(UUID.randomUUID())), testCtx2, 2, 1)); | ||
161 | + | ||
162 | + actorId1.tell(new IntTbActorMsg(42)); | ||
163 | + actorId2.tell(new IntTbActorMsg(42)); | ||
164 | + | ||
165 | + Assert.assertFalse(testCtx1.getLatch().await(2, TimeUnit.SECONDS)); | ||
166 | + Assert.assertTrue(testCtx2.getLatch().await(1, TimeUnit.SECONDS)); | ||
167 | + Assert.assertTrue(testCtx1.getLatch().await(3, TimeUnit.SECONDS)); | ||
168 | + } | ||
169 | + | ||
170 | + | ||
171 | + public void testActorsAndMessages(int actorsCount, int msgNumber, int times) throws InterruptedException { | ||
172 | + Random random = new Random(); | ||
173 | + int[] randomIntegers = new int[msgNumber]; | ||
174 | + long sumTmp = 0; | ||
175 | + for (int i = 0; i < msgNumber; i++) { | ||
176 | + int tmp = random.nextInt(); | ||
177 | + randomIntegers[i] = tmp; | ||
178 | + sumTmp += tmp; | ||
179 | + } | ||
180 | + long expected = sumTmp; | ||
181 | + | ||
182 | + List<ActorTestCtx> testCtxes = new ArrayList<>(); | ||
183 | + | ||
184 | + List<TbActorRef> actorRefs = new ArrayList<>(); | ||
185 | + for (int actorIdx = 0; actorIdx < actorsCount; actorIdx++) { | ||
186 | + ActorTestCtx testCtx = getActorTestCtx(msgNumber); | ||
187 | + actorRefs.add(actorSystem.createRootActor(ROOT_DISPATCHER, new TestRootActor.TestRootActorCreator( | ||
188 | + new TbEntityActorId(new DeviceId(UUID.randomUUID())), testCtx))); | ||
189 | + testCtxes.add(testCtx); | ||
190 | + } | ||
191 | + | ||
192 | + for (int t = 0; t < times; t++) { | ||
193 | + long start = System.nanoTime(); | ||
194 | + for (int i = 0; i < msgNumber; i++) { | ||
195 | + int tmp = randomIntegers[i]; | ||
196 | + submitPool.execute(() -> actorRefs.forEach(actorId -> actorId.tell(new IntTbActorMsg(tmp)))); | ||
197 | + } | ||
198 | + log.info("Submitted all messages"); | ||
199 | + testCtxes.forEach(ctx -> { | ||
200 | + try { | ||
201 | + boolean success = ctx.getLatch().await(1, TimeUnit.MINUTES); | ||
202 | + if (!success) { | ||
203 | + log.warn("Failed: {}, {}", ctx.getActual().get(), ctx.getInvocationCount().get()); | ||
204 | + } | ||
205 | + Assert.assertTrue(success); | ||
206 | + Assert.assertEquals(expected, ctx.getActual().get()); | ||
207 | + Assert.assertEquals(msgNumber, ctx.getInvocationCount().get()); | ||
208 | + ctx.clear(); | ||
209 | + } catch (InterruptedException e) { | ||
210 | + e.printStackTrace(); | ||
211 | + } | ||
212 | + }); | ||
213 | + long duration = System.nanoTime() - start; | ||
214 | + log.info("Time spend: {}ns ({} ms)", duration, TimeUnit.NANOSECONDS.toMillis(duration)); | ||
215 | + } | ||
216 | + } | ||
217 | + | ||
218 | + private ActorTestCtx getActorTestCtx(int i) { | ||
219 | + CountDownLatch countDownLatch = new CountDownLatch(1); | ||
220 | + AtomicLong actual = new AtomicLong(); | ||
221 | + AtomicInteger invocations = new AtomicInteger(); | ||
222 | + return new ActorTestCtx(countDownLatch, invocations, i, actual); | ||
223 | + } | ||
224 | +} |
1 | +/** | ||
2 | + * Copyright © 2016-2020 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; | ||
17 | + | ||
18 | +import lombok.AllArgsConstructor; | ||
19 | +import lombok.Data; | ||
20 | + | ||
21 | +import java.util.concurrent.CountDownLatch; | ||
22 | +import java.util.concurrent.atomic.AtomicInteger; | ||
23 | +import java.util.concurrent.atomic.AtomicLong; | ||
24 | + | ||
25 | +@Data | ||
26 | +@AllArgsConstructor | ||
27 | +public class ActorTestCtx { | ||
28 | + | ||
29 | + private volatile CountDownLatch latch; | ||
30 | + private final AtomicInteger invocationCount; | ||
31 | + private final int expectedInvocationCount; | ||
32 | + private final AtomicLong actual; | ||
33 | + | ||
34 | + public void clear() { | ||
35 | + latch = new CountDownLatch(1); | ||
36 | + invocationCount.set(0); | ||
37 | + actual.set(0L); | ||
38 | + } | ||
39 | +} |
1 | +/** | ||
2 | + * Copyright © 2016-2020 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; | ||
17 | + | ||
18 | +import lombok.extern.slf4j.Slf4j; | ||
19 | + | ||
20 | +@Slf4j | ||
21 | +public class FailedToInitActor extends TestRootActor { | ||
22 | + | ||
23 | + int retryAttempts; | ||
24 | + int retryDelay; | ||
25 | + int attempts = 0; | ||
26 | + | ||
27 | + public FailedToInitActor(TbActorId actorId, ActorTestCtx testCtx, int retryAttempts, int retryDelay) { | ||
28 | + super(actorId, testCtx); | ||
29 | + this.retryAttempts = retryAttempts; | ||
30 | + this.retryDelay = retryDelay; | ||
31 | + } | ||
32 | + | ||
33 | + @Override | ||
34 | + public void init(TbActorCtx ctx) throws TbActorException { | ||
35 | + if (attempts < retryAttempts) { | ||
36 | + attempts++; | ||
37 | + throw new TbActorException("Test attempt", new RuntimeException()); | ||
38 | + } else { | ||
39 | + super.init(ctx); | ||
40 | + } | ||
41 | + } | ||
42 | + | ||
43 | + @Override | ||
44 | + public InitFailureStrategy onInitFailure(int attempt, Throwable t) { | ||
45 | + return InitFailureStrategy.retryWithDelay(retryDelay); | ||
46 | + } | ||
47 | + | ||
48 | + public static class FailedToInitActorCreator implements TbActorCreator { | ||
49 | + | ||
50 | + private final TbActorId actorId; | ||
51 | + private final ActorTestCtx testCtx; | ||
52 | + private final int retryAttempts; | ||
53 | + private final int retryDelay; | ||
54 | + | ||
55 | + public FailedToInitActorCreator(TbActorId actorId, ActorTestCtx testCtx, int retryAttempts, int retryDelay) { | ||
56 | + this.actorId = actorId; | ||
57 | + this.testCtx = testCtx; | ||
58 | + this.retryAttempts = retryAttempts; | ||
59 | + this.retryDelay = retryDelay; | ||
60 | + } | ||
61 | + | ||
62 | + @Override | ||
63 | + public TbActorId createActorId() { | ||
64 | + return actorId; | ||
65 | + } | ||
66 | + | ||
67 | + @Override | ||
68 | + public TbActor createActor() { | ||
69 | + return new FailedToInitActor(actorId, testCtx, retryAttempts, retryDelay); | ||
70 | + } | ||
71 | + } | ||
72 | +} |
1 | +/** | ||
2 | + * Copyright © 2016-2020 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; | ||
17 | + | ||
18 | +import lombok.Getter; | ||
19 | +import org.thingsboard.server.common.msg.MsgType; | ||
20 | +import org.thingsboard.server.common.msg.TbActorMsg; | ||
21 | + | ||
22 | +public class IntTbActorMsg implements TbActorMsg { | ||
23 | + | ||
24 | + @Getter | ||
25 | + private final int value; | ||
26 | + | ||
27 | + public IntTbActorMsg(int value) { | ||
28 | + this.value = value; | ||
29 | + } | ||
30 | + | ||
31 | + @Override | ||
32 | + public MsgType getMsgType() { | ||
33 | + return MsgType.QUEUE_TO_RULE_ENGINE_MSG; | ||
34 | + } | ||
35 | +} |
1 | +/** | ||
2 | + * Copyright © 2016-2020 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; | ||
17 | + | ||
18 | +import lombok.extern.slf4j.Slf4j; | ||
19 | + | ||
20 | +@Slf4j | ||
21 | +public class SlowCreateActor extends TestRootActor { | ||
22 | + | ||
23 | + public SlowCreateActor(TbActorId actorId, ActorTestCtx testCtx) { | ||
24 | + super(actorId, testCtx); | ||
25 | + try { | ||
26 | + Thread.sleep(500); | ||
27 | + } catch (InterruptedException e) { | ||
28 | + e.printStackTrace(); | ||
29 | + } | ||
30 | + testCtx.getInvocationCount().incrementAndGet(); | ||
31 | + } | ||
32 | + | ||
33 | + public static class SlowCreateActorCreator implements TbActorCreator { | ||
34 | + | ||
35 | + private final TbActorId actorId; | ||
36 | + private final ActorTestCtx testCtx; | ||
37 | + | ||
38 | + public SlowCreateActorCreator(TbActorId actorId, ActorTestCtx testCtx) { | ||
39 | + this.actorId = actorId; | ||
40 | + this.testCtx = testCtx; | ||
41 | + } | ||
42 | + | ||
43 | + @Override | ||
44 | + public TbActorId createActorId() { | ||
45 | + return actorId; | ||
46 | + } | ||
47 | + | ||
48 | + @Override | ||
49 | + public TbActor createActor() { | ||
50 | + return new SlowCreateActor(actorId, testCtx); | ||
51 | + } | ||
52 | + } | ||
53 | +} |
1 | +/** | ||
2 | + * Copyright © 2016-2020 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; | ||
17 | + | ||
18 | +import lombok.extern.slf4j.Slf4j; | ||
19 | + | ||
20 | +@Slf4j | ||
21 | +public class SlowInitActor extends TestRootActor { | ||
22 | + | ||
23 | + public SlowInitActor(TbActorId actorId, ActorTestCtx testCtx) { | ||
24 | + super(actorId, testCtx); | ||
25 | + } | ||
26 | + | ||
27 | + @Override | ||
28 | + public void init(TbActorCtx ctx) throws TbActorException { | ||
29 | + try { | ||
30 | + Thread.sleep(500); | ||
31 | + } catch (InterruptedException e) { | ||
32 | + e.printStackTrace(); | ||
33 | + } | ||
34 | + super.init(ctx); | ||
35 | + } | ||
36 | + | ||
37 | + public static class SlowInitActorCreator implements TbActorCreator { | ||
38 | + | ||
39 | + private final TbActorId actorId; | ||
40 | + private final ActorTestCtx testCtx; | ||
41 | + | ||
42 | + public SlowInitActorCreator(TbActorId actorId, ActorTestCtx testCtx) { | ||
43 | + this.actorId = actorId; | ||
44 | + this.testCtx = testCtx; | ||
45 | + } | ||
46 | + | ||
47 | + @Override | ||
48 | + public TbActorId createActorId() { | ||
49 | + return actorId; | ||
50 | + } | ||
51 | + | ||
52 | + @Override | ||
53 | + public TbActor createActor() { | ||
54 | + return new SlowInitActor(actorId, testCtx); | ||
55 | + } | ||
56 | + } | ||
57 | +} |
1 | +/** | ||
2 | + * Copyright © 2016-2020 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; | ||
17 | + | ||
18 | +import lombok.Getter; | ||
19 | +import lombok.extern.slf4j.Slf4j; | ||
20 | +import org.thingsboard.server.common.msg.TbActorMsg; | ||
21 | + | ||
22 | +@Slf4j | ||
23 | +public class TestRootActor extends AbstractTbActor { | ||
24 | + | ||
25 | + @Getter | ||
26 | + private final TbActorId actorId; | ||
27 | + @Getter | ||
28 | + private final ActorTestCtx testCtx; | ||
29 | + | ||
30 | + private boolean initialized; | ||
31 | + private long sum; | ||
32 | + private int count; | ||
33 | + | ||
34 | + public TestRootActor(TbActorId actorId, ActorTestCtx testCtx) { | ||
35 | + this.actorId = actorId; | ||
36 | + this.testCtx = testCtx; | ||
37 | + } | ||
38 | + | ||
39 | + @Override | ||
40 | + public void init(TbActorCtx ctx) throws TbActorException { | ||
41 | + super.init(ctx); | ||
42 | + initialized = true; | ||
43 | + } | ||
44 | + | ||
45 | + @Override | ||
46 | + public boolean process(TbActorMsg msg) { | ||
47 | + if (initialized) { | ||
48 | + int value = ((IntTbActorMsg) msg).getValue(); | ||
49 | + sum += value; | ||
50 | + count += 1; | ||
51 | + if (count == testCtx.getExpectedInvocationCount()) { | ||
52 | + testCtx.getActual().set(sum); | ||
53 | + testCtx.getInvocationCount().addAndGet(count); | ||
54 | + sum = 0; | ||
55 | + count = 0; | ||
56 | + testCtx.getLatch().countDown(); | ||
57 | + } | ||
58 | + } | ||
59 | + return true; | ||
60 | + } | ||
61 | + | ||
62 | + @Override | ||
63 | + public void destroy() { | ||
64 | + | ||
65 | + } | ||
66 | + | ||
67 | + public static class TestRootActorCreator implements TbActorCreator { | ||
68 | + | ||
69 | + private final TbActorId actorId; | ||
70 | + private final ActorTestCtx testCtx; | ||
71 | + | ||
72 | + public TestRootActorCreator(TbActorId actorId, ActorTestCtx testCtx) { | ||
73 | + this.actorId = actorId; | ||
74 | + this.testCtx = testCtx; | ||
75 | + } | ||
76 | + | ||
77 | + @Override | ||
78 | + public TbActorId createActorId() { | ||
79 | + return actorId; | ||
80 | + } | ||
81 | + | ||
82 | + @Override | ||
83 | + public TbActor createActor() { | ||
84 | + return new TestRootActor(actorId, testCtx); | ||
85 | + } | ||
86 | + } | ||
87 | +} |
common/actor/src/test/resources/logback.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8" ?> | ||
2 | + | ||
3 | +<configuration> | ||
4 | + <appender name="console" class="ch.qos.logback.core.ConsoleAppender"> | ||
5 | + <encoder> | ||
6 | + <pattern>%d{ISO8601} [%thread] %-5level %logger{36} - %msg%n</pattern> | ||
7 | + </encoder> | ||
8 | + </appender> | ||
9 | + | ||
10 | + <root level="INFO"> | ||
11 | + <appender-ref ref="console"/> | ||
12 | + </root> | ||
13 | + | ||
14 | +</configuration> |
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard</groupId> | 22 | <groupId>org.thingsboard</groupId> |
23 | - <version>2.5.1-SNAPSHOT</version> | 23 | + <version>2.5.3-SNAPSHOT</version> |
24 | <artifactId>common</artifactId> | 24 | <artifactId>common</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <groupId>org.thingsboard.common</groupId> | 26 | <groupId>org.thingsboard.common</groupId> |
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard</groupId> | 22 | <groupId>org.thingsboard</groupId> |
23 | - <version>2.5.1-SNAPSHOT</version> | 23 | + <version>2.5.3-SNAPSHOT</version> |
24 | <artifactId>common</artifactId> | 24 | <artifactId>common</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <groupId>org.thingsboard.common</groupId> | 26 | <groupId>org.thingsboard.common</groupId> |
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard</groupId> | 22 | <groupId>org.thingsboard</groupId> |
23 | - <version>2.5.1-SNAPSHOT</version> | 23 | + <version>2.5.3-SNAPSHOT</version> |
24 | <artifactId>common</artifactId> | 24 | <artifactId>common</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <groupId>org.thingsboard.common</groupId> | 26 | <groupId>org.thingsboard.common</groupId> |
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard</groupId> | 22 | <groupId>org.thingsboard</groupId> |
23 | - <version>2.5.1-SNAPSHOT</version> | 23 | + <version>2.5.3-SNAPSHOT</version> |
24 | <artifactId>common</artifactId> | 24 | <artifactId>common</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <groupId>org.thingsboard.common</groupId> | 26 | <groupId>org.thingsboard.common</groupId> |
@@ -21,7 +21,6 @@ import org.thingsboard.server.common.msg.queue.QueueToRuleEngineMsg; | @@ -21,7 +21,6 @@ import org.thingsboard.server.common.msg.queue.QueueToRuleEngineMsg; | ||
21 | /** | 21 | /** |
22 | * Created by ashvayka on 15.03.18. | 22 | * Created by ashvayka on 15.03.18. |
23 | */ | 23 | */ |
24 | -//TODO: add all "See" references | ||
25 | public enum MsgType { | 24 | public enum MsgType { |
26 | 25 | ||
27 | /** | 26 | /** |
@@ -97,6 +96,7 @@ public enum MsgType { | @@ -97,6 +96,7 @@ public enum MsgType { | ||
97 | 96 | ||
98 | STATS_PERSIST_TICK_MSG, | 97 | STATS_PERSIST_TICK_MSG, |
99 | 98 | ||
99 | + STATS_PERSIST_MSG, | ||
100 | 100 | ||
101 | /** | 101 | /** |
102 | * Message that is sent by TransportRuleEngineService to Device Actor. Represents messages from the device itself. | 102 | * Message that is sent by TransportRuleEngineService to Device Actor. Represents messages from the device itself. |
@@ -25,6 +25,7 @@ import org.thingsboard.server.common.data.id.EntityIdFactory; | @@ -25,6 +25,7 @@ import org.thingsboard.server.common.data.id.EntityIdFactory; | ||
25 | import org.thingsboard.server.common.data.id.RuleChainId; | 25 | import org.thingsboard.server.common.data.id.RuleChainId; |
26 | import org.thingsboard.server.common.data.id.RuleNodeId; | 26 | import org.thingsboard.server.common.data.id.RuleNodeId; |
27 | import org.thingsboard.server.common.msg.gen.MsgProtos; | 27 | import org.thingsboard.server.common.msg.gen.MsgProtos; |
28 | +import org.thingsboard.server.common.msg.queue.ServiceQueue; | ||
28 | import org.thingsboard.server.common.msg.queue.TbMsgCallback; | 29 | import org.thingsboard.server.common.msg.queue.TbMsgCallback; |
29 | 30 | ||
30 | import java.io.IOException; | 31 | import java.io.IOException; |
@@ -39,6 +40,7 @@ import java.util.UUID; | @@ -39,6 +40,7 @@ import java.util.UUID; | ||
39 | @Slf4j | 40 | @Slf4j |
40 | public final class TbMsg implements Serializable { | 41 | public final class TbMsg implements Serializable { |
41 | 42 | ||
43 | + private final String queueName; | ||
42 | private final UUID id; | 44 | private final UUID id; |
43 | private final long ts; | 45 | private final long ts; |
44 | private final String type; | 46 | private final String type; |
@@ -51,39 +53,44 @@ public final class TbMsg implements Serializable { | @@ -51,39 +53,44 @@ public final class TbMsg implements Serializable { | ||
51 | //This field is not serialized because we use queues and there is no need to do it | 53 | //This field is not serialized because we use queues and there is no need to do it |
52 | transient private final TbMsgCallback callback; | 54 | transient private final TbMsgCallback callback; |
53 | 55 | ||
56 | + public static TbMsg newMsg(String queueName, String type, EntityId originator, TbMsgMetaData metaData, String data, RuleChainId ruleChainId, RuleNodeId ruleNodeId) { | ||
57 | + return new TbMsg(queueName, UUID.randomUUID(), System.currentTimeMillis(), type, originator, metaData.copy(), TbMsgDataType.JSON, data, ruleChainId, ruleNodeId, TbMsgCallback.EMPTY); | ||
58 | + } | ||
59 | + | ||
54 | public static TbMsg newMsg(String type, EntityId originator, TbMsgMetaData metaData, String data) { | 60 | public static TbMsg newMsg(String type, EntityId originator, TbMsgMetaData metaData, String data) { |
55 | - return new TbMsg(UUID.randomUUID(), System.currentTimeMillis(), type, originator, metaData.copy(), TbMsgDataType.JSON, data, null, null, TbMsgCallback.EMPTY); | 61 | + return new TbMsg(ServiceQueue.MAIN, UUID.randomUUID(), System.currentTimeMillis(), type, originator, metaData.copy(), TbMsgDataType.JSON, data, null, null, TbMsgCallback.EMPTY); |
56 | } | 62 | } |
57 | 63 | ||
58 | - public static TbMsg newMsg(String type, EntityId originator, TbMsgMetaData metaData, String data, RuleChainId ruleChainId, RuleNodeId ruleNodeId) { | ||
59 | - return new TbMsg(UUID.randomUUID(), System.currentTimeMillis(), type, originator, metaData.copy(), TbMsgDataType.JSON, data, ruleChainId, ruleNodeId, TbMsgCallback.EMPTY); | 64 | + public static TbMsg newMsg(String queueName, String type, EntityId originator, TbMsgMetaData metaData, String data) { |
65 | + return new TbMsg(queueName, UUID.randomUUID(), System.currentTimeMillis(), type, originator, metaData.copy(), TbMsgDataType.JSON, data, null, null, TbMsgCallback.EMPTY); | ||
60 | } | 66 | } |
61 | 67 | ||
62 | public static TbMsg newMsg(String type, EntityId originator, TbMsgMetaData metaData, TbMsgDataType dataType, String data) { | 68 | public static TbMsg newMsg(String type, EntityId originator, TbMsgMetaData metaData, TbMsgDataType dataType, String data) { |
63 | - return new TbMsg(UUID.randomUUID(), System.currentTimeMillis(), type, originator, metaData.copy(), dataType, data, null, null, TbMsgCallback.EMPTY); | 69 | + return new TbMsg(ServiceQueue.MAIN, UUID.randomUUID(), System.currentTimeMillis(), type, originator, metaData.copy(), dataType, data, null, null, TbMsgCallback.EMPTY); |
64 | } | 70 | } |
65 | 71 | ||
66 | public static TbMsg newMsg(String type, EntityId originator, TbMsgMetaData metaData, TbMsgDataType dataType, String data, RuleChainId ruleChainId, RuleNodeId ruleNodeId) { | 72 | public static TbMsg newMsg(String type, EntityId originator, TbMsgMetaData metaData, TbMsgDataType dataType, String data, RuleChainId ruleChainId, RuleNodeId ruleNodeId) { |
67 | - return new TbMsg(UUID.randomUUID(), System.currentTimeMillis(), type, originator, metaData.copy(), dataType, data, ruleChainId, ruleNodeId, TbMsgCallback.EMPTY); | 73 | + return new TbMsg(ServiceQueue.MAIN, UUID.randomUUID(), System.currentTimeMillis(), type, originator, metaData.copy(), dataType, data, ruleChainId, ruleNodeId, TbMsgCallback.EMPTY); |
68 | } | 74 | } |
69 | 75 | ||
70 | public static TbMsg newMsg(String type, EntityId originator, TbMsgMetaData metaData, String data, TbMsgCallback callback) { | 76 | public static TbMsg newMsg(String type, EntityId originator, TbMsgMetaData metaData, String data, TbMsgCallback callback) { |
71 | - return new TbMsg(UUID.randomUUID(), System.currentTimeMillis(), type, originator, metaData.copy(), TbMsgDataType.JSON, data, null, null, callback); | 77 | + return new TbMsg(ServiceQueue.MAIN, UUID.randomUUID(), System.currentTimeMillis(), type, originator, metaData.copy(), TbMsgDataType.JSON, data, null, null, callback); |
72 | } | 78 | } |
73 | 79 | ||
74 | public static TbMsg transformMsg(TbMsg origMsg, String type, EntityId originator, TbMsgMetaData metaData, String data) { | 80 | public static TbMsg transformMsg(TbMsg origMsg, String type, EntityId originator, TbMsgMetaData metaData, String data) { |
75 | - return new TbMsg(origMsg.getId(), origMsg.getTs(), type, originator, metaData.copy(), origMsg.getDataType(), | 81 | + return new TbMsg(origMsg.getQueueName(), origMsg.getId(), origMsg.getTs(), type, originator, metaData.copy(), origMsg.getDataType(), |
76 | data, origMsg.getRuleChainId(), origMsg.getRuleNodeId(), origMsg.getCallback()); | 82 | data, origMsg.getRuleChainId(), origMsg.getRuleNodeId(), origMsg.getCallback()); |
77 | } | 83 | } |
78 | 84 | ||
79 | public static TbMsg newMsg(TbMsg tbMsg, RuleChainId ruleChainId, RuleNodeId ruleNodeId) { | 85 | public static TbMsg newMsg(TbMsg tbMsg, RuleChainId ruleChainId, RuleNodeId ruleNodeId) { |
80 | - return new TbMsg(UUID.randomUUID(), tbMsg.getTs(), tbMsg.getType(), tbMsg.getOriginator(), tbMsg.getMetaData().copy(), | 86 | + return new TbMsg(tbMsg.getQueueName(), UUID.randomUUID(), tbMsg.getTs(), tbMsg.getType(), tbMsg.getOriginator(), tbMsg.getMetaData().copy(), |
81 | tbMsg.getDataType(), tbMsg.getData(), ruleChainId, ruleNodeId, TbMsgCallback.EMPTY); | 87 | tbMsg.getDataType(), tbMsg.getData(), ruleChainId, ruleNodeId, TbMsgCallback.EMPTY); |
82 | } | 88 | } |
83 | 89 | ||
84 | - private TbMsg(UUID id, long ts, String type, EntityId originator, TbMsgMetaData metaData, TbMsgDataType dataType, String data, | 90 | + private TbMsg(String queueName, UUID id, long ts, String type, EntityId originator, TbMsgMetaData metaData, TbMsgDataType dataType, String data, |
85 | RuleChainId ruleChainId, RuleNodeId ruleNodeId, TbMsgCallback callback) { | 91 | RuleChainId ruleChainId, RuleNodeId ruleNodeId, TbMsgCallback callback) { |
86 | this.id = id; | 92 | this.id = id; |
93 | + this.queueName = queueName; | ||
87 | if (ts > 0) { | 94 | if (ts > 0) { |
88 | this.ts = ts; | 95 | this.ts = ts; |
89 | } else { | 96 | } else { |
@@ -136,7 +143,7 @@ public final class TbMsg implements Serializable { | @@ -136,7 +143,7 @@ public final class TbMsg implements Serializable { | ||
136 | return builder.build().toByteArray(); | 143 | return builder.build().toByteArray(); |
137 | } | 144 | } |
138 | 145 | ||
139 | - public static TbMsg fromBytes(byte[] data, TbMsgCallback callback) { | 146 | + public static TbMsg fromBytes(String queueName, byte[] data, TbMsgCallback callback) { |
140 | try { | 147 | try { |
141 | MsgProtos.TbMsgProto proto = MsgProtos.TbMsgProto.parseFrom(data); | 148 | MsgProtos.TbMsgProto proto = MsgProtos.TbMsgProto.parseFrom(data); |
142 | TbMsgMetaData metaData = new TbMsgMetaData(proto.getMetaData().getDataMap()); | 149 | TbMsgMetaData metaData = new TbMsgMetaData(proto.getMetaData().getDataMap()); |
@@ -150,18 +157,18 @@ public final class TbMsg implements Serializable { | @@ -150,18 +157,18 @@ public final class TbMsg implements Serializable { | ||
150 | ruleNodeId = new RuleNodeId(new UUID(proto.getRuleNodeIdMSB(), proto.getRuleNodeIdLSB())); | 157 | ruleNodeId = new RuleNodeId(new UUID(proto.getRuleNodeIdMSB(), proto.getRuleNodeIdLSB())); |
151 | } | 158 | } |
152 | TbMsgDataType dataType = TbMsgDataType.values()[proto.getDataType()]; | 159 | TbMsgDataType dataType = TbMsgDataType.values()[proto.getDataType()]; |
153 | - return new TbMsg(UUID.fromString(proto.getId()), proto.getTs(), proto.getType(), entityId, metaData, dataType, proto.getData(), ruleChainId, ruleNodeId, callback); | 160 | + return new TbMsg(queueName, UUID.fromString(proto.getId()), proto.getTs(), proto.getType(), entityId, metaData, dataType, proto.getData(), ruleChainId, ruleNodeId, callback); |
154 | } catch (InvalidProtocolBufferException e) { | 161 | } catch (InvalidProtocolBufferException e) { |
155 | throw new IllegalStateException("Could not parse protobuf for TbMsg", e); | 162 | throw new IllegalStateException("Could not parse protobuf for TbMsg", e); |
156 | } | 163 | } |
157 | } | 164 | } |
158 | 165 | ||
159 | public TbMsg copyWithRuleChainId(RuleChainId ruleChainId) { | 166 | public TbMsg copyWithRuleChainId(RuleChainId ruleChainId) { |
160 | - return new TbMsg(this.id, this.ts, this.type, this.originator, this.metaData, this.dataType, this.data, ruleChainId, null, callback); | 167 | + return new TbMsg(this.queueName, this.id, this.ts, this.type, this.originator, this.metaData, this.dataType, this.data, ruleChainId, null, callback); |
161 | } | 168 | } |
162 | 169 | ||
163 | public TbMsg copyWithRuleNodeId(RuleChainId ruleChainId, RuleNodeId ruleNodeId) { | 170 | public TbMsg copyWithRuleNodeId(RuleChainId ruleChainId, RuleNodeId ruleNodeId) { |
164 | - return new TbMsg(this.id, this.ts, this.type, this.originator, this.metaData, this.dataType, this.data, ruleChainId, ruleNodeId, callback); | 171 | + return new TbMsg(this.queueName, this.id, this.ts, this.type, this.originator, this.metaData, this.dataType, this.data, ruleChainId, ruleNodeId, callback); |
165 | } | 172 | } |
166 | 173 | ||
167 | public TbMsgCallback getCallback() { | 174 | public TbMsgCallback getCallback() { |
@@ -172,4 +179,8 @@ public final class TbMsg implements Serializable { | @@ -172,4 +179,8 @@ public final class TbMsg implements Serializable { | ||
172 | return TbMsgCallback.EMPTY; | 179 | return TbMsgCallback.EMPTY; |
173 | } | 180 | } |
174 | } | 181 | } |
182 | + | ||
183 | + public String getQueueName() { | ||
184 | + return queueName != null ? queueName : ServiceQueue.MAIN; | ||
185 | + } | ||
175 | } | 186 | } |
@@ -16,8 +16,9 @@ | @@ -16,8 +16,9 @@ | ||
16 | package org.thingsboard.server.common.msg.aware; | 16 | package org.thingsboard.server.common.msg.aware; |
17 | 17 | ||
18 | import org.thingsboard.server.common.data.id.DeviceId; | 18 | import org.thingsboard.server.common.data.id.DeviceId; |
19 | +import org.thingsboard.server.common.msg.TbActorMsg; | ||
19 | 20 | ||
20 | -public interface DeviceAwareMsg { | 21 | +public interface DeviceAwareMsg extends TbActorMsg { |
21 | 22 | ||
22 | DeviceId getDeviceId(); | 23 | DeviceId getDeviceId(); |
23 | } | 24 | } |
@@ -16,8 +16,9 @@ | @@ -16,8 +16,9 @@ | ||
16 | package org.thingsboard.server.common.msg.aware; | 16 | package org.thingsboard.server.common.msg.aware; |
17 | 17 | ||
18 | import org.thingsboard.server.common.data.id.RuleChainId; | 18 | import org.thingsboard.server.common.data.id.RuleChainId; |
19 | +import org.thingsboard.server.common.msg.TbActorMsg; | ||
19 | 20 | ||
20 | -public interface RuleChainAwareMsg { | 21 | +public interface RuleChainAwareMsg extends TbActorMsg { |
21 | 22 | ||
22 | RuleChainId getRuleChainId(); | 23 | RuleChainId getRuleChainId(); |
23 | 24 |
@@ -16,8 +16,9 @@ | @@ -16,8 +16,9 @@ | ||
16 | package org.thingsboard.server.common.msg.aware; | 16 | package org.thingsboard.server.common.msg.aware; |
17 | 17 | ||
18 | import org.thingsboard.server.common.data.id.TenantId; | 18 | import org.thingsboard.server.common.data.id.TenantId; |
19 | +import org.thingsboard.server.common.msg.TbActorMsg; | ||
19 | 20 | ||
20 | -public interface TenantAwareMsg { | 21 | +public interface TenantAwareMsg extends TbActorMsg { |
21 | 22 | ||
22 | TenantId getTenantId(); | 23 | TenantId getTenantId(); |
23 | 24 |
@@ -34,7 +34,7 @@ public class ServiceQueue { | @@ -34,7 +34,7 @@ public class ServiceQueue { | ||
34 | 34 | ||
35 | public ServiceQueue(ServiceType type, String queue) { | 35 | public ServiceQueue(ServiceType type, String queue) { |
36 | this.type = type; | 36 | this.type = type; |
37 | - this.queue = queue; | 37 | + this.queue = queue != null ? queue : MAIN; |
38 | } | 38 | } |
39 | 39 | ||
40 | public ServiceType getType() { | 40 | public ServiceType getType() { |
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard</groupId> | 22 | <groupId>org.thingsboard</groupId> |
23 | - <version>2.5.1-SNAPSHOT</version> | 23 | + <version>2.5.3-SNAPSHOT</version> |
24 | <artifactId>thingsboard</artifactId> | 24 | <artifactId>thingsboard</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <artifactId>common</artifactId> | 26 | <artifactId>common</artifactId> |
@@ -37,6 +37,7 @@ | @@ -37,6 +37,7 @@ | ||
37 | <module>data</module> | 37 | <module>data</module> |
38 | <module>util</module> | 38 | <module>util</module> |
39 | <module>message</module> | 39 | <module>message</module> |
40 | + <module>actor</module> | ||
40 | <module>queue</module> | 41 | <module>queue</module> |
41 | <module>transport</module> | 42 | <module>transport</module> |
42 | <module>dao-api</module> | 43 | <module>dao-api</module> |
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard</groupId> | 22 | <groupId>org.thingsboard</groupId> |
23 | - <version>2.5.1-SNAPSHOT</version> | 23 | + <version>2.5.3-SNAPSHOT</version> |
24 | <artifactId>common</artifactId> | 24 | <artifactId>common</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <groupId>org.thingsboard.common</groupId> | 26 | <groupId>org.thingsboard.common</groupId> |
@@ -91,8 +91,6 @@ public class DefaultTbQueueRequestTemplate<Request extends TbQueueMsg, Response | @@ -91,8 +91,6 @@ public class DefaultTbQueueRequestTemplate<Request extends TbQueueMsg, Response | ||
91 | List<Response> responses = responseTemplate.poll(pollInterval); | 91 | List<Response> responses = responseTemplate.poll(pollInterval); |
92 | if (responses.size() > 0) { | 92 | if (responses.size() > 0) { |
93 | log.trace("Polling responses completed, consumer records count [{}]", responses.size()); | 93 | log.trace("Polling responses completed, consumer records count [{}]", responses.size()); |
94 | - } else { | ||
95 | - continue; | ||
96 | } | 94 | } |
97 | responses.forEach(response -> { | 95 | responses.forEach(response -> { |
98 | byte[] requestIdHeader = response.getHeaders().get(REQUEST_ID_HEADER); | 96 | byte[] requestIdHeader = response.getHeaders().get(REQUEST_ID_HEADER); |
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard.common</groupId> | 22 | <groupId>org.thingsboard.common</groupId> |
23 | - <version>2.5.1-SNAPSHOT</version> | 23 | + <version>2.5.3-SNAPSHOT</version> |
24 | <artifactId>transport</artifactId> | 24 | <artifactId>transport</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <groupId>org.thingsboard.common.transport</groupId> | 26 | <groupId>org.thingsboard.common.transport</groupId> |
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard.common</groupId> | 22 | <groupId>org.thingsboard.common</groupId> |
23 | - <version>2.5.1-SNAPSHOT</version> | 23 | + <version>2.5.3-SNAPSHOT</version> |
24 | <artifactId>transport</artifactId> | 24 | <artifactId>transport</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <groupId>org.thingsboard.common.transport</groupId> | 26 | <groupId>org.thingsboard.common.transport</groupId> |
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard.common</groupId> | 22 | <groupId>org.thingsboard.common</groupId> |
23 | - <version>2.5.1-SNAPSHOT</version> | 23 | + <version>2.5.3-SNAPSHOT</version> |
24 | <artifactId>transport</artifactId> | 24 | <artifactId>transport</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <groupId>org.thingsboard.common.transport</groupId> | 26 | <groupId>org.thingsboard.common.transport</groupId> |
@@ -521,11 +521,22 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement | @@ -521,11 +521,22 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement | ||
521 | .setDeviceName(msg.getDeviceInfo().getDeviceName()) | 521 | .setDeviceName(msg.getDeviceInfo().getDeviceName()) |
522 | .setDeviceType(msg.getDeviceInfo().getDeviceType()) | 522 | .setDeviceType(msg.getDeviceInfo().getDeviceType()) |
523 | .build(); | 523 | .build(); |
524 | - transportService.process(sessionInfo, DefaultTransportService.getSessionEventMsg(SessionEvent.OPEN), null); | ||
525 | - transportService.registerAsyncSession(sessionInfo, this); | ||
526 | - checkGatewaySession(); | ||
527 | - ctx.writeAndFlush(createMqttConnAckMsg(CONNECTION_ACCEPTED)); | ||
528 | - log.info("[{}] Client connected!", sessionId); | 524 | + transportService.process(sessionInfo, DefaultTransportService.getSessionEventMsg(SessionEvent.OPEN), new TransportServiceCallback<Void>() { |
525 | + @Override | ||
526 | + public void onSuccess(Void msg) { | ||
527 | + transportService.registerAsyncSession(sessionInfo, MqttTransportHandler.this); | ||
528 | + checkGatewaySession(); | ||
529 | + ctx.writeAndFlush(createMqttConnAckMsg(CONNECTION_ACCEPTED)); | ||
530 | + log.info("[{}] Client connected!", sessionId); | ||
531 | + } | ||
532 | + | ||
533 | + @Override | ||
534 | + public void onError(Throwable e) { | ||
535 | + log.warn("[{}] Failed to submit session event", sessionId, e); | ||
536 | + ctx.writeAndFlush(createMqttConnAckMsg(MqttConnectReturnCode.CONNECTION_REFUSED_SERVER_UNAVAILABLE)); | ||
537 | + ctx.close(); | ||
538 | + } | ||
539 | + }); | ||
529 | } | 540 | } |
530 | } | 541 | } |
531 | 542 |
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard</groupId> | 22 | <groupId>org.thingsboard</groupId> |
23 | - <version>2.5.1-SNAPSHOT</version> | 23 | + <version>2.5.3-SNAPSHOT</version> |
24 | <artifactId>common</artifactId> | 24 | <artifactId>common</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <groupId>org.thingsboard.common</groupId> | 26 | <groupId>org.thingsboard.common</groupId> |
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard.common</groupId> | 22 | <groupId>org.thingsboard.common</groupId> |
23 | - <version>2.5.1-SNAPSHOT</version> | 23 | + <version>2.5.3-SNAPSHOT</version> |
24 | <artifactId>transport</artifactId> | 24 | <artifactId>transport</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <groupId>org.thingsboard.common.transport</groupId> | 26 | <groupId>org.thingsboard.common.transport</groupId> |
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard</groupId> | 22 | <groupId>org.thingsboard</groupId> |
23 | - <version>2.5.1-SNAPSHOT</version> | 23 | + <version>2.5.3-SNAPSHOT</version> |
24 | <artifactId>common</artifactId> | 24 | <artifactId>common</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <groupId>org.thingsboard.common</groupId> | 26 | <groupId>org.thingsboard.common</groupId> |
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard</groupId> | 22 | <groupId>org.thingsboard</groupId> |
23 | - <version>2.5.1-SNAPSHOT</version> | 23 | + <version>2.5.3-SNAPSHOT</version> |
24 | <artifactId>thingsboard</artifactId> | 24 | <artifactId>thingsboard</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <artifactId>dao</artifactId> | 26 | <artifactId>dao</artifactId> |
@@ -91,26 +91,26 @@ | @@ -91,26 +91,26 @@ | ||
91 | <artifactId>mockito-all</artifactId> | 91 | <artifactId>mockito-all</artifactId> |
92 | <scope>test</scope> | 92 | <scope>test</scope> |
93 | </dependency> | 93 | </dependency> |
94 | - <dependency> | ||
95 | - <groupId>org.apache.commons</groupId> | ||
96 | - <artifactId>commons-lang3</artifactId> | ||
97 | - </dependency> | ||
98 | - <dependency> | ||
99 | - <groupId>commons-validator</groupId> | ||
100 | - <artifactId>commons-validator</artifactId> | ||
101 | - </dependency> | ||
102 | - <dependency> | ||
103 | - <groupId>com.fasterxml.jackson.core</groupId> | ||
104 | - <artifactId>jackson-databind</artifactId> | ||
105 | - </dependency> | 94 | + <dependency> |
95 | + <groupId>org.apache.commons</groupId> | ||
96 | + <artifactId>commons-lang3</artifactId> | ||
97 | + </dependency> | ||
98 | + <dependency> | ||
99 | + <groupId>commons-collections</groupId> | ||
100 | + <artifactId>commons-collections</artifactId> | ||
101 | + </dependency> | ||
102 | + <dependency> | ||
103 | + <groupId>com.fasterxml.jackson.core</groupId> | ||
104 | + <artifactId>jackson-databind</artifactId> | ||
105 | + </dependency> | ||
106 | <dependency> | 106 | <dependency> |
107 | <groupId>org.springframework</groupId> | 107 | <groupId>org.springframework</groupId> |
108 | <artifactId>spring-context</artifactId> | 108 | <artifactId>spring-context</artifactId> |
109 | </dependency> | 109 | </dependency> |
110 | - <dependency> | ||
111 | - <groupId>org.springframework</groupId> | ||
112 | - <artifactId>spring-tx</artifactId> | ||
113 | - </dependency> | 110 | + <dependency> |
111 | + <groupId>org.springframework</groupId> | ||
112 | + <artifactId>spring-tx</artifactId> | ||
113 | + </dependency> | ||
114 | <dependency> | 114 | <dependency> |
115 | <groupId>org.springframework</groupId> | 115 | <groupId>org.springframework</groupId> |
116 | <artifactId>spring-web</artifactId> | 116 | <artifactId>spring-web</artifactId> |
@@ -120,24 +120,24 @@ | @@ -120,24 +120,24 @@ | ||
120 | <groupId>org.springframework.security</groupId> | 120 | <groupId>org.springframework.security</groupId> |
121 | <artifactId>spring-security-oauth2-client</artifactId> | 121 | <artifactId>spring-security-oauth2-client</artifactId> |
122 | </dependency> | 122 | </dependency> |
123 | - <dependency> | ||
124 | - <groupId>com.datastax.cassandra</groupId> | ||
125 | - <artifactId>cassandra-driver-core</artifactId> | ||
126 | - </dependency> | ||
127 | - <dependency> | ||
128 | - <groupId>com.datastax.cassandra</groupId> | ||
129 | - <artifactId>cassandra-driver-mapping</artifactId> | ||
130 | - </dependency> | ||
131 | - <dependency> | ||
132 | - <groupId>com.datastax.cassandra</groupId> | ||
133 | - <artifactId>cassandra-driver-extras</artifactId> | ||
134 | - </dependency> | 123 | + <dependency> |
124 | + <groupId>com.datastax.cassandra</groupId> | ||
125 | + <artifactId>cassandra-driver-core</artifactId> | ||
126 | + </dependency> | ||
127 | + <dependency> | ||
128 | + <groupId>com.datastax.cassandra</groupId> | ||
129 | + <artifactId>cassandra-driver-mapping</artifactId> | ||
130 | + </dependency> | ||
131 | + <dependency> | ||
132 | + <groupId>com.datastax.cassandra</groupId> | ||
133 | + <artifactId>cassandra-driver-extras</artifactId> | ||
134 | + </dependency> | ||
135 | <dependency> | 135 | <dependency> |
136 | <groupId>io.takari.junit</groupId> | 136 | <groupId>io.takari.junit</groupId> |
137 | <artifactId>takari-cpsuite</artifactId> | 137 | <artifactId>takari-cpsuite</artifactId> |
138 | <scope>test</scope> | 138 | <scope>test</scope> |
139 | - </dependency> | ||
140 | - <dependency> | 139 | + </dependency> |
140 | + <dependency> | ||
141 | <groupId>com.google.guava</groupId> | 141 | <groupId>com.google.guava</groupId> |
142 | <artifactId>guava</artifactId> | 142 | <artifactId>guava</artifactId> |
143 | </dependency> | 143 | </dependency> |
@@ -215,18 +215,18 @@ | @@ -215,18 +215,18 @@ | ||
215 | </includes> | 215 | </includes> |
216 | </configuration> | 216 | </configuration> |
217 | </plugin> | 217 | </plugin> |
218 | - <plugin> | ||
219 | - <groupId>org.apache.maven.plugins</groupId> | ||
220 | - <artifactId>maven-jar-plugin</artifactId> | 218 | + <plugin> |
219 | + <groupId>org.apache.maven.plugins</groupId> | ||
220 | + <artifactId>maven-jar-plugin</artifactId> | ||
221 | <version>${jar-plugin.version}</version> | 221 | <version>${jar-plugin.version}</version> |
222 | - <executions> | ||
223 | - <execution> | ||
224 | - <goals> | ||
225 | - <goal>test-jar</goal> | ||
226 | - </goals> | ||
227 | - </execution> | ||
228 | - </executions> | ||
229 | - </plugin> | 222 | + <executions> |
223 | + <execution> | ||
224 | + <goals> | ||
225 | + <goal>test-jar</goal> | ||
226 | + </goals> | ||
227 | + </execution> | ||
228 | + </executions> | ||
229 | + </plugin> | ||
230 | </plugins> | 230 | </plugins> |
231 | </build> | 231 | </build> |
232 | </project> | 232 | </project> |
@@ -17,7 +17,6 @@ package org.thingsboard.server.dao.service; | @@ -17,7 +17,6 @@ package org.thingsboard.server.dao.service; | ||
17 | 17 | ||
18 | import com.fasterxml.jackson.databind.JsonNode; | 18 | import com.fasterxml.jackson.databind.JsonNode; |
19 | import lombok.extern.slf4j.Slf4j; | 19 | import lombok.extern.slf4j.Slf4j; |
20 | -import org.apache.commons.validator.routines.EmailValidator; | ||
21 | import org.thingsboard.server.common.data.BaseData; | 20 | import org.thingsboard.server.common.data.BaseData; |
22 | import org.thingsboard.server.common.data.id.TenantId; | 21 | import org.thingsboard.server.common.data.id.TenantId; |
23 | import org.thingsboard.server.dao.exception.DataValidationException; | 22 | import org.thingsboard.server.dao.exception.DataValidationException; |
@@ -26,11 +25,13 @@ import java.util.HashSet; | @@ -26,11 +25,13 @@ import java.util.HashSet; | ||
26 | import java.util.Iterator; | 25 | import java.util.Iterator; |
27 | import java.util.Set; | 26 | import java.util.Set; |
28 | import java.util.function.Function; | 27 | import java.util.function.Function; |
28 | +import java.util.regex.Matcher; | ||
29 | +import java.util.regex.Pattern; | ||
29 | 30 | ||
30 | @Slf4j | 31 | @Slf4j |
31 | public abstract class DataValidator<D extends BaseData<?>> { | 32 | public abstract class DataValidator<D extends BaseData<?>> { |
32 | - | ||
33 | - private static EmailValidator emailValidator = EmailValidator.getInstance(); | 33 | + private static final Pattern EMAIL_PATTERN = |
34 | + Pattern.compile("^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,6}$", Pattern.CASE_INSENSITIVE); | ||
34 | 35 | ||
35 | public void validate(D data, Function<D, TenantId> tenantIdFunction) { | 36 | public void validate(D data, Function<D, TenantId> tenantIdFunction) { |
36 | try { | 37 | try { |
@@ -64,11 +65,20 @@ public abstract class DataValidator<D extends BaseData<?>> { | @@ -64,11 +65,20 @@ public abstract class DataValidator<D extends BaseData<?>> { | ||
64 | } | 65 | } |
65 | 66 | ||
66 | protected static void validateEmail(String email) { | 67 | protected static void validateEmail(String email) { |
67 | - if (!emailValidator.isValid(email)) { | 68 | + if (!doValidateEmail(email)) { |
68 | throw new DataValidationException("Invalid email address format '" + email + "'!"); | 69 | throw new DataValidationException("Invalid email address format '" + email + "'!"); |
69 | } | 70 | } |
70 | } | 71 | } |
71 | 72 | ||
73 | + private static boolean doValidateEmail(String email) { | ||
74 | + if (email == null) { | ||
75 | + return false; | ||
76 | + } | ||
77 | + | ||
78 | + Matcher emailMatcher = EMAIL_PATTERN.matcher(email); | ||
79 | + return emailMatcher.matches(); | ||
80 | + } | ||
81 | + | ||
72 | protected static void validateJsonStructure(JsonNode expectedNode, JsonNode actualNode) { | 82 | protected static void validateJsonStructure(JsonNode expectedNode, JsonNode actualNode) { |
73 | Set<String> expectedFields = new HashSet<>(); | 83 | Set<String> expectedFields = new HashSet<>(); |
74 | Iterator<String> fieldsIterator = expectedNode.fieldNames(); | 84 | Iterator<String> fieldsIterator = expectedNode.fieldNames(); |
@@ -4,15 +4,15 @@ This folder containing scripts and Kubernetes resources configurations to run Th | @@ -4,15 +4,15 @@ This folder containing scripts and Kubernetes resources configurations to run Th | ||
4 | 4 | ||
5 | ## Prerequisites | 5 | ## Prerequisites |
6 | 6 | ||
7 | -ThingsBoard Microservices are running on Kubernetes cluster. | 7 | +ThingsBoard Microservices run on the Kubernetes cluster. |
8 | You need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. | 8 | You need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. |
9 | -If you do not already have a cluster, you can create one by using [Minikube](https://kubernetes.io/docs/setup/minikube), | 9 | +If you do not have a cluster already, you can create one by using [Minikube](https://kubernetes.io/docs/setup/minikube), |
10 | or you can choose any other available [Kubernetes cluster deployment solutions](https://kubernetes.io/docs/setup/pick-right-solution/). | 10 | or you can choose any other available [Kubernetes cluster deployment solutions](https://kubernetes.io/docs/setup/pick-right-solution/). |
11 | 11 | ||
12 | ### Enable ingress addon | 12 | ### Enable ingress addon |
13 | 13 | ||
14 | -By default ingress addon is disable in the Minikube, and available only in cluster providers. | ||
15 | -To enable ingress, please execute next command: | 14 | +By default ingress addon is disabled in the Minikube, and available only in cluster providers. |
15 | +To enable ingress, please execute the following command: | ||
16 | 16 | ||
17 | ` | 17 | ` |
18 | $ minikube addons enable ingress | 18 | $ minikube addons enable ingress |
@@ -21,21 +21,21 @@ $ minikube addons enable ingress | @@ -21,21 +21,21 @@ $ minikube addons enable ingress | ||
21 | ## Installation | 21 | ## Installation |
22 | 22 | ||
23 | Before performing initial installation you can configure the type of database to be used with ThingsBoard and the type of deployment. | 23 | Before performing initial installation you can configure the type of database to be used with ThingsBoard and the type of deployment. |
24 | -In order to set database type change the value of `DATABASE` variable in `.env` file to one of the following: | 24 | +To set database type change the value of `DATABASE` variable in `.env` file to one of the following: |
25 | 25 | ||
26 | - `postgres` - use PostgreSQL database; | 26 | - `postgres` - use PostgreSQL database; |
27 | - `cassandra` - use Cassandra database; | 27 | - `cassandra` - use Cassandra database; |
28 | 28 | ||
29 | **NOTE**: According to the database type corresponding kubernetes resources will be deployed (see `postgres.yml`, `cassandra.yml` for details). | 29 | **NOTE**: According to the database type corresponding kubernetes resources will be deployed (see `postgres.yml`, `cassandra.yml` for details). |
30 | 30 | ||
31 | -In order to set deployment type change the value of `DEPLOYMENT_TYPE` variable in `.env` file to one of the following: | 31 | +To set deployment type change the value of `DEPLOYMENT_TYPE` variable in `.env` file to one of the following: |
32 | 32 | ||
33 | -- `basic` - start up with single instance of Zookeeper, Kafka and Redis; | ||
34 | -- `high-availability` - start up with Zookeeper, Kafka and Redis in cluster modes; | 33 | +- `basic` - startup with a single instance of Zookeeper, Kafka and Redis; |
34 | +- `high-availability` - startup with Zookeeper, Kafka, and Redis in cluster modes; | ||
35 | 35 | ||
36 | -**NOTE**: According to the deployment type corresponding kubernetes resources will be deployed (see content of the directories `./basic` and `./high-availability` for details). | 36 | +**NOTE**: According to the deployment type corresponding kubernetes resources will be deployed (see the content of the directories `./basic` and `./high-availability` for details). |
37 | 37 | ||
38 | -Execute the following command to run installation: | 38 | +Execute the following command to run the installation: |
39 | 39 | ||
40 | ` | 40 | ` |
41 | $ ./k8s-install-tb.sh --loadDemo | 41 | $ ./k8s-install-tb.sh --loadDemo |
@@ -47,7 +47,7 @@ Where: | @@ -47,7 +47,7 @@ Where: | ||
47 | 47 | ||
48 | ## Running | 48 | ## Running |
49 | 49 | ||
50 | -Execute the following command to deploy thirdparty resources: | 50 | +Execute the following command to deploy third-party resources: |
51 | 51 | ||
52 | ` | 52 | ` |
53 | $ ./k8s-deploy-thirdparty.sh | 53 | $ ./k8s-deploy-thirdparty.sh |
@@ -61,8 +61,8 @@ Execute the following command to deploy resources: | @@ -61,8 +61,8 @@ Execute the following command to deploy resources: | ||
61 | $ ./k8s-deploy-resources.sh | 61 | $ ./k8s-deploy-resources.sh |
62 | ` | 62 | ` |
63 | 63 | ||
64 | -After a while when all resources will be successfully started you can open `http://{your-cluster-ip}` in you browser (for ex. `http://192.168.99.101`). | ||
65 | -You should see ThingsBoard login page. | 64 | +After a while when all resources will be successfully started you can open `http://{your-cluster-ip}` in your browser (for ex. `http://192.168.99.101`). |
65 | +You should see the ThingsBoard login page. | ||
66 | 66 | ||
67 | Use the following default credentials: | 67 | Use the following default credentials: |
68 | 68 | ||
@@ -73,16 +73,16 @@ If you installed DataBase with demo data (using `--loadDemo` flag) you can also | @@ -73,16 +73,16 @@ If you installed DataBase with demo data (using `--loadDemo` flag) you can also | ||
73 | - **Tenant Administrator**: tenant@thingsboard.org / tenant | 73 | - **Tenant Administrator**: tenant@thingsboard.org / tenant |
74 | - **Customer User**: customer@thingsboard.org / customer | 74 | - **Customer User**: customer@thingsboard.org / customer |
75 | 75 | ||
76 | -In case of any issues you can examine service logs for errors. | 76 | +In case of any issues, you can examine service logs for errors. |
77 | For example to see ThingsBoard node logs execute the following commands: | 77 | For example to see ThingsBoard node logs execute the following commands: |
78 | 78 | ||
79 | -1) Get list of the running tb-node pods: | 79 | +1) Get the list of the running tb-node pods: |
80 | 80 | ||
81 | ` | 81 | ` |
82 | $ kubectl get pods -l app=tb-node | 82 | $ kubectl get pods -l app=tb-node |
83 | ` | 83 | ` |
84 | 84 | ||
85 | -2) Fetch logs of tb-node pod: | 85 | +2) Fetch logs of the tb-node pod: |
86 | 86 | ||
87 | ` | 87 | ` |
88 | $ kubectl logs -f [tb-node-pod-name] | 88 | $ kubectl logs -f [tb-node-pod-name] |
@@ -103,7 +103,7 @@ Execute the following command to delete all ThingsBoard microservices: | @@ -103,7 +103,7 @@ Execute the following command to delete all ThingsBoard microservices: | ||
103 | $ ./k8s-delete-resources.sh | 103 | $ ./k8s-delete-resources.sh |
104 | ` | 104 | ` |
105 | 105 | ||
106 | -Execute the following command to delete all thirdparty microservices: | 106 | +Execute the following command to delete all third-party microservices: |
107 | 107 | ||
108 | ` | 108 | ` |
109 | $ ./k8s-delete-thirdparty.sh | 109 | $ ./k8s-delete-thirdparty.sh |