diff --git a/application/pom.xml b/application/pom.xml index 8508466012..ad4dd02794 100644 --- a/application/pom.xml +++ b/application/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.2-SNAPSHOT + 3.0.1-SNAPSHOT thingsboard application diff --git a/application/src/main/java/org/thingsboard/server/service/install/CassandraTsDatabaseUpgradeService.java b/application/src/main/java/org/thingsboard/server/service/install/CassandraTsDatabaseUpgradeService.java index 58180583ef..96bf414240 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/CassandraTsDatabaseUpgradeService.java +++ b/application/src/main/java/org/thingsboard/server/service/install/CassandraTsDatabaseUpgradeService.java @@ -48,8 +48,6 @@ public class CassandraTsDatabaseUpgradeService extends AbstractCassandraDatabase } log.info("Schema updated."); break; - case "2.5.0": - break; default: throw new RuntimeException("Unable to upgrade Cassandra database, unsupported fromVersion: " + fromVersion); } diff --git a/common/actor/pom.xml b/common/actor/pom.xml new file mode 100644 index 0000000000..c0dd554f0e --- /dev/null +++ b/common/actor/pom.xml @@ -0,0 +1,75 @@ + + + 4.0.0 + + org.thingsboard + 3.0.1-SNAPSHOT + common + + org.thingsboard.common + actor + jar + + Thingsboard Actor system + https://thingsboard.io + + + UTF-8 + ${basedir}/../.. + + + + + org.thingsboard.common + util + + + org.thingsboard.common + message + + + org.slf4j + slf4j-api + + + org.slf4j + log4j-over-slf4j + + + ch.qos.logback + logback-core + + + ch.qos.logback + logback-classic + + + junit + junit + test + + + org.mockito + mockito-all + test + + + + diff --git a/common/actor/src/main/java/org/thingsboard/server/actors/DefaultTbActorSystem.java b/common/actor/src/main/java/org/thingsboard/server/actors/DefaultTbActorSystem.java new file mode 100644 index 0000000000..7d89abd3bb --- /dev/null +++ b/common/actor/src/main/java/org/thingsboard/server/actors/DefaultTbActorSystem.java @@ -0,0 +1,133 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.actors; + +import lombok.Data; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.thingsboard.common.util.ThingsBoardThreadFactory; +import org.thingsboard.server.common.msg.TbActorMsg; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +@Slf4j +@Data +public class DefaultTbActorSystem implements TbActorSystem { + + private final ConcurrentMap dispatchers = new ConcurrentHashMap<>(); + private final ConcurrentMap actors = new ConcurrentHashMap<>(); + private final ConcurrentMap actorCreationLocks = new ConcurrentHashMap<>(); + @Getter + private final TbActorSystemSettings settings; + @Getter + private final ScheduledExecutorService scheduler; + + public DefaultTbActorSystem(TbActorSystemSettings settings) { + this.settings = settings; + this.scheduler = Executors.newScheduledThreadPool(settings.getSchedulerPoolSize(), ThingsBoardThreadFactory.forName("actor-system-scheduler")); + } + + @Override + public void createDispatcher(String dispatcherId, ExecutorService executor) { + Dispatcher current = dispatchers.putIfAbsent(dispatcherId, new Dispatcher(dispatcherId, executor)); + if (current != null) { + throw new RuntimeException("Dispatcher with id [" + dispatcherId + "] is already registered!"); + } + } + + @Override + public void destroyDispatcher(String dispatcherId) { + Dispatcher dispatcher = dispatchers.remove(dispatcherId); + if (dispatcher != null) { + dispatcher.getExecutor().shutdownNow(); + } else { + throw new RuntimeException("Dispatcher with id [" + dispatcherId + "] is not registered!"); + } + } + + @Override + public TbActorId createRootActor(String dispatcherId, TbActorCreator creator) { + return createActor(dispatcherId, creator, null); + } + + @Override + public TbActorId createChildActor(String dispatcherId, TbActorCreator creator, TbActorId parent) { + return createActor(dispatcherId, creator, parent); + } + + private TbActorId createActor(String dispatcherId, TbActorCreator creator, TbActorId parent) { + Dispatcher dispatcher = dispatchers.get(dispatcherId); + if (dispatcher == null) { + log.warn("Dispatcher with id [{}] is not registered!", dispatcherId); + throw new RuntimeException("Dispatcher with id [" + dispatcherId + "] is not registered!"); + } + + TbActorId actorId = creator.createActorId(); + TbActorMailbox actorMailbox = actors.get(actorId); + if (actorMailbox != null) { + log.debug("Actor with id [{}] is already registered!", actorId); + } else { + Lock actorCreationLock = actorCreationLocks.computeIfAbsent(actorId, id -> new ReentrantLock()); + actorCreationLock.lock(); + try { + actorMailbox = actors.get(actorId); + if (actorMailbox == null) { + log.debug("Creating actor with id [{}]!", actorId); + TbActor actor = creator.createActor(); + TbActorMailbox mailbox = new TbActorMailbox(this, settings, actorId, parent, actor, dispatcher); + actors.put(actorId, mailbox); + mailbox.initActor(); + } else { + log.debug("Actor with id [{}] is already registered!", actorId); + } + } finally { + actorCreationLock.unlock(); + actorCreationLocks.remove(actorId); + } + } + return actorId; + } + + @Override + public void tell(TbActorId target, TbActorMsg actorMsg) { + TbActorMailbox mailbox = actors.get(target); + if (mailbox == null) { + throw new TbActorNotRegisteredException(target, "Actor with id [" + target + "] is not registered!"); + } + mailbox.enqueue(actorMsg); + } + + @Override + public void stop(TbActorId actorId) { + TbActorMailbox mailbox = actors.remove(actorId); + if (mailbox != null) { + mailbox.destroy(); + } + } + + @Override + public void stop() { + dispatchers.values().forEach(dispatcher -> dispatcher.getExecutor().shutdownNow()); + actors.clear(); + } + +} diff --git a/common/actor/src/main/java/org/thingsboard/server/actors/Dispatcher.java b/common/actor/src/main/java/org/thingsboard/server/actors/Dispatcher.java new file mode 100644 index 0000000000..bd02e74603 --- /dev/null +++ b/common/actor/src/main/java/org/thingsboard/server/actors/Dispatcher.java @@ -0,0 +1,28 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.actors; + +import lombok.Data; + +import java.util.concurrent.ExecutorService; + +@Data +class Dispatcher { + + private final String dispatcherId; + private final ExecutorService executor; + +} diff --git a/common/actor/src/main/java/org/thingsboard/server/actors/InitFailureStrategy.java b/common/actor/src/main/java/org/thingsboard/server/actors/InitFailureStrategy.java new file mode 100644 index 0000000000..37d0379bb0 --- /dev/null +++ b/common/actor/src/main/java/org/thingsboard/server/actors/InitFailureStrategy.java @@ -0,0 +1,45 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.actors; + +import lombok.Getter; +import lombok.ToString; + +@ToString +public class InitFailureStrategy { + + @Getter + private boolean stop; + @Getter + private long retryDelay; + + private InitFailureStrategy(boolean stop, long retryDelay) { + this.stop = stop; + this.retryDelay = retryDelay; + } + + public static InitFailureStrategy retryImmediately() { + return new InitFailureStrategy(false, 0); + } + + public static InitFailureStrategy retryWithDelay(long ms) { + return new InitFailureStrategy(false, ms); + } + + public static InitFailureStrategy stop() { + return new InitFailureStrategy(true, 0); + } +} diff --git a/common/actor/src/main/java/org/thingsboard/server/actors/ProcessFailureStrategy.java b/common/actor/src/main/java/org/thingsboard/server/actors/ProcessFailureStrategy.java new file mode 100644 index 0000000000..7448ba964b --- /dev/null +++ b/common/actor/src/main/java/org/thingsboard/server/actors/ProcessFailureStrategy.java @@ -0,0 +1,38 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.actors; + +import lombok.Getter; +import lombok.ToString; + +@ToString +public class ProcessFailureStrategy { + + @Getter + private boolean stop; + + private ProcessFailureStrategy(boolean stop) { + this.stop = stop; + } + + public static ProcessFailureStrategy stop() { + return new ProcessFailureStrategy(true); + } + + public static ProcessFailureStrategy resume() { + return new ProcessFailureStrategy(false); + } +} diff --git a/common/actor/src/main/java/org/thingsboard/server/actors/TbActor.java b/common/actor/src/main/java/org/thingsboard/server/actors/TbActor.java new file mode 100644 index 0000000000..55419582bc --- /dev/null +++ b/common/actor/src/main/java/org/thingsboard/server/actors/TbActor.java @@ -0,0 +1,39 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.actors; + +import org.thingsboard.server.common.msg.TbActorMsg; + +public interface TbActor { + + void init(); + + boolean process(TbActorCtx ctx, TbActorMsg msg); + + void destroy(); + + default InitFailureStrategy onInitFailure(int attempt, Throwable t) { + return InitFailureStrategy.retryWithDelay(5000); + } + + default ProcessFailureStrategy onProcessFailure(Throwable t) { + if (t instanceof Error) { + return ProcessFailureStrategy.stop(); + } else { + return ProcessFailureStrategy.resume(); + } + } +} diff --git a/common/actor/src/main/java/org/thingsboard/server/actors/TbActorCreator.java b/common/actor/src/main/java/org/thingsboard/server/actors/TbActorCreator.java new file mode 100644 index 0000000000..f62bf17d53 --- /dev/null +++ b/common/actor/src/main/java/org/thingsboard/server/actors/TbActorCreator.java @@ -0,0 +1,24 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.actors; + +public interface TbActorCreator { + + TbActorId createActorId(); + + TbActor createActor(); + +} diff --git a/common/actor/src/main/java/org/thingsboard/server/actors/TbActorCtx.java b/common/actor/src/main/java/org/thingsboard/server/actors/TbActorCtx.java new file mode 100644 index 0000000000..7dd90c3478 --- /dev/null +++ b/common/actor/src/main/java/org/thingsboard/server/actors/TbActorCtx.java @@ -0,0 +1,28 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.actors; + +import org.thingsboard.server.common.msg.TbActorMsg; + +public interface TbActorCtx { + + TbActorId getSelf(); + + TbActorId getParent(); + + void tell(TbActorId target, TbActorMsg actorMsg); + +} diff --git a/common/actor/src/main/java/org/thingsboard/server/actors/TbActorId.java b/common/actor/src/main/java/org/thingsboard/server/actors/TbActorId.java new file mode 100644 index 0000000000..91f4363348 --- /dev/null +++ b/common/actor/src/main/java/org/thingsboard/server/actors/TbActorId.java @@ -0,0 +1,47 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.actors; + +import org.thingsboard.server.common.data.id.EntityId; + +import java.util.Objects; + +public class TbActorId { + + private final EntityId entityId; + + public TbActorId(EntityId entityId) { + this.entityId = entityId; + } + + @Override + public String toString() { + return entityId.toString(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + TbActorId actorId = (TbActorId) o; + return entityId.equals(actorId.entityId); + } + + @Override + public int hashCode() { + return Objects.hash(entityId); + } +} diff --git a/common/actor/src/main/java/org/thingsboard/server/actors/TbActorMailbox.java b/common/actor/src/main/java/org/thingsboard/server/actors/TbActorMailbox.java new file mode 100644 index 0000000000..cbd3f3903f --- /dev/null +++ b/common/actor/src/main/java/org/thingsboard/server/actors/TbActorMailbox.java @@ -0,0 +1,144 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.actors; + +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.thingsboard.server.common.msg.TbActorMsg; + +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + +@Slf4j +@Data +public final class TbActorMailbox implements TbActorCtx { + private static final boolean FREE = false; + private static final boolean BUSY = true; + + private static final boolean NOT_READY = false; + private static final boolean READY = true; + + private final TbActorSystem system; + private final TbActorSystemSettings settings; + private final TbActorId selfId; + private final TbActorId parentId; + private final TbActor actor; + private final Dispatcher dispatcher; + private final ConcurrentLinkedQueue msgs = new ConcurrentLinkedQueue<>(); + private final AtomicBoolean busy = new AtomicBoolean(FREE); + private final AtomicBoolean ready = new AtomicBoolean(NOT_READY); + private final AtomicBoolean destroyInProgress = new AtomicBoolean(); + + public void initActor() { + dispatcher.getExecutor().execute(() -> tryInit(1)); + } + + private void tryInit(int attempt) { + try { + log.debug("[{}] Trying to init actor, attempt: {}", selfId, attempt); + if (!destroyInProgress.get()) { + actor.init(); + if (!destroyInProgress.get()) { + ready.set(READY); + tryProcessQueue(false); + } + } + } catch (Throwable t) { + log.debug("[{}] Failed to init actor, attempt: {}", selfId, attempt, t); + int attemptIdx = attempt + 1; + InitFailureStrategy strategy = actor.onInitFailure(attempt, t); + if (strategy.isStop() || (settings.getMaxActorInitAttempts() > 0 && attemptIdx > settings.getMaxActorInitAttempts())) { + log.info("[{}] Failed to init actor, attempt {}, going to stop attempts.", selfId, attempt, t); + system.stop(selfId); + } else if (strategy.getRetryDelay() > 0) { + log.info("[{}] Failed to init actor, attempt {}, going to retry in attempts in {}ms", selfId, attempt, strategy.getRetryDelay(), t); + system.getScheduler().schedule(() -> dispatcher.getExecutor().execute(() -> tryInit(attemptIdx)), strategy.getRetryDelay(), TimeUnit.MILLISECONDS); + } else { + log.info("[{}] Failed to init actor, attempt {}, going to retry immediately", selfId, attempt, t); + dispatcher.getExecutor().execute(() -> tryInit(attemptIdx)); + } + } + } + + public void enqueue(TbActorMsg msg) { + msgs.add(msg); + tryProcessQueue(true); + } + + private void tryProcessQueue(boolean newMsg) { + if (ready.get() == READY && (newMsg || !msgs.isEmpty()) && busy.compareAndSet(FREE, BUSY)) { + dispatcher.getExecutor().execute(this::processMailbox); + } else { + log.trace("[{}] MessageBox is busy, new msg: {}", selfId, newMsg); + } + } + + private void processMailbox() { + boolean noMoreElements = false; + for (int i = 0; i < settings.getActorThroughput(); i++) { + TbActorMsg msg = msgs.poll(); + if (msg != null) { + try { + log.debug("[{}] Going to process message: {}", selfId, msg); + actor.process(this, msg); + } catch (Throwable t) { + log.debug("[{}] Failed to process message: {}", selfId, msg, t); + ProcessFailureStrategy strategy = actor.onProcessFailure(t); + if (strategy.isStop()) { + system.stop(selfId); + } + } + } else { + noMoreElements = true; + break; + } + } + if (noMoreElements) { + busy.set(FREE); + dispatcher.getExecutor().execute(() -> tryProcessQueue(false)); + } else { + dispatcher.getExecutor().execute(this::processMailbox); + } + } + + @Override + public TbActorId getSelf() { + return selfId; + } + + @Override + public TbActorId getParent() { + return parentId; + } + + @Override + public void tell(TbActorId target, TbActorMsg actorMsg) { + system.tell(target, actorMsg); + } + + public void destroy() { + destroyInProgress.set(true); + dispatcher.getExecutor().execute(() -> { + try { + ready.set(NOT_READY); + actor.destroy(); + } catch (Throwable t) { + log.warn("[{}] Failed to destroy actor: {}", selfId, t); + } + }); + } +} diff --git a/common/actor/src/main/java/org/thingsboard/server/actors/TbActorNotRegisteredException.java b/common/actor/src/main/java/org/thingsboard/server/actors/TbActorNotRegisteredException.java new file mode 100644 index 0000000000..1f30b29c1b --- /dev/null +++ b/common/actor/src/main/java/org/thingsboard/server/actors/TbActorNotRegisteredException.java @@ -0,0 +1,29 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.actors; + +import lombok.Getter; + +public class TbActorNotRegisteredException extends RuntimeException { + + @Getter + private TbActorId target; + + public TbActorNotRegisteredException(TbActorId target, String message) { + super(message); + this.target = target; + } +} diff --git a/common/actor/src/main/java/org/thingsboard/server/actors/TbActorSystem.java b/common/actor/src/main/java/org/thingsboard/server/actors/TbActorSystem.java new file mode 100644 index 0000000000..f2f08fb06a --- /dev/null +++ b/common/actor/src/main/java/org/thingsboard/server/actors/TbActorSystem.java @@ -0,0 +1,41 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.actors; + +import org.thingsboard.server.common.msg.TbActorMsg; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.ScheduledExecutorService; + +public interface TbActorSystem { + + ScheduledExecutorService getScheduler(); + + void createDispatcher(String dispatcherId, ExecutorService executor); + + void destroyDispatcher(String dispatcherId); + + TbActorId createRootActor(String dispatcherId, TbActorCreator creator); + + TbActorId createChildActor(String dispatcherId, TbActorCreator creator, TbActorId parent); + + void tell(TbActorId target, TbActorMsg actorMsg); + + void stop(TbActorId actorId); + + void stop(); + +} diff --git a/common/actor/src/main/java/org/thingsboard/server/actors/TbActorSystemSettings.java b/common/actor/src/main/java/org/thingsboard/server/actors/TbActorSystemSettings.java new file mode 100644 index 0000000000..51798611f2 --- /dev/null +++ b/common/actor/src/main/java/org/thingsboard/server/actors/TbActorSystemSettings.java @@ -0,0 +1,27 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.actors; + +import lombok.Data; + +@Data +public class TbActorSystemSettings { + + private final int actorThroughput; + private final int schedulerPoolSize; + private final int maxActorInitAttempts; + +} diff --git a/common/actor/src/test/java/org/thingsboard/server/actors/ActorSystemTest.java b/common/actor/src/test/java/org/thingsboard/server/actors/ActorSystemTest.java new file mode 100644 index 0000000000..2f7a786fe3 --- /dev/null +++ b/common/actor/src/test/java/org/thingsboard/server/actors/ActorSystemTest.java @@ -0,0 +1,178 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.actors; + +import lombok.extern.slf4j.Slf4j; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.runners.MockitoJUnitRunner; +import org.thingsboard.server.common.data.id.DeviceId; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.UUID; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; + +@Slf4j +@RunWith(MockitoJUnitRunner.class) +public class ActorSystemTest { + + public static final String ROOT_DISPATCHER = "root-dispatcher"; + private static final int _1M = 1024 * 1024; + + private TbActorSystem actorSystem; + private ExecutorService submitPool; + + @Before + public void initActorSystem() { + int cores = Runtime.getRuntime().availableProcessors(); + int parallelism = Math.max(1, cores / 2); + TbActorSystemSettings settings = new TbActorSystemSettings(5, parallelism, 42); + actorSystem = new DefaultTbActorSystem(settings); + submitPool = Executors.newWorkStealingPool(parallelism); + actorSystem.createDispatcher(ROOT_DISPATCHER, Executors.newWorkStealingPool(parallelism)); + } + + @After + public void shutdownActorSystem() { + actorSystem.stop(); + submitPool.shutdownNow(); + } + + @Test + public void test10actorsAnd1MMessages() throws InterruptedException { + testActorsAndMessages(10, _1M); + } + + @Test + public void test1MActorsAnd10Messages() throws InterruptedException { + testActorsAndMessages(_1M, 10); + } + + @Test + public void test1KActorsAnd1KMessages() throws InterruptedException { + testActorsAndMessages(1000, 1000); + } + + @Test + public void testNoMessagesAfterDestroy() throws InterruptedException { + ActorTestCtx testCtx1 = getActorTestCtx(1); + ActorTestCtx testCtx2 = getActorTestCtx(1); + + TbActorId actorId1 = actorSystem.createRootActor(ROOT_DISPATCHER, new SlowInitActor.SlowInitActorCreator( + new TbActorId(new DeviceId(UUID.randomUUID())), testCtx1)); + TbActorId actorId2 = actorSystem.createRootActor(ROOT_DISPATCHER, new SlowInitActor.SlowInitActorCreator( + new TbActorId(new DeviceId(UUID.randomUUID())), testCtx2)); + + actorSystem.tell(actorId1, new IntTbActorMsg(42)); + actorSystem.tell(actorId2, new IntTbActorMsg(42)); + actorSystem.stop(actorId1); + + Assert.assertTrue(testCtx2.getLatch().await(1, TimeUnit.SECONDS)); + Assert.assertFalse(testCtx1.getLatch().await(2, TimeUnit.SECONDS)); + } + + @Test + public void testOneActorCreated() throws InterruptedException { + ActorTestCtx testCtx1 = getActorTestCtx(1); + ActorTestCtx testCtx2 = getActorTestCtx(1); + TbActorId actorId = new TbActorId(new DeviceId(UUID.randomUUID())); + submitPool.submit(() -> actorSystem.createRootActor(ROOT_DISPATCHER, new SlowCreateActor.SlowCreateActorCreator(actorId, testCtx1))); + submitPool.submit(() -> actorSystem.createRootActor(ROOT_DISPATCHER, new SlowCreateActor.SlowCreateActorCreator(actorId, testCtx2))); + + Thread.sleep(1000); + actorSystem.tell(actorId, new IntTbActorMsg(42)); + + Assert.assertTrue(testCtx1.getLatch().await(3, TimeUnit.SECONDS)); + Assert.assertFalse(testCtx2.getLatch().await(3, TimeUnit.SECONDS)); + } + + @Test + public void testActorCreatorCalledOnce() throws InterruptedException { + ActorTestCtx testCtx = getActorTestCtx(1); + TbActorId actorId = new TbActorId(new DeviceId(UUID.randomUUID())); + for(int i =0; i < 1000; i++) { + submitPool.submit(() -> actorSystem.createRootActor(ROOT_DISPATCHER, new SlowCreateActor.SlowCreateActorCreator(actorId, testCtx))); + } + Thread.sleep(1000); + actorSystem.tell(actorId, new IntTbActorMsg(42)); + + Assert.assertTrue(testCtx.getLatch().await(1, TimeUnit.SECONDS)); + //One for creation and one for message + Assert.assertEquals(2, testCtx.getInvocationCount().get()); + } + + + public void testActorsAndMessages(int actorsCount, int msgNumber) throws InterruptedException { + Random random = new Random(); + int[] randomIntegers = new int[msgNumber]; + long sumTmp = 0; + for (int i = 0; i < msgNumber; i++) { + int tmp = random.nextInt(); + randomIntegers[i] = tmp; + sumTmp += tmp; + } + long expected = sumTmp; + + List testCtxes = new ArrayList<>(); + + List actorIds = new ArrayList<>(); + for (int actorIdx = 0; actorIdx < actorsCount; actorIdx++) { + ActorTestCtx testCtx = getActorTestCtx(msgNumber); + + actorIds.add(actorSystem.createRootActor(ROOT_DISPATCHER, new TestRootActor.TestRootActorCreator( + new TbActorId(new DeviceId(UUID.randomUUID())), testCtx))); + testCtxes.add(testCtx); + } + + long start = System.nanoTime(); + + for (int i = 0; i < msgNumber; i++) { + int tmp = randomIntegers[i]; + submitPool.execute(() -> actorIds.forEach(actorId -> actorSystem.tell(actorId, new IntTbActorMsg(tmp)))); + } + log.info("Submitted all messages"); + + testCtxes.forEach(ctx -> { + try { + Assert.assertTrue(ctx.getLatch().await(1, TimeUnit.MINUTES)); + Assert.assertEquals(expected, ctx.getActual().get()); + Assert.assertEquals(msgNumber, ctx.getInvocationCount().get()); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }); + + long duration = System.nanoTime() - start; + log.info("Time spend: {}ns ({} ms)", duration, TimeUnit.NANOSECONDS.toMillis(duration)); + } + + private ActorTestCtx getActorTestCtx(int i) { + CountDownLatch countDownLatch = new CountDownLatch(1); + AtomicLong actual = new AtomicLong(); + AtomicInteger invocations = new AtomicInteger(); + return new ActorTestCtx(countDownLatch, invocations, i, actual); + } +} diff --git a/common/actor/src/test/java/org/thingsboard/server/actors/ActorTestCtx.java b/common/actor/src/test/java/org/thingsboard/server/actors/ActorTestCtx.java new file mode 100644 index 0000000000..7e898f51ac --- /dev/null +++ b/common/actor/src/test/java/org/thingsboard/server/actors/ActorTestCtx.java @@ -0,0 +1,31 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.actors; + +import lombok.Data; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; + +@Data +public class ActorTestCtx { + + private final CountDownLatch latch; + private final AtomicInteger invocationCount; + private final int expectedInvocationCount; + private final AtomicLong actual; +} diff --git a/common/actor/src/test/java/org/thingsboard/server/actors/IntTbActorMsg.java b/common/actor/src/test/java/org/thingsboard/server/actors/IntTbActorMsg.java new file mode 100644 index 0000000000..b3591d9642 --- /dev/null +++ b/common/actor/src/test/java/org/thingsboard/server/actors/IntTbActorMsg.java @@ -0,0 +1,35 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.actors; + +import lombok.Getter; +import org.thingsboard.server.common.msg.MsgType; +import org.thingsboard.server.common.msg.TbActorMsg; + +public class IntTbActorMsg implements TbActorMsg { + + @Getter + private final int value; + + public IntTbActorMsg(int value) { + this.value = value; + } + + @Override + public MsgType getMsgType() { + return MsgType.QUEUE_TO_RULE_ENGINE_MSG; + } +} diff --git a/common/actor/src/test/java/org/thingsboard/server/actors/SlowCreateActor.java b/common/actor/src/test/java/org/thingsboard/server/actors/SlowCreateActor.java new file mode 100644 index 0000000000..af1dfa6b45 --- /dev/null +++ b/common/actor/src/test/java/org/thingsboard/server/actors/SlowCreateActor.java @@ -0,0 +1,53 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.actors; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class SlowCreateActor extends TestRootActor { + + public SlowCreateActor(TbActorId actorId, ActorTestCtx testCtx) { + super(actorId, testCtx); + try { + Thread.sleep(500); + } catch (InterruptedException e) { + e.printStackTrace(); + } + testCtx.getInvocationCount().incrementAndGet(); + } + + public static class SlowCreateActorCreator implements TbActorCreator { + + private final TbActorId actorId; + private final ActorTestCtx testCtx; + + public SlowCreateActorCreator(TbActorId actorId, ActorTestCtx testCtx) { + this.actorId = actorId; + this.testCtx = testCtx; + } + + @Override + public TbActorId createActorId() { + return actorId; + } + + @Override + public TbActor createActor() { + return new SlowCreateActor(actorId, testCtx); + } + } +} diff --git a/common/actor/src/test/java/org/thingsboard/server/actors/SlowInitActor.java b/common/actor/src/test/java/org/thingsboard/server/actors/SlowInitActor.java new file mode 100644 index 0000000000..4cb59be058 --- /dev/null +++ b/common/actor/src/test/java/org/thingsboard/server/actors/SlowInitActor.java @@ -0,0 +1,57 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.actors; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class SlowInitActor extends TestRootActor { + + public SlowInitActor(TbActorId actorId, ActorTestCtx testCtx) { + super(actorId, testCtx); + } + + @Override + public void init() { + try { + Thread.sleep(500); + } catch (InterruptedException e) { + e.printStackTrace(); + } + super.init(); + } + + public static class SlowInitActorCreator implements TbActorCreator { + + private final TbActorId actorId; + private final ActorTestCtx testCtx; + + public SlowInitActorCreator(TbActorId actorId, ActorTestCtx testCtx) { + this.actorId = actorId; + this.testCtx = testCtx; + } + + @Override + public TbActorId createActorId() { + return actorId; + } + + @Override + public TbActor createActor() { + return new SlowInitActor(actorId, testCtx); + } + } +} diff --git a/common/actor/src/test/java/org/thingsboard/server/actors/TestRootActor.java b/common/actor/src/test/java/org/thingsboard/server/actors/TestRootActor.java new file mode 100644 index 0000000000..54bf044aa8 --- /dev/null +++ b/common/actor/src/test/java/org/thingsboard/server/actors/TestRootActor.java @@ -0,0 +1,84 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.actors; + +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.thingsboard.server.common.msg.TbActorMsg; + +@Slf4j +public class TestRootActor implements TbActor { + + @Getter + private final TbActorId actorId; + @Getter + private final ActorTestCtx testCtx; + + private boolean initialized; + private long sum; + private int count; + + public TestRootActor(TbActorId actorId, ActorTestCtx testCtx) { + this.actorId = actorId; + this.testCtx = testCtx; + } + + @Override + public void init() { + initialized = true; + } + + @Override + public boolean process(TbActorCtx ctx, TbActorMsg msg) { + if (initialized) { + int value = ((IntTbActorMsg) msg).getValue(); + sum += value; + count += 1; + if (count == testCtx.getExpectedInvocationCount()) { + testCtx.getActual().set(sum); + testCtx.getInvocationCount().addAndGet(count); + testCtx.getLatch().countDown(); + } + } + return true; + } + + @Override + public void destroy() { + + } + + public static class TestRootActorCreator implements TbActorCreator { + + private final TbActorId actorId; + private final ActorTestCtx testCtx; + + public TestRootActorCreator(TbActorId actorId, ActorTestCtx testCtx) { + this.actorId = actorId; + this.testCtx = testCtx; + } + + @Override + public TbActorId createActorId() { + return actorId; + } + + @Override + public TbActor createActor() { + return new TestRootActor(actorId, testCtx); + } + } +} diff --git a/common/actor/src/test/resources/logback.xml b/common/actor/src/test/resources/logback.xml new file mode 100644 index 0000000000..52f2a77588 --- /dev/null +++ b/common/actor/src/test/resources/logback.xml @@ -0,0 +1,14 @@ + + + + + + %d{ISO8601} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + diff --git a/common/dao-api/pom.xml b/common/dao-api/pom.xml index d9692f0a90..4bde73d29b 100644 --- a/common/dao-api/pom.xml +++ b/common/dao-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.2-SNAPSHOT + 3.0.1-SNAPSHOT common org.thingsboard.common diff --git a/common/data/pom.xml b/common/data/pom.xml index e529157f47..51fa32c2bb 100644 --- a/common/data/pom.xml +++ b/common/data/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.2-SNAPSHOT + 3.0.1-SNAPSHOT common org.thingsboard.common diff --git a/common/message/pom.xml b/common/message/pom.xml index 54df1085b8..4cc3473dda 100644 --- a/common/message/pom.xml +++ b/common/message/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.2-SNAPSHOT + 3.0.1-SNAPSHOT common org.thingsboard.common diff --git a/common/pom.xml b/common/pom.xml index 4eeebbb8ac..cc2e2a47e2 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.2-SNAPSHOT + 3.0.1-SNAPSHOT thingsboard common @@ -37,6 +37,7 @@ data util message + actor queue transport dao-api diff --git a/common/queue/pom.xml b/common/queue/pom.xml index 8376d30484..eb8cb4da45 100644 --- a/common/queue/pom.xml +++ b/common/queue/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.2-SNAPSHOT + 3.0.1-SNAPSHOT common org.thingsboard.common diff --git a/common/transport/coap/pom.xml b/common/transport/coap/pom.xml index cdc4978892..d1df792d33 100644 --- a/common/transport/coap/pom.xml +++ b/common/transport/coap/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 2.5.2-SNAPSHOT + 3.0.1-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/transport/http/pom.xml b/common/transport/http/pom.xml index 5f715a7a27..a9501d17ca 100644 --- a/common/transport/http/pom.xml +++ b/common/transport/http/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 2.5.2-SNAPSHOT + 3.0.1-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/transport/mqtt/pom.xml b/common/transport/mqtt/pom.xml index 3fd09077f4..b14205f2c1 100644 --- a/common/transport/mqtt/pom.xml +++ b/common/transport/mqtt/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 2.5.2-SNAPSHOT + 3.0.1-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/transport/pom.xml b/common/transport/pom.xml index 9f10a8959d..fd9b183f90 100644 --- a/common/transport/pom.xml +++ b/common/transport/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.2-SNAPSHOT + 3.0.1-SNAPSHOT common org.thingsboard.common diff --git a/common/transport/transport-api/pom.xml b/common/transport/transport-api/pom.xml index a836a98ebb..b2d1d33139 100644 --- a/common/transport/transport-api/pom.xml +++ b/common/transport/transport-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 2.5.2-SNAPSHOT + 3.0.1-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/util/pom.xml b/common/util/pom.xml index d32c56bc1b..49efd021be 100644 --- a/common/util/pom.xml +++ b/common/util/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.2-SNAPSHOT + 3.0.1-SNAPSHOT common org.thingsboard.common diff --git a/dao/pom.xml b/dao/pom.xml index 6413a2472a..fc991101ab 100644 --- a/dao/pom.xml +++ b/dao/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.2-SNAPSHOT + 3.0.1-SNAPSHOT thingsboard dao diff --git a/k8s/README.md b/k8s/README.md index ce1df8ec05..9d91c8c0e8 100644 --- a/k8s/README.md +++ b/k8s/README.md @@ -4,15 +4,15 @@ This folder containing scripts and Kubernetes resources configurations to run Th ## Prerequisites -ThingsBoard Microservices are running on Kubernetes cluster. +ThingsBoard Microservices run on the Kubernetes cluster. You need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. -If you do not already have a cluster, you can create one by using [Minikube](https://kubernetes.io/docs/setup/minikube), +If you do not have a cluster already, you can create one by using [Minikube](https://kubernetes.io/docs/setup/minikube), or you can choose any other available [Kubernetes cluster deployment solutions](https://kubernetes.io/docs/setup/pick-right-solution/). ### Enable ingress addon -By default ingress addon is disable in the Minikube, and available only in cluster providers. -To enable ingress, please execute next command: +By default ingress addon is disabled in the Minikube, and available only in cluster providers. +To enable ingress, please execute the following command: ` $ minikube addons enable ingress @@ -21,21 +21,21 @@ $ minikube addons enable ingress ## Installation Before performing initial installation you can configure the type of database to be used with ThingsBoard and the type of deployment. -In order to set database type change the value of `DATABASE` variable in `.env` file to one of the following: +To set database type change the value of `DATABASE` variable in `.env` file to one of the following: - `postgres` - use PostgreSQL database; - `hybrid` - use PostgreSQL for entities database and Cassandra for timeseries database; **NOTE**: According to the database type corresponding kubernetes resources will be deployed (see `postgres.yml`, `cassandra.yml` for details). -In order to set deployment type change the value of `DEPLOYMENT_TYPE` variable in `.env` file to one of the following: +To set deployment type change the value of `DEPLOYMENT_TYPE` variable in `.env` file to one of the following: -- `basic` - start up with single instance of Zookeeper, Kafka and Redis; -- `high-availability` - start up with Zookeeper, Kafka and Redis in cluster modes; +- `basic` - startup with a single instance of Zookeeper, Kafka and Redis; +- `high-availability` - startup with Zookeeper, Kafka, and Redis in cluster modes; -**NOTE**: According to the deployment type corresponding kubernetes resources will be deployed (see content of the directories `./basic` and `./high-availability` for details). +**NOTE**: According to the deployment type corresponding kubernetes resources will be deployed (see the content of the directories `./basic` and `./high-availability` for details). -Execute the following command to run installation: +Execute the following command to run the installation: ` $ ./k8s-install-tb.sh --loadDemo @@ -47,7 +47,7 @@ Where: ## Running -Execute the following command to deploy thirdparty resources: +Execute the following command to deploy third-party resources: ` $ ./k8s-deploy-thirdparty.sh @@ -61,8 +61,8 @@ Execute the following command to deploy resources: $ ./k8s-deploy-resources.sh ` -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`). -You should see ThingsBoard login page. +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`). +You should see the ThingsBoard login page. Use the following default credentials: @@ -73,16 +73,16 @@ If you installed DataBase with demo data (using `--loadDemo` flag) you can also - **Tenant Administrator**: tenant@thingsboard.org / tenant - **Customer User**: customer@thingsboard.org / customer -In case of any issues you can examine service logs for errors. +In case of any issues, you can examine service logs for errors. For example to see ThingsBoard node logs execute the following commands: -1) Get list of the running tb-node pods: +1) Get the list of the running tb-node pods: ` $ kubectl get pods -l app=tb-node ` -2) Fetch logs of tb-node pod: +2) Fetch logs of the tb-node pod: ` $ kubectl logs -f [tb-node-pod-name] @@ -103,7 +103,7 @@ Execute the following command to delete all ThingsBoard microservices: $ ./k8s-delete-resources.sh ` -Execute the following command to delete all thirdparty microservices: +Execute the following command to delete all third-party microservices: ` $ ./k8s-delete-thirdparty.sh diff --git a/msa/black-box-tests/pom.xml b/msa/black-box-tests/pom.xml index f60afff08d..73aa03968d 100644 --- a/msa/black-box-tests/pom.xml +++ b/msa/black-box-tests/pom.xml @@ -21,7 +21,7 @@ org.thingsboard - 2.5.2-SNAPSHOT + 3.0.1-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/js-executor/pom.xml b/msa/js-executor/pom.xml index 16a0bb7570..a3d0bb77cc 100644 --- a/msa/js-executor/pom.xml +++ b/msa/js-executor/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.2-SNAPSHOT + 3.0.1-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/pom.xml b/msa/pom.xml index e37ecf0af8..68d7ca52e9 100644 --- a/msa/pom.xml +++ b/msa/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.2-SNAPSHOT + 3.0.1-SNAPSHOT thingsboard msa diff --git a/msa/tb-node/pom.xml b/msa/tb-node/pom.xml index d1a67a891a..10a3c9533b 100644 --- a/msa/tb-node/pom.xml +++ b/msa/tb-node/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.2-SNAPSHOT + 3.0.1-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/tb/pom.xml b/msa/tb/pom.xml index 3a48db9ae3..8dcbaebec2 100644 --- a/msa/tb/pom.xml +++ b/msa/tb/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.2-SNAPSHOT + 3.0.1-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/transport/coap/pom.xml b/msa/transport/coap/pom.xml index c611578819..efcf2f8723 100644 --- a/msa/transport/coap/pom.xml +++ b/msa/transport/coap/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.msa - 2.5.2-SNAPSHOT + 3.0.1-SNAPSHOT transport org.thingsboard.msa.transport diff --git a/msa/transport/http/pom.xml b/msa/transport/http/pom.xml index 561106a50e..7b6a5bda10 100644 --- a/msa/transport/http/pom.xml +++ b/msa/transport/http/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.msa - 2.5.2-SNAPSHOT + 3.0.1-SNAPSHOT transport org.thingsboard.msa.transport diff --git a/msa/transport/mqtt/pom.xml b/msa/transport/mqtt/pom.xml index 9412dd422e..e113402b77 100644 --- a/msa/transport/mqtt/pom.xml +++ b/msa/transport/mqtt/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.msa - 2.5.2-SNAPSHOT + 3.0.1-SNAPSHOT transport org.thingsboard.msa.transport diff --git a/msa/transport/pom.xml b/msa/transport/pom.xml index cc2b196f2c..1137506fa0 100644 --- a/msa/transport/pom.xml +++ b/msa/transport/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.2-SNAPSHOT + 3.0.1-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/web-ui/pom.xml b/msa/web-ui/pom.xml index 119ff7b24e..e12e26c551 100644 --- a/msa/web-ui/pom.xml +++ b/msa/web-ui/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.2-SNAPSHOT + 3.0.1-SNAPSHOT msa org.thingsboard.msa diff --git a/netty-mqtt/pom.xml b/netty-mqtt/pom.xml index 00f5a9ef4f..b3de2f5fd7 100644 --- a/netty-mqtt/pom.xml +++ b/netty-mqtt/pom.xml @@ -19,11 +19,11 @@ 4.0.0 org.thingsboard - 2.5.2-SNAPSHOT + 3.0.1-SNAPSHOT thingsboard netty-mqtt - 2.5.2-SNAPSHOT + 3.0.1-SNAPSHOT jar Netty MQTT Client diff --git a/pom.xml b/pom.xml index 2ae25dbfb9..2b4471f493 100755 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard thingsboard - 2.5.2-SNAPSHOT + 3.0.1-SNAPSHOT pom Thingsboard diff --git a/rest-client/pom.xml b/rest-client/pom.xml index b2a9ecd668..331a5c5926 100644 --- a/rest-client/pom.xml +++ b/rest-client/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.2-SNAPSHOT + 3.0.1-SNAPSHOT thingsboard rest-client diff --git a/rule-engine/pom.xml b/rule-engine/pom.xml index c7a1e8eb79..410c339153 100644 --- a/rule-engine/pom.xml +++ b/rule-engine/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.2-SNAPSHOT + 3.0.1-SNAPSHOT thingsboard rule-engine diff --git a/rule-engine/rule-engine-api/pom.xml b/rule-engine/rule-engine-api/pom.xml index 74b546b930..5acf0332b9 100644 --- a/rule-engine/rule-engine-api/pom.xml +++ b/rule-engine/rule-engine-api/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 2.5.2-SNAPSHOT + 3.0.1-SNAPSHOT rule-engine org.thingsboard.rule-engine diff --git a/rule-engine/rule-engine-components/pom.xml b/rule-engine/rule-engine-components/pom.xml index 11b1860022..621dcaa1da 100644 --- a/rule-engine/rule-engine-components/pom.xml +++ b/rule-engine/rule-engine-components/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 2.5.2-SNAPSHOT + 3.0.1-SNAPSHOT rule-engine org.thingsboard.rule-engine diff --git a/tools/pom.xml b/tools/pom.xml index 464610edfd..264221797e 100644 --- a/tools/pom.xml +++ b/tools/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.2-SNAPSHOT + 3.0.1-SNAPSHOT thingsboard tools diff --git a/transport/coap/pom.xml b/transport/coap/pom.xml index a4f24ed547..776a4d938d 100644 --- a/transport/coap/pom.xml +++ b/transport/coap/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.2-SNAPSHOT + 3.0.1-SNAPSHOT transport org.thingsboard.transport diff --git a/transport/http/pom.xml b/transport/http/pom.xml index 86e952822a..f769f0185e 100644 --- a/transport/http/pom.xml +++ b/transport/http/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.2-SNAPSHOT + 3.0.1-SNAPSHOT transport org.thingsboard.transport diff --git a/transport/mqtt/pom.xml b/transport/mqtt/pom.xml index 5caea325da..4975694c34 100644 --- a/transport/mqtt/pom.xml +++ b/transport/mqtt/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.2-SNAPSHOT + 3.0.1-SNAPSHOT transport org.thingsboard.transport diff --git a/transport/pom.xml b/transport/pom.xml index 20d4f188b2..ed4ca7b44c 100644 --- a/transport/pom.xml +++ b/transport/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.2-SNAPSHOT + 3.0.1-SNAPSHOT thingsboard transport diff --git a/ui-ngx/pom.xml b/ui-ngx/pom.xml index fb403fba01..8a0e60aac4 100644 --- a/ui-ngx/pom.xml +++ b/ui-ngx/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 2.5.2-SNAPSHOT + 3.0.1-SNAPSHOT thingsboard org.thingsboard diff --git a/ui-ngx/src/app/modules/home/pages/widget/widget-editor.component.scss b/ui-ngx/src/app/modules/home/pages/widget/widget-editor.component.scss index a23f8f3626..afb804612a 100644 --- a/ui-ngx/src/app/modules/home/pages/widget/widget-editor.component.scss +++ b/ui-ngx/src/app/modules/home/pages/widget/widget-editor.component.scss @@ -86,6 +86,11 @@ tb-widget-editor { height: 100%; } } + + .container{ + width: 100%; + height: 100%; + } } .tb-split-vertical {