Commit bd98ce8deb0794ca4edbd64cac4ad3cd2396ef51

Authored by Igor Kulikov
2 parents 78a91b8c f572f473

Merge with develop/2.5.2

Showing 58 changed files with 1209 additions and 55 deletions
... ... @@ -20,7 +20,7 @@
20 20 <modelVersion>4.0.0</modelVersion>
21 21 <parent>
22 22 <groupId>org.thingsboard</groupId>
23   - <version>2.5.2-SNAPSHOT</version>
  23 + <version>3.0.1-SNAPSHOT</version>
24 24 <artifactId>thingsboard</artifactId>
25 25 </parent>
26 26 <artifactId>application</artifactId>
... ...
... ... @@ -48,8 +48,6 @@ public class CassandraTsDatabaseUpgradeService extends AbstractCassandraDatabase
48 48 }
49 49 log.info("Schema updated.");
50 50 break;
51   - case "2.5.0":
52   - break;
53 51 default:
54 52 throw new RuntimeException("Unable to upgrade Cassandra database, unsupported fromVersion: " + fromVersion);
55 53 }
... ...
  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>3.0.1-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.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.concurrent.ConcurrentHashMap;
  25 +import java.util.concurrent.ConcurrentMap;
  26 +import java.util.concurrent.ExecutorService;
  27 +import java.util.concurrent.Executors;
  28 +import java.util.concurrent.ScheduledExecutorService;
  29 +import java.util.concurrent.locks.Lock;
  30 +import java.util.concurrent.locks.ReentrantLock;
  31 +
  32 +@Slf4j
  33 +@Data
  34 +public class DefaultTbActorSystem implements TbActorSystem {
  35 +
  36 + private final ConcurrentMap<String, Dispatcher> dispatchers = new ConcurrentHashMap<>();
  37 + private final ConcurrentMap<TbActorId, TbActorMailbox> actors = new ConcurrentHashMap<>();
  38 + private final ConcurrentMap<TbActorId, ReentrantLock> actorCreationLocks = new ConcurrentHashMap<>();
  39 + @Getter
  40 + private final TbActorSystemSettings settings;
  41 + @Getter
  42 + private final ScheduledExecutorService scheduler;
  43 +
  44 + public DefaultTbActorSystem(TbActorSystemSettings settings) {
  45 + this.settings = settings;
  46 + this.scheduler = Executors.newScheduledThreadPool(settings.getSchedulerPoolSize(), ThingsBoardThreadFactory.forName("actor-system-scheduler"));
  47 + }
  48 +
  49 + @Override
  50 + public void createDispatcher(String dispatcherId, ExecutorService executor) {
  51 + Dispatcher current = dispatchers.putIfAbsent(dispatcherId, new Dispatcher(dispatcherId, executor));
  52 + if (current != null) {
  53 + throw new RuntimeException("Dispatcher with id [" + dispatcherId + "] is already registered!");
  54 + }
  55 + }
  56 +
  57 + @Override
  58 + public void destroyDispatcher(String dispatcherId) {
  59 + Dispatcher dispatcher = dispatchers.remove(dispatcherId);
  60 + if (dispatcher != null) {
  61 + dispatcher.getExecutor().shutdownNow();
  62 + } else {
  63 + throw new RuntimeException("Dispatcher with id [" + dispatcherId + "] is not registered!");
  64 + }
  65 + }
  66 +
  67 + @Override
  68 + public TbActorId createRootActor(String dispatcherId, TbActorCreator creator) {
  69 + return createActor(dispatcherId, creator, null);
  70 + }
  71 +
  72 + @Override
  73 + public TbActorId createChildActor(String dispatcherId, TbActorCreator creator, TbActorId parent) {
  74 + return createActor(dispatcherId, creator, parent);
  75 + }
  76 +
  77 + private TbActorId createActor(String dispatcherId, TbActorCreator creator, TbActorId parent) {
  78 + Dispatcher dispatcher = dispatchers.get(dispatcherId);
  79 + if (dispatcher == null) {
  80 + log.warn("Dispatcher with id [{}] is not registered!", dispatcherId);
  81 + throw new RuntimeException("Dispatcher with id [" + dispatcherId + "] is not registered!");
  82 + }
  83 +
  84 + TbActorId actorId = creator.createActorId();
  85 + TbActorMailbox actorMailbox = actors.get(actorId);
  86 + if (actorMailbox != null) {
  87 + log.debug("Actor with id [{}] is already registered!", actorId);
  88 + } else {
  89 + Lock actorCreationLock = actorCreationLocks.computeIfAbsent(actorId, id -> new ReentrantLock());
  90 + actorCreationLock.lock();
  91 + try {
  92 + actorMailbox = actors.get(actorId);
  93 + if (actorMailbox == null) {
  94 + log.debug("Creating actor with id [{}]!", actorId);
  95 + TbActor actor = creator.createActor();
  96 + TbActorMailbox mailbox = new TbActorMailbox(this, settings, actorId, parent, actor, dispatcher);
  97 + actors.put(actorId, mailbox);
  98 + mailbox.initActor();
  99 + } else {
  100 + log.debug("Actor with id [{}] is already registered!", actorId);
  101 + }
  102 + } finally {
  103 + actorCreationLock.unlock();
  104 + actorCreationLocks.remove(actorId);
  105 + }
  106 + }
  107 + return actorId;
  108 + }
  109 +
  110 + @Override
  111 + public void tell(TbActorId target, TbActorMsg actorMsg) {
  112 + TbActorMailbox mailbox = actors.get(target);
  113 + if (mailbox == null) {
  114 + throw new TbActorNotRegisteredException(target, "Actor with id [" + target + "] is not registered!");
  115 + }
  116 + mailbox.enqueue(actorMsg);
  117 + }
  118 +
  119 + @Override
  120 + public void stop(TbActorId actorId) {
  121 + TbActorMailbox mailbox = actors.remove(actorId);
  122 + if (mailbox != null) {
  123 + mailbox.destroy();
  124 + }
  125 + }
  126 +
  127 + @Override
  128 + public void stop() {
  129 + dispatchers.values().forEach(dispatcher -> dispatcher.getExecutor().shutdownNow());
  130 + actors.clear();
  131 + }
  132 +
  133 +}
... ...
  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 + void init();
  23 +
  24 + boolean process(TbActorCtx ctx, TbActorMsg msg);
  25 +
  26 + void destroy();
  27 +
  28 + default InitFailureStrategy onInitFailure(int attempt, Throwable t) {
  29 + return InitFailureStrategy.retryWithDelay(5000);
  30 + }
  31 +
  32 + default ProcessFailureStrategy onProcessFailure(Throwable t) {
  33 + if (t instanceof Error) {
  34 + return ProcessFailureStrategy.stop();
  35 + } else {
  36 + return ProcessFailureStrategy.resume();
  37 + }
  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 +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 +public interface TbActorCtx {
  21 +
  22 + TbActorId getSelf();
  23 +
  24 + TbActorId getParent();
  25 +
  26 + void tell(TbActorId target, 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.data.id.EntityId;
  19 +
  20 +import java.util.Objects;
  21 +
  22 +public class TbActorId {
  23 +
  24 + private final EntityId entityId;
  25 +
  26 + public TbActorId(EntityId entityId) {
  27 + this.entityId = entityId;
  28 + }
  29 +
  30 + @Override
  31 + public String toString() {
  32 + return entityId.toString();
  33 + }
  34 +
  35 + @Override
  36 + public boolean equals(Object o) {
  37 + if (this == o) return true;
  38 + if (o == null || getClass() != o.getClass()) return false;
  39 + TbActorId actorId = (TbActorId) o;
  40 + return entityId.equals(actorId.entityId);
  41 + }
  42 +
  43 + @Override
  44 + public int hashCode() {
  45 + return Objects.hash(entityId);
  46 + }
  47 +}
... ...
  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.concurrent.ConcurrentLinkedQueue;
  23 +import java.util.concurrent.TimeUnit;
  24 +import java.util.concurrent.atomic.AtomicBoolean;
  25 +
  26 +@Slf4j
  27 +@Data
  28 +public final class TbActorMailbox implements TbActorCtx {
  29 + private static final boolean FREE = false;
  30 + private static final boolean BUSY = true;
  31 +
  32 + private static final boolean NOT_READY = false;
  33 + private static final boolean READY = true;
  34 +
  35 + private final TbActorSystem system;
  36 + private final TbActorSystemSettings settings;
  37 + private final TbActorId selfId;
  38 + private final TbActorId parentId;
  39 + private final TbActor actor;
  40 + private final Dispatcher dispatcher;
  41 + private final ConcurrentLinkedQueue<TbActorMsg> msgs = new ConcurrentLinkedQueue<>();
  42 + private final AtomicBoolean busy = new AtomicBoolean(FREE);
  43 + private final AtomicBoolean ready = new AtomicBoolean(NOT_READY);
  44 + private final AtomicBoolean destroyInProgress = new AtomicBoolean();
  45 +
  46 + public void initActor() {
  47 + dispatcher.getExecutor().execute(() -> tryInit(1));
  48 + }
  49 +
  50 + private void tryInit(int attempt) {
  51 + try {
  52 + log.debug("[{}] Trying to init actor, attempt: {}", selfId, attempt);
  53 + if (!destroyInProgress.get()) {
  54 + actor.init();
  55 + if (!destroyInProgress.get()) {
  56 + ready.set(READY);
  57 + tryProcessQueue(false);
  58 + }
  59 + }
  60 + } catch (Throwable t) {
  61 + log.debug("[{}] Failed to init actor, attempt: {}", selfId, attempt, t);
  62 + int attemptIdx = attempt + 1;
  63 + InitFailureStrategy strategy = actor.onInitFailure(attempt, t);
  64 + if (strategy.isStop() || (settings.getMaxActorInitAttempts() > 0 && attemptIdx > settings.getMaxActorInitAttempts())) {
  65 + log.info("[{}] Failed to init actor, attempt {}, going to stop attempts.", selfId, attempt, t);
  66 + system.stop(selfId);
  67 + } else if (strategy.getRetryDelay() > 0) {
  68 + log.info("[{}] Failed to init actor, attempt {}, going to retry in attempts in {}ms", selfId, attempt, strategy.getRetryDelay(), t);
  69 + system.getScheduler().schedule(() -> dispatcher.getExecutor().execute(() -> tryInit(attemptIdx)), strategy.getRetryDelay(), TimeUnit.MILLISECONDS);
  70 + } else {
  71 + log.info("[{}] Failed to init actor, attempt {}, going to retry immediately", selfId, attempt, t);
  72 + dispatcher.getExecutor().execute(() -> tryInit(attemptIdx));
  73 + }
  74 + }
  75 + }
  76 +
  77 + public void enqueue(TbActorMsg msg) {
  78 + msgs.add(msg);
  79 + tryProcessQueue(true);
  80 + }
  81 +
  82 + private void tryProcessQueue(boolean newMsg) {
  83 + if (ready.get() == READY && (newMsg || !msgs.isEmpty()) && busy.compareAndSet(FREE, BUSY)) {
  84 + dispatcher.getExecutor().execute(this::processMailbox);
  85 + } else {
  86 + log.trace("[{}] MessageBox is busy, new msg: {}", selfId, newMsg);
  87 + }
  88 + }
  89 +
  90 + private void processMailbox() {
  91 + boolean noMoreElements = false;
  92 + for (int i = 0; i < settings.getActorThroughput(); i++) {
  93 + TbActorMsg msg = msgs.poll();
  94 + if (msg != null) {
  95 + try {
  96 + log.debug("[{}] Going to process message: {}", selfId, msg);
  97 + actor.process(this, msg);
  98 + } catch (Throwable t) {
  99 + log.debug("[{}] Failed to process message: {}", selfId, msg, t);
  100 + ProcessFailureStrategy strategy = actor.onProcessFailure(t);
  101 + if (strategy.isStop()) {
  102 + system.stop(selfId);
  103 + }
  104 + }
  105 + } else {
  106 + noMoreElements = true;
  107 + break;
  108 + }
  109 + }
  110 + if (noMoreElements) {
  111 + busy.set(FREE);
  112 + dispatcher.getExecutor().execute(() -> tryProcessQueue(false));
  113 + } else {
  114 + dispatcher.getExecutor().execute(this::processMailbox);
  115 + }
  116 + }
  117 +
  118 + @Override
  119 + public TbActorId getSelf() {
  120 + return selfId;
  121 + }
  122 +
  123 + @Override
  124 + public TbActorId getParent() {
  125 + return parentId;
  126 + }
  127 +
  128 + @Override
  129 + public void tell(TbActorId target, TbActorMsg actorMsg) {
  130 + system.tell(target, actorMsg);
  131 + }
  132 +
  133 + public void destroy() {
  134 + destroyInProgress.set(true);
  135 + dispatcher.getExecutor().execute(() -> {
  136 + try {
  137 + ready.set(NOT_READY);
  138 + actor.destroy();
  139 + } catch (Throwable t) {
  140 + log.warn("[{}] Failed to destroy actor: {}", selfId, t);
  141 + }
  142 + });
  143 + }
  144 +}
... ...
  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 +import java.util.concurrent.ExecutorService;
  21 +import java.util.concurrent.ScheduledExecutorService;
  22 +
  23 +public interface TbActorSystem {
  24 +
  25 + ScheduledExecutorService getScheduler();
  26 +
  27 + void createDispatcher(String dispatcherId, ExecutorService executor);
  28 +
  29 + void destroyDispatcher(String dispatcherId);
  30 +
  31 + TbActorId createRootActor(String dispatcherId, TbActorCreator creator);
  32 +
  33 + TbActorId createChildActor(String dispatcherId, TbActorCreator creator, TbActorId parent);
  34 +
  35 + void tell(TbActorId target, TbActorMsg actorMsg);
  36 +
  37 + void stop(TbActorId actorId);
  38 +
  39 + void stop();
  40 +
  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 +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.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 _1M = 1024 * 1024;
  44 +
  45 + private TbActorSystem actorSystem;
  46 + private ExecutorService submitPool;
  47 +
  48 + @Before
  49 + public void initActorSystem() {
  50 + int cores = Runtime.getRuntime().availableProcessors();
  51 + int parallelism = Math.max(1, cores / 2);
  52 + TbActorSystemSettings settings = new TbActorSystemSettings(5, parallelism, 42);
  53 + actorSystem = new DefaultTbActorSystem(settings);
  54 + submitPool = Executors.newWorkStealingPool(parallelism);
  55 + actorSystem.createDispatcher(ROOT_DISPATCHER, Executors.newWorkStealingPool(parallelism));
  56 + }
  57 +
  58 + @After
  59 + public void shutdownActorSystem() {
  60 + actorSystem.stop();
  61 + submitPool.shutdownNow();
  62 + }
  63 +
  64 + @Test
  65 + public void test10actorsAnd1MMessages() throws InterruptedException {
  66 + testActorsAndMessages(10, _1M);
  67 + }
  68 +
  69 + @Test
  70 + public void test1MActorsAnd10Messages() throws InterruptedException {
  71 + testActorsAndMessages(_1M, 10);
  72 + }
  73 +
  74 + @Test
  75 + public void test1KActorsAnd1KMessages() throws InterruptedException {
  76 + testActorsAndMessages(1000, 1000);
  77 + }
  78 +
  79 + @Test
  80 + public void testNoMessagesAfterDestroy() throws InterruptedException {
  81 + ActorTestCtx testCtx1 = getActorTestCtx(1);
  82 + ActorTestCtx testCtx2 = getActorTestCtx(1);
  83 +
  84 + TbActorId actorId1 = actorSystem.createRootActor(ROOT_DISPATCHER, new SlowInitActor.SlowInitActorCreator(
  85 + new TbActorId(new DeviceId(UUID.randomUUID())), testCtx1));
  86 + TbActorId actorId2 = actorSystem.createRootActor(ROOT_DISPATCHER, new SlowInitActor.SlowInitActorCreator(
  87 + new TbActorId(new DeviceId(UUID.randomUUID())), testCtx2));
  88 +
  89 + actorSystem.tell(actorId1, new IntTbActorMsg(42));
  90 + actorSystem.tell(actorId2, new IntTbActorMsg(42));
  91 + actorSystem.stop(actorId1);
  92 +
  93 + Assert.assertTrue(testCtx2.getLatch().await(1, TimeUnit.SECONDS));
  94 + Assert.assertFalse(testCtx1.getLatch().await(2, TimeUnit.SECONDS));
  95 + }
  96 +
  97 + @Test
  98 + public void testOneActorCreated() throws InterruptedException {
  99 + ActorTestCtx testCtx1 = getActorTestCtx(1);
  100 + ActorTestCtx testCtx2 = getActorTestCtx(1);
  101 + TbActorId actorId = new TbActorId(new DeviceId(UUID.randomUUID()));
  102 + submitPool.submit(() -> actorSystem.createRootActor(ROOT_DISPATCHER, new SlowCreateActor.SlowCreateActorCreator(actorId, testCtx1)));
  103 + submitPool.submit(() -> actorSystem.createRootActor(ROOT_DISPATCHER, new SlowCreateActor.SlowCreateActorCreator(actorId, testCtx2)));
  104 +
  105 + Thread.sleep(1000);
  106 + actorSystem.tell(actorId, new IntTbActorMsg(42));
  107 +
  108 + Assert.assertTrue(testCtx1.getLatch().await(3, TimeUnit.SECONDS));
  109 + Assert.assertFalse(testCtx2.getLatch().await(3, TimeUnit.SECONDS));
  110 + }
  111 +
  112 + @Test
  113 + public void testActorCreatorCalledOnce() throws InterruptedException {
  114 + ActorTestCtx testCtx = getActorTestCtx(1);
  115 + TbActorId actorId = new TbActorId(new DeviceId(UUID.randomUUID()));
  116 + for(int i =0; i < 1000; i++) {
  117 + submitPool.submit(() -> actorSystem.createRootActor(ROOT_DISPATCHER, new SlowCreateActor.SlowCreateActorCreator(actorId, testCtx)));
  118 + }
  119 + Thread.sleep(1000);
  120 + actorSystem.tell(actorId, new IntTbActorMsg(42));
  121 +
  122 + Assert.assertTrue(testCtx.getLatch().await(1, TimeUnit.SECONDS));
  123 + //One for creation and one for message
  124 + Assert.assertEquals(2, testCtx.getInvocationCount().get());
  125 + }
  126 +
  127 +
  128 + public void testActorsAndMessages(int actorsCount, int msgNumber) throws InterruptedException {
  129 + Random random = new Random();
  130 + int[] randomIntegers = new int[msgNumber];
  131 + long sumTmp = 0;
  132 + for (int i = 0; i < msgNumber; i++) {
  133 + int tmp = random.nextInt();
  134 + randomIntegers[i] = tmp;
  135 + sumTmp += tmp;
  136 + }
  137 + long expected = sumTmp;
  138 +
  139 + List<ActorTestCtx> testCtxes = new ArrayList<>();
  140 +
  141 + List<TbActorId> actorIds = new ArrayList<>();
  142 + for (int actorIdx = 0; actorIdx < actorsCount; actorIdx++) {
  143 + ActorTestCtx testCtx = getActorTestCtx(msgNumber);
  144 +
  145 + actorIds.add(actorSystem.createRootActor(ROOT_DISPATCHER, new TestRootActor.TestRootActorCreator(
  146 + new TbActorId(new DeviceId(UUID.randomUUID())), testCtx)));
  147 + testCtxes.add(testCtx);
  148 + }
  149 +
  150 + long start = System.nanoTime();
  151 +
  152 + for (int i = 0; i < msgNumber; i++) {
  153 + int tmp = randomIntegers[i];
  154 + submitPool.execute(() -> actorIds.forEach(actorId -> actorSystem.tell(actorId, new IntTbActorMsg(tmp))));
  155 + }
  156 + log.info("Submitted all messages");
  157 +
  158 + testCtxes.forEach(ctx -> {
  159 + try {
  160 + Assert.assertTrue(ctx.getLatch().await(1, TimeUnit.MINUTES));
  161 + Assert.assertEquals(expected, ctx.getActual().get());
  162 + Assert.assertEquals(msgNumber, ctx.getInvocationCount().get());
  163 + } catch (InterruptedException e) {
  164 + e.printStackTrace();
  165 + }
  166 + });
  167 +
  168 + long duration = System.nanoTime() - start;
  169 + log.info("Time spend: {}ns ({} ms)", duration, TimeUnit.NANOSECONDS.toMillis(duration));
  170 + }
  171 +
  172 + private ActorTestCtx getActorTestCtx(int i) {
  173 + CountDownLatch countDownLatch = new CountDownLatch(1);
  174 + AtomicLong actual = new AtomicLong();
  175 + AtomicInteger invocations = new AtomicInteger();
  176 + return new ActorTestCtx(countDownLatch, invocations, i, actual);
  177 + }
  178 +}
... ...
  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.CountDownLatch;
  21 +import java.util.concurrent.atomic.AtomicInteger;
  22 +import java.util.concurrent.atomic.AtomicLong;
  23 +
  24 +@Data
  25 +public class ActorTestCtx {
  26 +
  27 + private final CountDownLatch latch;
  28 + private final AtomicInteger invocationCount;
  29 + private final int expectedInvocationCount;
  30 + private final AtomicLong actual;
  31 +}
... ...
  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() {
  29 + try {
  30 + Thread.sleep(500);
  31 + } catch (InterruptedException e) {
  32 + e.printStackTrace();
  33 + }
  34 + super.init();
  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 implements TbActor {
  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() {
  41 + initialized = true;
  42 + }
  43 +
  44 + @Override
  45 + public boolean process(TbActorCtx ctx, TbActorMsg msg) {
  46 + if (initialized) {
  47 + int value = ((IntTbActorMsg) msg).getValue();
  48 + sum += value;
  49 + count += 1;
  50 + if (count == testCtx.getExpectedInvocationCount()) {
  51 + testCtx.getActual().set(sum);
  52 + testCtx.getInvocationCount().addAndGet(count);
  53 + testCtx.getLatch().countDown();
  54 + }
  55 + }
  56 + return true;
  57 + }
  58 +
  59 + @Override
  60 + public void destroy() {
  61 +
  62 + }
  63 +
  64 + public static class TestRootActorCreator implements TbActorCreator {
  65 +
  66 + private final TbActorId actorId;
  67 + private final ActorTestCtx testCtx;
  68 +
  69 + public TestRootActorCreator(TbActorId actorId, ActorTestCtx testCtx) {
  70 + this.actorId = actorId;
  71 + this.testCtx = testCtx;
  72 + }
  73 +
  74 + @Override
  75 + public TbActorId createActorId() {
  76 + return actorId;
  77 + }
  78 +
  79 + @Override
  80 + public TbActor createActor() {
  81 + return new TestRootActor(actorId, testCtx);
  82 + }
  83 + }
  84 +}
... ...
  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 20 <modelVersion>4.0.0</modelVersion>
21 21 <parent>
22 22 <groupId>org.thingsboard</groupId>
23   - <version>2.5.2-SNAPSHOT</version>
  23 + <version>3.0.1-SNAPSHOT</version>
24 24 <artifactId>common</artifactId>
25 25 </parent>
26 26 <groupId>org.thingsboard.common</groupId>
... ...
... ... @@ -20,7 +20,7 @@
20 20 <modelVersion>4.0.0</modelVersion>
21 21 <parent>
22 22 <groupId>org.thingsboard</groupId>
23   - <version>2.5.2-SNAPSHOT</version>
  23 + <version>3.0.1-SNAPSHOT</version>
24 24 <artifactId>common</artifactId>
25 25 </parent>
26 26 <groupId>org.thingsboard.common</groupId>
... ...
... ... @@ -20,7 +20,7 @@
20 20 <modelVersion>4.0.0</modelVersion>
21 21 <parent>
22 22 <groupId>org.thingsboard</groupId>
23   - <version>2.5.2-SNAPSHOT</version>
  23 + <version>3.0.1-SNAPSHOT</version>
24 24 <artifactId>common</artifactId>
25 25 </parent>
26 26 <groupId>org.thingsboard.common</groupId>
... ...
... ... @@ -20,7 +20,7 @@
20 20 <modelVersion>4.0.0</modelVersion>
21 21 <parent>
22 22 <groupId>org.thingsboard</groupId>
23   - <version>2.5.2-SNAPSHOT</version>
  23 + <version>3.0.1-SNAPSHOT</version>
24 24 <artifactId>thingsboard</artifactId>
25 25 </parent>
26 26 <artifactId>common</artifactId>
... ... @@ -37,6 +37,7 @@
37 37 <module>data</module>
38 38 <module>util</module>
39 39 <module>message</module>
  40 + <module>actor</module>
40 41 <module>queue</module>
41 42 <module>transport</module>
42 43 <module>dao-api</module>
... ...
... ... @@ -20,7 +20,7 @@
20 20 <modelVersion>4.0.0</modelVersion>
21 21 <parent>
22 22 <groupId>org.thingsboard</groupId>
23   - <version>2.5.2-SNAPSHOT</version>
  23 + <version>3.0.1-SNAPSHOT</version>
24 24 <artifactId>common</artifactId>
25 25 </parent>
26 26 <groupId>org.thingsboard.common</groupId>
... ...
... ... @@ -20,7 +20,7 @@
20 20 <modelVersion>4.0.0</modelVersion>
21 21 <parent>
22 22 <groupId>org.thingsboard.common</groupId>
23   - <version>2.5.2-SNAPSHOT</version>
  23 + <version>3.0.1-SNAPSHOT</version>
24 24 <artifactId>transport</artifactId>
25 25 </parent>
26 26 <groupId>org.thingsboard.common.transport</groupId>
... ...
... ... @@ -20,7 +20,7 @@
20 20 <modelVersion>4.0.0</modelVersion>
21 21 <parent>
22 22 <groupId>org.thingsboard.common</groupId>
23   - <version>2.5.2-SNAPSHOT</version>
  23 + <version>3.0.1-SNAPSHOT</version>
24 24 <artifactId>transport</artifactId>
25 25 </parent>
26 26 <groupId>org.thingsboard.common.transport</groupId>
... ...
... ... @@ -20,7 +20,7 @@
20 20 <modelVersion>4.0.0</modelVersion>
21 21 <parent>
22 22 <groupId>org.thingsboard.common</groupId>
23   - <version>2.5.2-SNAPSHOT</version>
  23 + <version>3.0.1-SNAPSHOT</version>
24 24 <artifactId>transport</artifactId>
25 25 </parent>
26 26 <groupId>org.thingsboard.common.transport</groupId>
... ...
... ... @@ -20,7 +20,7 @@
20 20 <modelVersion>4.0.0</modelVersion>
21 21 <parent>
22 22 <groupId>org.thingsboard</groupId>
23   - <version>2.5.2-SNAPSHOT</version>
  23 + <version>3.0.1-SNAPSHOT</version>
24 24 <artifactId>common</artifactId>
25 25 </parent>
26 26 <groupId>org.thingsboard.common</groupId>
... ...
... ... @@ -20,7 +20,7 @@
20 20 <modelVersion>4.0.0</modelVersion>
21 21 <parent>
22 22 <groupId>org.thingsboard.common</groupId>
23   - <version>2.5.2-SNAPSHOT</version>
  23 + <version>3.0.1-SNAPSHOT</version>
24 24 <artifactId>transport</artifactId>
25 25 </parent>
26 26 <groupId>org.thingsboard.common.transport</groupId>
... ...
... ... @@ -20,7 +20,7 @@
20 20 <modelVersion>4.0.0</modelVersion>
21 21 <parent>
22 22 <groupId>org.thingsboard</groupId>
23   - <version>2.5.2-SNAPSHOT</version>
  23 + <version>3.0.1-SNAPSHOT</version>
24 24 <artifactId>common</artifactId>
25 25 </parent>
26 26 <groupId>org.thingsboard.common</groupId>
... ...
... ... @@ -20,7 +20,7 @@
20 20 <modelVersion>4.0.0</modelVersion>
21 21 <parent>
22 22 <groupId>org.thingsboard</groupId>
23   - <version>2.5.2-SNAPSHOT</version>
  23 + <version>3.0.1-SNAPSHOT</version>
24 24 <artifactId>thingsboard</artifactId>
25 25 </parent>
26 26 <artifactId>dao</artifactId>
... ...
... ... @@ -4,15 +4,15 @@ This folder containing scripts and Kubernetes resources configurations to run Th
4 4
5 5 ## Prerequisites
6 6
7   -ThingsBoard Microservices are running on Kubernetes cluster.
  7 +ThingsBoard Microservices run on the Kubernetes cluster.
8 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 10 or you can choose any other available [Kubernetes cluster deployment solutions](https://kubernetes.io/docs/setup/pick-right-solution/).
11 11
12 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 18 $ minikube addons enable ingress
... ... @@ -21,21 +21,21 @@ $ minikube addons enable ingress
21 21 ## Installation
22 22
23 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 26 - `postgres` - use PostgreSQL database;
27 27 - `hybrid` - use PostgreSQL for entities database and Cassandra for timeseries database;
28 28
29 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 41 $ ./k8s-install-tb.sh --loadDemo
... ... @@ -47,7 +47,7 @@ Where:
47 47
48 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 53 $ ./k8s-deploy-thirdparty.sh
... ... @@ -61,8 +61,8 @@ Execute the following command to deploy resources:
61 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 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 73 - **Tenant Administrator**: tenant@thingsboard.org / tenant
74 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 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 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 88 $ kubectl logs -f [tb-node-pod-name]
... ... @@ -103,7 +103,7 @@ Execute the following command to delete all ThingsBoard microservices:
103 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 109 $ ./k8s-delete-thirdparty.sh
... ...
... ... @@ -21,7 +21,7 @@
21 21
22 22 <parent>
23 23 <groupId>org.thingsboard</groupId>
24   - <version>2.5.2-SNAPSHOT</version>
  24 + <version>3.0.1-SNAPSHOT</version>
25 25 <artifactId>msa</artifactId>
26 26 </parent>
27 27 <groupId>org.thingsboard.msa</groupId>
... ...
... ... @@ -20,7 +20,7 @@
20 20 <modelVersion>4.0.0</modelVersion>
21 21 <parent>
22 22 <groupId>org.thingsboard</groupId>
23   - <version>2.5.2-SNAPSHOT</version>
  23 + <version>3.0.1-SNAPSHOT</version>
24 24 <artifactId>msa</artifactId>
25 25 </parent>
26 26 <groupId>org.thingsboard.msa</groupId>
... ...
... ... @@ -20,7 +20,7 @@
20 20 <modelVersion>4.0.0</modelVersion>
21 21 <parent>
22 22 <groupId>org.thingsboard</groupId>
23   - <version>2.5.2-SNAPSHOT</version>
  23 + <version>3.0.1-SNAPSHOT</version>
24 24 <artifactId>thingsboard</artifactId>
25 25 </parent>
26 26 <artifactId>msa</artifactId>
... ...
... ... @@ -20,7 +20,7 @@
20 20 <modelVersion>4.0.0</modelVersion>
21 21 <parent>
22 22 <groupId>org.thingsboard</groupId>
23   - <version>2.5.2-SNAPSHOT</version>
  23 + <version>3.0.1-SNAPSHOT</version>
24 24 <artifactId>msa</artifactId>
25 25 </parent>
26 26 <groupId>org.thingsboard.msa</groupId>
... ...
... ... @@ -20,7 +20,7 @@
20 20 <modelVersion>4.0.0</modelVersion>
21 21 <parent>
22 22 <groupId>org.thingsboard</groupId>
23   - <version>2.5.2-SNAPSHOT</version>
  23 + <version>3.0.1-SNAPSHOT</version>
24 24 <artifactId>msa</artifactId>
25 25 </parent>
26 26 <groupId>org.thingsboard.msa</groupId>
... ...
... ... @@ -20,7 +20,7 @@
20 20 <modelVersion>4.0.0</modelVersion>
21 21 <parent>
22 22 <groupId>org.thingsboard.msa</groupId>
23   - <version>2.5.2-SNAPSHOT</version>
  23 + <version>3.0.1-SNAPSHOT</version>
24 24 <artifactId>transport</artifactId>
25 25 </parent>
26 26 <groupId>org.thingsboard.msa.transport</groupId>
... ...
... ... @@ -20,7 +20,7 @@
20 20 <modelVersion>4.0.0</modelVersion>
21 21 <parent>
22 22 <groupId>org.thingsboard.msa</groupId>
23   - <version>2.5.2-SNAPSHOT</version>
  23 + <version>3.0.1-SNAPSHOT</version>
24 24 <artifactId>transport</artifactId>
25 25 </parent>
26 26 <groupId>org.thingsboard.msa.transport</groupId>
... ...
... ... @@ -20,7 +20,7 @@
20 20 <modelVersion>4.0.0</modelVersion>
21 21 <parent>
22 22 <groupId>org.thingsboard.msa</groupId>
23   - <version>2.5.2-SNAPSHOT</version>
  23 + <version>3.0.1-SNAPSHOT</version>
24 24 <artifactId>transport</artifactId>
25 25 </parent>
26 26 <groupId>org.thingsboard.msa.transport</groupId>
... ...
... ... @@ -20,7 +20,7 @@
20 20 <modelVersion>4.0.0</modelVersion>
21 21 <parent>
22 22 <groupId>org.thingsboard</groupId>
23   - <version>2.5.2-SNAPSHOT</version>
  23 + <version>3.0.1-SNAPSHOT</version>
24 24 <artifactId>msa</artifactId>
25 25 </parent>
26 26 <groupId>org.thingsboard.msa</groupId>
... ...
... ... @@ -20,7 +20,7 @@
20 20 <modelVersion>4.0.0</modelVersion>
21 21 <parent>
22 22 <groupId>org.thingsboard</groupId>
23   - <version>2.5.2-SNAPSHOT</version>
  23 + <version>3.0.1-SNAPSHOT</version>
24 24 <artifactId>msa</artifactId>
25 25 </parent>
26 26 <groupId>org.thingsboard.msa</groupId>
... ...
... ... @@ -19,11 +19,11 @@
19 19 <modelVersion>4.0.0</modelVersion>
20 20 <parent>
21 21 <groupId>org.thingsboard</groupId>
22   - <version>2.5.2-SNAPSHOT</version>
  22 + <version>3.0.1-SNAPSHOT</version>
23 23 <artifactId>thingsboard</artifactId>
24 24 </parent>
25 25 <artifactId>netty-mqtt</artifactId>
26   - <version>2.5.2-SNAPSHOT</version>
  26 + <version>3.0.1-SNAPSHOT</version>
27 27 <packaging>jar</packaging>
28 28
29 29 <name>Netty MQTT Client</name>
... ...
... ... @@ -20,7 +20,7 @@
20 20 <modelVersion>4.0.0</modelVersion>
21 21 <groupId>org.thingsboard</groupId>
22 22 <artifactId>thingsboard</artifactId>
23   - <version>2.5.2-SNAPSHOT</version>
  23 + <version>3.0.1-SNAPSHOT</version>
24 24 <packaging>pom</packaging>
25 25
26 26 <name>Thingsboard</name>
... ...
... ... @@ -20,7 +20,7 @@
20 20 <modelVersion>4.0.0</modelVersion>
21 21 <parent>
22 22 <groupId>org.thingsboard</groupId>
23   - <version>2.5.2-SNAPSHOT</version>
  23 + <version>3.0.1-SNAPSHOT</version>
24 24 <artifactId>thingsboard</artifactId>
25 25 </parent>
26 26 <artifactId>rest-client</artifactId>
... ...
... ... @@ -20,7 +20,7 @@
20 20 <modelVersion>4.0.0</modelVersion>
21 21 <parent>
22 22 <groupId>org.thingsboard</groupId>
23   - <version>2.5.2-SNAPSHOT</version>
  23 + <version>3.0.1-SNAPSHOT</version>
24 24 <artifactId>thingsboard</artifactId>
25 25 </parent>
26 26 <artifactId>rule-engine</artifactId>
... ...
... ... @@ -22,7 +22,7 @@
22 22 <modelVersion>4.0.0</modelVersion>
23 23 <parent>
24 24 <groupId>org.thingsboard</groupId>
25   - <version>2.5.2-SNAPSHOT</version>
  25 + <version>3.0.1-SNAPSHOT</version>
26 26 <artifactId>rule-engine</artifactId>
27 27 </parent>
28 28 <groupId>org.thingsboard.rule-engine</groupId>
... ...
... ... @@ -22,7 +22,7 @@
22 22 <modelVersion>4.0.0</modelVersion>
23 23 <parent>
24 24 <groupId>org.thingsboard</groupId>
25   - <version>2.5.2-SNAPSHOT</version>
  25 + <version>3.0.1-SNAPSHOT</version>
26 26 <artifactId>rule-engine</artifactId>
27 27 </parent>
28 28 <groupId>org.thingsboard.rule-engine</groupId>
... ...
... ... @@ -20,7 +20,7 @@
20 20 <modelVersion>4.0.0</modelVersion>
21 21 <parent>
22 22 <groupId>org.thingsboard</groupId>
23   - <version>2.5.2-SNAPSHOT</version>
  23 + <version>3.0.1-SNAPSHOT</version>
24 24 <artifactId>thingsboard</artifactId>
25 25 </parent>
26 26 <artifactId>tools</artifactId>
... ...
... ... @@ -20,7 +20,7 @@
20 20 <modelVersion>4.0.0</modelVersion>
21 21 <parent>
22 22 <groupId>org.thingsboard</groupId>
23   - <version>2.5.2-SNAPSHOT</version>
  23 + <version>3.0.1-SNAPSHOT</version>
24 24 <artifactId>transport</artifactId>
25 25 </parent>
26 26 <groupId>org.thingsboard.transport</groupId>
... ...
... ... @@ -20,7 +20,7 @@
20 20 <modelVersion>4.0.0</modelVersion>
21 21 <parent>
22 22 <groupId>org.thingsboard</groupId>
23   - <version>2.5.2-SNAPSHOT</version>
  23 + <version>3.0.1-SNAPSHOT</version>
24 24 <artifactId>transport</artifactId>
25 25 </parent>
26 26 <groupId>org.thingsboard.transport</groupId>
... ...
... ... @@ -20,7 +20,7 @@
20 20 <modelVersion>4.0.0</modelVersion>
21 21 <parent>
22 22 <groupId>org.thingsboard</groupId>
23   - <version>2.5.2-SNAPSHOT</version>
  23 + <version>3.0.1-SNAPSHOT</version>
24 24 <artifactId>transport</artifactId>
25 25 </parent>
26 26 <groupId>org.thingsboard.transport</groupId>
... ...
... ... @@ -20,7 +20,7 @@
20 20 <modelVersion>4.0.0</modelVersion>
21 21 <parent>
22 22 <groupId>org.thingsboard</groupId>
23   - <version>2.5.2-SNAPSHOT</version>
  23 + <version>3.0.1-SNAPSHOT</version>
24 24 <artifactId>thingsboard</artifactId>
25 25 </parent>
26 26 <artifactId>transport</artifactId>
... ...
... ... @@ -20,7 +20,7 @@
20 20 <modelVersion>4.0.0</modelVersion>
21 21 <parent>
22 22 <groupId>org.thingsboard</groupId>
23   - <version>2.5.2-SNAPSHOT</version>
  23 + <version>3.0.1-SNAPSHOT</version>
24 24 <artifactId>thingsboard</artifactId>
25 25 </parent>
26 26 <groupId>org.thingsboard</groupId>
... ...
... ... @@ -86,6 +86,11 @@ tb-widget-editor {
86 86 height: 100%;
87 87 }
88 88 }
  89 +
  90 + .container{
  91 + width: 100%;
  92 + height: 100%;
  93 + }
89 94 }
90 95
91 96 .tb-split-vertical {
... ...