diff --git a/application/src/main/java/org/thingsboard/server/actors/app/AppActor.java b/application/src/main/java/org/thingsboard/server/actors/app/AppActor.java index 93cf5bd8c7..622812b327 100644 --- a/application/src/main/java/org/thingsboard/server/actors/app/AppActor.java +++ b/application/src/main/java/org/thingsboard/server/actors/app/AppActor.java @@ -37,12 +37,10 @@ import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; import org.thingsboard.server.common.msg.MsgType; import org.thingsboard.server.common.msg.TbActorMsg; import org.thingsboard.server.common.msg.aware.TenantAwareMsg; -import org.thingsboard.server.common.msg.edge.EdgeSessionMsg; import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; import org.thingsboard.server.common.msg.queue.QueueToRuleEngineMsg; import org.thingsboard.server.common.msg.queue.RuleEngineException; import org.thingsboard.server.common.msg.queue.ServiceType; -import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.tenant.TenantService; import org.thingsboard.server.service.transport.msg.TransportToDeviceActorMsgWrapper; @@ -110,11 +108,6 @@ public class AppActor extends ContextAwareActor { case REMOVE_RPC_TO_DEVICE_ACTOR_MSG: onToDeviceActorMsg((TenantAwareMsg) msg, true); break; - case EDGE_EVENT_UPDATE_TO_EDGE_SESSION_MSG: - case EDGE_SYNC_REQUEST_TO_EDGE_SESSION_MSG: - case EDGE_SYNC_RESPONSE_FROM_EDGE_SESSION_MSG: - onToEdgeSessionMsg((EdgeSessionMsg) msg); - break; case SESSION_TIMEOUT_MSG: ctx.broadcastToChildrenByType(msg, EntityType.TENANT); break; @@ -206,20 +199,6 @@ public class AppActor extends ContextAwareActor { () -> true)); } - private void onToEdgeSessionMsg(EdgeSessionMsg msg) { - TbActorRef target = null; - if (ModelConstants.SYSTEM_TENANT.equals(msg.getTenantId())) { - log.warn("Message has system tenant id: {}", msg); - } else { - target = getOrCreateTenantActor(msg.getTenantId()).orElse(null); - } - if (target != null) { - target.tellWithHighPriority(msg); - } else { - log.debug("[{}] Invalid edge session msg: {}", msg.getTenantId(), msg); - } - } - @Override public ProcessFailureStrategy onProcessFailure(TbActorMsg msg, Throwable t) { log.error("Failed to process msg: {}", msg, t); diff --git a/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java b/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java index b34ddca1af..3e8cd9592f 100644 --- a/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java +++ b/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java @@ -56,6 +56,7 @@ import org.thingsboard.server.common.data.security.DeviceCredentials; import org.thingsboard.server.common.data.security.DeviceCredentialsType; import org.thingsboard.server.common.msg.TbActorMsg; import org.thingsboard.server.common.msg.TbMsgMetaData; +import org.thingsboard.server.common.msg.edge.EdgeHighPriorityMsg; import org.thingsboard.server.common.msg.queue.TbCallback; import org.thingsboard.server.common.msg.rpc.FromDeviceRpcResponse; import org.thingsboard.server.common.msg.rpc.FromDeviceRpcResponseActorMsg; @@ -214,7 +215,7 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso log.debug("[{}][{}] device is related to edge: [{}]. Saving RPC request: [{}][{}] to edge queue", tenantId, deviceId, edgeId.getId(), rpcId, requestId); try { if (systemContext.getEdgeService().isEdgeActiveAsync(tenantId, edgeId, DefaultDeviceStateService.ACTIVITY_STATE).get()) { - saveRpcRequestToEdgeQueue(request, requestId).get(); + saveRpcRequestToEdgeQueue(request, requestId); } else { log.error("[{}][{}][{}] Failed to save RPC request to edge queue {}. The Edge is currently offline or unreachable", tenantId, deviceId, edgeId.getId(), request); } @@ -921,7 +922,7 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso systemContext.getTbCoreToTransportService().process(nodeId, msg); } - private ListenableFuture saveRpcRequestToEdgeQueue(ToDeviceRpcRequest msg, Integer requestId) { + private void saveRpcRequestToEdgeQueue(ToDeviceRpcRequest msg, Integer requestId) { ObjectNode body = JacksonUtil.newObjectNode(); body.put("requestId", requestId); body.put("requestUUID", msg.getId().toString()); @@ -935,7 +936,7 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso EdgeEvent edgeEvent = EdgeUtils.constructEdgeEvent(tenantId, edgeId, EdgeEventType.DEVICE, EdgeEventActionType.RPC_CALL, deviceId, body); - return systemContext.getEdgeEventService().saveAsync(edgeEvent); + systemContext.getClusterService().onEdgeHighPriorityMsg(new EdgeHighPriorityMsg(tenantId, edgeEvent)); } void restoreSessions() { diff --git a/application/src/main/java/org/thingsboard/server/actors/tenant/TenantActor.java b/application/src/main/java/org/thingsboard/server/actors/tenant/TenantActor.java index d55e08143b..5edecba31a 100644 --- a/application/src/main/java/org/thingsboard/server/actors/tenant/TenantActor.java +++ b/application/src/main/java/org/thingsboard/server/actors/tenant/TenantActor.java @@ -33,9 +33,7 @@ import org.thingsboard.server.actors.service.DefaultActorService; import org.thingsboard.server.common.data.ApiUsageState; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.Tenant; -import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.id.DeviceId; -import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.TenantId; @@ -48,14 +46,12 @@ import org.thingsboard.server.common.msg.TbActorStopReason; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.aware.DeviceAwareMsg; import org.thingsboard.server.common.msg.aware.RuleChainAwareMsg; -import org.thingsboard.server.common.msg.edge.EdgeSessionMsg; import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; import org.thingsboard.server.common.msg.queue.QueueToRuleEngineMsg; import org.thingsboard.server.common.msg.queue.RuleEngineException; import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.common.msg.rule.engine.DeviceDeleteMsg; -import org.thingsboard.server.service.edge.rpc.EdgeRpcService; import org.thingsboard.server.service.transport.msg.TransportToDeviceActorMsgWrapper; import java.util.HashSet; @@ -163,11 +159,6 @@ public class TenantActor extends RuleChainManagerActor { case RULE_CHAIN_TO_RULE_CHAIN_MSG: onRuleChainMsg((RuleChainAwareMsg) msg); break; - case EDGE_EVENT_UPDATE_TO_EDGE_SESSION_MSG: - case EDGE_SYNC_REQUEST_TO_EDGE_SESSION_MSG: - case EDGE_SYNC_RESPONSE_FROM_EDGE_SESSION_MSG: - onToEdgeSessionMsg((EdgeSessionMsg) msg); - break; default: return false; } @@ -270,18 +261,6 @@ public class TenantActor extends RuleChainManagerActor { initRuleChains(); } } - if (msg.getEntityId().getEntityType() == EntityType.EDGE && isCore) { - EdgeId edgeId = new EdgeId(msg.getEntityId().getId()); - EdgeRpcService edgeRpcService = systemContext.getEdgeRpcService(); - if (edgeRpcService != null) { - if (msg.getEvent() == ComponentLifecycleEvent.DELETED) { - edgeRpcService.deleteEdge(tenantId, edgeId); - } else if (msg.getEvent() == ComponentLifecycleEvent.UPDATED) { - Edge edge = systemContext.getEdgeService().findEdgeById(tenantId, edgeId); - edgeRpcService.updateEdge(tenantId, edge); - } - } - } if (msg.getEntityId().getEntityType() == EntityType.DEVICE && ComponentLifecycleEvent.DELETED == msg.getEvent() && isMyPartition(msg.getEntityId())) { DeviceId deviceId = (DeviceId) msg.getEntityId(); onToDeviceActorMsg(new DeviceDeleteMsg(tenantId, deviceId), true); @@ -311,10 +290,6 @@ public class TenantActor extends RuleChainManagerActor { () -> true); } - private void onToEdgeSessionMsg(EdgeSessionMsg msg) { - systemContext.getEdgeRpcService().onToEdgeSessionMsg(tenantId, msg); - } - private ApiUsageState getApiUsageState() { if (apiUsageState == null) { apiUsageState = new ApiUsageState(systemContext.getApiUsageStateService().getApiUsageState(tenantId)); diff --git a/application/src/main/java/org/thingsboard/server/controller/EdgeController.java b/application/src/main/java/org/thingsboard/server/controller/EdgeController.java index 26c30f85d1..2cb8eb7378 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EdgeController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EdgeController.java @@ -478,8 +478,7 @@ public class EdgeController extends BaseController { edgeId = checkNotNull(edgeId); SecurityUser user = getCurrentUser(); TenantId tenantId = user.getTenantId(); - ToEdgeSyncRequest request = new ToEdgeSyncRequest(UUID.randomUUID(), tenantId, edgeId); - edgeRpcServiceOpt.get().processSyncRequest(request, fromEdgeSyncResponse -> reply(response, fromEdgeSyncResponse)); + edgeRpcServiceOpt.get().processSyncRequest(tenantId, edgeId, fromEdgeSyncResponse -> reply(response, fromEdgeSyncResponse)); } else { throw new ThingsboardException("Edges support disabled", ThingsboardErrorCode.GENERAL); } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java deleted file mode 100644 index 740b19e5d8..0000000000 --- a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java +++ /dev/null @@ -1,222 +0,0 @@ -/** - * Copyright © 2016-2024 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.service.edge; - -import com.fasterxml.jackson.databind.node.ObjectNode; -import jakarta.annotation.PostConstruct; -import jakarta.annotation.PreDestroy; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.stereotype.Service; -import org.thingsboard.common.util.JacksonUtil; -import org.thingsboard.common.util.ThingsBoardExecutors; -import org.thingsboard.server.common.data.audit.ActionType; -import org.thingsboard.server.common.data.edge.Edge; -import org.thingsboard.server.common.data.edge.EdgeEventType; -import org.thingsboard.server.common.data.id.RuleChainId; -import org.thingsboard.server.common.data.id.TenantId; -import org.thingsboard.server.common.msg.queue.TbCallback; -import org.thingsboard.server.dao.edge.EdgeService; -import org.thingsboard.server.dao.eventsourcing.ActionEntityEvent; -import org.thingsboard.server.gen.transport.TransportProtos; -import org.thingsboard.server.queue.util.TbCoreComponent; -import org.thingsboard.server.service.edge.rpc.processor.alarm.AlarmEdgeProcessor; -import org.thingsboard.server.service.edge.rpc.processor.asset.AssetEdgeProcessor; -import org.thingsboard.server.service.edge.rpc.processor.asset.profile.AssetProfileEdgeProcessor; -import org.thingsboard.server.service.edge.rpc.processor.customer.CustomerEdgeProcessor; -import org.thingsboard.server.service.edge.rpc.processor.dashboard.DashboardEdgeProcessor; -import org.thingsboard.server.service.edge.rpc.processor.device.DeviceEdgeProcessor; -import org.thingsboard.server.service.edge.rpc.processor.device.profile.DeviceProfileEdgeProcessor; -import org.thingsboard.server.service.edge.rpc.processor.edge.EdgeProcessor; -import org.thingsboard.server.service.edge.rpc.processor.entityview.EntityViewEdgeProcessor; -import org.thingsboard.server.service.edge.rpc.processor.notification.NotificationEdgeProcessor; -import org.thingsboard.server.service.edge.rpc.processor.oauth2.OAuth2EdgeProcessor; -import org.thingsboard.server.service.edge.rpc.processor.ota.OtaPackageEdgeProcessor; -import org.thingsboard.server.service.edge.rpc.processor.queue.QueueEdgeProcessor; -import org.thingsboard.server.service.edge.rpc.processor.relation.RelationEdgeProcessor; -import org.thingsboard.server.service.edge.rpc.processor.resource.ResourceEdgeProcessor; -import org.thingsboard.server.service.edge.rpc.processor.rule.RuleChainEdgeProcessor; -import org.thingsboard.server.service.edge.rpc.processor.tenant.TenantEdgeProcessor; -import org.thingsboard.server.service.edge.rpc.processor.tenant.TenantProfileEdgeProcessor; -import org.thingsboard.server.service.edge.rpc.processor.user.UserEdgeProcessor; -import org.thingsboard.server.service.edge.rpc.processor.widget.WidgetBundleEdgeProcessor; -import org.thingsboard.server.service.edge.rpc.processor.widget.WidgetTypeEdgeProcessor; - -import java.util.UUID; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.TimeUnit; - -@Service -@TbCoreComponent -@Slf4j -public class DefaultEdgeNotificationService implements EdgeNotificationService { - - public static final String EDGE_IS_ROOT_BODY_KEY = "isRoot"; - - @Autowired - private EdgeService edgeService; - - @Autowired - private EdgeProcessor edgeProcessor; - - @Autowired - private AssetEdgeProcessor assetProcessor; - - @Autowired - private AssetProfileEdgeProcessor assetProfileEdgeProcessor; - - @Autowired - private DeviceEdgeProcessor deviceProcessor; - - @Autowired - private DeviceProfileEdgeProcessor deviceProfileEdgeProcessor; - - @Autowired - private EntityViewEdgeProcessor entityViewProcessor; - - @Autowired - private DashboardEdgeProcessor dashboardProcessor; - - @Autowired - private RuleChainEdgeProcessor ruleChainProcessor; - - @Autowired - private UserEdgeProcessor userProcessor; - - @Autowired - private CustomerEdgeProcessor customerProcessor; - - @Autowired - private OtaPackageEdgeProcessor otaPackageProcessor; - - @Autowired - private WidgetBundleEdgeProcessor widgetBundleProcessor; - - @Autowired - private WidgetTypeEdgeProcessor widgetTypeProcessor; - - @Autowired - private QueueEdgeProcessor queueProcessor; - - @Autowired - private TenantEdgeProcessor tenantEdgeProcessor; - - @Autowired - private TenantProfileEdgeProcessor tenantProfileEdgeProcessor; - - @Autowired - private AlarmEdgeProcessor alarmProcessor; - - @Autowired - private RelationEdgeProcessor relationProcessor; - - @Autowired - private ResourceEdgeProcessor resourceEdgeProcessor; - - @Autowired - private NotificationEdgeProcessor notificationEdgeProcessor; - - @Autowired - private OAuth2EdgeProcessor oAuth2EdgeProcessor; - - @Autowired - protected ApplicationEventPublisher eventPublisher; - - @Value("${actors.system.edge_dispatcher_pool_size:4}") - private int edgeDispatcherSize; - - private ExecutorService executor; - - @PostConstruct - public void initExecutor() { - executor = ThingsBoardExecutors.newWorkStealingPool(edgeDispatcherSize, "edge-notifications"); - } - - @PreDestroy - public void shutdownExecutor() { - if (executor != null) { - executor.shutdownNow(); - } - } - - @Override - public Edge setEdgeRootRuleChain(TenantId tenantId, Edge edge, RuleChainId ruleChainId) { - edge.setRootRuleChainId(ruleChainId); - Edge savedEdge = edgeService.saveEdge(edge); - ObjectNode isRootBody = JacksonUtil.newObjectNode(); - isRootBody.put(EDGE_IS_ROOT_BODY_KEY, Boolean.TRUE); - eventPublisher.publishEvent(ActionEntityEvent.builder().tenantId(tenantId).edgeId(edge.getId()).entityId(ruleChainId) - .body(JacksonUtil.toString(isRootBody)).actionType(ActionType.UPDATED).build()); - return savedEdge; - } - - @Override - public void pushNotificationToEdge(TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg, TbCallback callback) { - TenantId tenantId = TenantId.fromUUID(new UUID(edgeNotificationMsg.getTenantIdMSB(), edgeNotificationMsg.getTenantIdLSB())); - log.debug("[{}] Pushing notification to edge {}", tenantId, edgeNotificationMsg); - final long deadline = System.nanoTime() + TimeUnit.SECONDS.toNanos(60); - try { - executor.submit(() -> { - try { - if (deadline < System.nanoTime()) { - log.warn("[{}] Skipping notification message because deadline reached {}", tenantId, edgeNotificationMsg); - return; - } - EdgeEventType type = EdgeEventType.valueOf(edgeNotificationMsg.getType()); - switch (type) { - case EDGE -> edgeProcessor.processEdgeNotification(tenantId, edgeNotificationMsg); - case ASSET -> assetProcessor.processEntityNotification(tenantId, edgeNotificationMsg); - case ASSET_PROFILE -> assetProfileEdgeProcessor.processEntityNotification(tenantId, edgeNotificationMsg); - case DEVICE -> deviceProcessor.processEntityNotification(tenantId, edgeNotificationMsg); - case DEVICE_PROFILE -> deviceProfileEdgeProcessor.processEntityNotification(tenantId, edgeNotificationMsg); - case ENTITY_VIEW -> entityViewProcessor.processEntityNotification(tenantId, edgeNotificationMsg); - case DASHBOARD -> dashboardProcessor.processEntityNotification(tenantId, edgeNotificationMsg); - case RULE_CHAIN -> ruleChainProcessor.processEntityNotification(tenantId, edgeNotificationMsg); - case USER -> userProcessor.processEntityNotification(tenantId, edgeNotificationMsg); - case CUSTOMER -> customerProcessor.processCustomerNotification(tenantId, edgeNotificationMsg); - case OTA_PACKAGE -> otaPackageProcessor.processEntityNotification(tenantId, edgeNotificationMsg); - case WIDGETS_BUNDLE -> widgetBundleProcessor.processEntityNotification(tenantId, edgeNotificationMsg); - case WIDGET_TYPE -> widgetTypeProcessor.processEntityNotification(tenantId, edgeNotificationMsg); - case QUEUE -> queueProcessor.processEntityNotification(tenantId, edgeNotificationMsg); - case ALARM -> alarmProcessor.processAlarmNotification(tenantId, edgeNotificationMsg); - case ALARM_COMMENT -> alarmProcessor.processAlarmCommentNotification(tenantId, edgeNotificationMsg); - case RELATION -> relationProcessor.processRelationNotification(tenantId, edgeNotificationMsg); - case TENANT -> tenantEdgeProcessor.processEntityNotification(tenantId, edgeNotificationMsg); - case TENANT_PROFILE -> tenantProfileEdgeProcessor.processEntityNotification(tenantId, edgeNotificationMsg); - case NOTIFICATION_RULE, NOTIFICATION_TARGET, NOTIFICATION_TEMPLATE -> - notificationEdgeProcessor.processEntityNotification(tenantId, edgeNotificationMsg); - case TB_RESOURCE -> resourceEdgeProcessor.processEntityNotification(tenantId, edgeNotificationMsg); - case DOMAIN, OAUTH2_CLIENT -> oAuth2EdgeProcessor.processEntityNotification(tenantId, edgeNotificationMsg); - default -> log.warn("[{}] Edge event type [{}] is not designed to be pushed to edge", tenantId, type); - } - } catch (Exception e) { - callBackFailure(tenantId, edgeNotificationMsg, callback, e); - } - }); - callback.onSuccess(); - } catch (Exception e) { - callBackFailure(tenantId, edgeNotificationMsg, callback, e); - } - } - - private void callBackFailure(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg, TbCallback callback, Throwable throwable) { - log.error("[{}] Can't push to edge updates, edgeNotificationMsg [{}]", tenantId, edgeNotificationMsg, throwable); - callback.onFailure(throwable); - } - -} diff --git a/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java b/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java index 2d9fa01796..f0f41e3083 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java @@ -48,6 +48,7 @@ import org.thingsboard.server.dao.widget.WidgetTypeService; import org.thingsboard.server.dao.widget.WidgetsBundleService; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.edge.rpc.EdgeEventStorageSettings; +import org.thingsboard.server.service.edge.rpc.EdgeRpcService; import org.thingsboard.server.service.edge.rpc.constructor.edge.EdgeMsgConstructor; import org.thingsboard.server.service.edge.rpc.processor.alarm.AlarmEdgeProcessor; import org.thingsboard.server.service.edge.rpc.processor.alarm.AlarmEdgeProcessorFactory; @@ -97,6 +98,9 @@ public class EdgeContextComponent { @Autowired private EdgeService edgeService; + @Autowired(required = false) + private EdgeRpcService edgeRpcService; + @Autowired private EdgeEventService edgeEventService; @@ -224,19 +228,19 @@ public class EdgeContextComponent { private AdminSettingsEdgeProcessor adminSettingsProcessor; @Autowired - private OtaPackageEdgeProcessor otaPackageEdgeProcessor; + private OtaPackageEdgeProcessor otaPackageProcessor; @Autowired - private QueueEdgeProcessor queueEdgeProcessor; + private QueueEdgeProcessor queueProcessor; @Autowired - private TenantEdgeProcessor tenantEdgeProcessor; + private TenantEdgeProcessor tenantProcessor; @Autowired - private TenantProfileEdgeProcessor tenantProfileEdgeProcessor; + private TenantProfileEdgeProcessor tenantProfileProcessor; @Autowired - private ResourceEdgeProcessor resourceEdgeProcessor; + private ResourceEdgeProcessor resourceProcessor; @Autowired private NotificationEdgeProcessor notificationEdgeProcessor; diff --git a/application/src/main/java/org/thingsboard/server/service/edge/EdgeEventSourcingListener.java b/application/src/main/java/org/thingsboard/server/service/edge/EdgeEventSourcingListener.java index 789320e352..840750a781 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/EdgeEventSourcingListener.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/EdgeEventSourcingListener.java @@ -130,8 +130,7 @@ public class EdgeEventSourcingListener { @TransactionalEventListener(fallbackExecution = true) public void handleEvent(ActionEntityEvent event) { - if (EntityType.DEVICE.equals(event.getEntityId().getEntityType()) - && ActionType.ASSIGNED_TO_TENANT.equals(event.getActionType())) { + if (EntityType.DEVICE.equals(event.getEntityId().getEntityType()) && ActionType.ASSIGNED_TO_TENANT.equals(event.getActionType())) { return; } try { diff --git a/application/src/main/java/org/thingsboard/server/service/edge/instructions/DefaultEdgeInstallInstructionsService.java b/application/src/main/java/org/thingsboard/server/service/edge/instructions/DefaultEdgeInstallInstructionsService.java index 64f96aa4e4..7c8489067c 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/instructions/DefaultEdgeInstallInstructionsService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/instructions/DefaultEdgeInstallInstructionsService.java @@ -94,4 +94,5 @@ public class DefaultEdgeInstallInstructionsService extends BaseEdgeInstallUpgrad protected String getBaseDirName() { return INSTALL_DIR; } + } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/instructions/DefaultEdgeUpgradeInstructionsService.java b/application/src/main/java/org/thingsboard/server/service/edge/instructions/DefaultEdgeUpgradeInstructionsService.java index 275de6bafe..2f783c98ab 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/instructions/DefaultEdgeUpgradeInstructionsService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/instructions/DefaultEdgeUpgradeInstructionsService.java @@ -74,7 +74,8 @@ public class DefaultEdgeUpgradeInstructionsService extends BaseEdgeInstallUpgrad Optional attributeKvEntryOpt = attributesService.find(tenantId, edgeId, AttributeScope.SERVER_SCOPE, DataConstants.EDGE_VERSION_ATTR_KEY).get(); if (attributeKvEntryOpt.isPresent()) { String edgeVersionFormatted = convertEdgeVersionToDocsFormat(attributeKvEntryOpt.get().getValueAsString()); - return isVersionGreaterOrEqualsThan(edgeVersionFormatted, "3.6.0") && !isVersionGreaterOrEqualsThan(edgeVersionFormatted, appVersion); + String appVersionFormatted = appVersion.replace("-SNAPSHOT", ""); + return isVersionGreaterOrEqualsThan(edgeVersionFormatted, "3.6.0") && !isVersionGreaterOrEqualsThan(edgeVersionFormatted, appVersionFormatted); } return false; } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/instructions/EdgeUpgradeInstructionsService.java b/application/src/main/java/org/thingsboard/server/service/edge/instructions/EdgeUpgradeInstructionsService.java index 2517b615a8..47bde24bc7 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/instructions/EdgeUpgradeInstructionsService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/instructions/EdgeUpgradeInstructionsService.java @@ -31,4 +31,5 @@ public interface EdgeUpgradeInstructionsService { void setAppVersion(String version); boolean isUpgradeAvailable(TenantId tenantId, EdgeId edgeId) throws Exception; + } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java index 46bf3f69a4..5d45e1c3d5 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java @@ -28,14 +28,17 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.common.util.ThingsBoardThreadFactory; +import org.thingsboard.server.cache.TbTransactionalCache; import org.thingsboard.server.cluster.TbClusterService; import org.thingsboard.server.common.data.AttributeScope; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.ResourceUtils; import org.thingsboard.server.common.data.edge.Edge; +import org.thingsboard.server.common.data.edge.EdgeEvent; import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.kv.BasicTsKvEntry; @@ -47,12 +50,14 @@ import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgDataType; import org.thingsboard.server.common.msg.TbMsgMetaData; import org.thingsboard.server.common.msg.edge.EdgeEventUpdateMsg; +import org.thingsboard.server.common.msg.edge.EdgeHighPriorityMsg; import org.thingsboard.server.common.msg.edge.EdgeSessionMsg; import org.thingsboard.server.common.msg.edge.FromEdgeSyncResponse; import org.thingsboard.server.common.msg.edge.ToEdgeSyncRequest; import org.thingsboard.server.gen.edge.v1.EdgeRpcServiceGrpc; import org.thingsboard.server.gen.edge.v1.RequestMsg; import org.thingsboard.server.gen.edge.v1.ResponseMsg; +import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.edge.EdgeContextComponent; import org.thingsboard.server.service.state.DefaultDeviceStateService; @@ -84,7 +89,6 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i private final ConcurrentMap sessionNewEventsLocks = new ConcurrentHashMap<>(); private final Map sessionNewEvents = new HashMap<>(); private final ConcurrentMap> sessionEdgeEventChecks = new ConcurrentHashMap<>(); - private final ConcurrentMap> localSyncEdgeRequests = new ConcurrentHashMap<>(); @Value("${edges.rpc.port}") @@ -111,7 +115,11 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i @Value("${edges.send_scheduler_pool_size}") private int sendSchedulerPoolSize; + @Value("${edges.max_high_priority_queue_size_per_session:10000}") + private int maxHighPriorityQueueSizePerSession; + @Autowired + @Lazy private EdgeContextComponent ctx; @Autowired @@ -120,6 +128,12 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i @Autowired private TbClusterService clusterService; + @Autowired + private TbServiceInfoProvider serviceInfoProvider; + + @Autowired + private TbTransactionalCache edgeIdServiceIdCache; + private Server server; private ScheduledExecutorService edgeEventProcessingExecutorService; @@ -188,79 +202,100 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i @Override public StreamObserver handleMsgs(StreamObserver outputStream) { - return new EdgeGrpcSession(ctx, outputStream, this::onEdgeConnect, this::onEdgeDisconnect, sendDownlinkExecutorService, this.maxInboundMessageSize).getInputStream(); + return new EdgeGrpcSession(ctx, + outputStream, + this::onEdgeConnect, + this::onEdgeDisconnect, + sendDownlinkExecutorService, + this.maxInboundMessageSize, + this.maxHighPriorityQueueSizePerSession).getInputStream(); } @Override public void onToEdgeSessionMsg(TenantId tenantId, EdgeSessionMsg msg) { - executorService.execute(() -> { - switch (msg.getMsgType()) { - case EDGE_EVENT_UPDATE_TO_EDGE_SESSION_MSG: - EdgeEventUpdateMsg edgeEventUpdateMsg = (EdgeEventUpdateMsg) msg; - log.trace("[{}] onToEdgeSessionMsg [{}]", tenantId, msg); - onEdgeEvent(tenantId, edgeEventUpdateMsg.getEdgeId()); - break; - case EDGE_SYNC_REQUEST_TO_EDGE_SESSION_MSG: - ToEdgeSyncRequest toEdgeSyncRequest = (ToEdgeSyncRequest) msg; - log.trace("[{}] toEdgeSyncRequest [{}]", tenantId, msg); - startSyncProcess(tenantId, toEdgeSyncRequest.getEdgeId(), toEdgeSyncRequest.getId()); - break; - case EDGE_SYNC_RESPONSE_FROM_EDGE_SESSION_MSG: - FromEdgeSyncResponse fromEdgeSyncResponse = (FromEdgeSyncResponse) msg; - log.trace("[{}] fromEdgeSyncResponse [{}]", tenantId, msg); - processSyncResponse(fromEdgeSyncResponse); - break; + switch (msg.getMsgType()) { + case EDGE_HIGH_PRIORITY_TO_EDGE_SESSION_MSG -> { + EdgeHighPriorityMsg edgeHighPriorityMsg = (EdgeHighPriorityMsg) msg; + log.trace("[{}] edgeEventMsg [{}]", tenantId, msg); + onEdgeHighPriorityEvent(edgeHighPriorityMsg); } - }); + case EDGE_EVENT_UPDATE_TO_EDGE_SESSION_MSG -> { + EdgeEventUpdateMsg edgeEventUpdateMsg = (EdgeEventUpdateMsg) msg; + log.trace("[{}] onToEdgeEventUpdateMsg [{}]", tenantId, msg); + onEdgeEventUpdate(tenantId, edgeEventUpdateMsg.getEdgeId()); + } + case EDGE_SYNC_REQUEST_TO_EDGE_SESSION_MSG -> { + ToEdgeSyncRequest toEdgeSyncRequest = (ToEdgeSyncRequest) msg; + log.trace("[{}] toEdgeSyncRequest [{}]", tenantId, msg); + startSyncProcess(tenantId, toEdgeSyncRequest.getEdgeId(), toEdgeSyncRequest.getId(), toEdgeSyncRequest.getServiceId()); + } + case EDGE_SYNC_RESPONSE_FROM_EDGE_SESSION_MSG -> { + FromEdgeSyncResponse fromEdgeSyncResponse = (FromEdgeSyncResponse) msg; + log.trace("[{}] fromEdgeSyncResponse [{}]", tenantId, msg); + processSyncResponse(fromEdgeSyncResponse); + } + } } @Override public void updateEdge(TenantId tenantId, Edge edge) { - executorService.execute(() -> { - EdgeGrpcSession session = sessions.get(edge.getId()); - if (session != null && session.isConnected()) { - log.debug("[{}] Updating configuration for edge [{}] [{}]", tenantId, edge.getName(), edge.getId()); - session.onConfigurationUpdate(edge); - } else { - log.debug("[{}] Session doesn't exist for edge [{}] [{}]", tenantId, edge.getName(), edge.getId()); - } - }); + EdgeGrpcSession session = sessions.get(edge.getId()); + if (session != null && session.isConnected()) { + log.debug("[{}] Updating configuration for edge [{}] [{}]", tenantId, edge.getName(), edge.getId()); + session.onConfigurationUpdate(edge); + } else { + log.debug("[{}] Session doesn't exist for edge [{}] [{}]", tenantId, edge.getName(), edge.getId()); + } } @Override public void deleteEdge(TenantId tenantId, EdgeId edgeId) { - executorService.execute(() -> { - EdgeGrpcSession session = sessions.get(edgeId); - if (session != null && session.isConnected()) { - log.info("[{}] Closing and removing session for edge [{}]", tenantId, edgeId); - session.close(); - sessions.remove(edgeId); - final Lock newEventLock = sessionNewEventsLocks.computeIfAbsent(edgeId, id -> new ReentrantLock()); - newEventLock.lock(); - try { - sessionNewEvents.remove(edgeId); - } finally { - newEventLock.unlock(); - } - cancelScheduleEdgeEventsCheck(edgeId); - } - }); - } - - private void onEdgeEvent(TenantId tenantId, EdgeId edgeId) { EdgeGrpcSession session = sessions.get(edgeId); if (session != null && session.isConnected()) { - log.trace("[{}] onEdgeEvent [{}]", tenantId, edgeId.getId()); + log.info("[{}] Closing and removing session for edge [{}]", tenantId, edgeId); + session.close(); + sessions.remove(edgeId); final Lock newEventLock = sessionNewEventsLocks.computeIfAbsent(edgeId, id -> new ReentrantLock()); newEventLock.lock(); try { - if (Boolean.FALSE.equals(sessionNewEvents.get(edgeId))) { - log.trace("[{}] set session new events flag to true [{}]", tenantId, edgeId.getId()); - sessionNewEvents.put(edgeId, true); - } + sessionNewEvents.remove(edgeId); } finally { newEventLock.unlock(); } + cancelScheduleEdgeEventsCheck(edgeId); + } + } + + private void onEdgeEventUpdate(TenantId tenantId, EdgeId edgeId) { + EdgeGrpcSession session = sessions.get(edgeId); + if (session != null && session.isConnected()) { + log.trace("[{}] onEdgeEventUpdate [{}]", tenantId, edgeId.getId()); + updateSessionEventsFlag(tenantId, edgeId); + } + } + + private void onEdgeHighPriorityEvent(EdgeHighPriorityMsg msg) { + TenantId tenantId = msg.getTenantId(); + EdgeEvent edgeEvent = msg.getEdgeEvent(); + EdgeId edgeId = edgeEvent.getEdgeId(); + EdgeGrpcSession session = sessions.get(edgeId); + if (session != null && session.isConnected()) { + log.trace("[{}] onEdgeEvent [{}]", tenantId, edgeId); + session.addEventToHighPriorityQueue(edgeEvent); + updateSessionEventsFlag(tenantId, edgeId); + } + } + + private void updateSessionEventsFlag(TenantId tenantId, EdgeId edgeId) { + final Lock newEventLock = sessionNewEventsLocks.computeIfAbsent(edgeId, id -> new ReentrantLock()); + newEventLock.lock(); + try { + if (Boolean.FALSE.equals(sessionNewEvents.get(edgeId))) { + log.trace("[{}] set session new events flag to true [{}]", tenantId, edgeId.getId()); + sessionNewEvents.put(edgeId, true); + } + } finally { + newEventLock.unlock(); } } @@ -279,37 +314,40 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i save(tenantId, edgeId, DefaultDeviceStateService.ACTIVITY_STATE, true); long lastConnectTs = System.currentTimeMillis(); save(tenantId, edgeId, DefaultDeviceStateService.LAST_CONNECT_TIME, lastConnectTs); + edgeIdServiceIdCache.put(edgeId, serviceInfoProvider.getServiceId()); pushRuleEngineMessage(tenantId, edge, lastConnectTs, TbMsgType.CONNECT_EVENT); cancelScheduleEdgeEventsCheck(edgeId); scheduleEdgeEventsCheck(edgeGrpcSession); } - private void startSyncProcess(TenantId tenantId, EdgeId edgeId, UUID requestId) { + private void startSyncProcess(TenantId tenantId, EdgeId edgeId, UUID requestId, String requestServiceId) { EdgeGrpcSession session = sessions.get(edgeId); if (session != null) { if (!session.isSyncCompleted()) { - clusterService.pushEdgeSyncResponseToCore(new FromEdgeSyncResponse(requestId, tenantId, edgeId, false, "Sync process is active at the moment")); + clusterService.pushEdgeSyncResponseToCore(new FromEdgeSyncResponse(requestId, tenantId, edgeId, false, "Sync process is active at the moment"), requestServiceId); } else { boolean success = false; if (session.isConnected()) { session.startSyncProcess(true); success = true; } - clusterService.pushEdgeSyncResponseToCore(new FromEdgeSyncResponse(requestId, tenantId, edgeId, success, "")); + clusterService.pushEdgeSyncResponseToCore(new FromEdgeSyncResponse(requestId, tenantId, edgeId, success, ""), requestServiceId); } } } @Override - public void processSyncRequest(ToEdgeSyncRequest request, Consumer responseConsumer) { + public void processSyncRequest(TenantId tenantId, EdgeId edgeId, Consumer responseConsumer) { + ToEdgeSyncRequest request = new ToEdgeSyncRequest(UUID.randomUUID(), tenantId, edgeId, serviceInfoProvider.getServiceId()); + UUID requestId = request.getId(); EdgeGrpcSession session = sessions.get(request.getEdgeId()); if (session != null && !session.isSyncCompleted()) { responseConsumer.accept(new FromEdgeSyncResponse(requestId, request.getTenantId(), request.getEdgeId(), false, "Sync process is active at the moment")); } else { - log.trace("[{}][{}] Processing sync edge request [{}]", request.getTenantId(), request.getId(), request.getEdgeId()); + log.trace("[{}][{}] Processing sync edge request [{}], serviceId [{}]", request.getTenantId(), request.getId(), request.getEdgeId(), request.getServiceId()); localSyncEdgeRequests.put(requestId, responseConsumer); - clusterService.pushEdgeSyncRequestToCore(request); + clusterService.pushEdgeSyncRequestToEdge(request); scheduleSyncRequestTimeout(request, requestId); } } @@ -415,6 +453,7 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i } else { log.debug("[{}] edge session [{}] is not available anymore, nothing to remove. most probably this session is already outdated!", edgeId, sessionId); } + edgeIdServiceIdCache.evict(edgeId); } private void save(TenantId tenantId, EdgeId edgeId, String key, long value) { diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java index c4e8f1ec7c..c397807c5f 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java @@ -42,6 +42,7 @@ import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.SortOrder; import org.thingsboard.server.common.data.page.TimePageLink; +import org.thingsboard.server.common.msg.edge.EdgeEventUpdateMsg; import org.thingsboard.server.gen.edge.v1.AlarmCommentUpdateMsg; import org.thingsboard.server.gen.edge.v1.AlarmUpdateMsg; import org.thingsboard.server.gen.edge.v1.AssetProfileUpdateMsg; @@ -96,6 +97,7 @@ import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.UUID; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; @@ -106,6 +108,7 @@ import java.util.function.BiConsumer; public final class EdgeGrpcSession implements Closeable { private static final ReentrantLock downlinkMsgLock = new ReentrantLock(); + private static final ConcurrentLinkedQueue highPriorityQueue = new ConcurrentLinkedQueue<>(); private static final int MAX_DOWNLINK_ATTEMPTS = 10; // max number of attemps to send downlink message if edge connected @@ -125,7 +128,7 @@ public final class EdgeGrpcSession implements Closeable { private StreamObserver inputStream; private StreamObserver outputStream; private boolean connected; - private boolean syncCompleted; + private volatile boolean syncCompleted; private Long newStartTs; private Long previousStartTs; @@ -137,11 +140,12 @@ public final class EdgeGrpcSession implements Closeable { private int maxInboundMessageSize; private int clientMaxInboundMessageSize; + private int maxHighPriorityQueueSizePerSession; private ScheduledExecutorService sendDownlinkExecutorService; EdgeGrpcSession(EdgeContextComponent ctx, StreamObserver outputStream, BiConsumer sessionOpenListener, - BiConsumer sessionCloseListener, ScheduledExecutorService sendDownlinkExecutorService, int maxInboundMessageSize) { + BiConsumer sessionCloseListener, ScheduledExecutorService sendDownlinkExecutorService, int maxInboundMessageSize, int maxHighPriorityQueueSizePerSession) { this.sessionId = UUID.randomUUID(); this.ctx = ctx; this.outputStream = outputStream; @@ -149,6 +153,7 @@ public final class EdgeGrpcSession implements Closeable { this.sessionCloseListener = sessionCloseListener; this.sendDownlinkExecutorService = sendDownlinkExecutorService; this.maxInboundMessageSize = maxInboundMessageSize; + this.maxHighPriorityQueueSizePerSession = maxHighPriorityQueueSizePerSession; initInputStream(); } @@ -223,7 +228,7 @@ public final class EdgeGrpcSession implements Closeable { } public void startSyncProcess(boolean fullSync) { - log.trace("[{}][{}][{}] Staring edge sync process", this.tenantId, edge.getId(), this.sessionId); + log.info("[{}][{}][{}] Staring edge sync process", this.tenantId, edge.getId(), this.sessionId); syncCompleted = false; interruptGeneralProcessingOnSync(); doSync(new EdgeSyncCursor(ctx, edge, fullSync)); @@ -255,18 +260,23 @@ public final class EdgeGrpcSession implements Closeable { Futures.addCallback(sendDownlinkMsgsPack(Collections.singletonList(syncCompleteDownlinkMsg)), new FutureCallback<>() { @Override public void onSuccess(Boolean isInterrupted) { - syncCompleted = true; - ctx.getClusterService().onEdgeEventUpdate(edge.getTenantId(), edge.getId()); + markSyncCompletedSendEdgeEventUpdate(); } @Override public void onFailure(Throwable t) { log.error("[{}][{}] Exception during sending sync complete", tenantId, edge.getId(), t); + markSyncCompletedSendEdgeEventUpdate(); } }, ctx.getGrpcCallbackExecutorService()); } } + private void markSyncCompletedSendEdgeEventUpdate() { + syncCompleted = true; + ctx.getClusterService().onEdgeEventUpdate(new EdgeEventUpdateMsg(edge.getTenantId(), edge.getId())); + } + private void onUplinkMsg(UplinkMsg uplinkMsg) { if (isRateLimitViolated(uplinkMsg)) { return; @@ -429,6 +439,9 @@ public final class EdgeGrpcSession implements Closeable { private void processEdgeEvents(EdgeEventFetcher fetcher, PageLink pageLink, SettableFuture> result) { try { + if (!highPriorityQueue.isEmpty()) { + processHighPriorityEvents(); + } PageData pageData = fetcher.fetchEdgeEvents(edge.getTenantId(), edge, pageLink); if (isConnected() && !pageData.getData().isEmpty()) { log.trace("[{}][{}][{}] event(s) are going to be processed.", this.tenantId, this.sessionId, pageData.getData().size()); @@ -472,6 +485,20 @@ public final class EdgeGrpcSession implements Closeable { } } + private void processHighPriorityEvents() { + try { + List highPriorityEvents = new ArrayList<>(); + EdgeEvent event; + while ((event = highPriorityQueue.poll()) != null) { + highPriorityEvents.add(event); + } + List downlinkMsgsPack = convertToDownlinkMsgsPack(highPriorityEvents); + sendDownlinkMsgsPack(downlinkMsgsPack).get(); + } catch (Exception e) { + log.error("[{}] Failed to process high priority events", this.sessionId, e); + } + } + private ListenableFuture sendDownlinkMsgsPack(List downlinkMsgsPack) { interruptPreviousSendDownlinkMsgsTask(); @@ -556,7 +583,9 @@ public final class EdgeGrpcSession implements Closeable { DownlinkMsg downlinkMsg = null; try { switch (edgeEvent.getAction()) { - case UPDATED, ADDED, DELETED, ASSIGNED_TO_EDGE, UNASSIGNED_FROM_EDGE, ALARM_ACK, ALARM_CLEAR, ALARM_DELETE, CREDENTIALS_UPDATED, RELATION_ADD_OR_UPDATE, RELATION_DELETED, RPC_CALL, ASSIGNED_TO_CUSTOMER, UNASSIGNED_FROM_CUSTOMER, ADDED_COMMENT, UPDATED_COMMENT, DELETED_COMMENT -> { + case UPDATED, ADDED, DELETED, ASSIGNED_TO_EDGE, UNASSIGNED_FROM_EDGE, ALARM_ACK, ALARM_CLEAR, ALARM_DELETE, + CREDENTIALS_UPDATED, RELATION_ADD_OR_UPDATE, RELATION_DELETED, RPC_CALL, + ASSIGNED_TO_CUSTOMER, UNASSIGNED_FROM_CUSTOMER, ADDED_COMMENT, UPDATED_COMMENT, DELETED_COMMENT -> { downlinkMsg = convertEntityEventToDownlink(edgeEvent); if (downlinkMsg != null && downlinkMsg.getWidgetTypeUpdateMsgCount() > 0) { log.trace("[{}][{}] widgetTypeUpdateMsg message processed, downlinkMsgId = {}", this.tenantId, this.sessionId, downlinkMsg.getDownlinkMsgId()); @@ -683,15 +712,15 @@ public final class EdgeGrpcSession implements Closeable { case ADMIN_SETTINGS: return ctx.getAdminSettingsProcessor().convertAdminSettingsEventToDownlink(edgeEvent, this.edgeVersion); case OTA_PACKAGE: - return ctx.getOtaPackageEdgeProcessor().convertOtaPackageEventToDownlink(edgeEvent, this.edgeVersion); + return ctx.getOtaPackageProcessor().convertOtaPackageEventToDownlink(edgeEvent, this.edgeVersion); case TB_RESOURCE: - return ctx.getResourceEdgeProcessor().convertResourceEventToDownlink(edgeEvent, this.edgeVersion); + return ctx.getResourceProcessor().convertResourceEventToDownlink(edgeEvent, this.edgeVersion); case QUEUE: - return ctx.getQueueEdgeProcessor().convertQueueEventToDownlink(edgeEvent, this.edgeVersion); + return ctx.getQueueProcessor().convertQueueEventToDownlink(edgeEvent, this.edgeVersion); case TENANT: - return ctx.getTenantEdgeProcessor().convertTenantEventToDownlink(edgeEvent, this.edgeVersion); + return ctx.getTenantProcessor().convertTenantEventToDownlink(edgeEvent, this.edgeVersion); case TENANT_PROFILE: - return ctx.getTenantProfileEdgeProcessor().convertTenantProfileEventToDownlink(edgeEvent, this.edgeVersion); + return ctx.getTenantProfileProcessor().convertTenantProfileEventToDownlink(edgeEvent, this.edgeVersion); case NOTIFICATION_RULE: return ctx.getNotificationEdgeProcessor().convertNotificationRuleToDownlink(edgeEvent); case NOTIFICATION_TARGET: @@ -914,4 +943,15 @@ public final class EdgeGrpcSession implements Closeable { } } + public void addEventToHighPriorityQueue(EdgeEvent edgeEvent) { + while (highPriorityQueue.size() > maxHighPriorityQueueSizePerSession) { + EdgeEvent oldestHighPriority = highPriorityQueue.poll(); + if (oldestHighPriority != null) { + log.warn("[{}][{}][{}] High priority queue is full. Removing oldest high priority event from queue {}", + this.tenantId, edge.getId(), this.sessionId, oldestHighPriority); + } + } + highPriorityQueue.add(edgeEvent); + } + } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeRpcService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeRpcService.java index 12203db0c2..7c832ca760 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeRpcService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeRpcService.java @@ -32,5 +32,6 @@ public interface EdgeRpcService { void deleteEdge(TenantId tenantId, EdgeId edgeId); - void processSyncRequest(ToEdgeSyncRequest request, Consumer responseConsumer); + void processSyncRequest(TenantId tenantId, EdgeId edgeId, Consumer responseConsumer); + } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeSessionState.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeSessionState.java index 6218b1f9a6..3f925c3787 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeSessionState.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeSessionState.java @@ -30,4 +30,5 @@ public class EdgeSessionState { private final Map pendingMsgsMap = Collections.synchronizedMap(new LinkedHashMap<>()); private SettableFuture sendDownlinkMsgsFuture; private ScheduledFuture scheduledSendDownlinkTask; + } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/BasePageableEdgeEventFetcher.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/BasePageableEdgeEventFetcher.java index 747dc5722f..40fc3559ed 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/BasePageableEdgeEventFetcher.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/BasePageableEdgeEventFetcher.java @@ -35,7 +35,7 @@ public abstract class BasePageableEdgeEventFetcher implements EdgeEventFetche @Override public PageData fetchEdgeEvents(TenantId tenantId, Edge edge, PageLink pageLink) { - log.trace("[{}] start fetching edge events [{}]", tenantId, edge.getId()); + log.trace("[{}][{}] start fetching edge events [{}], pageLink {}", getClass().getSimpleName(), tenantId, edge.getId(), pageLink); PageData entities = fetchEntities(tenantId, edge, pageLink); List result = new ArrayList<>(); if (!entities.getData().isEmpty()) { diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/RuleChainsEdgeEventFetcher.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/RuleChainsEdgeEventFetcher.java index 5569c30018..328072aeea 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/RuleChainsEdgeEventFetcher.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/RuleChainsEdgeEventFetcher.java @@ -30,7 +30,7 @@ import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.dao.rule.RuleChainService; -import static org.thingsboard.server.service.edge.DefaultEdgeNotificationService.EDGE_IS_ROOT_BODY_KEY; +import static org.thingsboard.server.dao.edge.EdgeServiceImpl.EDGE_IS_ROOT_BODY_KEY; @Slf4j @AllArgsConstructor diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/BaseEdgeProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/BaseEdgeProcessor.java index 8dee74aac1..3c18e02324 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/BaseEdgeProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/BaseEdgeProcessor.java @@ -374,23 +374,20 @@ public abstract class BaseEdgeProcessor { }, dbCallbackExecutorService); } - private boolean doSaveIfEdgeIsOffline(EdgeEventType type, - EdgeEventActionType action) { + private boolean doSaveIfEdgeIsOffline(EdgeEventType type, EdgeEventActionType action) { return switch (action) { case TIMESERIES_UPDATED, ALARM_ACK, ALARM_CLEAR, ALARM_ASSIGNED, ALARM_UNASSIGNED, ADDED_COMMENT, UPDATED_COMMENT -> true; default -> switch (type) { case ALARM, ALARM_COMMENT, RULE_CHAIN, RULE_CHAIN_METADATA, USER, CUSTOMER, TENANT, TENANT_PROFILE, WIDGETS_BUNDLE, WIDGET_TYPE, - ADMIN_SETTINGS, OTA_PACKAGE, QUEUE, RELATION, NOTIFICATION_TEMPLATE, NOTIFICATION_TARGET, NOTIFICATION_RULE -> - true; + ADMIN_SETTINGS, OTA_PACKAGE, QUEUE, RELATION, NOTIFICATION_TEMPLATE, NOTIFICATION_TARGET, NOTIFICATION_RULE -> true; default -> false; }; }; } private ListenableFuture doSaveEdgeEvent(TenantId tenantId, EdgeId edgeId, EdgeEventType type, EdgeEventActionType action, EntityId entityId, JsonNode body) { - log.debug("Pushing event to edge queue. tenantId [{}], edgeId [{}], type[{}], " + - "action [{}], entityId [{}], body [{}]", + log.debug("Pushing event to edge queue. tenantId [{}], edgeId [{}], type[{}], action [{}], entityId [{}], body [{}]", tenantId, edgeId, type, action, entityId, body); EdgeEvent edgeEvent = EdgeUtils.constructEdgeEvent(tenantId, edgeId, type, action, entityId, body); diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/rule/RuleChainEdgeProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/rule/RuleChainEdgeProcessor.java index b71493fa39..310d8d9b9b 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/rule/RuleChainEdgeProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/rule/RuleChainEdgeProcessor.java @@ -32,7 +32,7 @@ import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.edge.rpc.constructor.rule.RuleChainMsgConstructor; import org.thingsboard.server.service.edge.rpc.processor.BaseEdgeProcessor; -import static org.thingsboard.server.service.edge.DefaultEdgeNotificationService.EDGE_IS_ROOT_BODY_KEY; +import static org.thingsboard.server.dao.edge.EdgeServiceImpl.EDGE_IS_ROOT_BODY_KEY; @Slf4j @Component diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/sync/DefaultEdgeRequestsService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/sync/DefaultEdgeRequestsService.java index 6e4117869b..46f1d7ef57 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/sync/DefaultEdgeRequestsService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/sync/DefaultEdgeRequestsService.java @@ -113,10 +113,8 @@ public class DefaultEdgeRequestsService implements EdgeRequestsService { if (ruleChainMetadataRequestMsg.getRuleChainIdMSB() == 0 || ruleChainMetadataRequestMsg.getRuleChainIdLSB() == 0) { return Futures.immediateFuture(null); } - RuleChainId ruleChainId = - new RuleChainId(new UUID(ruleChainMetadataRequestMsg.getRuleChainIdMSB(), ruleChainMetadataRequestMsg.getRuleChainIdLSB())); - return saveEdgeEvent(tenantId, edge.getId(), - EdgeEventType.RULE_CHAIN_METADATA, EdgeEventActionType.ADDED, ruleChainId, null); + RuleChainId ruleChainId = new RuleChainId(new UUID(ruleChainMetadataRequestMsg.getRuleChainIdMSB(), ruleChainMetadataRequestMsg.getRuleChainIdLSB())); + return saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.RULE_CHAIN_METADATA, EdgeEventActionType.ADDED, ruleChainId, null); } @Override diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/EntityStateSourcingListener.java b/application/src/main/java/org/thingsboard/server/service/entitiy/EntityStateSourcingListener.java index 08b1e57651..863be23e42 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/EntityStateSourcingListener.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/EntityStateSourcingListener.java @@ -35,7 +35,6 @@ import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.edge.EdgeEvent; import org.thingsboard.server.common.data.id.DeviceId; -import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.TenantId; @@ -48,6 +47,8 @@ import org.thingsboard.server.common.data.security.DeviceCredentials; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgDataType; import org.thingsboard.server.common.msg.TbMsgMetaData; +import org.thingsboard.server.common.msg.edge.EdgeEventUpdateMsg; +import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; import org.thingsboard.server.common.msg.rule.engine.DeviceCredentialsUpdateNotificationMsg; import org.thingsboard.server.dao.eventsourcing.ActionEntityEvent; import org.thingsboard.server.dao.eventsourcing.DeleteEntityEvent; @@ -107,7 +108,7 @@ public class EntityStateSourcingListener { onDeviceProfileUpdate(deviceProfile, event.getOldEntity(), isCreated); } case EDGE -> { - handleEdgeEvent(tenantId, entityId, event.getEntity(), lifecycleEvent); + onEdgeEvent(tenantId, entityId, event.getEntity(), lifecycleEvent); } case TB_RESOURCE -> { TbResource tbResource = (TbResource) event.getEntity(); @@ -221,10 +222,7 @@ public class EntityStateSourcingListener { } private DeviceProfile getOldDeviceProfile(Object oldEntity) { - if (oldEntity instanceof DeviceProfile) { - return (DeviceProfile) oldEntity; - } - return null; + return oldEntity instanceof DeviceProfile ? (DeviceProfile) oldEntity : null; } private void onDeviceProfileDelete(TenantId tenantId, EntityId entityId, DeviceProfile deviceProfile) { @@ -241,11 +239,11 @@ public class EntityStateSourcingListener { tbClusterService.onDeviceUpdated(device, oldDevice); } - private void handleEdgeEvent(TenantId tenantId, EntityId entityId, Object entity, ComponentLifecycleEvent lifecycleEvent) { + private void onEdgeEvent(TenantId tenantId, EntityId entityId, Object entity, ComponentLifecycleEvent lifecycleEvent) { if (entity instanceof Edge) { - tbClusterService.broadcastEntityStateChangeEvent(tenantId, entityId, lifecycleEvent); - } else if (entity instanceof EdgeEvent) { - tbClusterService.onEdgeEventUpdate(tenantId, (EdgeId) entityId); + tbClusterService.onEdgeStateChangeEvent(new ComponentLifecycleMsg(tenantId, entityId, lifecycleEvent)); + } else if (entity instanceof EdgeEvent edgeEvent) { + tbClusterService.onEdgeEventUpdate(new EdgeEventUpdateMsg(tenantId, edgeEvent.getEdgeId())); } } diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/edge/DefaultTbEdgeService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/edge/DefaultTbEdgeService.java index 9fcd8e2187..5b8fd949bd 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/edge/DefaultTbEdgeService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/edge/DefaultTbEdgeService.java @@ -31,7 +31,6 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.dao.rule.RuleChainService; import org.thingsboard.server.queue.util.TbCoreComponent; -import org.thingsboard.server.service.edge.EdgeNotificationService; import org.thingsboard.server.service.entitiy.AbstractTbEntityService; @AllArgsConstructor @@ -40,7 +39,6 @@ import org.thingsboard.server.service.entitiy.AbstractTbEntityService; @Slf4j public class DefaultTbEdgeService extends AbstractTbEntityService implements TbEdgeService { - private final EdgeNotificationService edgeNotificationService; private final RuleChainService ruleChainService; @Override @@ -56,7 +54,7 @@ public class DefaultTbEdgeService extends AbstractTbEntityService implements TbE if (ActionType.ADDED.equals(actionType)) { ruleChainService.assignRuleChainToEdge(tenantId, edgeTemplateRootRuleChain.getId(), edgeId); - edgeNotificationService.setEdgeRootRuleChain(tenantId, savedEdge, edgeTemplateRootRuleChain.getId()); + edgeService.setEdgeRootRuleChain(tenantId, savedEdge, edgeTemplateRootRuleChain.getId()); edgeService.assignDefaultRuleChainsToEdge(tenantId, edgeId); } @@ -143,7 +141,7 @@ public class DefaultTbEdgeService extends AbstractTbEntityService implements TbE TenantId tenantId = edge.getTenantId(); EdgeId edgeId = edge.getId(); try { - Edge updatedEdge = edgeNotificationService.setEdgeRootRuleChain(tenantId, edge, ruleChainId); + Edge updatedEdge = edgeService.setEdgeRootRuleChain(tenantId, edge, ruleChainId); logEntityActionService.logEntityAction(tenantId, edgeId, edge, null, ActionType.UPDATED, user); return updatedEdge; } catch (Exception e) { @@ -152,4 +150,5 @@ public class DefaultTbEdgeService extends AbstractTbEntityService implements TbE throw e; } } + } diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/edge/TbEdgeService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/edge/TbEdgeService.java index 8dc447b731..3afd32c3fd 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/edge/TbEdgeService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/edge/TbEdgeService.java @@ -25,6 +25,7 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.rule.RuleChain; public interface TbEdgeService { + Edge save(Edge edge, RuleChain edgeTemplateRootRuleChain, User user) throws Exception; void delete(Edge edge, User user); @@ -36,4 +37,5 @@ public interface TbEdgeService { Edge assignEdgeToPublicCustomer(TenantId tenantId, EdgeId edgeId, User user) throws ThingsboardException; Edge setEdgeRootRuleChain(Edge edge, RuleChainId ruleChainId, User user) throws Exception; + } diff --git a/application/src/main/java/org/thingsboard/server/service/partition/AbstractPartitionBasedService.java b/application/src/main/java/org/thingsboard/server/service/partition/AbstractPartitionBasedService.java index 676dbc1e3d..fc5ce5214c 100644 --- a/application/src/main/java/org/thingsboard/server/service/partition/AbstractPartitionBasedService.java +++ b/application/src/main/java/org/thingsboard/server/service/partition/AbstractPartitionBasedService.java @@ -90,13 +90,13 @@ public abstract class AbstractPartitionBasedService extends @Override protected void onTbApplicationEvent(PartitionChangeEvent partitionChangeEvent) { log.debug("onTbApplicationEvent, processing event: {}", partitionChangeEvent); - subscribeQueue.add(partitionChangeEvent.getPartitions()); + subscribeQueue.add(partitionChangeEvent.getCorePartitions()); scheduledExecutor.submit(this::pollInitStateFromDB); } @Override protected boolean filterTbApplicationEvent(PartitionChangeEvent event) { - return getServiceType().equals(event.getServiceType()); + return event.getServiceType() == getServiceType(); } protected void pollInitStateFromDB() { diff --git a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbClusterService.java b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbClusterService.java index 7699a4f7c2..301f8e8838 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbClusterService.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbClusterService.java @@ -23,6 +23,7 @@ import org.springframework.context.annotation.Lazy; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import org.thingsboard.common.util.JacksonUtil; +import org.thingsboard.server.cache.TbTransactionalCache; import org.thingsboard.server.cluster.TbClusterService; import org.thingsboard.server.common.data.ApiUsageState; import org.thingsboard.server.common.data.DataConstants; @@ -55,6 +56,7 @@ import org.thingsboard.server.common.data.queue.Queue; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.ToDeviceActorNotificationMsg; import org.thingsboard.server.common.msg.edge.EdgeEventUpdateMsg; +import org.thingsboard.server.common.msg.edge.EdgeHighPriorityMsg; import org.thingsboard.server.common.msg.edge.FromEdgeSyncResponse; import org.thingsboard.server.common.msg.edge.ToEdgeSyncRequest; import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; @@ -66,14 +68,23 @@ import org.thingsboard.server.common.msg.rule.engine.DeviceNameOrTypeUpdateMsg; import org.thingsboard.server.common.util.ProtoUtils; import org.thingsboard.server.dao.edge.EdgeService; import org.thingsboard.server.gen.transport.TransportProtos; +import org.thingsboard.server.gen.transport.TransportProtos.ComponentLifecycleMsgProto; +import org.thingsboard.server.gen.transport.TransportProtos.DeviceStateServiceMsgProto; +import org.thingsboard.server.gen.transport.TransportProtos.EdgeNotificationMsgProto; +import org.thingsboard.server.gen.transport.TransportProtos.EntityDeleteMsg; import org.thingsboard.server.gen.transport.TransportProtos.FromDeviceRPCResponseProto; import org.thingsboard.server.gen.transport.TransportProtos.QueueDeleteMsg; import org.thingsboard.server.gen.transport.TransportProtos.QueueUpdateMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ResourceDeleteMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ResourceUpdateMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeNotificationMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToVersionControlServiceMsg; import org.thingsboard.server.queue.TbQueueCallback; import org.thingsboard.server.queue.TbQueueProducer; import org.thingsboard.server.queue.common.MultipleTbQueueCallbackWrapper; @@ -112,6 +123,8 @@ public class DefaultTbClusterService implements TbClusterService { private final AtomicInteger toRuleEngineMsgs = new AtomicInteger(0); private final AtomicInteger toRuleEngineNfs = new AtomicInteger(0); private final AtomicInteger toTransportNfs = new AtomicInteger(0); + private final AtomicInteger toEdgeMsgs = new AtomicInteger(0); + private final AtomicInteger toEdgeNfs = new AtomicInteger(0); @Autowired @Lazy @@ -133,6 +146,7 @@ public class DefaultTbClusterService implements TbClusterService { private final TbAssetProfileCache assetProfileCache; private final GatewayNotificationsService gatewayNotificationsService; private final EdgeService edgeService; + private final TbTransactionalCache edgeIdServiceIdCache; @Override public void pushMsgToCore(TenantId tenantId, EntityId entityId, ToCoreMsg msg, TbQueueCallback callback) { @@ -169,7 +183,7 @@ public class DefaultTbClusterService implements TbClusterService { } @Override - public void pushMsgToVersionControl(TenantId tenantId, TransportProtos.ToVersionControlServiceMsg msg, TbQueueCallback callback) { + public void pushMsgToVersionControl(TenantId tenantId, ToVersionControlServiceMsg msg, TbQueueCallback callback) { TopicPartitionInfo tpi = partitionService.resolve(ServiceType.TB_VC_EXECUTOR, TenantId.SYS_TENANT_ID, tenantId); log.trace("PUSHING msg: {} to:{}", msg, tpi); producerProvider.getTbVersionControlMsgProducer().send(tpi, new TbProtoQueueMsg<>(tenantId.getId(), msg), callback); @@ -386,7 +400,7 @@ public class DefaultTbClusterService implements TbClusterService { if (resource.getResourceType() == ResourceType.LWM2M_MODEL) { TenantId tenantId = resource.getTenantId(); log.trace("[{}][{}][{}] Processing change resource", tenantId, resource.getResourceType(), resource.getResourceKey()); - TransportProtos.ResourceUpdateMsg resourceUpdateMsg = TransportProtos.ResourceUpdateMsg.newBuilder() + ResourceUpdateMsg resourceUpdateMsg = ResourceUpdateMsg.newBuilder() .setTenantIdMSB(tenantId.getId().getMostSignificantBits()) .setTenantIdLSB(tenantId.getId().getLeastSignificantBits()) .setResourceType(resource.getResourceType().name()) @@ -401,7 +415,7 @@ public class DefaultTbClusterService implements TbClusterService { public void onResourceDeleted(TbResourceInfo resource, TbQueueCallback callback) { if (resource.getResourceType() == ResourceType.LWM2M_MODEL) { log.trace("[{}][{}][{}] Processing delete resource", resource.getTenantId(), resource.getResourceType(), resource.getResourceKey()); - TransportProtos.ResourceDeleteMsg resourceDeleteMsg = TransportProtos.ResourceDeleteMsg.newBuilder() + ResourceDeleteMsg resourceDeleteMsg = ResourceDeleteMsg.newBuilder() .setTenantIdMSB(resource.getTenantId().getId().getMostSignificantBits()) .setTenantIdLSB(resource.getTenantId().getId().getLeastSignificantBits()) .setResourceType(resource.getResourceType().name()) @@ -421,7 +435,7 @@ public class DefaultTbClusterService implements TbClusterService { private void broadcastEntityDeleteToTransport(TenantId tenantId, EntityId entityId, String name, TbQueueCallback callback) { log.trace("[{}][{}][{}] Processing [{}] delete event", tenantId, entityId.getEntityType(), entityId.getId(), name); - TransportProtos.EntityDeleteMsg entityDeleteMsg = TransportProtos.EntityDeleteMsg.newBuilder() + EntityDeleteMsg entityDeleteMsg = EntityDeleteMsg.newBuilder() .setEntityType(entityId.getEntityType().name()) .setEntityIdMSB(entityId.getId().getMostSignificantBits()) .setEntityIdLSB(entityId.getId().getLeastSignificantBits()) @@ -453,39 +467,76 @@ public class DefaultTbClusterService implements TbClusterService { } @Override - public void onEdgeEventUpdate(TenantId tenantId, EdgeId edgeId) { - log.trace("[{}] Processing edge {} event update ", tenantId, edgeId); - EdgeEventUpdateMsg msg = new EdgeEventUpdateMsg(tenantId, edgeId); - ToCoreNotificationMsg toCoreMsg = ToCoreNotificationMsg.newBuilder().setEdgeEventUpdate(toProto(msg)).build(); - pushEdgeSyncMsgToCore(edgeId, toCoreMsg); + public void pushMsgToEdge(TenantId tenantId, EntityId entityId, ToEdgeMsg msg, TbQueueCallback callback) { + TopicPartitionInfo tpi = partitionService.resolve(ServiceType.TB_CORE, DataConstants.EDGE_QUEUE_NAME, tenantId, entityId); + TbQueueProducer> toEdgeProducer = producerProvider.getTbEdgeMsgProducer(); + toEdgeProducer.send(tpi, new TbProtoQueueMsg<>(UUID.randomUUID(), msg), callback); + toEdgeMsgs.incrementAndGet(); } @Override - public void pushEdgeSyncRequestToCore(ToEdgeSyncRequest toEdgeSyncRequest) { - log.trace("[{}] Processing edge sync request {} ", toEdgeSyncRequest.getTenantId(), toEdgeSyncRequest); - ToCoreNotificationMsg toCoreMsg = ToCoreNotificationMsg.newBuilder().setToEdgeSyncRequest(toProto(toEdgeSyncRequest)).build(); - pushEdgeSyncMsgToCore(toEdgeSyncRequest.getEdgeId(), toCoreMsg); + public void onEdgeHighPriorityMsg(EdgeHighPriorityMsg msg) { + log.trace("[{}] Processing edge event for edgeId: {}", msg.getTenantId(), msg.getEdgeEvent().getEdgeId()); + ToEdgeNotificationMsg toEdgeNotificationMsg = ToEdgeNotificationMsg.newBuilder().setEdgeHighPriority(toProto(msg)).build(); + processEdgeNotification(msg.getEdgeEvent().getEdgeId(), toEdgeNotificationMsg); } @Override - public void pushEdgeSyncResponseToCore(FromEdgeSyncResponse fromEdgeSyncResponse) { - log.trace("[{}] Processing edge sync response {}", fromEdgeSyncResponse.getTenantId(), fromEdgeSyncResponse); - ToCoreNotificationMsg toCoreMsg = ToCoreNotificationMsg.newBuilder().setFromEdgeSyncResponse(toProto(fromEdgeSyncResponse)).build(); - pushEdgeSyncMsgToCore(fromEdgeSyncResponse.getEdgeId(), toCoreMsg); + public void onEdgeEventUpdate(EdgeEventUpdateMsg msg) { + log.trace("[{}] Processing edge event update for edgeId: {}", msg.getTenantId(), msg.getEdgeId()); + ToEdgeNotificationMsg toEdgeNotificationMsg = ToEdgeNotificationMsg.newBuilder().setEdgeEventUpdate(toProto(msg)).build(); + processEdgeNotification(msg.getEdgeId(), toEdgeNotificationMsg); } - private void pushEdgeSyncMsgToCore(EdgeId edgeId, ToCoreNotificationMsg toCoreMsg) { - TbQueueProducer> toCoreNfProducer = producerProvider.getTbCoreNotificationsMsgProducer(); - Set tbCoreServices = partitionService.getAllServiceIds(ServiceType.TB_CORE); - for (String serviceId : tbCoreServices) { - TopicPartitionInfo tpi = topicService.getNotificationsTopic(ServiceType.TB_CORE, serviceId); - toCoreNfProducer.send(tpi, new TbProtoQueueMsg<>(edgeId.getId(), toCoreMsg), null); - toCoreNfs.incrementAndGet(); + @Override + public void onEdgeStateChangeEvent(ComponentLifecycleMsg msg) { + log.trace("[{}] Processing {} state change event: {}", msg.getTenantId(), EntityType.EDGE, msg.getEvent()); + ComponentLifecycleMsgProto componentLifecycleMsgProto = toProto(msg); + ToEdgeNotificationMsg toEdgeNotificationMsg = ToEdgeNotificationMsg.newBuilder().setComponentLifecycle(componentLifecycleMsgProto).build(); + processEdgeNotification((EdgeId) msg.getEntityId(), toEdgeNotificationMsg); + } + + @Override + public void pushEdgeSyncRequestToEdge(ToEdgeSyncRequest request) { + log.trace("[{}] Processing edge sync request for edgeId: {}", request.getTenantId(), request.getEdgeId()); + ToEdgeNotificationMsg toEdgeNotificationMsg = ToEdgeNotificationMsg.newBuilder().setToEdgeSyncRequest(toProto(request)).build(); + processEdgeNotification(request.getEdgeId(), toEdgeNotificationMsg); + } + + @Override + public void pushEdgeSyncResponseToCore(FromEdgeSyncResponse response, String requestServiceId) { + log.trace("[{}] Processing edge sync response for edgeId: {}", response.getTenantId(), response.getEdgeId()); + ToEdgeNotificationMsg toEdgeNotificationMsg = ToEdgeNotificationMsg.newBuilder().setFromEdgeSyncResponse(toProto(response)).build(); + pushMsgToEdgeNotification(toEdgeNotificationMsg, requestServiceId); + } + + private void processEdgeNotification(EdgeId edgeId, ToEdgeNotificationMsg toEdgeNotificationMsg) { + var serviceIdOpt = Optional.ofNullable(edgeIdServiceIdCache.get(edgeId)); + serviceIdOpt.ifPresentOrElse( + serviceId -> pushMsgToEdgeNotification(toEdgeNotificationMsg, serviceId.get()), + () -> broadcastEdgeNotification(edgeId, toEdgeNotificationMsg) + ); + } + + private void pushMsgToEdgeNotification(ToEdgeNotificationMsg toEdgeNotificationMsg, String serviceId) { + TopicPartitionInfo tpi = topicService.getEdgeNotificationsTopic(serviceId); + TbQueueProducer> toEdgeNotificationProducer = producerProvider.getTbEdgeNotificationsMsgProducer(); + toEdgeNotificationProducer.send(tpi, new TbProtoQueueMsg<>(UUID.randomUUID(), toEdgeNotificationMsg), null); + toEdgeNfs.incrementAndGet(); + } + + private void broadcastEdgeNotification(EdgeId edgeId, ToEdgeNotificationMsg toEdgeNotificationMsg) { + TbQueueProducer> toEdgeNotificationProducer = producerProvider.getTbEdgeNotificationsMsgProducer(); + Set serviceIds = partitionService.getAllServiceIds(ServiceType.TB_CORE); + for (String serviceId : serviceIds) { + TopicPartitionInfo tpi = topicService.getEdgeNotificationsTopic(serviceId); + toEdgeNotificationProducer.send(tpi, new TbProtoQueueMsg<>(edgeId.getId(), toEdgeNotificationMsg), null); + toEdgeNfs.incrementAndGet(); } } private void broadcast(ComponentLifecycleMsg msg) { - TransportProtos.ComponentLifecycleMsgProto componentLifecycleMsgProto = toProto(msg); + ComponentLifecycleMsgProto componentLifecycleMsgProto = toProto(msg); TbQueueProducer> toRuleEngineProducer = producerProvider.getRuleEngineNotificationsMsgProducer(); Set tbRuleEngineServices = partitionService.getAllServiceIds(ServiceType.TB_RULE_ENGINE); EntityType entityType = msg.getEntityId().getEntityType(); @@ -497,7 +548,6 @@ public class DefaultTbClusterService implements TbClusterService { || entityType.equals(EntityType.API_USAGE_STATE) || (entityType.equals(EntityType.DEVICE) && msg.getEvent() == ComponentLifecycleEvent.UPDATED) || entityType.equals(EntityType.ENTITY_VIEW) - || entityType.equals(EntityType.EDGE) || entityType.equals(EntityType.NOTIFICATION_RULE)) { TbQueueProducer> toCoreNfProducer = producerProvider.getTbCoreNotificationsMsgProducer(); Set tbCoreServices = partitionService.getAllServiceIds(ServiceType.TB_CORE); @@ -526,15 +576,17 @@ public class DefaultTbClusterService implements TbClusterService { int toRuleEngineMsgsCnt = toRuleEngineMsgs.getAndSet(0); int toRuleEngineNfsCnt = toRuleEngineNfs.getAndSet(0); int toTransportNfsCnt = toTransportNfs.getAndSet(0); - if (toCoreMsgCnt > 0 || toCoreNfsCnt > 0 || toRuleEngineMsgsCnt > 0 || toRuleEngineNfsCnt > 0 || toTransportNfsCnt > 0) { - log.info("To TbCore: [{}] messages [{}] notifications; To TbRuleEngine: [{}] messages [{}] notifications; To Transport: [{}] notifications", - toCoreMsgCnt, toCoreNfsCnt, toRuleEngineMsgsCnt, toRuleEngineNfsCnt, toTransportNfsCnt); + int toEdgeMsgCnt = toEdgeMsgs.getAndSet(0); + int toEdgeNfsCnt = toEdgeNfs.getAndSet(0); + if (toCoreMsgCnt > 0 || toCoreNfsCnt > 0 || toRuleEngineMsgsCnt > 0 || toRuleEngineNfsCnt > 0 || toTransportNfsCnt > 0 || toEdgeMsgCnt > 0 || toEdgeNfsCnt > 0) { + log.info("To TbCore: [{}] messages [{}] notifications; To TbRuleEngine: [{}] messages [{}] notifications; To Transport: [{}] notifications;" + + "To Edge: [{}] messages [{}] notifications", toCoreMsgCnt, toCoreNfsCnt, toRuleEngineMsgsCnt, toRuleEngineNfsCnt, toTransportNfsCnt, toEdgeMsgCnt, toEdgeNfsCnt); } } } private void sendDeviceStateServiceEvent(TenantId tenantId, DeviceId deviceId, boolean added, boolean updated, boolean deleted) { - TransportProtos.DeviceStateServiceMsgProto.Builder builder = TransportProtos.DeviceStateServiceMsgProto.newBuilder(); + DeviceStateServiceMsgProto.Builder builder = DeviceStateServiceMsgProto.newBuilder(); builder.setTenantIdMSB(tenantId.getId().getMostSignificantBits()); builder.setTenantIdLSB(tenantId.getId().getLeastSignificantBits()); builder.setDeviceIdMSB(deviceId.getId().getMostSignificantBits()); @@ -542,8 +594,8 @@ public class DefaultTbClusterService implements TbClusterService { builder.setAdded(added); builder.setUpdated(updated); builder.setDeleted(deleted); - TransportProtos.DeviceStateServiceMsgProto msg = builder.build(); - pushMsgToCore(tenantId, deviceId, TransportProtos.ToCoreMsg.newBuilder().setDeviceStateServiceMsg(msg).build(), null); + DeviceStateServiceMsgProto msg = builder.build(); + pushMsgToCore(tenantId, deviceId, ToCoreMsg.newBuilder().setDeviceStateServiceMsg(msg).build(), null); } @Override @@ -581,7 +633,7 @@ public class DefaultTbClusterService implements TbClusterService { return; } } - TransportProtos.EdgeNotificationMsgProto.Builder builder = TransportProtos.EdgeNotificationMsgProto.newBuilder(); + EdgeNotificationMsgProto.Builder builder = EdgeNotificationMsgProto.newBuilder(); builder.setTenantIdMSB(tenantId.getId().getMostSignificantBits()); builder.setTenantIdLSB(tenantId.getId().getLeastSignificantBits()); builder.setType(type.name()); @@ -602,9 +654,9 @@ public class DefaultTbClusterService implements TbClusterService { builder.setOriginatorEdgeIdMSB(originatorEdgeId.getId().getMostSignificantBits()); builder.setOriginatorEdgeIdLSB(originatorEdgeId.getId().getLeastSignificantBits()); } - TransportProtos.EdgeNotificationMsgProto msg = builder.build(); + EdgeNotificationMsgProto msg = builder.build(); log.trace("[{}] sending notification to edge service {}", tenantId.getId(), msg); - pushMsgToCore(tenantId, entityId != null ? entityId : tenantId, TransportProtos.ToCoreMsg.newBuilder().setEdgeNotificationMsg(msg).build(), null); + pushMsgToEdge(tenantId, entityId != null ? entityId : tenantId, ToEdgeMsg.newBuilder().setEdgeNotificationMsg(msg).build(), null); if (entityId != null && EntityType.DEVICE.equals(entityId.getEntityType())) { pushDeviceUpdateMessage(tenantId, edgeId, entityId, action); @@ -690,4 +742,5 @@ public class DefaultTbClusterService implements TbClusterService { toTransportNfs.incrementAndGet(); } } + } diff --git a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java index 4462183baa..2a64dd3388 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java @@ -59,7 +59,6 @@ import org.thingsboard.server.dao.resource.ImageCacheKey; import org.thingsboard.server.dao.tenant.TbTenantProfileCache; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos.DeviceStateServiceMsgProto; -import org.thingsboard.server.gen.transport.TransportProtos.EdgeNotificationMsgProto; import org.thingsboard.server.gen.transport.TransportProtos.ErrorEventProto; import org.thingsboard.server.gen.transport.TransportProtos.FromDeviceRPCResponseProto; import org.thingsboard.server.gen.transport.TransportProtos.LifecycleEventProto; @@ -86,7 +85,6 @@ import org.thingsboard.server.queue.discovery.event.PartitionChangeEvent; import org.thingsboard.server.queue.provider.TbCoreQueueFactory; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.apiusage.TbApiUsageStateService; -import org.thingsboard.server.service.edge.EdgeNotificationService; import org.thingsboard.server.service.notification.NotificationSchedulerService; import org.thingsboard.server.service.ota.OtaPackageStateService; import org.thingsboard.server.service.profile.TbAssetProfileCache; @@ -142,7 +140,6 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService tpi.newByTopic(usageStatsConsumer.getConsumer().getTopic())) .collect(Collectors.toSet())); } private void processMsgs(List> msgs, TbQueueConsumer> consumer, CoreQueueConfig config) throws Exception { - List> orderedMsgList = msgs.stream().map(msg -> new IdMsgPair<>(UUID.randomUUID(), msg)).collect(Collectors.toList()); + List> orderedMsgList = msgs.stream().map(msg -> new IdMsgPair<>(UUID.randomUUID(), msg)).toList(); ConcurrentMap> pendingMap = orderedMsgList.stream().collect( Collectors.toConcurrentMap(IdMsgPair::getUuid, IdMsgPair::getMsg)); CountDownLatch processingTimeoutLatch = new CountDownLatch(1); @@ -282,9 +277,6 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService 0) { partitionService.updateQueues(toCoreNotification.getQueueUpdateMsgsList()); callback.onSuccess(); @@ -686,13 +669,6 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService implements TbEdgeConsumerService { + + @Value("${queue.edge.pool-interval:25}") + private int pollInterval; + @Value("${queue.edge.pack-processing-timeout:10000}") + private int packProcessingTimeout; + @Value("${queue.edge.consumer-per-partition:false}") + private boolean consumerPerPartition; + @Value("${queue.edge.pack-processing-retries:3}") + private int packProcessingRetries; + @Value("${queue.edge.stats.enabled:false}") + private boolean statsEnabled; + + private final TbCoreQueueFactory queueFactory; + private final EdgeContextComponent edgeCtx; + private final EdgeConsumerStats stats; + + private MainQueueConsumerManager, EdgeQueueConfig> mainConsumer; + + public DefaultTbEdgeConsumerService(TbCoreQueueFactory tbCoreQueueFactory, ActorSystemContext actorContext, + StatsFactory statsFactory, EdgeContextComponent edgeCtx) { + super(actorContext, null, null, null, null, null, + null, null); + this.edgeCtx = edgeCtx; + this.stats = new EdgeConsumerStats(statsFactory); + this.queueFactory = tbCoreQueueFactory; + } + + @PostConstruct + public void init() { + super.init("tb-edge"); + + this.mainConsumer = MainQueueConsumerManager., EdgeQueueConfig>builder() + .queueKey(new QueueKey(ServiceType.TB_CORE).withQueueName(DataConstants.EDGE_QUEUE_NAME)) + .config(EdgeQueueConfig.of(consumerPerPartition, (int) pollInterval)) + .msgPackProcessor(this::processMsgs) + .consumerCreator((config, partitionId) -> queueFactory.createEdgeMsgConsumer()) + .consumerExecutor(consumersExecutor) + .scheduler(scheduler) + .taskExecutor(mgmtExecutor) + .build(); + } + + @PreDestroy + public void destroy() { + super.destroy(); + } + + @Override + protected void startConsumers() { + super.startConsumers(); + } + + @Override + protected void onTbApplicationEvent(PartitionChangeEvent event) { + var partitions = event.getEdgePartitions(); + log.debug("Subscribing to partitions: {}", partitions); + mainConsumer.update(partitions); + } + + private void processMsgs(List> msgs, TbQueueConsumer> consumer, EdgeQueueConfig edgeQueueConfig) throws InterruptedException { + List> orderedMsgList = msgs.stream().map(msg -> new IdMsgPair<>(UUID.randomUUID(), msg)).toList(); + ConcurrentMap> pendingMap = orderedMsgList.stream().collect( + Collectors.toConcurrentMap(IdMsgPair::getUuid, IdMsgPair::getMsg)); + CountDownLatch processingTimeoutLatch = new CountDownLatch(1); + TbPackProcessingContext> ctx = new TbPackProcessingContext<>( + processingTimeoutLatch, pendingMap, new ConcurrentHashMap<>()); + PendingMsgHolder pendingMsgHolder = new PendingMsgHolder(); + Future submitFuture = consumersExecutor.submit(() -> { + orderedMsgList.forEach((element) -> { + UUID id = element.getUuid(); + TbProtoQueueMsg msg = element.getMsg(); + TbCallback callback = new TbPackCallback<>(id, ctx); + try { + ToEdgeMsg toEdgeMsg = msg.getValue(); + pendingMsgHolder.setToEdgeMsg(toEdgeMsg); + if (toEdgeMsg.hasEdgeNotificationMsg()) { + pushNotificationToEdge(toEdgeMsg.getEdgeNotificationMsg(), 0, packProcessingRetries, callback); + } + if (statsEnabled) { + stats.log(toEdgeMsg); + } + } catch (Throwable e) { + log.warn("[{}] Failed to process message: {}", id, msg, e); + callback.onFailure(e); + } + }); + }); + if (!processingTimeoutLatch.await(packProcessingTimeout, TimeUnit.MILLISECONDS)) { + if (!submitFuture.isDone()) { + submitFuture.cancel(true); + ToEdgeMsg lastSubmitMsg = pendingMsgHolder.getToEdgeMsg(); + log.info("Timeout to process message: {}", lastSubmitMsg); + } + ctx.getFailedMap().forEach((id, msg) -> log.warn("[{}] Failed to process message: {}", id, msg.getValue())); + } + consumer.commit(); + } + + private static class PendingMsgHolder { + @Getter + @Setter + private volatile ToEdgeMsg toEdgeMsg; + } + + @Override + protected ServiceType getServiceType() { + return ServiceType.TB_CORE; + } + + @Override + protected long getNotificationPollDuration() { + return pollInterval; + } + + @Override + protected long getNotificationPackProcessingTimeout() { + return packProcessingTimeout; + } + + @Override + protected int getMgmtThreadPoolSize() { + return Math.max(Runtime.getRuntime().availableProcessors(), 4); + } + + @Override + protected TbQueueConsumer> createNotificationsConsumer() { + return queueFactory.createToEdgeNotificationsMsgConsumer(); + } + + @Override + protected void handleNotification(UUID id, TbProtoQueueMsg msg, TbCallback callback) { + ToEdgeNotificationMsg toEdgeNotificationMsg = msg.getValue(); + try { + if (toEdgeNotificationMsg.hasEdgeHighPriority()) { + EdgeSessionMsg edgeSessionMsg = ProtoUtils.fromProto(toEdgeNotificationMsg.getEdgeHighPriority()); + edgeCtx.getEdgeRpcService().onToEdgeSessionMsg(edgeSessionMsg.getTenantId(), edgeSessionMsg); + callback.onSuccess(); + } else if (toEdgeNotificationMsg.hasEdgeEventUpdate()) { + EdgeSessionMsg edgeSessionMsg = ProtoUtils.fromProto(toEdgeNotificationMsg.getEdgeEventUpdate()); + edgeCtx.getEdgeRpcService().onToEdgeSessionMsg(edgeSessionMsg.getTenantId(), edgeSessionMsg); + callback.onSuccess(); + } else if (toEdgeNotificationMsg.hasToEdgeSyncRequest()) { + EdgeSessionMsg edgeSessionMsg = ProtoUtils.fromProto(toEdgeNotificationMsg.getToEdgeSyncRequest()); + edgeCtx.getEdgeRpcService().onToEdgeSessionMsg(edgeSessionMsg.getTenantId(), edgeSessionMsg); + callback.onSuccess(); + } else if (toEdgeNotificationMsg.hasFromEdgeSyncResponse()) { + EdgeSessionMsg edgeSessionMsg = ProtoUtils.fromProto(toEdgeNotificationMsg.getFromEdgeSyncResponse()); + edgeCtx.getEdgeRpcService().onToEdgeSessionMsg(edgeSessionMsg.getTenantId(), edgeSessionMsg); + callback.onSuccess(); + } else if (toEdgeNotificationMsg.hasComponentLifecycle()) { + ComponentLifecycleMsg componentLifecycle = ProtoUtils.fromProto(toEdgeNotificationMsg.getComponentLifecycle()); + TenantId tenantId = componentLifecycle.getTenantId(); + EdgeId edgeId = new EdgeId(componentLifecycle.getEntityId().getId()); + if (ComponentLifecycleEvent.DELETED.equals(componentLifecycle.getEvent())) { + edgeCtx.getEdgeRpcService().deleteEdge(tenantId, edgeId); + } else if (ComponentLifecycleEvent.UPDATED.equals(componentLifecycle.getEvent())) { + Edge edge = edgeCtx.getEdgeService().findEdgeById(tenantId, edgeId); + edgeCtx.getEdgeRpcService().updateEdge(tenantId, edge); + } + callback.onSuccess(); + } + } catch (Exception e) { + log.error("Error processing edge notification message", e); + callback.onFailure(e); + } + + if (statsEnabled) { + stats.log(msg.getValue()); + } + } + + private void pushNotificationToEdge(EdgeNotificationMsgProto edgeNotificationMsg, int retryCount, int retryLimit, TbCallback callback) { + TenantId tenantId = TenantId.fromUUID(new UUID(edgeNotificationMsg.getTenantIdMSB(), edgeNotificationMsg.getTenantIdLSB())); + log.debug("[{}] Pushing notification to edge {}", tenantId, edgeNotificationMsg); + try { + EdgeEventType type = EdgeEventType.valueOf(edgeNotificationMsg.getType()); + ListenableFuture future; + switch (type) { + case EDGE -> future = edgeCtx.getEdgeProcessor().processEdgeNotification(tenantId, edgeNotificationMsg); + case ASSET -> future = edgeCtx.getAssetProcessor().processEntityNotification(tenantId, edgeNotificationMsg); + case ASSET_PROFILE -> future = edgeCtx.getAssetProfileProcessor().processEntityNotification(tenantId, edgeNotificationMsg); + case DEVICE -> future = edgeCtx.getDeviceProcessor().processEntityNotification(tenantId, edgeNotificationMsg); + case DEVICE_PROFILE -> future = edgeCtx.getDeviceProfileProcessor().processEntityNotification(tenantId, edgeNotificationMsg); + case ENTITY_VIEW -> future = edgeCtx.getEntityViewProcessor().processEntityNotification(tenantId, edgeNotificationMsg); + case DASHBOARD -> future = edgeCtx.getDashboardProcessor().processEntityNotification(tenantId, edgeNotificationMsg); + case RULE_CHAIN -> future = edgeCtx.getRuleChainProcessor().processEntityNotification(tenantId, edgeNotificationMsg); + case USER -> future = edgeCtx.getUserProcessor().processEntityNotification(tenantId, edgeNotificationMsg); + case CUSTOMER -> future = edgeCtx.getCustomerProcessor().processCustomerNotification(tenantId, edgeNotificationMsg); + case OTA_PACKAGE -> future = edgeCtx.getOtaPackageProcessor().processEntityNotification(tenantId, edgeNotificationMsg); + case WIDGETS_BUNDLE -> future = edgeCtx.getWidgetBundleProcessor().processEntityNotification(tenantId, edgeNotificationMsg); + case WIDGET_TYPE -> future = edgeCtx.getWidgetTypeProcessor().processEntityNotification(tenantId, edgeNotificationMsg); + case QUEUE -> future = edgeCtx.getQueueProcessor().processEntityNotification(tenantId, edgeNotificationMsg); + case ALARM -> future = edgeCtx.getAlarmProcessor().processAlarmNotification(tenantId, edgeNotificationMsg); + case ALARM_COMMENT -> future = edgeCtx.getAlarmProcessor().processAlarmCommentNotification(tenantId, edgeNotificationMsg); + case RELATION -> future = edgeCtx.getRelationProcessor().processRelationNotification(tenantId, edgeNotificationMsg); + case TENANT -> future = edgeCtx.getTenantProcessor().processEntityNotification(tenantId, edgeNotificationMsg); + case TENANT_PROFILE -> future = edgeCtx.getTenantProfileProcessor().processEntityNotification(tenantId, edgeNotificationMsg); + case NOTIFICATION_RULE, NOTIFICATION_TARGET, NOTIFICATION_TEMPLATE -> + future = edgeCtx.getNotificationEdgeProcessor().processEntityNotification(tenantId, edgeNotificationMsg); + case TB_RESOURCE -> future = edgeCtx.getResourceProcessor().processEntityNotification(tenantId, edgeNotificationMsg); + case DOMAIN, OAUTH2_CLIENT -> future = edgeCtx.getOAuth2EdgeProcessor().processEntityNotification(tenantId, edgeNotificationMsg); + default -> { + future = Futures.immediateFuture(null); + log.warn("[{}] Edge event type [{}] is not designed to be pushed to edge", tenantId, type); + } + } + Futures.addCallback(future, new FutureCallback<>() { + @Override + public void onSuccess(@Nullable Void unused) { + callback.onSuccess(); + } + + @Override + public void onFailure(@NotNull Throwable throwable) { + if (retryCount < retryLimit) { + log.warn("[{}] Retry {} for message due to failure: {}", tenantId, retryCount + 1, throwable.getMessage()); + pushNotificationToEdge(edgeNotificationMsg, retryCount + 1, retryLimit, callback); + } else { + callBackFailure(tenantId, edgeNotificationMsg, callback, throwable); + } + } + }, MoreExecutors.directExecutor()); + } catch (Exception e) { + if (retryCount < retryLimit) { + log.warn("[{}] Retry {} for message due to exception: {}", tenantId, retryCount + 1, e.getMessage()); + pushNotificationToEdge(edgeNotificationMsg, retryCount + 1, retryLimit, callback); + } else { + callBackFailure(tenantId, edgeNotificationMsg, callback, e); + } + } + } + + private void callBackFailure(TenantId tenantId, EdgeNotificationMsgProto edgeNotificationMsg, TbCallback callback, Throwable throwable) { + log.error("[{}] Can't push to edge updates, edgeNotificationMsg [{}]", tenantId, edgeNotificationMsg, throwable); + callback.onFailure(throwable); + } + + @Scheduled(fixedDelayString = "${queue.edge.stats.print-interval-ms}") + public void printStats() { + if (statsEnabled) { + stats.printStats(); + stats.reset(); + } + } + + @Override + protected void stopConsumers() { + super.stopConsumers(); + mainConsumer.stop(); + mainConsumer.awaitStop(); + } + + @Data(staticConstructor = "of") + public static class EdgeQueueConfig implements QueueConfig { + private final boolean consumerPerPartition; + private final int pollInterval; + } + +} diff --git a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbRuleEngineConsumerService.java b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbRuleEngineConsumerService.java index d36d44e276..c9a6dee588 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbRuleEngineConsumerService.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbRuleEngineConsumerService.java @@ -165,7 +165,7 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService< } @Override - protected void handleNotification(UUID id, TbProtoQueueMsg msg, TbCallback callback) throws Exception { + protected void handleNotification(UUID id, TbProtoQueueMsg msg, TbCallback callback) { ToRuleEngineNotificationMsg nfMsg = msg.getValue(); if (nfMsg.hasComponentLifecycle()) { handleComponentLifecycleMsg(id, ProtoUtils.fromProto(nfMsg.getComponentLifecycle())); diff --git a/application/src/main/java/org/thingsboard/server/service/queue/EdgeConsumerStats.java b/application/src/main/java/org/thingsboard/server/service/queue/EdgeConsumerStats.java new file mode 100644 index 0000000000..be2d060f03 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/queue/EdgeConsumerStats.java @@ -0,0 +1,99 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.service.queue; + +import lombok.extern.slf4j.Slf4j; +import org.thingsboard.server.common.stats.StatsCounter; +import org.thingsboard.server.common.stats.StatsFactory; +import org.thingsboard.server.common.stats.StatsType; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeNotificationMsg; + +import java.util.ArrayList; +import java.util.List; + +@Slf4j +public class EdgeConsumerStats { + + public static final String TOTAL_MSGS = "totalMsgs"; + public static final String EDGE_NOTIFICATIONS = "edgeNfs"; + public static final String TO_CORE_NF_EDGE_EVENT = "coreNfEdgeHPUpd"; + public static final String TO_CORE_NF_EDGE_EVENT_UPDATE = "coreNfEdgeUpd"; + public static final String TO_CORE_NF_EDGE_SYNC_REQUEST = "coreNfEdgeSyncReq"; + public static final String TO_CORE_NF_EDGE_SYNC_RESPONSE = "coreNfEdgeSyncResp"; + public static final String TO_CORE_NF_EDGE_COMPONENT_LIFECYCLE = "coreNfEdgeCompLfcl"; + + private final StatsCounter totalCounter; + private final StatsCounter edgeNotificationsCounter; + private final StatsCounter edgeHighPriorityCounter; + private final StatsCounter edgeEventUpdateCounter; + private final StatsCounter edgeSyncRequestCounter; + private final StatsCounter edgeSyncResponseCounter; + private final StatsCounter edgeComponentLifecycle; + + private final List counters = new ArrayList<>(7); + + public EdgeConsumerStats(StatsFactory statsFactory) { + String statsKey = StatsType.EDGE.getName(); + + this.totalCounter = register(statsFactory.createStatsCounter(statsKey, TOTAL_MSGS)); + this.edgeNotificationsCounter = register(statsFactory.createStatsCounter(statsKey, EDGE_NOTIFICATIONS)); + this.edgeHighPriorityCounter = register(statsFactory.createStatsCounter(statsKey, TO_CORE_NF_EDGE_EVENT)); + this.edgeEventUpdateCounter = register(statsFactory.createStatsCounter(statsKey, TO_CORE_NF_EDGE_EVENT_UPDATE)); + this.edgeSyncRequestCounter = register(statsFactory.createStatsCounter(statsKey, TO_CORE_NF_EDGE_SYNC_REQUEST)); + this.edgeSyncResponseCounter = register(statsFactory.createStatsCounter(statsKey, TO_CORE_NF_EDGE_SYNC_RESPONSE)); + this.edgeComponentLifecycle = register(statsFactory.createStatsCounter(statsKey, TO_CORE_NF_EDGE_COMPONENT_LIFECYCLE)); + } + + private StatsCounter register(StatsCounter counter) { + counters.add(counter); + return counter; + } + + public void log(ToEdgeNotificationMsg msg) { + totalCounter.increment(); + if (msg.hasEdgeHighPriority()) { + edgeHighPriorityCounter.increment(); + } else if (msg.hasEdgeEventUpdate()) { + edgeEventUpdateCounter.increment(); + } else if (msg.hasToEdgeSyncRequest()) { + edgeSyncRequestCounter.increment(); + } else if (msg.hasFromEdgeSyncResponse()) { + edgeSyncResponseCounter.increment(); + } else if (msg.hasComponentLifecycle()) { + edgeComponentLifecycle.increment(); + } + } + + public void log(ToEdgeMsg msg) { + totalCounter.increment(); + edgeNotificationsCounter.increment(); + } + + public void printStats() { + int total = totalCounter.get(); + if (total > 0) { + StringBuilder stats = new StringBuilder(); + counters.forEach(counter -> stats.append(counter.getName()).append(" = [").append(counter.get()).append("] ")); + log.info("Edge Stats: {}", stats); + } + } + + public void reset() { + counters.forEach(StatsCounter::clear); + } + +} diff --git a/application/src/main/java/org/thingsboard/server/service/queue/TbCoreConsumerStats.java b/application/src/main/java/org/thingsboard/server/service/queue/TbCoreConsumerStats.java index 1bd1cb2d5e..aede1263eb 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/TbCoreConsumerStats.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/TbCoreConsumerStats.java @@ -36,7 +36,6 @@ public class TbCoreConsumerStats { public static final String DEVICE_CLAIMS = "claimDevice"; public static final String DEVICE_STATES = "deviceState"; public static final String SUBSCRIPTION_MSGS = "subMsgs"; - public static final String EDGE_NOTIFICATIONS = "edgeNfs"; public static final String DEVICE_CONNECTS = "deviceConnect"; public static final String DEVICE_ACTIVITIES = "deviceActivity"; public static final String DEVICE_DISCONNECTS = "deviceDisconnect"; @@ -45,9 +44,6 @@ public class TbCoreConsumerStats { public static final String TO_CORE_NF_OTHER = "coreNfOther"; // normally, there is no messages when codebase is fine public static final String TO_CORE_NF_COMPONENT_LIFECYCLE = "coreNfCompLfcl"; public static final String TO_CORE_NF_DEVICE_RPC_RESPONSE = "coreNfDevRpcRsp"; - public static final String TO_CORE_NF_EDGE_EVENT_UPDATE = "coreNfEdgeUpd"; - public static final String TO_CORE_NF_EDGE_SYNC_REQUEST = "coreNfEdgeSyncReq"; - public static final String TO_CORE_NF_EDGE_SYNC_RESPONSE = "coreNfEdgeSyncResp"; public static final String TO_CORE_NF_NOTIFICATION_RULE_PROCESSOR = "coreNfNfRlProc"; public static final String TO_CORE_NF_QUEUE_UPDATE = "coreNfQueueUpd"; public static final String TO_CORE_NF_QUEUE_DELETE = "coreNfQueueDel"; @@ -65,7 +61,6 @@ public class TbCoreConsumerStats { private final StatsCounter claimDeviceCounter; private final StatsCounter deviceStateCounter; private final StatsCounter subscriptionMsgCounter; - private final StatsCounter edgeNotificationsCounter; private final StatsCounter deviceConnectsCounter; private final StatsCounter deviceActivitiesCounter; private final StatsCounter deviceDisconnectsCounter; @@ -74,9 +69,6 @@ public class TbCoreConsumerStats { private final StatsCounter toCoreNfOtherCounter; private final StatsCounter toCoreNfComponentLifecycleCounter; private final StatsCounter toCoreNfDeviceRpcResponseCounter; - private final StatsCounter toCoreNfEdgeEventUpdateCounter; - private final StatsCounter toCoreNfEdgeSyncRequestCounter; - private final StatsCounter toCoreNfEdgeSyncResponseCounter; private final StatsCounter toCoreNfNotificationRuleProcessorCounter; private final StatsCounter toCoreNfQueueUpdateCounter; private final StatsCounter toCoreNfQueueDeleteCounter; @@ -84,7 +76,7 @@ public class TbCoreConsumerStats { private final StatsCounter toCoreNfSubscriptionManagerCounter; private final StatsCounter toCoreNfVersionControlResponseCounter; - private final List counters = new ArrayList<>(24); + private final List counters = new ArrayList<>(23); public TbCoreConsumerStats(StatsFactory statsFactory) { String statsKey = StatsType.CORE.getName(); @@ -99,7 +91,6 @@ public class TbCoreConsumerStats { this.claimDeviceCounter = register(statsFactory.createStatsCounter(statsKey, DEVICE_CLAIMS)); this.deviceStateCounter = register(statsFactory.createStatsCounter(statsKey, DEVICE_STATES)); this.subscriptionMsgCounter = register(statsFactory.createStatsCounter(statsKey, SUBSCRIPTION_MSGS)); - this.edgeNotificationsCounter = register(statsFactory.createStatsCounter(statsKey, EDGE_NOTIFICATIONS)); this.deviceConnectsCounter = register(statsFactory.createStatsCounter(statsKey, DEVICE_CONNECTS)); this.deviceActivitiesCounter = register(statsFactory.createStatsCounter(statsKey, DEVICE_ACTIVITIES)); this.deviceDisconnectsCounter = register(statsFactory.createStatsCounter(statsKey, DEVICE_DISCONNECTS)); @@ -109,9 +100,6 @@ public class TbCoreConsumerStats { this.toCoreNfOtherCounter = register(statsFactory.createStatsCounter(statsKey, TO_CORE_NF_OTHER)); this.toCoreNfComponentLifecycleCounter = register(statsFactory.createStatsCounter(statsKey, TO_CORE_NF_COMPONENT_LIFECYCLE)); this.toCoreNfDeviceRpcResponseCounter = register(statsFactory.createStatsCounter(statsKey, TO_CORE_NF_DEVICE_RPC_RESPONSE)); - this.toCoreNfEdgeEventUpdateCounter = register(statsFactory.createStatsCounter(statsKey, TO_CORE_NF_EDGE_EVENT_UPDATE)); - this.toCoreNfEdgeSyncRequestCounter = register(statsFactory.createStatsCounter(statsKey, TO_CORE_NF_EDGE_SYNC_REQUEST)); - this.toCoreNfEdgeSyncResponseCounter = register(statsFactory.createStatsCounter(statsKey, TO_CORE_NF_EDGE_SYNC_RESPONSE)); this.toCoreNfNotificationRuleProcessorCounter = register(statsFactory.createStatsCounter(statsKey, TO_CORE_NF_NOTIFICATION_RULE_PROCESSOR)); this.toCoreNfQueueUpdateCounter = register(statsFactory.createStatsCounter(statsKey, TO_CORE_NF_QUEUE_UPDATE)); this.toCoreNfQueueDeleteCounter = register(statsFactory.createStatsCounter(statsKey, TO_CORE_NF_QUEUE_DELETE)); @@ -155,11 +143,6 @@ public class TbCoreConsumerStats { deviceStateCounter.increment(); } - public void log(TransportProtos.EdgeNotificationMsgProto msg) { - totalCounter.increment(); - edgeNotificationsCounter.increment(); - } - public void log(TransportProtos.DeviceConnectProto msg) { totalCounter.increment(); deviceConnectsCounter.increment(); @@ -193,12 +176,6 @@ public class TbCoreConsumerStats { toCoreNfDeviceRpcResponseCounter.increment(); } else if (msg.hasComponentLifecycle()) { toCoreNfComponentLifecycleCounter.increment(); - } else if (msg.hasEdgeEventUpdate()) { - toCoreNfEdgeEventUpdateCounter.increment(); - } else if (msg.hasToEdgeSyncRequest()) { - toCoreNfEdgeSyncRequestCounter.increment(); - } else if (msg.hasFromEdgeSyncResponse()) { - toCoreNfEdgeSyncResponseCounter.increment(); } else if (msg.getQueueUpdateMsgsCount() > 0) { toCoreNfQueueUpdateCounter.increment(); } else if (msg.getQueueDeleteMsgsCount() > 0) { @@ -218,9 +195,8 @@ public class TbCoreConsumerStats { int total = totalCounter.get(); if (total > 0) { StringBuilder stats = new StringBuilder(); - counters.forEach(counter -> { - stats.append(counter.getName()).append(" = [").append(counter.get()).append("] "); - }); + counters.forEach(counter -> + stats.append(counter.getName()).append(" = [").append(counter.get()).append("] ")); log.info("Core Stats: {}", stats); } } @@ -228,4 +204,5 @@ public class TbCoreConsumerStats { public void reset() { counters.forEach(StatsCounter::clear); } + } diff --git a/application/src/main/java/org/thingsboard/server/service/queue/TbEdgeConsumerService.java b/application/src/main/java/org/thingsboard/server/service/queue/TbEdgeConsumerService.java new file mode 100644 index 0000000000..086a4b2a63 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/queue/TbEdgeConsumerService.java @@ -0,0 +1,19 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.service.queue; + +public interface TbEdgeConsumerService { +} diff --git a/application/src/main/java/org/thingsboard/server/service/queue/processing/AbstractConsumerService.java b/application/src/main/java/org/thingsboard/server/service/queue/processing/AbstractConsumerService.java index a264f912cb..1b7e5d53a3 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/processing/AbstractConsumerService.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/processing/AbstractConsumerService.java @@ -124,7 +124,7 @@ public abstract class AbstractConsumerService> createNotificationsConsumer(); protected void processNotifications(List> msgs, TbQueueConsumer> consumer) throws Exception { - List> orderedMsgList = msgs.stream().map(msg -> new IdMsgPair<>(UUID.randomUUID(), msg)).collect(Collectors.toList()); + List> orderedMsgList = msgs.stream().map(msg -> new IdMsgPair<>(UUID.randomUUID(), msg)).toList(); ConcurrentMap> pendingMap = orderedMsgList.stream().collect( Collectors.toConcurrentMap(IdMsgPair::getUuid, IdMsgPair::getMsg)); CountDownLatch processingTimeoutLatch = new CountDownLatch(1); @@ -211,4 +211,5 @@ public abstract class AbstractConsumerService { softly.assertThat(name).as("cache name").isNotEmpty(); - softly.assertThat(cacheSpecs.getTimeToLiveInMinutes()).as("cache %s time to live", name).isGreaterThan(0); + if (name.equals("edgeSessions")) { + softly.assertThat(cacheSpecs.getTimeToLiveInMinutes()).as("cache %s time to live", name).isEqualTo(0); + } else { + softly.assertThat(cacheSpecs.getTimeToLiveInMinutes()).as("cache %s time to live", name).isGreaterThan(0); + } softly.assertThat(cacheSpecs.getMaxSize()).as("cache %s max size", name).isGreaterThan(0); }); softly.assertAll(); diff --git a/application/src/test/java/org/thingsboard/server/controller/AbstractNotifyEntityTest.java b/application/src/test/java/org/thingsboard/server/controller/AbstractNotifyEntityTest.java index d549407c44..238203cdb0 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AbstractNotifyEntityTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AbstractNotifyEntityTest.java @@ -37,6 +37,7 @@ import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.ToDeviceActorNotificationMsg; +import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; import org.thingsboard.server.dao.audit.AuditLogService; import org.thingsboard.server.dao.model.ModelConstants; @@ -230,6 +231,19 @@ public abstract class AbstractNotifyEntityTest extends AbstractWebTest { Mockito.reset(tbClusterService, auditLogService); } + protected void testNotifyEdgeStateChangeEventManyTimeMsgToEdgeServiceNever(HasName entity, EntityId entityId, EntityId originatorId, + TenantId tenantId, CustomerId customerId, UserId userId, String userName, + ActionType actionType, int cntTimeBroadcast, Object... additionalInfo) { + int cntTime = 1; + testNotificationMsgToEdgeServiceNeverWithActionType(entityId, actionType); + testLogEntityAction(entity, originatorId, tenantId, customerId, userId, userName, actionType, cntTime, additionalInfo); + ArgumentMatcher matcherOriginatorId = argument -> argument.equals(originatorId); + testPushMsgToRuleEngineTime(matcherOriginatorId, tenantId, entity, cntTime); + testBroadcastEdgeStateChangeEventTime(tenantId, cntTimeBroadcast); + Mockito.reset(tbClusterService, auditLogService); + } + + protected void testNotifyEntityBroadcastEntityStateChangeEventMany(HasName entity, HasName originator, TenantId tenantId, CustomerId customerId, UserId userId, String userName, ActionType actionType, @@ -351,11 +365,17 @@ public abstract class AbstractNotifyEntityTest extends AbstractWebTest { protected void testBroadcastEntityStateChangeEventTime(EntityId entityId, TenantId tenantId, int cntTime) { ArgumentMatcher matcherTenantIdId = cntTime > 1 || tenantId == null ? argument -> argument.getClass().equals(TenantId.class) : - argument -> argument.equals(tenantId) ; + argument -> argument.equals(tenantId); Mockito.verify(tbClusterService, times(cntTime)).broadcastEntityStateChangeEvent(Mockito.argThat(matcherTenantIdId), Mockito.any(entityId.getClass()), Mockito.any(ComponentLifecycleEvent.class)); } + protected void testBroadcastEdgeStateChangeEventTime(TenantId tenantId, int cntTime) { + ArgumentMatcher matcherTenantIdId = cntTime > 1 || tenantId == null ? argument -> argument.getClass().equals(TenantId.class) : + argument -> argument.equals(tenantId); + Mockito.verify(tbClusterService, times(cntTime)).onEdgeStateChangeEvent(Mockito.any(ComponentLifecycleMsg.class)); + } + private void testPushMsgToCoreTime(int cntTime) { Mockito.verify(tbClusterService, times(cntTime)).pushMsgToCore(Mockito.any(ToDeviceActorNotificationMsg.class), Mockito.isNull()); } @@ -608,8 +628,8 @@ public abstract class AbstractNotifyEntityTest extends AbstractWebTest { } private String entityClassToEntityTypeName(HasName entity) { - String entityType = entityClassToString(entity); - return "SAVE_OTA_PACKAGE_INFO_REQUEST".equals(entityType) || "OTA_PACKAGE_INFO".equals(entityType)? + String entityType = entityClassToString(entity); + return "SAVE_OTA_PACKAGE_INFO_REQUEST".equals(entityType) || "OTA_PACKAGE_INFO".equals(entityType) ? EntityType.OTA_PACKAGE.name().toUpperCase(Locale.ENGLISH) : entityType; } diff --git a/application/src/test/java/org/thingsboard/server/controller/EdgeControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/EdgeControllerTest.java index b636849774..4d38934dcb 100644 --- a/application/src/test/java/org/thingsboard/server/controller/EdgeControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/EdgeControllerTest.java @@ -40,8 +40,8 @@ import org.springframework.test.context.TestPropertySource; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.common.util.ThingsBoardExecutors; import org.thingsboard.server.common.data.AdminSettings; +import org.thingsboard.server.common.data.AttributeScope; import org.thingsboard.server.common.data.Customer; -import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.EdgeUpgradeInfo; @@ -62,6 +62,7 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantProfileId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; +import org.thingsboard.server.common.data.page.TimePageLink; import org.thingsboard.server.common.data.queue.Queue; import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.common.data.rule.RuleChainMetaData; @@ -166,7 +167,7 @@ public class EdgeControllerTest extends AbstractControllerTest { Assert.assertEquals(NULL_UUID, savedEdge.getCustomerId().getId()); Assert.assertEquals(edge.getName(), savedEdge.getName()); - testNotifyEntityBroadcastEntityStateChangeEventManyTimeMsgToEdgeServiceNever(savedEdge, savedEdge.getId(), savedEdge.getId(), + testNotifyEdgeStateChangeEventManyTimeMsgToEdgeServiceNever(savedEdge, savedEdge.getId(), savedEdge.getId(), tenantId, tenantAdminUser.getCustomerId(), tenantAdminUser.getId(), tenantAdminUser.getEmail(), ActionType.ADDED, 2); @@ -176,7 +177,7 @@ public class EdgeControllerTest extends AbstractControllerTest { Edge foundEdge = doGet("/api/edge/" + savedEdge.getId().getId().toString(), Edge.class); Assert.assertEquals(foundEdge.getName(), savedEdge.getName()); - testNotifyEntityBroadcastEntityStateChangeEventManyTimeMsgToEdgeServiceNever(foundEdge, foundEdge.getId(), foundEdge.getId(), + testNotifyEdgeStateChangeEventManyTimeMsgToEdgeServiceNever(foundEdge, foundEdge.getId(), foundEdge.getId(), tenantId, tenantAdminUser.getCustomerId(), tenantAdminUser.getId(), tenantAdminUser.getEmail(), ActionType.UPDATED, 1); } @@ -876,7 +877,7 @@ public class EdgeControllerTest extends AbstractControllerTest { Asset asset = new Asset(); asset.setName("Test Sync Edge Asset 1"); - asset.setType("test"); + asset.setType("default"); Asset savedAsset = doPost("/api/asset", asset, Asset.class); Device device = new Device(); @@ -896,7 +897,7 @@ public class EdgeControllerTest extends AbstractControllerTest { edgeImitator.ignoreType(OAuth2ClientUpdateMsg.class); edgeImitator.ignoreType(OAuth2DomainUpdateMsg.class); - edgeImitator.expectMessageAmount(27); + edgeImitator.expectMessageAmount(26); edgeImitator.connect(); waitForMessages(edgeImitator); @@ -905,16 +906,16 @@ public class EdgeControllerTest extends AbstractControllerTest { Assert.assertTrue(popDeviceProfileMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "default")); Assert.assertTrue(popDeviceMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "Test Sync Edge Device 1")); Assert.assertTrue(popDeviceCredentialsMsg(edgeImitator.getDownlinkMsgs(), savedDevice.getId())); - Assert.assertTrue(popAssetProfileMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "test")); + Assert.assertTrue(popAssetProfileMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "default")); Assert.assertTrue(popAssetMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "Test Sync Edge Asset 1")); - Assert.assertTrue(edgeImitator.getDownlinkMsgs().isEmpty()); + printQueueMsgsIfNotEmpty(edgeImitator); - edgeImitator.expectMessageAmount(22); - doPost("/api/edge/sync/" + edge.getId()); + edgeImitator.expectMessageAmount(21); + doPost("/api/edge/sync/" + edge.getId()).andExpect(status().isOk()); waitForMessages(edgeImitator); verifyFetchersMsgs(edgeImitator, savedDevice); - Assert.assertTrue(edgeImitator.getDownlinkMsgs().isEmpty()); + printQueueMsgsIfNotEmpty(edgeImitator); edgeImitator.allowIgnoredTypes(); try { @@ -930,6 +931,15 @@ public class EdgeControllerTest extends AbstractControllerTest { .andExpect(status().isOk()); } + private static void printQueueMsgsIfNotEmpty(EdgeImitator edgeImitator) { + if (!edgeImitator.getDownlinkMsgs().isEmpty()) { + for (AbstractMessage downlinkMsg : edgeImitator.getDownlinkMsgs()) { + log.warn("Unexpected message in the queue: {}", downlinkMsg); + } + } + Assert.assertTrue(edgeImitator.getDownlinkMsgs().isEmpty()); + } + private RuleChainId getEdgeRootRuleChainId(EdgeImitator edgeImitator) { try { EdgeId edgeId = new EdgeId(new UUID(edgeImitator.getConfiguration().getEdgeIdMSB(), edgeImitator.getConfiguration().getEdgeIdLSB())); @@ -948,11 +958,18 @@ public class EdgeControllerTest extends AbstractControllerTest { } private void simulateEdgeActivation(Edge edge) throws Exception { + Awaitility.await() + .atMost(TIMEOUT, TimeUnit.SECONDS) + .until(() -> { + List ruleChains = getEdgeRuleChains(edge.getId()); + return ruleChains.size() == 1 && ruleChains.get(0).getId().equals(edge.getRootRuleChainId()); + }); + ObjectNode attributes = JacksonUtil.newObjectNode(); attributes.put("active", true); - doPost("/api/plugins/telemetry/EDGE/" + edge.getId() + "/attributes/" + DataConstants.SERVER_SCOPE, attributes); + doPost("/api/plugins/telemetry/EDGE/" + edge.getId() + "/attributes/" + AttributeScope.SERVER_SCOPE, attributes); Awaitility.await() - .atMost(30, TimeUnit.SECONDS) + .atMost(TIMEOUT, TimeUnit.SECONDS) .until(() -> { List> values = doGetAsyncTyped("/api/plugins/telemetry/EDGE/" + edge.getId() + "/values/attributes/SERVER_SCOPE", new TypeReference<>() {}); @@ -960,8 +977,9 @@ public class EdgeControllerTest extends AbstractControllerTest { if (activeAttrOpt.isEmpty()) { return false; } + List ruleChains = getEdgeRuleChains(edge.getId()); Map activeAttr = activeAttrOpt.get(); - return "true".equals(activeAttr.get("value").toString()); + return "true".equals(activeAttr.get("value").toString()) && ruleChains.size() == 1; }); } @@ -988,13 +1006,12 @@ public class EdgeControllerTest extends AbstractControllerTest { Assert.assertTrue(popAssetProfileMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "default")); Assert.assertTrue(popDeviceProfileMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "default")); Assert.assertTrue(popAssetProfileMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "default")); - Assert.assertTrue(popAssetProfileMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "test")); Assert.assertTrue(popUserMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, TENANT_ADMIN_EMAIL, Authority.TENANT_ADMIN)); Assert.assertTrue(popCustomerMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "Public")); Assert.assertTrue(popDeviceProfileMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "default")); Assert.assertTrue(popDeviceMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "Test Sync Edge Device 1")); Assert.assertTrue(popDeviceCredentialsMsg(edgeImitator.getDownlinkMsgs(), savedDevice.getId())); - Assert.assertTrue(popAssetProfileMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "test")); + Assert.assertTrue(popAssetProfileMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "default")); Assert.assertTrue(popAssetMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "Test Sync Edge Asset 1")); Assert.assertTrue(popTenantMsg(edgeImitator.getDownlinkMsgs(), tenantId)); Assert.assertTrue(popTenantProfileMsg(edgeImitator.getDownlinkMsgs(), tenantProfileId)); @@ -1223,6 +1240,12 @@ public class EdgeControllerTest extends AbstractControllerTest { return doPost("/api/edge", edge, Edge.class); } + private List getEdgeRuleChains(EdgeId edgeId) throws Exception { + return doGetTypedWithTimePageLink("/api/edge/" + edgeId + "/ruleChains?", + new TypeReference>() { + }, new TimePageLink(10)).getData(); + } + @Test public void testGetEdgeInstallInstructions() throws Exception { Edge edge = constructEdge(tenantId, "Edge for Test Docker Install Instructions", "default", "7390c3a6-69b0-9910-d155-b90aca4b772e", "l7q4zsjplzwhk16geqxy"); @@ -1271,6 +1294,8 @@ public class EdgeControllerTest extends AbstractControllerTest { Assert.assertFalse(edgeUpgradeInstructionsService.isUpgradeAvailable(savedEdge.getTenantId(), savedEdge.getId())); edgeUpgradeInstructionsService.setAppVersion("3.6.1.5"); Assert.assertTrue(edgeUpgradeInstructionsService.isUpgradeAvailable(savedEdge.getTenantId(), savedEdge.getId())); + edgeUpgradeInstructionsService.setAppVersion("3.6.1.6-SNAPSHOT"); + Assert.assertTrue(edgeUpgradeInstructionsService.isUpgradeAvailable(savedEdge.getTenantId(), savedEdge.getId())); edgeUpgradeInstructionsService.setAppVersion("3.6.2"); Assert.assertTrue(edgeUpgradeInstructionsService.isUpgradeAvailable(savedEdge.getTenantId(), savedEdge.getId())); @@ -1281,6 +1306,8 @@ public class EdgeControllerTest extends AbstractControllerTest { Assert.assertFalse(edgeUpgradeInstructionsService.isUpgradeAvailable(savedEdge.getTenantId(), savedEdge.getId())); edgeUpgradeInstructionsService.setAppVersion("3.6.2"); Assert.assertTrue(edgeUpgradeInstructionsService.isUpgradeAvailable(savedEdge.getTenantId(), savedEdge.getId())); + edgeUpgradeInstructionsService.setAppVersion("3.6.2-SNAPSHOT"); + Assert.assertTrue(edgeUpgradeInstructionsService.isUpgradeAvailable(savedEdge.getTenantId(), savedEdge.getId())); edgeUpgradeInstructionsService.setAppVersion("3.6.2.6"); Assert.assertTrue(edgeUpgradeInstructionsService.isUpgradeAvailable(savedEdge.getTenantId(), savedEdge.getId())); } diff --git a/application/src/test/java/org/thingsboard/server/controller/EntityQueryControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/EntityQueryControllerTest.java index 17de555bdc..5d04b16dfa 100644 --- a/application/src/test/java/org/thingsboard/server/controller/EntityQueryControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/EntityQueryControllerTest.java @@ -629,7 +629,7 @@ public class EntityQueryControllerTest extends AbstractControllerTest { Awaitility.await() .alias("data by query") - .atMost(30, TimeUnit.SECONDS) + .atMost(TIMEOUT, TimeUnit.SECONDS) .until(() -> { var data = doPostWithTypedResponse("/api/entitiesQuery/find", query, new TypeReference>() {}); var loadedEntities = new ArrayList<>(data.getData()); diff --git a/application/src/test/java/org/thingsboard/server/controller/TenantControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/TenantControllerTest.java index e1beda28d8..c8cc72c5b5 100644 --- a/application/src/test/java/org/thingsboard/server/controller/TenantControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/TenantControllerTest.java @@ -664,7 +664,7 @@ public class TenantControllerTest extends AbstractControllerTest { savedDifferentTenant.setTenantProfileId(tenantProfile.getId()); savedDifferentTenant = saveTenant(savedDifferentTenant); TenantId tenantId = differentTenantId; - await().atMost(30, TimeUnit.SECONDS) + await().atMost(TIMEOUT, TimeUnit.SECONDS) .until(() -> { TopicPartitionInfo tpi = partitionService.resolve(ServiceType.TB_RULE_ENGINE, MAIN_QUEUE_NAME, tenantId, tenantId); return !tpi.getTenantId().get().isSysTenantId(); @@ -678,7 +678,7 @@ public class TenantControllerTest extends AbstractControllerTest { tenantProfile.setIsolatedTbRuleEngine(false); tenantProfile.getProfileData().setQueueConfiguration(Collections.emptyList()); tenantProfile = doPost("/api/tenantProfile", tenantProfile, TenantProfile.class); - await().atMost(30, TimeUnit.SECONDS) + await().atMost(TIMEOUT, TimeUnit.SECONDS) .until(() -> partitionService.resolve(ServiceType.TB_RULE_ENGINE, MAIN_QUEUE_NAME, tenantId, tenantId) .getTenantId().get().isSysTenantId()); @@ -690,7 +690,7 @@ public class TenantControllerTest extends AbstractControllerTest { submittedMsgs.add(tbMsg.getId()); Thread.sleep(timeLeft / msgs); } - await().atMost(30, TimeUnit.SECONDS).untilAsserted(() -> { + await().atMost(TIMEOUT, TimeUnit.SECONDS).untilAsserted(() -> { verify(queueAdmin, times(1)).deleteTopic(eq(isolatedTopic)); }); @@ -719,13 +719,13 @@ public class TenantControllerTest extends AbstractControllerTest { savedDifferentTenant.setTenantProfileId(tenantProfile.getId()); savedDifferentTenant = saveTenant(savedDifferentTenant); TenantId tenantId = differentTenantId; - await().atMost(30, TimeUnit.SECONDS).untilAsserted(() -> { + await().atMost(TIMEOUT, TimeUnit.SECONDS).untilAsserted(() -> { assertThat(partitionService.getMyPartitions(new QueueKey(ServiceType.TB_RULE_ENGINE, tenantId))).isNotNull(); }); TopicPartitionInfo tpi = partitionService.resolve(ServiceType.TB_RULE_ENGINE, tenantId, tenantId); assertThat(tpi.getTenantId()).hasValue(tenantId); TbMsg tbMsg = publishTbMsg(tenantId, tpi); - await().atMost(30, TimeUnit.SECONDS).untilAsserted(() -> { + await().atMost(TIMEOUT, TimeUnit.SECONDS).untilAsserted(() -> { verify(actorContext).tell(argThat(msg -> { return msg instanceof QueueToRuleEngineMsg && ((QueueToRuleEngineMsg) msg).getMsg().getId().equals(tbMsg.getId()); })); @@ -733,7 +733,7 @@ public class TenantControllerTest extends AbstractControllerTest { deleteDifferentTenant(); - await().atMost(30, TimeUnit.SECONDS).untilAsserted(() -> { + await().atMost(TIMEOUT, TimeUnit.SECONDS).untilAsserted(() -> { assertThat(partitionService.getMyPartitions(new QueueKey(ServiceType.TB_RULE_ENGINE, tenantId))).isNull(); assertThatThrownBy(() -> partitionService.resolve(ServiceType.TB_RULE_ENGINE, tenantId, tenantId)) .isInstanceOf(TenantNotFoundException.class); @@ -753,7 +753,7 @@ public class TenantControllerTest extends AbstractControllerTest { } private void verifyUsedQueueAndMessage(String queue, TenantId tenantId, EntityId entityId, String msgType, Runnable action, Consumer tpiAssert) { - await().atMost(30, TimeUnit.SECONDS) + await().atMost(TIMEOUT, TimeUnit.SECONDS) .untilAsserted(() -> { TopicPartitionInfo tpi = partitionService.resolve(ServiceType.TB_RULE_ENGINE, queue, tenantId, entityId); tpiAssert.accept(tpi); diff --git a/application/src/test/java/org/thingsboard/server/edge/AbstractEdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/AbstractEdgeTest.java index bd8a59a975..b3a1dd790e 100644 --- a/application/src/test/java/org/thingsboard/server/edge/AbstractEdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/AbstractEdgeTest.java @@ -17,6 +17,7 @@ package org.thingsboard.server.edge; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.protobuf.AbstractMessage; import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.MessageLite; @@ -27,7 +28,6 @@ import org.junit.Before; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.TestPropertySource; import org.thingsboard.common.util.JacksonUtil; -import org.thingsboard.server.cluster.TbClusterService; import org.thingsboard.server.common.data.AdminSettings; import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.Dashboard; @@ -127,9 +127,6 @@ abstract public class AbstractEdgeTest extends AbstractControllerTest { @Autowired protected EdgeEventService edgeEventService; - @Autowired - protected TbClusterService clusterService; - @Before public void setupEdgeTest() throws Exception { loginSysAdmin(); @@ -207,7 +204,7 @@ abstract public class AbstractEdgeTest extends AbstractControllerTest { + "/asset/" + savedAsset.getUuidId(), Asset.class); // wait until assign device and asset events are fully processed by edge notification service - TimeUnit.MILLISECONDS.sleep(500); + TimeUnit.MILLISECONDS.sleep(1000); } protected void extendDeviceProfileData(DeviceProfile deviceProfile) { @@ -697,4 +694,25 @@ abstract public class AbstractEdgeTest extends AbstractControllerTest { .andExpect(status().isOk()); } + + protected ObjectNode createDefaultRpc() { + return createDefaultRpc(1); + } + + protected ObjectNode createDefaultRpc(Integer value) { + ObjectNode rpc = JacksonUtil.newObjectNode(); + rpc.put("method", "setGpio"); + + ObjectNode params = JacksonUtil.newObjectNode(); + + params.put("pin", 7); + params.put("value", value); + + rpc.set("params", params); + rpc.put("persistent", true); + rpc.put("timeout", 5000); + + return rpc; + } + } diff --git a/application/src/test/java/org/thingsboard/server/edge/DeviceEdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/DeviceEdgeTest.java index 071d6b1391..387011717a 100644 --- a/application/src/test/java/org/thingsboard/server/edge/DeviceEdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/DeviceEdgeTest.java @@ -51,7 +51,6 @@ import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.ota.OtaPackageType; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; -import org.thingsboard.server.common.data.page.TimePageLink; import org.thingsboard.server.common.data.security.DeviceCredentials; import org.thingsboard.server.common.data.security.DeviceCredentialsType; import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration; @@ -79,9 +78,13 @@ import java.util.Optional; import java.util.Random; import java.util.UUID; import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.thingsboard.server.gen.edge.v1.UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE; @TestPropertySource(properties = { "transport.mqtt.enabled=true" @@ -107,7 +110,7 @@ public class DeviceEdgeTest extends AbstractEdgeTest { AbstractMessage latestMessage = edgeImitator.getLatestMessage(); Assert.assertTrue(latestMessage instanceof DeviceUpdateMsg); DeviceUpdateMsg deviceUpdateMsg = (DeviceUpdateMsg) latestMessage; - Assert.assertEquals(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE, deviceUpdateMsg.getMsgType()); + Assert.assertEquals(ENTITY_DELETED_RPC_MESSAGE, deviceUpdateMsg.getMsgType()); Assert.assertEquals(savedDevice.getUuidId().getMostSignificantBits(), deviceUpdateMsg.getIdMSB()); Assert.assertEquals(savedDevice.getUuidId().getLeastSignificantBits(), deviceUpdateMsg.getIdLSB()); @@ -184,7 +187,7 @@ public class DeviceEdgeTest extends AbstractEdgeTest { latestMessage = edgeImitator.getLatestMessage(); Assert.assertTrue(latestMessage instanceof DeviceUpdateMsg); deviceUpdateMsg = (DeviceUpdateMsg) latestMessage; - Assert.assertEquals(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE, deviceUpdateMsg.getMsgType()); + Assert.assertEquals(ENTITY_DELETED_RPC_MESSAGE, deviceUpdateMsg.getMsgType()); Assert.assertEquals(savedDevice.getUuidId().getMostSignificantBits(), deviceUpdateMsg.getIdMSB()); Assert.assertEquals(savedDevice.getUuidId().getLeastSignificantBits(), deviceUpdateMsg.getIdLSB()); @@ -399,7 +402,7 @@ public class DeviceEdgeTest extends AbstractEdgeTest { Device savedDevice = saveDeviceOnCloudAndVerifyDeliveryToEdge(); UplinkMsg.Builder upLinkMsgBuilder = UplinkMsg.newBuilder(); DeviceUpdateMsg.Builder deviceDeleteMsgBuilder = DeviceUpdateMsg.newBuilder(); - deviceDeleteMsgBuilder.setMsgType(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE); + deviceDeleteMsgBuilder.setMsgType(ENTITY_DELETED_RPC_MESSAGE); deviceDeleteMsgBuilder.setIdMSB(savedDevice.getId().getId().getMostSignificantBits()); deviceDeleteMsgBuilder.setIdLSB(savedDevice.getId().getId().getLeastSignificantBits()); testAutoGeneratedCodeByProtobuf(deviceDeleteMsgBuilder); @@ -624,17 +627,10 @@ public class DeviceEdgeTest extends AbstractEdgeTest { if (keyValueProto.getKey().equals(expectedKey)) { Assert.assertEquals(expectedKey, keyValueProto.getKey()); switch (keyValueProto.getType()) { - case STRING_V: - Assert.assertEquals(expectedValue, keyValueProto.getStringV()); - break; - case LONG_V: - Assert.assertEquals(Long.parseLong(expectedValue), keyValueProto.getLongV()); - break; - case JSON_V: - Assert.assertEquals(JacksonUtil.toJsonNode(expectedValue), JacksonUtil.toJsonNode(keyValueProto.getJsonV())); - break; - default: - Assert.fail("Unexpected data type: " + keyValueProto.getType()); + case STRING_V -> Assert.assertEquals(expectedValue, keyValueProto.getStringV()); + case LONG_V -> Assert.assertEquals(Long.parseLong(expectedValue), keyValueProto.getLongV()); + case JSON_V -> Assert.assertEquals(JacksonUtil.toJsonNode(expectedValue), JacksonUtil.toJsonNode(keyValueProto.getJsonV())); + default -> Assert.fail("Unexpected data type: " + keyValueProto.getType()); } found = true; } @@ -768,9 +764,6 @@ public class DeviceEdgeTest extends AbstractEdgeTest { Assert.assertEquals(1, relatedEdgeIds.size()); Assert.assertEquals(tmpEdge.getId(), relatedEdgeIds.get(0)); - // clean up stored edge events - edgeEventService.cleanupEvents(1); - // edge is disconnected: perform rpc call - no edge event saved doPostAsync( "/api/rpc/oneway/" + device.getId().getId().toString(), @@ -779,10 +772,7 @@ public class DeviceEdgeTest extends AbstractEdgeTest { status().isOk()); Awaitility.await() .atMost(TIMEOUT, TimeUnit.SECONDS) - .until(() -> { - PageData result = edgeEventService.findEdgeEvents(tenantId, tmpEdge.getId(), 0L, null, new TimePageLink(1)); - return result.getTotalElements() == 0; - }); + .untilAsserted(() -> verify(tbClusterService, never()).onEdgeHighPriorityMsg(any())); // edge is connected: perform rpc call to verify edgeId in DeviceActorMessageProcessor updated properly simulateEdgeActivation(tmpEdge); @@ -792,21 +782,9 @@ public class DeviceEdgeTest extends AbstractEdgeTest { String.class, status().isOk()); - final AtomicReference> resultRef = new AtomicReference<>(); Awaitility.await() .atMost(TIMEOUT, TimeUnit.SECONDS) - .until(() -> { - PageData result = edgeEventService.findEdgeEvents(tenantId, tmpEdge.getId(), 0L, null, new TimePageLink(1)); - resultRef.set(result); - return result != null && result.getData().size() == 1; - }); - - PageData result = resultRef.get(); - EdgeEvent edgeEvent = result.getData().get(0); - Assert.assertEquals(EdgeEventActionType.RPC_CALL, edgeEvent.getAction()); - Assert.assertEquals(EdgeEventType.DEVICE, edgeEvent.getType()); - Assert.assertEquals(tmpEdge.getId(), edgeEvent.getEdgeId()); - Assert.assertEquals(device.getId().getId(), edgeEvent.getEntityId()); + .untilAsserted(() -> verify(tbClusterService, times(1)).onEdgeHighPriorityMsg(any())); // clean up tmp edge doDelete("/api/edge/" + tmpEdge.getId().getId().toString()).andExpect(status().isOk()); @@ -824,27 +802,12 @@ public class DeviceEdgeTest extends AbstractEdgeTest { private DeviceCredentials buildDeviceCredentialsForUplinkMsg(DeviceId deviceId) { DeviceCredentials deviceCredentials = new DeviceCredentials(); deviceCredentials.setDeviceId(deviceId); + deviceCredentials.setCredentialsId(String.valueOf(UUID.randomUUID())); deviceCredentials.setCredentialsValue("NEW_TOKEN"); deviceCredentials.setCredentialsType(DeviceCredentialsType.ACCESS_TOKEN); return deviceCredentials; } - private ObjectNode createDefaultRpc() { - ObjectNode rpc = JacksonUtil.newObjectNode(); - rpc.put("method", "setGpio"); - - ObjectNode params = JacksonUtil.newObjectNode(); - - params.put("pin", 7); - params.put("value", 1); - - rpc.set("params", params); - rpc.put("persistent", true); - rpc.put("timeout", 5000); - - return rpc; - } - private void simulateEdgeActivation(Edge edge) throws Exception { ObjectNode attributes = JacksonUtil.newObjectNode(); attributes.put("active", true); diff --git a/application/src/test/java/org/thingsboard/server/edge/TelemetryEdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/TelemetryEdgeTest.java index b77e0b5ccc..2afe17f935 100644 --- a/application/src/test/java/org/thingsboard/server/edge/TelemetryEdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/TelemetryEdgeTest.java @@ -33,33 +33,46 @@ import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.dao.service.DaoSqlTest; import org.thingsboard.server.gen.edge.v1.AttributeDeleteMsg; import org.thingsboard.server.gen.edge.v1.DeviceCredentialsUpdateMsg; +import org.thingsboard.server.gen.edge.v1.DeviceRpcCallMsg; import org.thingsboard.server.gen.edge.v1.DeviceUpdateMsg; import org.thingsboard.server.gen.edge.v1.EntityDataProto; +import org.thingsboard.server.gen.edge.v1.RpcRequestMsg; import org.thingsboard.server.gen.edge.v1.UplinkMsg; import org.thingsboard.server.gen.transport.TransportProtos; import java.util.List; import java.util.concurrent.TimeUnit; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + @DaoSqlTest public class TelemetryEdgeTest extends AbstractEdgeTest { @Test public void testTimeseriesWithFailures() throws Exception { int numberOfTimeseriesToSend = 333; + int numberOfHighPriorityRpcRequests = 13; + int frequencyOfRpcRequestsPerTimeseries = 25; Device device = findDeviceByName("Edge Device 1"); edgeImitator.setRandomFailuresOnTimeseriesDownlink(true); // imitator will generate failure in 5% of cases edgeImitator.setFailureProbability(5.0); - edgeImitator.expectMessageAmount(numberOfTimeseriesToSend); + edgeImitator.expectMessageAmount(numberOfTimeseriesToSend + numberOfHighPriorityRpcRequests); for (int idx = 1; idx <= numberOfTimeseriesToSend; idx++) { String timeseriesData = "{\"data\":{\"idx\":" + idx + "},\"ts\":" + System.currentTimeMillis() + "}"; JsonNode timeseriesEntityData = JacksonUtil.toJsonNode(timeseriesData); EdgeEvent edgeEvent = constructEdgeEvent(tenantId, edge.getId(), EdgeEventActionType.TIMESERIES_UPDATED, device.getId().getId(), EdgeEventType.DEVICE, timeseriesEntityData); edgeEventService.saveAsync(edgeEvent).get(); + if (idx % frequencyOfRpcRequestsPerTimeseries == 0) { + doPostAsync( + "/api/rpc/oneway/" + device.getId().getId().toString(), + JacksonUtil.toString(createDefaultRpc(idx)), + String.class, + status().isOk()); + } } Assert.assertTrue(edgeImitator.waitForMessages(120)); @@ -71,6 +84,14 @@ public class TelemetryEdgeTest extends AbstractEdgeTest { Assert.assertTrue(isIdxExistsInTheDownlinkList(idx, allTelemetryMsgs)); } + List allDeviceRpcCallMsgs = edgeImitator.findAllMessagesByType(DeviceRpcCallMsg.class); + Assert.assertEquals(numberOfHighPriorityRpcRequests, allDeviceRpcCallMsgs.size()); + + for (int idx = 1; idx <= numberOfHighPriorityRpcRequests; idx++) { + int pinValue = idx * frequencyOfRpcRequestsPerTimeseries; + Assert.assertTrue(isPinValueExistsInTheRpcDownlinkList(pinValue, allDeviceRpcCallMsgs)); + } + edgeImitator.setRandomFailuresOnTimeseriesDownlink(false); } @@ -175,6 +196,16 @@ public class TelemetryEdgeTest extends AbstractEdgeTest { return false; } + private boolean isPinValueExistsInTheRpcDownlinkList(int idx, List rpcDownlinkMsgs) { + for (DeviceRpcCallMsg proto : rpcDownlinkMsgs) { + RpcRequestMsg rpcRequestMsg = proto.getRequestMsg(); + if ((JacksonUtil.toJsonNode(rpcRequestMsg.getParams())).get("value").intValue() == idx) { + return true; + } + } + return false; + } + @Test public void testTimeseriesDeliveryFailuresForever_deliverOnlyDeviceUpdateMsgs() throws Exception { int numberOfMsgsToSend = 100; diff --git a/application/src/test/java/org/thingsboard/server/edge/UserEdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/UserEdgeTest.java index fc9eeaa36e..1c3b5ccb7a 100644 --- a/application/src/test/java/org/thingsboard/server/edge/UserEdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/UserEdgeTest.java @@ -17,7 +17,6 @@ package org.thingsboard.server.edge; import com.google.protobuf.AbstractMessage; import org.junit.Assert; -import org.junit.Ignore; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @@ -46,10 +45,9 @@ public class UserEdgeTest extends AbstractEdgeTest { private BCryptPasswordEncoder passwordEncoder; @Test - @Ignore("Ignored until fix") public void testCreateUpdateDeleteTenantUser() throws Exception { // create user - edgeImitator.expectMessageAmount(4); + edgeImitator.expectMessageAmount(6); User newTenantAdmin = new User(); newTenantAdmin.setAuthority(Authority.TENANT_ADMIN); newTenantAdmin.setTenantId(tenantId); @@ -57,7 +55,9 @@ public class UserEdgeTest extends AbstractEdgeTest { newTenantAdmin.setFirstName("Boris"); newTenantAdmin.setLastName("Johnson"); User savedTenantAdmin = createUser(newTenantAdmin, "tenant"); - Assert.assertTrue(edgeImitator.waitForMessages()); // wait 4 messages - x2 user update msg and x2 user credentials update msgs + Assert.assertTrue(edgeImitator.waitForMessages()); // wait 6 messages - x2 user update msg and x4 user credentials update msgs (create + authenticate user) + Assert.assertEquals(2, edgeImitator.findAllMessagesByType(UserUpdateMsg.class).size()); + Assert.assertEquals(4, edgeImitator.findAllMessagesByType(UserCredentialsUpdateMsg.class).size()); Optional userUpdateMsgOpt = edgeImitator.findMessageByType(UserUpdateMsg.class); Assert.assertTrue(userUpdateMsgOpt.isPresent()); UserUpdateMsg userUpdateMsg = userUpdateMsgOpt.get(); @@ -133,7 +133,7 @@ public class UserEdgeTest extends AbstractEdgeTest { Assert.assertTrue(edgeImitator.waitForMessages()); // create user - edgeImitator.expectMessageAmount(4); + edgeImitator.expectMessageAmount(6); User customerUser = new User(); customerUser.setAuthority(Authority.CUSTOMER_USER); customerUser.setTenantId(tenantId); @@ -142,7 +142,9 @@ public class UserEdgeTest extends AbstractEdgeTest { customerUser.setFirstName("John"); customerUser.setLastName("Edwards"); User savedCustomerUser = createUser(customerUser, "customer"); - Assert.assertTrue(edgeImitator.waitForMessages()); // wait 4 messages - x2 user update msg and x2 user credentials update msgs + Assert.assertTrue(edgeImitator.waitForMessages()); // wait 6 messages - x2 user update msg and x4 user credentials update msgs (create + authenticate user) + Assert.assertEquals(2, edgeImitator.findAllMessagesByType(UserUpdateMsg.class).size()); + Assert.assertEquals(4, edgeImitator.findAllMessagesByType(UserCredentialsUpdateMsg.class).size()); Optional userUpdateMsgOpt = edgeImitator.findMessageByType(UserUpdateMsg.class); Assert.assertTrue(userUpdateMsgOpt.isPresent()); UserUpdateMsg userUpdateMsg = userUpdateMsgOpt.get(); @@ -253,4 +255,5 @@ public class UserEdgeTest extends AbstractEdgeTest { testAutoGeneratedCodeByProtobuf(userCredentialsUpdateMsg); } + } diff --git a/application/src/test/java/org/thingsboard/server/queue/discovery/HashPartitionServiceTest.java b/application/src/test/java/org/thingsboard/server/queue/discovery/HashPartitionServiceTest.java index c468387c55..52cbaa4add 100644 --- a/application/src/test/java/org/thingsboard/server/queue/discovery/HashPartitionServiceTest.java +++ b/application/src/test/java/org/thingsboard/server/queue/discovery/HashPartitionServiceTest.java @@ -429,6 +429,8 @@ public class HashPartitionServiceTest { ReflectionTestUtils.setField(partitionService, "vcTopic", "tb.vc"); ReflectionTestUtils.setField(partitionService, "vcPartitions", 10); ReflectionTestUtils.setField(partitionService, "hashFunctionName", hashFunctionName); + ReflectionTestUtils.setField(partitionService, "edgeTopic", "tb.edge"); + ReflectionTestUtils.setField(partitionService, "edgePartitions", 10); partitionService.init(); partitionService.partitionsInit(); return partitionService; diff --git a/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java b/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java index 9981b7935d..53ae5f36ae 100644 --- a/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java +++ b/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java @@ -904,7 +904,7 @@ public class NotificationApiTest extends AbstractNotificationApiTest { String expectedSubject = "Comment on 'test' alarm"; String expectedBody = TENANT_ADMIN_EMAIL + " added comment: text"; ArgumentCaptor> msgCaptor = ArgumentCaptor.forClass(Map.class); - await().atMost(30, TimeUnit.SECONDS).untilAsserted(() -> { + await().atMost(TIMEOUT, TimeUnit.SECONDS).untilAsserted(() -> { verify(firebaseService).sendMessage(eq(tenantId), eq("testCredentials"), eq(TEST_MOBILE_TOKEN), eq(expectedSubject), eq(expectedBody), @@ -959,7 +959,7 @@ public class NotificationApiTest extends AbstractNotificationApiTest { } private NotificationRequestStats awaitNotificationRequest(NotificationRequestId requestId) { - return await().atMost(30, TimeUnit.SECONDS) + return await().atMost(TIMEOUT, TimeUnit.SECONDS) .until(() -> getStats(requestId), Objects::nonNull); } diff --git a/application/src/test/java/org/thingsboard/server/service/notification/NotificationRuleApiTest.java b/application/src/test/java/org/thingsboard/server/service/notification/NotificationRuleApiTest.java index 9cf73894c2..852ddd757c 100644 --- a/application/src/test/java/org/thingsboard/server/service/notification/NotificationRuleApiTest.java +++ b/application/src/test/java/org/thingsboard/server/service/notification/NotificationRuleApiTest.java @@ -780,7 +780,7 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest { assertThat(getMyNotifications(false, 100)).size().isZero(); createDevice("Device 1", "default", "111"); - await().atMost(30, TimeUnit.SECONDS) + await().atMost(TIMEOUT, TimeUnit.SECONDS) .untilAsserted(() -> { assertThat(getMyNotifications(false, 100)).size().isEqualTo(1); }); @@ -798,7 +798,7 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest { notificationRulesCache.evict(tenantId); createDevice("Device 3", "default", "333"); - await().atMost(30, TimeUnit.SECONDS) + await().atMost(TIMEOUT, TimeUnit.SECONDS) .untilAsserted(() -> { assertThat(getMyNotifications(false, 100)).size().isEqualTo(2); }); diff --git a/application/src/test/java/org/thingsboard/server/service/queue/DefaultTbClusterServiceTest.java b/application/src/test/java/org/thingsboard/server/service/queue/DefaultTbClusterServiceTest.java index 59cca779f5..25fe589a08 100644 --- a/application/src/test/java/org/thingsboard/server/service/queue/DefaultTbClusterServiceTest.java +++ b/application/src/test/java/org/thingsboard/server/service/queue/DefaultTbClusterServiceTest.java @@ -25,6 +25,7 @@ import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; import org.thingsboard.common.util.JacksonUtil; +import org.thingsboard.server.cache.TbTransactionalCache; import org.thingsboard.server.cluster.TbClusterService; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.Device; @@ -34,6 +35,7 @@ import org.thingsboard.server.common.data.id.AssetId; import org.thingsboard.server.common.data.id.AssetProfileId; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.DeviceProfileId; +import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.QueueId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.msg.TbMsgType; @@ -98,6 +100,8 @@ public class DefaultTbClusterServiceTest { protected TbQueueProducerProvider producerProvider; @MockBean protected TbRuleEngineProducerService ruleEngineProducerService; + @MockBean + protected TbTransactionalCache edgeCache; @SpyBean protected TopicService topicService; @@ -400,4 +404,5 @@ public class DefaultTbClusterServiceTest { ((DefaultTbClusterService) clusterService).getRuleEngineProfileForEntityOrElseNull(tenantId, assetId, tbMsg); verify(assetProfileCache, times(1)).get(tenantId, assetProfileId); } -} \ No newline at end of file + +} diff --git a/application/src/test/java/org/thingsboard/server/service/script/TbelInvokeServiceTest.java b/application/src/test/java/org/thingsboard/server/service/script/TbelInvokeServiceTest.java index 76f8ff654e..9e3b6221b1 100644 --- a/application/src/test/java/org/thingsboard/server/service/script/TbelInvokeServiceTest.java +++ b/application/src/test/java/org/thingsboard/server/service/script/TbelInvokeServiceTest.java @@ -69,14 +69,14 @@ class TbelInvokeServiceTest extends AbstractControllerTest { for (int i = 0; i < 100; i++) { msg.put("temperature", i); boolean expected = i > 20; - boolean result = Boolean.valueOf(invokeScript(scriptId, JacksonUtil.toString(msg))); + boolean result = Boolean.parseBoolean(invokeScript(scriptId, JacksonUtil.toString(msg))); Assert.assertEquals(expected, result); } long startTs = System.currentTimeMillis(); for (int i = 0; i < iterations; i++) { msg.put("temperature", i); boolean expected = i > 20; - boolean result = Boolean.valueOf(invokeScript(scriptId, JacksonUtil.toString(msg))); + boolean result = Boolean.parseBoolean(invokeScript(scriptId, JacksonUtil.toString(msg))); Assert.assertEquals(expected, result); } long duration = System.currentTimeMillis() - startTs; diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/OtaLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/OtaLwM2MIntegrationTest.java index 4f24c58916..b78e738d72 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/OtaLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/OtaLwM2MIntegrationTest.java @@ -95,7 +95,7 @@ public class OtaLwM2MIntegrationTest extends AbstractOtaLwM2MIntegrationTest { expectedStatuses = Arrays.asList(QUEUED, INITIATED, DOWNLOADING, DOWNLOADED, UPDATING, UPDATED); List ts = await("await on timeseries") - .atMost(30, TimeUnit.SECONDS) + .atMost(TIMEOUT, TimeUnit.SECONDS) .until(() -> toTimeseries(doGetAsyncTyped("/api/plugins/telemetry/DEVICE/" + savedDevice.getId().getId() + "/values/timeseries?orderBy=ASC&keys=fw_state&startTs=0&endTs=" + System.currentTimeMillis(), new TypeReference<>() { @@ -127,7 +127,7 @@ public class OtaLwM2MIntegrationTest extends AbstractOtaLwM2MIntegrationTest { QUEUED, INITIATED, DOWNLOADING, DOWNLOADING, DOWNLOADING, DOWNLOADED, VERIFIED, UPDATED); List ts = await("await on timeseries") - .atMost(30, TimeUnit.SECONDS) + .atMost(TIMEOUT, TimeUnit.SECONDS) .until(() -> getSwStateTelemetryFromAPI(device.getId().getId()), this::predicateForStatuses); log.warn("Object9: Got the ts: {}", ts); } diff --git a/common/cache/src/main/java/org/thingsboard/server/cache/RedisTbTransactionalCache.java b/common/cache/src/main/java/org/thingsboard/server/cache/RedisTbTransactionalCache.java index 3531c3846e..fbf88bb5e4 100644 --- a/common/cache/src/main/java/org/thingsboard/server/cache/RedisTbTransactionalCache.java +++ b/common/cache/src/main/java/org/thingsboard/server/cache/RedisTbTransactionalCache.java @@ -72,9 +72,10 @@ public abstract class RedisTbTransactionalCache x.get(cacheName)) + .map(specs -> specs.get(cacheName)) .map(CacheSpecs::getTimeToLiveInMinutes) - .map(t -> Expiration.from(t, TimeUnit.MINUTES)) + .filter(ttl -> !ttl.equals(0)) + .map(ttl -> Expiration.from(ttl, TimeUnit.MINUTES)) .orElseGet(Expiration::persistent); this.cacheEnabled = Optional.ofNullable(cacheSpecsMap) .map(CacheSpecsMap::getSpecs) diff --git a/common/cache/src/main/java/org/thingsboard/server/cache/TbCaffeineCacheConfiguration.java b/common/cache/src/main/java/org/thingsboard/server/cache/TbCaffeineCacheConfiguration.java index fe47a7a02d..be3a264720 100644 --- a/common/cache/src/main/java/org/thingsboard/server/cache/TbCaffeineCacheConfiguration.java +++ b/common/cache/src/main/java/org/thingsboard/server/cache/TbCaffeineCacheConfiguration.java @@ -75,8 +75,10 @@ public class TbCaffeineCacheConfiguration { = Caffeine.newBuilder() .weigher(collectionSafeWeigher()) .maximumWeight(cacheSpec.getMaxSize()) - .expireAfterWrite(cacheSpec.getTimeToLiveInMinutes(), TimeUnit.MINUTES) .ticker(ticker()); + if (!cacheSpec.getTimeToLiveInMinutes().equals(0)) { + caffeineBuilder.expireAfterWrite(cacheSpec.getTimeToLiveInMinutes(), TimeUnit.MINUTES); + } return new CaffeineCache(name, caffeineBuilder.build()); } diff --git a/common/cluster-api/src/main/java/org/thingsboard/server/cluster/TbClusterService.java b/common/cluster-api/src/main/java/org/thingsboard/server/cluster/TbClusterService.java index 399a27f07e..5112e93da7 100644 --- a/common/cluster-api/src/main/java/org/thingsboard/server/cluster/TbClusterService.java +++ b/common/cluster-api/src/main/java/org/thingsboard/server/cluster/TbClusterService.java @@ -29,13 +29,17 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.ToDeviceActorNotificationMsg; +import org.thingsboard.server.common.msg.edge.EdgeEventUpdateMsg; +import org.thingsboard.server.common.msg.edge.EdgeHighPriorityMsg; import org.thingsboard.server.common.msg.edge.FromEdgeSyncResponse; import org.thingsboard.server.common.msg.edge.ToEdgeSyncRequest; +import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; import org.thingsboard.server.common.msg.rpc.FromDeviceRpcResponse; -import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos.RestApiCallResponseMsgProto; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToVersionControlServiceMsg; @@ -52,7 +56,7 @@ public interface TbClusterService extends TbQueueClusterService { void pushMsgToCore(ToDeviceActorNotificationMsg msg, TbQueueCallback callback); - void broadcastToCore(TransportProtos.ToCoreNotificationMsg msg); + void broadcastToCore(ToCoreNotificationMsg msg); void pushMsgToVersionControl(TenantId tenantId, ToVersionControlServiceMsg msg, TbQueueCallback callback); @@ -96,11 +100,17 @@ public interface TbClusterService extends TbQueueClusterService { void onResourceDeleted(TbResourceInfo resource, TbQueueCallback callback); - void onEdgeEventUpdate(TenantId tenantId, EdgeId edgeId); + void onEdgeHighPriorityMsg(EdgeHighPriorityMsg msg); - void pushEdgeSyncRequestToCore(ToEdgeSyncRequest toEdgeSyncRequest); + void onEdgeEventUpdate(EdgeEventUpdateMsg msg); - void pushEdgeSyncResponseToCore(FromEdgeSyncResponse fromEdgeSyncResponse); + void onEdgeStateChangeEvent(ComponentLifecycleMsg msg); + + void pushEdgeSyncRequestToEdge(ToEdgeSyncRequest request); + + void pushEdgeSyncResponseToCore(FromEdgeSyncResponse response, String requestServiceId); + + void pushMsgToEdge(TenantId tenantId, EntityId entityId, ToEdgeMsg msg, TbQueueCallback callback); void sendNotificationMsgToEdge(TenantId tenantId, EdgeId edgeId, EntityId entityId, String body, EdgeEventType type, EdgeEventActionType action, EdgeId sourceEdgeId); diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeService.java index 278232d2f3..c18f42ace7 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeService.java @@ -23,6 +23,7 @@ import org.thingsboard.server.common.data.edge.EdgeSearchQuery; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantProfileId; import org.thingsboard.server.common.data.page.PageData; @@ -97,6 +98,8 @@ public interface EdgeService extends EntityDaoService { String findMissingToRelatedRuleChains(TenantId tenantId, EdgeId edgeId, String tbRuleChainInputNodeClassName); + Edge setEdgeRootRuleChain(TenantId tenantId, Edge edge, RuleChainId ruleChainId) throws Exception; + ListenableFuture isEdgeActiveAsync(TenantId tenantId, EdgeId edgeId, String activityState); } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/CacheConstants.java b/common/data/src/main/java/org/thingsboard/server/common/data/CacheConstants.java index adf626a8d0..54a5bc755d 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/CacheConstants.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/CacheConstants.java @@ -25,6 +25,7 @@ public class CacheConstants { public static final String USER_CACHE = "users"; public static final String ENTITY_VIEW_CACHE = "entityViews"; public static final String EDGE_CACHE = "edges"; + public static final String EDGE_SESSIONS_CACHE = "edgeSessions"; public static final String RELATED_EDGES_CACHE = "relatedEdges"; public static final String CLAIM_DEVICES_CACHE = "claimDevices"; public static final String SECURITY_SETTINGS_CACHE = "securitySettings"; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/DataConstants.java b/common/data/src/main/java/org/thingsboard/server/common/data/DataConstants.java index 9641b5e69f..aef3751f0c 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/DataConstants.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/DataConstants.java @@ -140,4 +140,6 @@ public class DataConstants { public static final String SQ_QUEUE_TOPIC = "tb_rule_engine.sq"; public static final String QUEUE_NAME = "queueName"; + public static final String EDGE_QUEUE_NAME = "Edge"; + } diff --git a/common/message/src/main/java/org/thingsboard/server/common/msg/MsgType.java b/common/message/src/main/java/org/thingsboard/server/common/msg/MsgType.java index 68f2db88b2..b05bb75032 100644 --- a/common/message/src/main/java/org/thingsboard/server/common/msg/MsgType.java +++ b/common/message/src/main/java/org/thingsboard/server/common/msg/MsgType.java @@ -16,6 +16,7 @@ package org.thingsboard.server.common.msg; import lombok.Getter; +import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; import org.thingsboard.server.common.msg.queue.QueueToRuleEngineMsg; @@ -36,7 +37,7 @@ public enum MsgType { /** * ADDED/UPDATED/DELETED events for main entities. * - * See {@link org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg} + * See {@link ComponentLifecycleMsg} */ COMPONENT_LIFE_CYCLE_MSG, @@ -126,6 +127,7 @@ public enum MsgType { * Message that is sent on Edge Event to Edge Session */ EDGE_EVENT_UPDATE_TO_EDGE_SESSION_MSG, + EDGE_HIGH_PRIORITY_TO_EDGE_SESSION_MSG, /** * Messages that are sent to and from edge session to start edge synchronization process @@ -143,4 +145,5 @@ public enum MsgType { MsgType(boolean ignoreOnStart) { this.ignoreOnStart = ignoreOnStart; } + } diff --git a/common/message/src/main/java/org/thingsboard/server/common/msg/edge/EdgeEventUpdateMsg.java b/common/message/src/main/java/org/thingsboard/server/common/msg/edge/EdgeEventUpdateMsg.java index 3fd70f90c7..892b2a57dd 100644 --- a/common/message/src/main/java/org/thingsboard/server/common/msg/edge/EdgeEventUpdateMsg.java +++ b/common/message/src/main/java/org/thingsboard/server/common/msg/edge/EdgeEventUpdateMsg.java @@ -32,4 +32,5 @@ public class EdgeEventUpdateMsg implements EdgeSessionMsg { public MsgType getMsgType() { return MsgType.EDGE_EVENT_UPDATE_TO_EDGE_SESSION_MSG; } + } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/EdgeNotificationService.java b/common/message/src/main/java/org/thingsboard/server/common/msg/edge/EdgeHighPriorityMsg.java similarity index 55% rename from application/src/main/java/org/thingsboard/server/service/edge/EdgeNotificationService.java rename to common/message/src/main/java/org/thingsboard/server/common/msg/edge/EdgeHighPriorityMsg.java index 4f90023f68..03f039f2e4 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/EdgeNotificationService.java +++ b/common/message/src/main/java/org/thingsboard/server/common/msg/edge/EdgeHighPriorityMsg.java @@ -13,17 +13,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.service.edge; +package org.thingsboard.server.common.msg.edge; -import org.thingsboard.server.common.data.edge.Edge; -import org.thingsboard.server.common.data.id.RuleChainId; +import lombok.Data; +import org.thingsboard.server.common.data.edge.EdgeEvent; import org.thingsboard.server.common.data.id.TenantId; -import org.thingsboard.server.common.msg.queue.TbCallback; -import org.thingsboard.server.gen.transport.TransportProtos; +import org.thingsboard.server.common.msg.MsgType; -public interface EdgeNotificationService { +@Data +public class EdgeHighPriorityMsg implements EdgeSessionMsg { - Edge setEdgeRootRuleChain(TenantId tenantId, Edge edge, RuleChainId ruleChainId) throws Exception; + private final TenantId tenantId; + private final EdgeEvent edgeEvent; + + @Override + public MsgType getMsgType() { + return MsgType.EDGE_HIGH_PRIORITY_TO_EDGE_SESSION_MSG; + } - void pushNotificationToEdge(TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg, TbCallback callback); } diff --git a/common/message/src/main/java/org/thingsboard/server/common/msg/edge/EdgeSessionMsg.java b/common/message/src/main/java/org/thingsboard/server/common/msg/edge/EdgeSessionMsg.java index 58e31234fc..4e658d6dd4 100644 --- a/common/message/src/main/java/org/thingsboard/server/common/msg/edge/EdgeSessionMsg.java +++ b/common/message/src/main/java/org/thingsboard/server/common/msg/edge/EdgeSessionMsg.java @@ -15,8 +15,13 @@ */ package org.thingsboard.server.common.msg.edge; -import org.thingsboard.server.common.msg.aware.TenantAwareMsg; -import org.thingsboard.server.common.msg.cluster.ToAllNodesMsg; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.msg.MsgType; + +public interface EdgeSessionMsg { + + TenantId getTenantId(); + + MsgType getMsgType(); -public interface EdgeSessionMsg extends TenantAwareMsg, ToAllNodesMsg { } diff --git a/common/message/src/main/java/org/thingsboard/server/common/msg/edge/FromEdgeSyncResponse.java b/common/message/src/main/java/org/thingsboard/server/common/msg/edge/FromEdgeSyncResponse.java index baf483310c..1e8beea443 100644 --- a/common/message/src/main/java/org/thingsboard/server/common/msg/edge/FromEdgeSyncResponse.java +++ b/common/message/src/main/java/org/thingsboard/server/common/msg/edge/FromEdgeSyncResponse.java @@ -37,4 +37,5 @@ public class FromEdgeSyncResponse implements EdgeSessionMsg { public MsgType getMsgType() { return MsgType.EDGE_SYNC_RESPONSE_FROM_EDGE_SESSION_MSG; } + } diff --git a/common/message/src/main/java/org/thingsboard/server/common/msg/edge/ToEdgeSyncRequest.java b/common/message/src/main/java/org/thingsboard/server/common/msg/edge/ToEdgeSyncRequest.java index 6c9ac545b4..04516b58c5 100644 --- a/common/message/src/main/java/org/thingsboard/server/common/msg/edge/ToEdgeSyncRequest.java +++ b/common/message/src/main/java/org/thingsboard/server/common/msg/edge/ToEdgeSyncRequest.java @@ -30,9 +30,11 @@ public class ToEdgeSyncRequest implements EdgeSessionMsg { private final UUID id; private final TenantId tenantId; private final EdgeId edgeId; + private final String serviceId; @Override public MsgType getMsgType() { return MsgType.EDGE_SYNC_REQUEST_TO_EDGE_SESSION_MSG; } + } diff --git a/common/proto/src/main/java/org/thingsboard/server/common/util/ProtoUtils.java b/common/proto/src/main/java/org/thingsboard/server/common/util/ProtoUtils.java index 5646a37a68..b61dc16384 100644 --- a/common/proto/src/main/java/org/thingsboard/server/common/util/ProtoUtils.java +++ b/common/proto/src/main/java/org/thingsboard/server/common/util/ProtoUtils.java @@ -16,6 +16,7 @@ package org.thingsboard.server.common.util; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; import com.google.protobuf.ByteString; import lombok.extern.slf4j.Slf4j; import org.thingsboard.common.util.JacksonUtil; @@ -26,6 +27,7 @@ import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.DeviceProfileProvisionType; import org.thingsboard.server.common.data.DeviceProfileType; import org.thingsboard.server.common.data.DeviceTransportType; +import org.thingsboard.server.common.data.EdgeUtils; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.ResourceSubType; import org.thingsboard.server.common.data.ResourceType; @@ -36,6 +38,8 @@ import org.thingsboard.server.common.data.device.data.CoapDeviceTransportConfigu import org.thingsboard.server.common.data.device.data.Lwm2mDeviceTransportConfiguration; import org.thingsboard.server.common.data.device.data.PowerMode; import org.thingsboard.server.common.data.device.data.PowerSavingConfiguration; +import org.thingsboard.server.common.data.edge.EdgeEventActionType; +import org.thingsboard.server.common.data.edge.EdgeEventType; import org.thingsboard.server.common.data.id.ApiUsageStateId; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.DashboardId; @@ -68,6 +72,7 @@ import org.thingsboard.server.common.data.sync.vc.RepositoryAuthMethod; import org.thingsboard.server.common.data.sync.vc.RepositorySettings; import org.thingsboard.server.common.msg.ToDeviceActorNotificationMsg; import org.thingsboard.server.common.msg.edge.EdgeEventUpdateMsg; +import org.thingsboard.server.common.msg.edge.EdgeHighPriorityMsg; import org.thingsboard.server.common.msg.edge.FromEdgeSyncResponse; import org.thingsboard.server.common.msg.edge.ToEdgeSyncRequest; import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; @@ -140,6 +145,7 @@ public class ProtoUtils { .setRequestIdLSB(request.getId().getLeastSignificantBits()) .setEdgeIdMSB(request.getEdgeId().getId().getMostSignificantBits()) .setEdgeIdLSB(request.getEdgeId().getId().getLeastSignificantBits()) + .setServiceId(request.getServiceId()) .build(); } @@ -147,7 +153,8 @@ public class ProtoUtils { return new ToEdgeSyncRequest( new UUID(proto.getRequestIdMSB(), proto.getRequestIdLSB()), TenantId.fromUUID(new UUID(proto.getTenantIdMSB(), proto.getTenantIdLSB())), - new EdgeId(new UUID(proto.getEdgeIdMSB(), proto.getEdgeIdLSB())) + EdgeId.fromUUID(new UUID(proto.getEdgeIdMSB(), proto.getEdgeIdLSB())), + proto.getServiceId() ); } @@ -168,12 +175,56 @@ public class ProtoUtils { return new FromEdgeSyncResponse( new UUID(proto.getResponseIdMSB(), proto.getResponseIdLSB()), TenantId.fromUUID(new UUID(proto.getTenantIdMSB(), proto.getTenantIdLSB())), - new EdgeId(new UUID(proto.getEdgeIdMSB(), proto.getEdgeIdLSB())), + EdgeId.fromUUID(new UUID(proto.getEdgeIdMSB(), proto.getEdgeIdLSB())), proto.getSuccess(), proto.getError() ); } + public static TransportProtos.EdgeHighPriorityMsgProto toProto(EdgeHighPriorityMsg msg) { + TransportProtos.EdgeHighPriorityMsgProto.Builder builder = TransportProtos.EdgeHighPriorityMsgProto.newBuilder() + .setTenantIdMSB(msg.getTenantId().getId().getMostSignificantBits()) + .setTenantIdLSB(msg.getTenantId().getId().getLeastSignificantBits()) + .setType(msg.getEdgeEvent().getType().name()) + .setAction(msg.getEdgeEvent().getAction().name()); + + if (msg.getEdgeEvent().getEntityId() != null) { + builder.setEntityIdMSB(msg.getEdgeEvent().getEntityId().getMostSignificantBits()); + builder.setEntityIdLSB(msg.getEdgeEvent().getEntityId().getLeastSignificantBits()); + } + if (msg.getEdgeEvent().getEdgeId() != null) { + builder.setEdgeIdMSB(msg.getEdgeEvent().getEdgeId().getId().getMostSignificantBits()); + builder.setEdgeIdLSB(msg.getEdgeEvent().getEdgeId().getId().getLeastSignificantBits()); + } + if (msg.getEdgeEvent().getBody() != null) { + builder.setBody(JacksonUtil.toString(msg.getEdgeEvent().getBody())); + } + + return builder.build(); + } + + public static EdgeHighPriorityMsg fromProto(TransportProtos.EdgeHighPriorityMsgProto proto) { + EdgeEventType type = EdgeEventType.valueOf(proto.getType()); + EdgeEventActionType actionType = EdgeEventActionType.valueOf(proto.getAction()); + JsonNode body = proto.hasBody() ? JacksonUtil.toJsonNode(proto.getBody()) : null; + + EdgeId edgeId = null; + if (proto.hasEdgeIdMSB() && proto.hasEdgeIdLSB()) { + edgeId = EdgeId.fromUUID(new UUID(proto.getEdgeIdMSB(), proto.getEdgeIdLSB())); + } + + EntityId entityId = null; + if (proto.hasEntityIdMSB() && proto.hasEntityIdLSB()) { + entityId = EntityIdFactory.getByEdgeEventTypeAndUuid(type, new UUID(proto.getEntityIdMSB(), proto.getEntityIdLSB())); + } + + return new EdgeHighPriorityMsg( + TenantId.fromUUID(new UUID(proto.getTenantIdMSB(), proto.getTenantIdLSB())), + EdgeUtils.constructEdgeEvent(TenantId.fromUUID(new UUID(proto.getTenantIdMSB(), proto.getTenantIdLSB())), + edgeId, type, actionType, entityId, body) + ); + } + public static TransportProtos.EdgeEventUpdateMsgProto toProto(EdgeEventUpdateMsg msg) { return TransportProtos.EdgeEventUpdateMsgProto.newBuilder() .setTenantIdMSB(msg.getTenantId().getId().getMostSignificantBits()) @@ -186,7 +237,7 @@ public class ProtoUtils { public static EdgeEventUpdateMsg fromProto(TransportProtos.EdgeEventUpdateMsgProto proto) { return new EdgeEventUpdateMsg( TenantId.fromUUID(new UUID(proto.getTenantIdMSB(), proto.getTenantIdLSB())), - new EdgeId(new UUID(proto.getEdgeIdMSB(), proto.getEdgeIdLSB())) + EdgeId.fromUUID(new UUID(proto.getEdgeIdMSB(), proto.getEdgeIdLSB())) ); } @@ -208,7 +259,7 @@ public class ProtoUtils { private static DeviceEdgeUpdateMsg fromProto(TransportProtos.DeviceEdgeUpdateMsgProto proto) { EdgeId edgeId = null; if (proto.hasEdgeIdMSB() && proto.hasEdgeIdLSB()) { - edgeId = new EdgeId(new UUID(proto.getEdgeIdMSB(), proto.getEdgeIdLSB())); + edgeId = EdgeId.fromUUID(new UUID(proto.getEdgeIdMSB(), proto.getEdgeIdLSB())); } return new DeviceEdgeUpdateMsg( TenantId.fromUUID(new UUID(proto.getTenantIdMSB(), proto.getTenantIdLSB())), diff --git a/common/proto/src/main/proto/queue.proto b/common/proto/src/main/proto/queue.proto index 67d88afa89..dd32ee1c67 100644 --- a/common/proto/src/main/proto/queue.proto +++ b/common/proto/src/main/proto/queue.proto @@ -146,9 +146,9 @@ message KeyValueProto { } enum AttributeScopeProto { - CLIENT_SCOPE = 0; - SERVER_SCOPE = 1; - SHARED_SCOPE = 2; + CLIENT_SCOPE = 0; + SERVER_SCOPE = 1; + SHARED_SCOPE = 2; } message AttributeKey { @@ -421,7 +421,7 @@ message GatewayDisconnectDeviceMsg { } enum TransportApiRequestErrorCode { - UNKNOWN_TRANSPORT_API_ERROR = 0; + UNKNOWN_TRANSPORT_API_ERROR = 0; ENTITY_LIMIT = 1; } @@ -1142,6 +1142,18 @@ message EdgeNotificationMsgProto { int64 originatorEdgeIdLSB = 14; } +message EdgeHighPriorityMsgProto { + int64 tenantIdMSB = 1; + int64 tenantIdLSB = 2; + optional int64 edgeIdMSB = 3; + optional int64 edgeIdLSB = 4; + string type = 5; + string action = 6; + optional string body = 7; + optional int64 entityIdMSB = 8; + optional int64 entityIdLSB = 9; +} + message EdgeEventUpdateMsgProto { int64 tenantIdMSB = 1; int64 tenantIdLSB = 2; @@ -1156,6 +1168,7 @@ message ToEdgeSyncRequestMsgProto { int64 requestIdLSB = 4; int64 edgeIdMSB = 5; int64 edgeIdLSB = 6; + string serviceId = 7; } message FromEdgeSyncResponseMsgProto { @@ -1477,7 +1490,7 @@ message ToCoreMsg { DeviceStateServiceMsgProto deviceStateServiceMsg = 2; SubscriptionMgrMsgProto toSubscriptionMgrMsg = 3; bytes toDeviceActorNotificationMsg = 4 [deprecated = true]; - EdgeNotificationMsgProto edgeNotificationMsg = 5; + EdgeNotificationMsgProto edgeNotificationMsg = 5 [deprecated = true]; DeviceActivityProto deviceActivityMsg = 6; NotificationSchedulerServiceMsg notificationSchedulerServiceMsg = 7; LifecycleEventProto lifecycleEventMsg = 8; @@ -1500,13 +1513,27 @@ message ToCoreNotificationMsg { NotificationRuleProcessorMsg notificationRuleProcessorMsg = 7; ComponentLifecycleMsgProto componentLifecycle = 8; CoreStartupMsg coreStartupMsg = 9; - EdgeEventUpdateMsgProto edgeEventUpdate = 10; - ToEdgeSyncRequestMsgProto toEdgeSyncRequest = 11; - FromEdgeSyncResponseMsgProto fromEdgeSyncResponse = 12; + EdgeEventUpdateMsgProto edgeEventUpdate = 10 [deprecated = true]; + ToEdgeSyncRequestMsgProto toEdgeSyncRequest = 11 [deprecated = true]; + FromEdgeSyncResponseMsgProto fromEdgeSyncResponse = 12 [deprecated = true]; ResourceCacheInvalidateMsg resourceCacheInvalidateMsg = 13; RestApiCallResponseMsgProto restApiCallResponseMsg = 50; } + +/* Messages to Edge queue that are handled by ThingsBoard Core Service */ +message ToEdgeMsg { + EdgeNotificationMsgProto edgeNotificationMsg = 1; +} + +message ToEdgeNotificationMsg { + EdgeHighPriorityMsgProto edgeHighPriority = 1; + EdgeEventUpdateMsgProto edgeEventUpdate = 2; + ToEdgeSyncRequestMsgProto toEdgeSyncRequest = 3; + FromEdgeSyncResponseMsgProto fromEdgeSyncResponse = 4; + ComponentLifecycleMsgProto componentLifecycle = 5; +} + /* Messages that are handled by ThingsBoard RuleEngine Service */ message ToRuleEngineMsg { int64 tenantIdMSB = 1; diff --git a/common/proto/src/test/java/org/thingsboard/server/common/util/ProtoUtilsTest.java b/common/proto/src/test/java/org/thingsboard/server/common/util/ProtoUtilsTest.java index a513d3e311..b253b4e444 100644 --- a/common/proto/src/test/java/org/thingsboard/server/common/util/ProtoUtilsTest.java +++ b/common/proto/src/test/java/org/thingsboard/server/common/util/ProtoUtilsTest.java @@ -25,6 +25,7 @@ import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.ApiUsageState; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceProfile; +import org.thingsboard.server.common.data.EdgeUtils; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.TbResource; import org.thingsboard.server.common.data.Tenant; @@ -34,6 +35,8 @@ import org.thingsboard.server.common.data.device.data.DefaultDeviceTransportConf import org.thingsboard.server.common.data.device.data.DeviceConfiguration; import org.thingsboard.server.common.data.device.data.DeviceTransportConfiguration; import org.thingsboard.server.common.data.device.profile.DeviceProfileData; +import org.thingsboard.server.common.data.edge.EdgeEventActionType; +import org.thingsboard.server.common.data.edge.EdgeEventType; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.EntityId; @@ -54,6 +57,7 @@ import org.thingsboard.server.common.data.sync.vc.RepositorySettings; import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration; import org.thingsboard.server.common.data.tenant.profile.TenantProfileConfiguration; import org.thingsboard.server.common.msg.edge.EdgeEventUpdateMsg; +import org.thingsboard.server.common.msg.edge.EdgeHighPriorityMsg; import org.thingsboard.server.common.msg.edge.FromEdgeSyncResponse; import org.thingsboard.server.common.msg.edge.ToEdgeSyncRequest; import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; @@ -110,6 +114,13 @@ class ProtoUtilsTest { } } + @Test + void protoEdgeHighPrioritySerialization() { + EdgeHighPriorityMsg msg = new EdgeHighPriorityMsg(tenantId, EdgeUtils.constructEdgeEvent(tenantId, edgeId, + EdgeEventType.DEVICE, EdgeEventActionType.ADDED, deviceId, JacksonUtil.newObjectNode())); + assertThat(ProtoUtils.fromProto(ProtoUtils.toProto(msg))).as("deserialized").isEqualTo(msg); + } + @Test void protoEdgeEventUpdateSerialization() { EdgeEventUpdateMsg msg = new EdgeEventUpdateMsg(tenantId, edgeId); @@ -118,7 +129,7 @@ class ProtoUtilsTest { @Test void protoToEdgeSyncRequestSerialization() { - ToEdgeSyncRequest msg = new ToEdgeSyncRequest(id, tenantId, edgeId); + ToEdgeSyncRequest msg = new ToEdgeSyncRequest(id, tenantId, edgeId, "serviceId"); assertThat(ProtoUtils.fromProto(ProtoUtils.toProto(msg))).as("deserialized").isEqualTo(msg); } diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/azure/servicebus/TbServiceBusQueueConfigs.java b/common/queue/src/main/java/org/thingsboard/server/queue/azure/servicebus/TbServiceBusQueueConfigs.java index 45d39d1cd6..80da7846ea 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/azure/servicebus/TbServiceBusQueueConfigs.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/azure/servicebus/TbServiceBusQueueConfigs.java @@ -27,6 +27,7 @@ import java.util.Map; @Component @ConditionalOnExpression("'${queue.type:null}'=='service-bus'") public class TbServiceBusQueueConfigs { + @Value("${queue.service-bus.queue-properties.core:}") private String coreProperties; @Value("${queue.service-bus.queue-properties.rule-engine:}") @@ -39,6 +40,9 @@ public class TbServiceBusQueueConfigs { private String jsExecutorProperties; @Value("${queue.service-bus.queue-properties.version-control:}") private String vcProperties; + @Value("${queue.service-bus.queue-properties.edge:}") + private String edgeProperties; + @Getter private Map coreConfigs; @Getter @@ -51,6 +55,8 @@ public class TbServiceBusQueueConfigs { private Map jsExecutorConfigs; @Getter private Map vcConfigs; + @Getter + private Map edgeConfigs; @PostConstruct private void init() { @@ -60,6 +66,7 @@ public class TbServiceBusQueueConfigs { notificationsConfigs = PropertyUtils.getProps(notificationsProperties); jsExecutorConfigs = PropertyUtils.getProps(jsExecutorProperties); vcConfigs = PropertyUtils.getProps(vcProperties); + edgeConfigs = PropertyUtils.getProps(edgeProperties); } } diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/DefaultTbServiceInfoProvider.java b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/DefaultTbServiceInfoProvider.java index 4caa3b92b3..1ceb52b3d6 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/DefaultTbServiceInfoProvider.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/DefaultTbServiceInfoProvider.java @@ -88,7 +88,7 @@ public class DefaultTbServiceInfoProvider implements TbServiceInfoProvider { assignedTenantProfiles = Collections.emptySet(); } - generateNewServiceInfoWithCurrentSystemInfo(); + generateNewServiceInfoWithCurrentSystemInfo(); } @AfterContextReady diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/HashPartitionService.java b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/HashPartitionService.java index 53a2152782..37e519e3f2 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/HashPartitionService.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/HashPartitionService.java @@ -51,6 +51,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.stream.Collectors; +import static org.thingsboard.server.common.data.DataConstants.EDGE_QUEUE_NAME; import static org.thingsboard.server.common.data.DataConstants.MAIN_QUEUE_NAME; @Service @@ -59,12 +60,16 @@ public class HashPartitionService implements PartitionService { @Value("${queue.core.topic}") private String coreTopic; - @Value("${queue.core.partitions:100}") + @Value("${queue.core.partitions:10}") private Integer corePartitions; @Value("${queue.vc.topic:tb_version_control}") private String vcTopic; @Value("${queue.vc.partitions:10}") private Integer vcPartitions; + @Value("${queue.edge.topic:tb_edge}") + private String edgeTopic; + @Value("${queue.edge.partitions:10}") + private Integer edgePartitions; @Value("${queue.partitions.hash_function_name:murmur3_128}") private String hashFunctionName; @@ -114,6 +119,10 @@ public class HashPartitionService implements PartitionService { if (!isTransport(serviceInfoProvider.getServiceType())) { doInitRuleEnginePartitions(); } + + QueueKey edgeKey = coreKey.withQueueName(EDGE_QUEUE_NAME); + partitionSizesMap.put(edgeKey, edgePartitions); + partitionTopicsMap.put(edgeKey, edgeTopic); } @AfterStartUp(order = AfterStartUp.QUEUE_INFO_INITIALIZATION) @@ -195,8 +204,7 @@ public class HashPartitionService implements PartitionService { .map(queueDeleteMsg -> { TenantId tenantId = TenantId.fromUUID(new UUID(queueDeleteMsg.getTenantIdMSB(), queueDeleteMsg.getTenantIdLSB())); return new QueueKey(ServiceType.TB_RULE_ENGINE, queueDeleteMsg.getQueueName(), tenantId); - }) - .collect(Collectors.toList()); + }).toList(); queueKeys.forEach(queueKey -> { removeQueue(queueKey); evictTenantInfo(queueKey.getTenantId()); @@ -210,8 +218,7 @@ public class HashPartitionService implements PartitionService { @Override public void removeTenant(TenantId tenantId) { List queueKeys = partitionSizesMap.keySet().stream() - .filter(queueKey -> tenantId.equals(queueKey.getTenantId())) - .collect(Collectors.toList()); + .filter(queueKey -> tenantId.equals(queueKey.getTenantId())).toList(); queueKeys.forEach(this::removeQueue); evictTenantInfo(tenantId); } @@ -546,12 +553,10 @@ public class HashPartitionService implements PartitionService { if (routingInfo == null) { throw new TenantNotFoundException(tenantId); } - switch (serviceType) { - case TB_RULE_ENGINE: - return routingInfo.isIsolated(); - default: - return false; + if (serviceType == ServiceType.TB_RULE_ENGINE) { + return routingInfo.isIsolated(); } + return false; } private TenantRoutingInfo getRoutingInfo(TenantId tenantId) { @@ -588,7 +593,10 @@ public class HashPartitionService implements PartitionService { responsibleServices.computeIfAbsent(profileId, k -> new ArrayList<>()).add(instance); } } - } else if (ServiceType.TB_CORE.equals(serviceType) || ServiceType.TB_VC_EXECUTOR.equals(serviceType)) { + } else if (ServiceType.TB_CORE.equals(serviceType)) { + queueServiceList.computeIfAbsent(new QueueKey(serviceType), key -> new ArrayList<>()).add(instance); + queueServiceList.computeIfAbsent(new QueueKey(serviceType).withQueueName(EDGE_QUEUE_NAME), key -> new ArrayList<>()).add(instance); + } else if (ServiceType.TB_VC_EXECUTOR.equals(serviceType)) { queueServiceList.computeIfAbsent(new QueueKey(serviceType), key -> new ArrayList<>()).add(instance); } } @@ -649,16 +657,12 @@ public class HashPartitionService implements PartitionService { } public static HashFunction forName(String name) { - switch (name) { - case "murmur3_32": - return Hashing.murmur3_32(); - case "murmur3_128": - return Hashing.murmur3_128(); - case "sha256": - return Hashing.sha256(); - default: - throw new IllegalArgumentException("Can't find hash function with name " + name); - } + return switch (name) { + case "murmur3_32" -> Hashing.murmur3_32(); + case "murmur3_128" -> Hashing.murmur3_128(); + case "sha256" -> Hashing.sha256(); + default -> throw new IllegalArgumentException("Can't find hash function with name " + name); + }; } private List toServiceIds(Collection serviceInfos) { diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/QueueKey.java b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/QueueKey.java index f0ae5af43c..b991e4614c 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/QueueKey.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/QueueKey.java @@ -17,6 +17,7 @@ package org.thingsboard.server.queue.discovery; import lombok.AllArgsConstructor; import lombok.Data; +import lombok.With; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.queue.Queue; @@ -27,6 +28,7 @@ import org.thingsboard.server.common.msg.queue.ServiceType; public class QueueKey { private final ServiceType type; + @With private final String queueName; private final TenantId tenantId; diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/TopicService.java b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/TopicService.java index 960be231c6..d8a409e704 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/TopicService.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/TopicService.java @@ -30,8 +30,9 @@ public class TopicService { @Value("${queue.prefix:}") private String prefix; - private Map tbCoreNotificationTopics = new HashMap<>(); - private Map tbRuleEngineNotificationTopics = new HashMap<>(); + private final Map tbCoreNotificationTopics = new HashMap<>(); + private final Map tbRuleEngineNotificationTopics = new HashMap<>(); + private final Map tbEdgeNotificationTopics = new HashMap<>(); /** * Each Service should start a consumer for messages that target individual service instance based on serviceId. @@ -41,16 +42,21 @@ public class TopicService { * @return */ public TopicPartitionInfo getNotificationsTopic(ServiceType serviceType, String serviceId) { - switch (serviceType) { - case TB_CORE: - return tbCoreNotificationTopics.computeIfAbsent(serviceId, - id -> buildNotificationsTopicPartitionInfo(serviceType, serviceId)); - case TB_RULE_ENGINE: - return tbRuleEngineNotificationTopics.computeIfAbsent(serviceId, - id -> buildNotificationsTopicPartitionInfo(serviceType, serviceId)); - default: - return buildNotificationsTopicPartitionInfo(serviceType, serviceId); - } + return switch (serviceType) { + case TB_CORE -> tbCoreNotificationTopics.computeIfAbsent(serviceId, + id -> buildNotificationsTopicPartitionInfo(serviceType, serviceId)); + case TB_RULE_ENGINE -> tbRuleEngineNotificationTopics.computeIfAbsent(serviceId, + id -> buildNotificationsTopicPartitionInfo(serviceType, serviceId)); + default -> buildNotificationsTopicPartitionInfo(serviceType, serviceId); + }; + } + + public TopicPartitionInfo getEdgeNotificationsTopic(String serviceId) { + return tbEdgeNotificationTopics.computeIfAbsent(serviceId, id -> buildEdgeNotificationsTopicPartitionInfo(serviceId)); + } + + private TopicPartitionInfo buildEdgeNotificationsTopicPartitionInfo(String serviceId) { + return buildTopicPartitionInfo("tb_edge.notifications." + serviceId, null, null, false); } private TopicPartitionInfo buildNotificationsTopicPartitionInfo(ServiceType serviceType, String serviceId) { diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/event/PartitionChangeEvent.java b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/event/PartitionChangeEvent.java index b5ad181a00..88ceb4aa08 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/event/PartitionChangeEvent.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/event/PartitionChangeEvent.java @@ -17,17 +17,20 @@ package org.thingsboard.server.queue.discovery.event; import lombok.Getter; import lombok.ToString; +import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; import org.thingsboard.server.queue.discovery.QueueKey; -import java.util.Collections; +import java.io.Serial; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; @ToString(callSuper = true) public class PartitionChangeEvent extends TbApplicationEvent { + @Serial private static final long serialVersionUID = -8731788167026510559L; @Getter @@ -41,9 +44,19 @@ public class PartitionChangeEvent extends TbApplicationEvent { this.partitionsMap = partitionsMap; } - // only for service types that have single QueueKey - public Set getPartitions() { - return partitionsMap.values().stream().findAny().orElse(Collections.emptySet()); + public Set getCorePartitions() { + return getPartitionsByServiceTypeAndQueueName(ServiceType.TB_CORE, DataConstants.MAIN_QUEUE_NAME); } + public Set getEdgePartitions() { + return getPartitionsByServiceTypeAndQueueName(ServiceType.TB_CORE, DataConstants.EDGE_QUEUE_NAME); + } + + private Set getPartitionsByServiceTypeAndQueueName(ServiceType serviceType, String queueName) { + return partitionsMap.entrySet() + .stream() + .filter(entry -> serviceType.equals(entry.getKey().getType()) && queueName.equals(entry.getKey().getQueueName())) + .flatMap(entry -> entry.getValue().stream()) + .collect(Collectors.toSet()); + } } diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/kafka/TbKafkaTopicConfigs.java b/common/queue/src/main/java/org/thingsboard/server/queue/kafka/TbKafkaTopicConfigs.java index 6f237894c2..300548e081 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/kafka/TbKafkaTopicConfigs.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/kafka/TbKafkaTopicConfigs.java @@ -27,6 +27,7 @@ import java.util.Map; @Component @ConditionalOnProperty(prefix = "queue", value = "type", havingValue = "kafka") public class TbKafkaTopicConfigs { + public static final String NUM_PARTITIONS_SETTING = "partitions"; @Value("${queue.kafka.topic-properties.core:}") @@ -43,6 +44,8 @@ public class TbKafkaTopicConfigs { private String fwUpdatesProperties; @Value("${queue.kafka.topic-properties.version-control:}") private String vcProperties; + @Value("${queue.kafka.topic-properties.edge:}") + private String edgeProperties; @Value("${queue.kafka.topic-properties.housekeeper:}") private String housekeeperProperties; @Value("${queue.kafka.topic-properties.housekeeper-reprocessing:}") @@ -70,6 +73,8 @@ public class TbKafkaTopicConfigs { private Map housekeeperConfigs; @Getter private Map housekeeperReprocessingConfigs; + @Getter + private Map edgeConfigs; @PostConstruct private void init() { @@ -86,6 +91,7 @@ public class TbKafkaTopicConfigs { vcConfigs = PropertyUtils.getProps(vcProperties); housekeeperConfigs = PropertyUtils.getProps(housekeeperProperties); housekeeperReprocessingConfigs = PropertyUtils.getProps(housekeeperReprocessingProperties); + edgeConfigs = PropertyUtils.getProps(edgeProperties); } } diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/AwsSqsMonolithQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/AwsSqsMonolithQueueFactory.java index d40a8bac85..005e9aee17 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/AwsSqsMonolithQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/AwsSqsMonolithQueueFactory.java @@ -24,15 +24,17 @@ import org.thingsboard.server.common.data.queue.Queue; import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.gen.js.JsInvokeProtos.RemoteJsRequest; import org.thingsboard.server.gen.js.JsInvokeProtos.RemoteJsResponse; -import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeNotificationMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToVersionControlServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg; import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg; import org.thingsboard.server.queue.TbQueueAdmin; @@ -45,6 +47,7 @@ import org.thingsboard.server.queue.common.TbProtoQueueMsg; import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; import org.thingsboard.server.queue.discovery.TopicService; import org.thingsboard.server.queue.settings.TbQueueCoreSettings; +import org.thingsboard.server.queue.settings.TbQueueEdgeSettings; import org.thingsboard.server.queue.settings.TbQueueRemoteJsInvokeSettings; import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; @@ -70,6 +73,7 @@ public class AwsSqsMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEng private final TbQueueTransportNotificationSettings transportNotificationSettings; private final TbAwsSqsSettings sqsSettings; private final TbQueueVersionControlSettings vcSettings; + private final TbQueueEdgeSettings edgeSettings; private final TbQueueRemoteJsInvokeSettings jsInvokeSettings; private final TbQueueAdmin coreAdmin; @@ -79,6 +83,7 @@ public class AwsSqsMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEng private final TbQueueAdmin notificationAdmin; private final TbQueueAdmin otaAdmin; private final TbQueueAdmin vcAdmin; + private final TbQueueAdmin edgeAdmin; public AwsSqsMonolithQueueFactory(TopicService topicService, TbQueueCoreSettings coreSettings, TbQueueRuleEngineSettings ruleEngineSettings, @@ -87,6 +92,7 @@ public class AwsSqsMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEng TbQueueTransportNotificationSettings transportNotificationSettings, TbAwsSqsSettings sqsSettings, TbQueueVersionControlSettings vcSettings, + TbQueueEdgeSettings edgeSettings, TbAwsSqsQueueAttributes sqsQueueAttributes, TbQueueRemoteJsInvokeSettings jsInvokeSettings) { this.topicService = topicService; @@ -97,6 +103,7 @@ public class AwsSqsMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEng this.transportNotificationSettings = transportNotificationSettings; this.sqsSettings = sqsSettings; this.vcSettings = vcSettings; + this.edgeSettings = edgeSettings; this.jsInvokeSettings = jsInvokeSettings; this.coreAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getCoreAttributes()); @@ -106,6 +113,7 @@ public class AwsSqsMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEng this.notificationAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getNotificationsAttributes()); this.otaAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getOtaAttributes()); this.vcAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getVcAttributes()); + this.edgeAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getEdgeAttributes()); } @Override @@ -130,13 +138,14 @@ public class AwsSqsMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEng @Override public TbQueueProducer> createTbCoreNotificationsMsgProducer() { - return new TbAwsSqsProducerTemplate<>(notificationAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getTopic())); + return new TbAwsSqsProducerTemplate<>(notificationAdmin, sqsSettings, + topicService.getNotificationsTopic(ServiceType.TB_CORE, serviceInfoProvider.getServiceId()).getFullTopicName()); } @Override - public TbQueueConsumer> createToVersionControlMsgConsumer() { + public TbQueueConsumer> createToVersionControlMsgConsumer() { return new TbAwsSqsConsumerTemplate<>(vcAdmin, sqsSettings, topicService.buildTopicName(vcSettings.getTopic()), - msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportProtos.ToVersionControlServiceMsg.parseFrom(msg.getData()), msg.getHeaders()) + msg -> new TbProtoQueueMsg<>(msg.getKey(), ToVersionControlServiceMsg.parseFrom(msg.getData()), msg.getHeaders()) ); } @@ -223,11 +232,10 @@ public class AwsSqsMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEng } @Override - public TbQueueProducer> createVersionControlMsgProducer() { + public TbQueueProducer> createVersionControlMsgProducer() { return new TbAwsSqsProducerTemplate<>(vcAdmin, sqsSettings, topicService.buildTopicName(vcSettings.getTopic())); } - @Override public TbQueueProducer> createHousekeeperMsgProducer() { return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic())); } @@ -249,6 +257,30 @@ public class AwsSqsMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEng msg -> new TbProtoQueueMsg<>(msg.getKey(), ToHousekeeperServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); } + @Override + public TbQueueConsumer> createEdgeMsgConsumer() { + return new TbAwsSqsConsumerTemplate<>(edgeAdmin, sqsSettings, topicService.buildTopicName(edgeSettings.getTopic()), + msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeMsg.parseFrom(msg.getData()), msg.getHeaders())); + } + + @Override + public TbQueueProducer> createEdgeMsgProducer() { + return new TbAwsSqsProducerTemplate<>(edgeAdmin, sqsSettings, topicService.buildTopicName(edgeSettings.getTopic())); + } + + @Override + public TbQueueConsumer> createToEdgeNotificationsMsgConsumer() { + return new TbAwsSqsConsumerTemplate<>(notificationAdmin, sqsSettings, + topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName(), + msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); + } + + @Override + public TbQueueProducer> createEdgeNotificationsMsgProducer() { + return new TbAwsSqsProducerTemplate<>(notificationAdmin, sqsSettings, + topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName()); + } + @PreDestroy private void destroy() { if (coreAdmin != null) { @@ -272,5 +304,8 @@ public class AwsSqsMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEng if (vcAdmin != null) { vcAdmin.destroy(); } + if (edgeAdmin != null) { + edgeAdmin.destroy(); + } } } diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/AwsSqsTbCoreQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/AwsSqsTbCoreQueueFactory.java index 05e435d7fb..515c1bba44 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/AwsSqsTbCoreQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/AwsSqsTbCoreQueueFactory.java @@ -22,15 +22,17 @@ import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Component; import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.gen.js.JsInvokeProtos; -import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeNotificationMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToVersionControlServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg; import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg; import org.thingsboard.server.queue.TbQueueAdmin; @@ -43,6 +45,7 @@ import org.thingsboard.server.queue.common.TbProtoQueueMsg; import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; import org.thingsboard.server.queue.discovery.TopicService; import org.thingsboard.server.queue.settings.TbQueueCoreSettings; +import org.thingsboard.server.queue.settings.TbQueueEdgeSettings; import org.thingsboard.server.queue.settings.TbQueueRemoteJsInvokeSettings; import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; @@ -69,6 +72,7 @@ public class AwsSqsTbCoreQueueFactory implements TbCoreQueueFactory { private final TbQueueRemoteJsInvokeSettings jsInvokeSettings; private final TbQueueTransportNotificationSettings transportNotificationSettings; private final TbQueueVersionControlSettings vcSettings; + private final TbQueueEdgeSettings edgeSettings; private final TbQueueAdmin coreAdmin; private final TbQueueAdmin ruleEngineAdmin; @@ -77,6 +81,7 @@ public class AwsSqsTbCoreQueueFactory implements TbCoreQueueFactory { private final TbQueueAdmin notificationAdmin; private final TbQueueAdmin otaAdmin; private final TbQueueAdmin vcAdmin; + private final TbQueueAdmin edgeAdmin; public AwsSqsTbCoreQueueFactory(TbAwsSqsSettings sqsSettings, TbQueueCoreSettings coreSettings, @@ -84,6 +89,7 @@ public class AwsSqsTbCoreQueueFactory implements TbCoreQueueFactory { TbQueueRuleEngineSettings ruleEngineSettings, TopicService topicService, TbQueueVersionControlSettings vcSettings, + TbQueueEdgeSettings edgeSettings, TbServiceInfoProvider serviceInfoProvider, TbQueueRemoteJsInvokeSettings jsInvokeSettings, TbAwsSqsQueueAttributes sqsQueueAttributes, @@ -92,6 +98,7 @@ public class AwsSqsTbCoreQueueFactory implements TbCoreQueueFactory { this.coreSettings = coreSettings; this.transportApiSettings = transportApiSettings; this.ruleEngineSettings = ruleEngineSettings; + this.edgeSettings = edgeSettings; this.topicService = topicService; this.serviceInfoProvider = serviceInfoProvider; this.jsInvokeSettings = jsInvokeSettings; @@ -105,6 +112,7 @@ public class AwsSqsTbCoreQueueFactory implements TbCoreQueueFactory { this.notificationAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getNotificationsAttributes()); this.otaAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getOtaAttributes()); this.vcAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getVcAttributes()); + this.edgeAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getEdgeAttributes()); } @Override @@ -129,7 +137,8 @@ public class AwsSqsTbCoreQueueFactory implements TbCoreQueueFactory { @Override public TbQueueProducer> createTbCoreNotificationsMsgProducer() { - return new TbAwsSqsProducerTemplate<>(notificationAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getTopic())); + return new TbAwsSqsProducerTemplate<>(notificationAdmin, sqsSettings, + topicService.getNotificationsTopic(ServiceType.TB_CORE, serviceInfoProvider.getServiceId()).getFullTopicName()); } @Override @@ -202,7 +211,7 @@ public class AwsSqsTbCoreQueueFactory implements TbCoreQueueFactory { } @Override - public TbQueueProducer> createVersionControlMsgProducer() { + public TbQueueProducer> createVersionControlMsgProducer() { return new TbAwsSqsProducerTemplate<>(vcAdmin, sqsSettings, topicService.buildTopicName(vcSettings.getTopic())); } @@ -228,6 +237,30 @@ public class AwsSqsTbCoreQueueFactory implements TbCoreQueueFactory { msg -> new TbProtoQueueMsg<>(msg.getKey(), ToHousekeeperServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); } + @Override + public TbQueueConsumer> createEdgeMsgConsumer() { + return new TbAwsSqsConsumerTemplate<>(edgeAdmin, sqsSettings, topicService.buildTopicName(edgeSettings.getTopic()), + msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeMsg.parseFrom(msg.getData()), msg.getHeaders())); + } + + @Override + public TbQueueProducer> createEdgeMsgProducer() { + return new TbAwsSqsProducerTemplate<>(edgeAdmin, sqsSettings, topicService.buildTopicName(edgeSettings.getTopic())); + } + + @Override + public TbQueueConsumer> createToEdgeNotificationsMsgConsumer() { + return new TbAwsSqsConsumerTemplate<>(notificationAdmin, sqsSettings, + topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName(), + msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); + } + + @Override + public TbQueueProducer> createEdgeNotificationsMsgProducer() { + return new TbAwsSqsProducerTemplate<>(notificationAdmin, sqsSettings, + topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName()); + } + @PreDestroy private void destroy() { if (coreAdmin != null) { @@ -251,5 +284,8 @@ public class AwsSqsTbCoreQueueFactory implements TbCoreQueueFactory { if (vcAdmin != null) { vcAdmin.destroy(); } + if (edgeAdmin != null) { + edgeAdmin.destroy(); + } } } diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/AwsSqsTbRuleEngineQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/AwsSqsTbRuleEngineQueueFactory.java index 7e6129a748..37319e378b 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/AwsSqsTbRuleEngineQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/AwsSqsTbRuleEngineQueueFactory.java @@ -25,8 +25,14 @@ import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.gen.js.JsInvokeProtos; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg; import org.thingsboard.server.queue.TbQueueAdmin; import org.thingsboard.server.queue.TbQueueConsumer; import org.thingsboard.server.queue.TbQueueProducer; @@ -37,6 +43,7 @@ import org.thingsboard.server.queue.common.TbProtoQueueMsg; import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; import org.thingsboard.server.queue.discovery.TopicService; import org.thingsboard.server.queue.settings.TbQueueCoreSettings; +import org.thingsboard.server.queue.settings.TbQueueEdgeSettings; import org.thingsboard.server.queue.settings.TbQueueRemoteJsInvokeSettings; import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; @@ -59,12 +66,14 @@ public class AwsSqsTbRuleEngineQueueFactory implements TbRuleEngineQueueFactory private final TbAwsSqsSettings sqsSettings; private final TbQueueRemoteJsInvokeSettings jsInvokeSettings; private final TbQueueTransportNotificationSettings transportNotificationSettings; + private final TbQueueEdgeSettings edgeSettings; private final TbQueueAdmin coreAdmin; private final TbQueueAdmin ruleEngineAdmin; private final TbQueueAdmin jsExecutorAdmin; private final TbQueueAdmin notificationAdmin; private final TbQueueAdmin otaAdmin; + private final TbQueueAdmin edgeAdmin; public AwsSqsTbRuleEngineQueueFactory(TopicService topicService, TbQueueCoreSettings coreSettings, TbQueueRuleEngineSettings ruleEngineSettings, @@ -72,7 +81,8 @@ public class AwsSqsTbRuleEngineQueueFactory implements TbRuleEngineQueueFactory TbAwsSqsSettings sqsSettings, TbAwsSqsQueueAttributes sqsQueueAttributes, TbQueueRemoteJsInvokeSettings jsInvokeSettings, - TbQueueTransportNotificationSettings transportNotificationSettings) { + TbQueueTransportNotificationSettings transportNotificationSettings, + TbQueueEdgeSettings edgeSettings) { this.topicService = topicService; this.coreSettings = coreSettings; this.serviceInfoProvider = serviceInfoProvider; @@ -80,12 +90,14 @@ public class AwsSqsTbRuleEngineQueueFactory implements TbRuleEngineQueueFactory this.sqsSettings = sqsSettings; this.jsInvokeSettings = jsInvokeSettings; this.transportNotificationSettings = transportNotificationSettings; + this.edgeSettings = edgeSettings; this.coreAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getCoreAttributes()); this.ruleEngineAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getRuleEngineAttributes()); this.jsExecutorAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getJsExecutorAttributes()); this.notificationAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getNotificationsAttributes()); this.otaAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getOtaAttributes()); + this.edgeAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getEdgeAttributes()); } @Override @@ -99,7 +111,7 @@ public class AwsSqsTbRuleEngineQueueFactory implements TbRuleEngineQueueFactory } @Override - public TbQueueProducer> createRuleEngineNotificationsMsgProducer() { + public TbQueueProducer> createRuleEngineNotificationsMsgProducer() { return new TbAwsSqsProducerTemplate<>(notificationAdmin, sqsSettings, topicService.buildTopicName(ruleEngineSettings.getTopic())); } @@ -109,10 +121,20 @@ public class AwsSqsTbRuleEngineQueueFactory implements TbRuleEngineQueueFactory } @Override - public TbQueueProducer> createTbCoreNotificationsMsgProducer() { + public TbQueueProducer> createTbCoreNotificationsMsgProducer() { return new TbAwsSqsProducerTemplate<>(notificationAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getTopic())); } + @Override + public TbQueueProducer> createEdgeMsgProducer() { + return new TbAwsSqsProducerTemplate<>(edgeAdmin, sqsSettings, topicService.buildTopicName(edgeSettings.getTopic())); + } + + @Override + public TbQueueProducer> createEdgeNotificationsMsgProducer() { + return new TbAwsSqsProducerTemplate<>(notificationAdmin, sqsSettings, topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName()); + } + @Override public TbQueueConsumer> createToRuleEngineMsgConsumer(Queue configuration) { return new TbAwsSqsConsumerTemplate<>(ruleEngineAdmin, sqsSettings, topicService.buildTopicName(configuration.getTopic()), @@ -120,10 +142,10 @@ public class AwsSqsTbRuleEngineQueueFactory implements TbRuleEngineQueueFactory } @Override - public TbQueueConsumer> createToRuleEngineNotificationsMsgConsumer() { + public TbQueueConsumer> createToRuleEngineNotificationsMsgConsumer() { return new TbAwsSqsConsumerTemplate<>(notificationAdmin, sqsSettings, topicService.getNotificationsTopic(ServiceType.TB_RULE_ENGINE, serviceInfoProvider.getServiceId()).getFullTopicName(), - msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportProtos.ToRuleEngineNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); + msg -> new TbProtoQueueMsg<>(msg.getKey(), ToRuleEngineNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); } @Override @@ -150,17 +172,17 @@ public class AwsSqsTbRuleEngineQueueFactory implements TbRuleEngineQueueFactory } @Override - public TbQueueProducer> createToUsageStatsServiceMsgProducer() { + public TbQueueProducer> createToUsageStatsServiceMsgProducer() { return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic())); } @Override - public TbQueueProducer> createToOtaPackageStateServiceMsgProducer() { + public TbQueueProducer> createToOtaPackageStateServiceMsgProducer() { return new TbAwsSqsProducerTemplate<>(otaAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getOtaPackageTopic())); } @Override - public TbQueueProducer> createHousekeeperMsgProducer() { + public TbQueueProducer> createHousekeeperMsgProducer() { return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic())); } diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/AwsSqsTbVersionControlQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/AwsSqsTbVersionControlQueueFactory.java index b14bb8d8e7..67ff0393bd 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/AwsSqsTbVersionControlQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/AwsSqsTbVersionControlQueueFactory.java @@ -41,7 +41,6 @@ public class AwsSqsTbVersionControlQueueFactory implements TbVersionControlQueue private final TbQueueVersionControlSettings vcSettings; private final TopicService topicService; - private final TbQueueAdmin coreAdmin; private final TbQueueAdmin notificationAdmin; private final TbQueueAdmin vcAdmin; diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/InMemoryMonolithQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/InMemoryMonolithQueueFactory.java index 225290ed63..c4281bc390 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/InMemoryMonolithQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/InMemoryMonolithQueueFactory.java @@ -34,6 +34,7 @@ import org.thingsboard.server.queue.memory.InMemoryStorage; import org.thingsboard.server.queue.memory.InMemoryTbQueueConsumer; import org.thingsboard.server.queue.memory.InMemoryTbQueueProducer; import org.thingsboard.server.queue.settings.TbQueueCoreSettings; +import org.thingsboard.server.queue.settings.TbQueueEdgeSettings; import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; @@ -51,6 +52,7 @@ public class InMemoryMonolithQueueFactory implements TbCoreQueueFactory, TbRuleE private final TbQueueVersionControlSettings vcSettings; private final TbQueueTransportApiSettings transportApiSettings; private final TbQueueTransportNotificationSettings transportNotificationSettings; + private final TbQueueEdgeSettings edgeSettings; private final InMemoryStorage storage; public InMemoryMonolithQueueFactory(TopicService topicService, TbQueueCoreSettings coreSettings, @@ -59,6 +61,7 @@ public class InMemoryMonolithQueueFactory implements TbCoreQueueFactory, TbRuleE TbServiceInfoProvider serviceInfoProvider, TbQueueTransportApiSettings transportApiSettings, TbQueueTransportNotificationSettings transportNotificationSettings, + TbQueueEdgeSettings edgeSettings, InMemoryStorage storage) { this.topicService = topicService; this.coreSettings = coreSettings; @@ -67,6 +70,7 @@ public class InMemoryMonolithQueueFactory implements TbCoreQueueFactory, TbRuleE this.ruleEngineSettings = ruleEngineSettings; this.transportApiSettings = transportApiSettings; this.transportNotificationSettings = transportNotificationSettings; + this.edgeSettings = edgeSettings; this.storage = storage; } @@ -92,7 +96,7 @@ public class InMemoryMonolithQueueFactory implements TbCoreQueueFactory, TbRuleE @Override public TbQueueProducer> createTbCoreNotificationsMsgProducer() { - return new InMemoryTbQueueProducer<>(storage, topicService.buildTopicName(coreSettings.getTopic())); + return new InMemoryTbQueueProducer<>(storage, topicService.getNotificationsTopic(ServiceType.TB_CORE, serviceInfoProvider.getServiceId()).getFullTopicName()); } @Override @@ -180,10 +184,29 @@ public class InMemoryMonolithQueueFactory implements TbCoreQueueFactory, TbRuleE return new InMemoryTbQueueConsumer<>(storage, topicService.buildTopicName(coreSettings.getHousekeeperReprocessingTopic())); } + @Override + public TbQueueConsumer> createEdgeMsgConsumer() { + return new InMemoryTbQueueConsumer<>(storage, topicService.buildTopicName(edgeSettings.getTopic())); + } + + @Override + public TbQueueProducer> createEdgeMsgProducer() { + return new InMemoryTbQueueProducer<>(storage, topicService.buildTopicName(edgeSettings.getTopic())); + } + + @Override + public TbQueueConsumer> createToEdgeNotificationsMsgConsumer() { + return new InMemoryTbQueueConsumer<>(storage, topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName()); + } + + @Override + public TbQueueProducer> createEdgeNotificationsMsgProducer() { + return new InMemoryTbQueueProducer<>(storage, topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName()); + } + @Scheduled(fixedRateString = "${queue.in_memory.stats.print-interval-ms:60000}") private void printInMemoryStats() { storage.printStats(); } - } diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaMonolithQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaMonolithQueueFactory.java index 87be03c8c7..46d94f094f 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaMonolithQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaMonolithQueueFactory.java @@ -23,15 +23,17 @@ import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.queue.Queue; import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.gen.js.JsInvokeProtos; -import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeNotificationMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToVersionControlServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg; import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg; import org.thingsboard.server.queue.TbQueueAdmin; @@ -50,6 +52,7 @@ import org.thingsboard.server.queue.kafka.TbKafkaProducerTemplate; import org.thingsboard.server.queue.kafka.TbKafkaSettings; import org.thingsboard.server.queue.kafka.TbKafkaTopicConfigs; import org.thingsboard.server.queue.settings.TbQueueCoreSettings; +import org.thingsboard.server.queue.settings.TbQueueEdgeSettings; import org.thingsboard.server.queue.settings.TbQueueRemoteJsInvokeSettings; import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; @@ -72,6 +75,7 @@ public class KafkaMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEngi private final TbQueueTransportNotificationSettings transportNotificationSettings; private final TbQueueRemoteJsInvokeSettings jsInvokeSettings; private final TbQueueVersionControlSettings vcSettings; + private final TbQueueEdgeSettings edgeSettings; private final TbKafkaConsumerStatsService consumerStatsService; private final TbQueueAdmin coreAdmin; @@ -85,6 +89,7 @@ public class KafkaMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEngi private final TbQueueAdmin vcAdmin; private final TbQueueAdmin housekeeperAdmin; private final TbQueueAdmin housekeeperReprocessingAdmin; + private final TbQueueAdmin edgeAdmin; private final AtomicLong consumerCount = new AtomicLong(); @@ -96,6 +101,7 @@ public class KafkaMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEngi TbQueueTransportNotificationSettings transportNotificationSettings, TbQueueRemoteJsInvokeSettings jsInvokeSettings, TbQueueVersionControlSettings vcSettings, + TbQueueEdgeSettings edgeSettings, TbKafkaConsumerStatsService consumerStatsService, TbKafkaTopicConfigs kafkaTopicConfigs) { this.topicService = topicService; @@ -108,6 +114,7 @@ public class KafkaMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEngi this.jsInvokeSettings = jsInvokeSettings; this.vcSettings = vcSettings; this.consumerStatsService = consumerStatsService; + this.edgeSettings = edgeSettings; this.coreAdmin = new TbKafkaAdmin(kafkaSettings, kafkaTopicConfigs.getCoreConfigs()); this.ruleEngineAdmin = new TbKafkaAdmin(kafkaSettings, kafkaTopicConfigs.getRuleEngineConfigs()); @@ -120,6 +127,7 @@ public class KafkaMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEngi this.vcAdmin = new TbKafkaAdmin(kafkaSettings, kafkaTopicConfigs.getVcConfigs()); this.housekeeperAdmin = new TbKafkaAdmin(kafkaSettings, kafkaTopicConfigs.getHousekeeperConfigs()); this.housekeeperReprocessingAdmin = new TbKafkaAdmin(kafkaSettings, kafkaTopicConfigs.getHousekeeperReprocessingConfigs()); + this.edgeAdmin = new TbKafkaAdmin(kafkaSettings, kafkaTopicConfigs.getEdgeConfigs()); } @Override @@ -167,19 +175,19 @@ public class KafkaMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEngi TbKafkaProducerTemplate.TbKafkaProducerTemplateBuilder> requestBuilder = TbKafkaProducerTemplate.builder(); requestBuilder.settings(kafkaSettings); requestBuilder.clientId("monolith-core-notifications-" + serviceInfoProvider.getServiceId()); - requestBuilder.defaultTopic(topicService.buildTopicName(coreSettings.getTopic())); + requestBuilder.defaultTopic(topicService.getNotificationsTopic(ServiceType.TB_CORE, serviceInfoProvider.getServiceId()).getFullTopicName()); requestBuilder.admin(notificationAdmin); return requestBuilder.build(); } @Override - public TbQueueConsumer> createToVersionControlMsgConsumer() { - TbKafkaConsumerTemplate.TbKafkaConsumerTemplateBuilder> consumerBuilder = TbKafkaConsumerTemplate.builder(); + public TbQueueConsumer> createToVersionControlMsgConsumer() { + TbKafkaConsumerTemplate.TbKafkaConsumerTemplateBuilder> consumerBuilder = TbKafkaConsumerTemplate.builder(); consumerBuilder.settings(kafkaSettings); consumerBuilder.topic(topicService.buildTopicName(vcSettings.getTopic())); consumerBuilder.clientId("monolith-vc-consumer-" + serviceInfoProvider.getServiceId()); consumerBuilder.groupId(topicService.buildTopicName("monolith-vc-node")); - consumerBuilder.decoder(msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportProtos.ToVersionControlServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); + consumerBuilder.decoder(msg -> new TbProtoQueueMsg<>(msg.getKey(), ToVersionControlServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); consumerBuilder.admin(vcAdmin); consumerBuilder.statsService(consumerStatsService); return consumerBuilder.build(); @@ -353,8 +361,8 @@ public class KafkaMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEngi } @Override - public TbQueueProducer> createVersionControlMsgProducer() { - TbKafkaProducerTemplate.TbKafkaProducerTemplateBuilder> requestBuilder = TbKafkaProducerTemplate.builder(); + public TbQueueProducer> createVersionControlMsgProducer() { + TbKafkaProducerTemplate.TbKafkaProducerTemplateBuilder> requestBuilder = TbKafkaProducerTemplate.builder(); requestBuilder.settings(kafkaSettings); requestBuilder.clientId("monolith-vc-producer-" + serviceInfoProvider.getServiceId()); requestBuilder.defaultTopic(topicService.buildTopicName(vcSettings.getTopic())); @@ -408,6 +416,52 @@ public class KafkaMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEngi .build(); } + @Override + public TbQueueConsumer> createEdgeMsgConsumer() { + TbKafkaConsumerTemplate.TbKafkaConsumerTemplateBuilder> consumerBuilder = TbKafkaConsumerTemplate.builder(); + consumerBuilder.settings(kafkaSettings); + consumerBuilder.topic(topicService.buildTopicName(edgeSettings.getTopic())); + consumerBuilder.clientId("monolith-edge-consumer-" + serviceInfoProvider.getServiceId()); + consumerBuilder.groupId(topicService.buildTopicName("monolith-edge-consumer")); + consumerBuilder.decoder(msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeMsg.parseFrom(msg.getData()), msg.getHeaders())); + consumerBuilder.admin(edgeAdmin); + consumerBuilder.statsService(consumerStatsService); + return consumerBuilder.build(); + } + + @Override + public TbQueueProducer> createEdgeMsgProducer() { + TbKafkaProducerTemplate.TbKafkaProducerTemplateBuilder> requestBuilder = TbKafkaProducerTemplate.builder(); + requestBuilder.settings(kafkaSettings); + requestBuilder.clientId("monolith-to-edge-" + serviceInfoProvider.getServiceId()); + requestBuilder.defaultTopic(topicService.buildTopicName(edgeSettings.getTopic())); + requestBuilder.admin(edgeAdmin); + return requestBuilder.build(); + } + + @Override + public TbQueueConsumer> createToEdgeNotificationsMsgConsumer() { + TbKafkaConsumerTemplate.TbKafkaConsumerTemplateBuilder> consumerBuilder = TbKafkaConsumerTemplate.builder(); + consumerBuilder.settings(kafkaSettings); + consumerBuilder.topic(topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName()); + consumerBuilder.clientId("monolith-edge-notifications-consumer-" + serviceInfoProvider.getServiceId()); + consumerBuilder.groupId(topicService.buildTopicName("monolith-edge-notifications-consumer-" + serviceInfoProvider.getServiceId())); + consumerBuilder.decoder(msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); + consumerBuilder.admin(notificationAdmin); + consumerBuilder.statsService(consumerStatsService); + return consumerBuilder.build(); + } + + @Override + public TbQueueProducer> createEdgeNotificationsMsgProducer() { + TbKafkaProducerTemplate.TbKafkaProducerTemplateBuilder> requestBuilder = TbKafkaProducerTemplate.builder(); + requestBuilder.settings(kafkaSettings); + requestBuilder.clientId("monolith-to-edge-notifications-" + serviceInfoProvider.getServiceId()); + requestBuilder.defaultTopic(topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName()); + requestBuilder.admin(notificationAdmin); + return requestBuilder.build(); + } + @PreDestroy private void destroy() { if (coreAdmin != null) { @@ -437,5 +491,8 @@ public class KafkaMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEngi if (vcAdmin != null) { vcAdmin.destroy(); } + if (edgeAdmin != null) { + edgeAdmin.destroy(); + } } } diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaTbCoreQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaTbCoreQueueFactory.java index f16f21ad66..b8b51706b2 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaTbCoreQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaTbCoreQueueFactory.java @@ -24,6 +24,8 @@ import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.gen.js.JsInvokeProtos; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeNotificationMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; @@ -49,6 +51,7 @@ import org.thingsboard.server.queue.kafka.TbKafkaProducerTemplate; import org.thingsboard.server.queue.kafka.TbKafkaSettings; import org.thingsboard.server.queue.kafka.TbKafkaTopicConfigs; import org.thingsboard.server.queue.settings.TbQueueCoreSettings; +import org.thingsboard.server.queue.settings.TbQueueEdgeSettings; import org.thingsboard.server.queue.settings.TbQueueRemoteJsInvokeSettings; import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; @@ -72,6 +75,7 @@ public class KafkaTbCoreQueueFactory implements TbCoreQueueFactory { private final TbQueueVersionControlSettings vcSettings; private final TbKafkaConsumerStatsService consumerStatsService; private final TbQueueTransportNotificationSettings transportNotificationSettings; + private final TbQueueEdgeSettings edgeSettings; private final TbQueueAdmin coreAdmin; private final TbQueueAdmin ruleEngineAdmin; @@ -84,6 +88,7 @@ public class KafkaTbCoreQueueFactory implements TbCoreQueueFactory { private final TbQueueAdmin vcAdmin; private final TbQueueAdmin housekeeperAdmin; private final TbQueueAdmin housekeeperReprocessingAdmin; + private final TbQueueAdmin edgeAdmin; private final AtomicLong consumerCount = new AtomicLong(); @@ -95,6 +100,7 @@ public class KafkaTbCoreQueueFactory implements TbCoreQueueFactory { TbQueueTransportApiSettings transportApiSettings, TbQueueRemoteJsInvokeSettings jsInvokeSettings, TbQueueVersionControlSettings vcSettings, + TbQueueEdgeSettings edgeSettings, TbKafkaConsumerStatsService consumerStatsService, TbQueueTransportNotificationSettings transportNotificationSettings, TbKafkaTopicConfigs kafkaTopicConfigs) { @@ -108,6 +114,7 @@ public class KafkaTbCoreQueueFactory implements TbCoreQueueFactory { this.vcSettings = vcSettings; this.consumerStatsService = consumerStatsService; this.transportNotificationSettings = transportNotificationSettings; + this.edgeSettings = edgeSettings; this.coreAdmin = new TbKafkaAdmin(kafkaSettings, kafkaTopicConfigs.getCoreConfigs()); this.ruleEngineAdmin = new TbKafkaAdmin(kafkaSettings, kafkaTopicConfigs.getRuleEngineConfigs()); @@ -120,6 +127,7 @@ public class KafkaTbCoreQueueFactory implements TbCoreQueueFactory { this.vcAdmin = new TbKafkaAdmin(kafkaSettings, kafkaTopicConfigs.getVcConfigs()); this.housekeeperAdmin = new TbKafkaAdmin(kafkaSettings, kafkaTopicConfigs.getHousekeeperConfigs()); this.housekeeperReprocessingAdmin = new TbKafkaAdmin(kafkaSettings, kafkaTopicConfigs.getHousekeeperReprocessingConfigs()); + this.edgeAdmin = new TbKafkaAdmin(kafkaSettings, kafkaTopicConfigs.getEdgeConfigs()); } @Override @@ -167,7 +175,7 @@ public class KafkaTbCoreQueueFactory implements TbCoreQueueFactory { TbKafkaProducerTemplate.TbKafkaProducerTemplateBuilder> requestBuilder = TbKafkaProducerTemplate.builder(); requestBuilder.settings(kafkaSettings); requestBuilder.clientId("tb-core-to-core-notifications-" + serviceInfoProvider.getServiceId()); - requestBuilder.defaultTopic(topicService.buildTopicName(coreSettings.getTopic())); + requestBuilder.defaultTopic(topicService.getNotificationsTopic(ServiceType.TB_CORE, serviceInfoProvider.getServiceId()).getFullTopicName()); requestBuilder.admin(notificationAdmin); return requestBuilder.build(); } @@ -357,6 +365,51 @@ public class KafkaTbCoreQueueFactory implements TbCoreQueueFactory { .build(); } + @Override + public TbQueueConsumer> createEdgeMsgConsumer() { + TbKafkaConsumerTemplate.TbKafkaConsumerTemplateBuilder> consumerBuilder = TbKafkaConsumerTemplate.builder(); + consumerBuilder.settings(kafkaSettings); + consumerBuilder.topic(topicService.buildTopicName(edgeSettings.getTopic())); + consumerBuilder.clientId("tb-core-edge-consumer-" + serviceInfoProvider.getServiceId()); + consumerBuilder.groupId(topicService.buildTopicName("tb-core-edge-consumer")); + consumerBuilder.decoder(msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeMsg.parseFrom(msg.getData()), msg.getHeaders())); + consumerBuilder.admin(edgeAdmin); + consumerBuilder.statsService(consumerStatsService); + return consumerBuilder.build(); + } + + @Override + public TbQueueProducer> createEdgeMsgProducer() { + TbKafkaProducerTemplate.TbKafkaProducerTemplateBuilder> requestBuilder = TbKafkaProducerTemplate.builder(); + requestBuilder.settings(kafkaSettings); + requestBuilder.clientId("tb-core-to-edge-" + serviceInfoProvider.getServiceId()); + requestBuilder.defaultTopic(topicService.buildTopicName(edgeSettings.getTopic())); + requestBuilder.admin(edgeAdmin); + return requestBuilder.build(); + } + + @Override + public TbQueueConsumer> createToEdgeNotificationsMsgConsumer() { + TbKafkaConsumerTemplate.TbKafkaConsumerTemplateBuilder> consumerBuilder = TbKafkaConsumerTemplate.builder(); + consumerBuilder.settings(kafkaSettings); + consumerBuilder.topic(topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName()); + consumerBuilder.clientId("tb-edge-notifications-consumer-" + serviceInfoProvider.getServiceId()); + consumerBuilder.groupId(topicService.buildTopicName("tb-edge-notifications-node-" + serviceInfoProvider.getServiceId())); + consumerBuilder.decoder(msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); + consumerBuilder.admin(notificationAdmin); + consumerBuilder.statsService(consumerStatsService); + return consumerBuilder.build(); + } + + @Override + public TbQueueProducer> createEdgeNotificationsMsgProducer() { + TbKafkaProducerTemplate.TbKafkaProducerTemplateBuilder> requestBuilder = TbKafkaProducerTemplate.builder(); + requestBuilder.settings(kafkaSettings); + requestBuilder.clientId("tb-core-to-edge-notifications-" + serviceInfoProvider.getServiceId()); + requestBuilder.defaultTopic(topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName()); + requestBuilder.admin(notificationAdmin); + return requestBuilder.build(); + } @PreDestroy private void destroy() { diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaTbRuleEngineQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaTbRuleEngineQueueFactory.java index 0b320ba617..485830caf4 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaTbRuleEngineQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaTbRuleEngineQueueFactory.java @@ -26,7 +26,9 @@ import org.thingsboard.server.gen.js.JsInvokeProtos; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; @@ -47,6 +49,7 @@ import org.thingsboard.server.queue.kafka.TbKafkaProducerTemplate; import org.thingsboard.server.queue.kafka.TbKafkaSettings; import org.thingsboard.server.queue.kafka.TbKafkaTopicConfigs; import org.thingsboard.server.queue.settings.TbQueueCoreSettings; +import org.thingsboard.server.queue.settings.TbQueueEdgeSettings; import org.thingsboard.server.queue.settings.TbQueueRemoteJsInvokeSettings; import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; @@ -66,6 +69,7 @@ public class KafkaTbRuleEngineQueueFactory implements TbRuleEngineQueueFactory { private final TbQueueRemoteJsInvokeSettings jsInvokeSettings; private final TbKafkaConsumerStatsService consumerStatsService; private final TbQueueTransportNotificationSettings transportNotificationSettings; + private final TbQueueEdgeSettings edgeSettings; private final TbQueueAdmin coreAdmin; private final TbKafkaAdmin ruleEngineAdmin; @@ -74,6 +78,7 @@ public class KafkaTbRuleEngineQueueFactory implements TbRuleEngineQueueFactory { private final TbQueueAdmin notificationAdmin; private final TbQueueAdmin fwUpdatesAdmin; private final TbQueueAdmin housekeeperAdmin; + private final TbQueueAdmin edgeAdmin; private final AtomicLong consumerCount = new AtomicLong(); public KafkaTbRuleEngineQueueFactory(TopicService topicService, TbKafkaSettings kafkaSettings, @@ -83,6 +88,7 @@ public class KafkaTbRuleEngineQueueFactory implements TbRuleEngineQueueFactory { TbQueueRemoteJsInvokeSettings jsInvokeSettings, TbKafkaConsumerStatsService consumerStatsService, TbQueueTransportNotificationSettings transportNotificationSettings, + TbQueueEdgeSettings edgeSettings, TbKafkaTopicConfigs kafkaTopicConfigs) { this.topicService = topicService; this.kafkaSettings = kafkaSettings; @@ -92,6 +98,7 @@ public class KafkaTbRuleEngineQueueFactory implements TbRuleEngineQueueFactory { this.jsInvokeSettings = jsInvokeSettings; this.consumerStatsService = consumerStatsService; this.transportNotificationSettings = transportNotificationSettings; + this.edgeSettings = edgeSettings; this.coreAdmin = new TbKafkaAdmin(kafkaSettings, kafkaTopicConfigs.getCoreConfigs()); this.ruleEngineAdmin = new TbKafkaAdmin(kafkaSettings, kafkaTopicConfigs.getRuleEngineConfigs()); @@ -100,6 +107,7 @@ public class KafkaTbRuleEngineQueueFactory implements TbRuleEngineQueueFactory { this.notificationAdmin = new TbKafkaAdmin(kafkaSettings, kafkaTopicConfigs.getNotificationsConfigs()); this.fwUpdatesAdmin = new TbKafkaAdmin(kafkaSettings, kafkaTopicConfigs.getFwUpdatesConfigs()); this.housekeeperAdmin = new TbKafkaAdmin(kafkaSettings, kafkaTopicConfigs.getHousekeeperConfigs()); + this.edgeAdmin = new TbKafkaAdmin(kafkaSettings, kafkaTopicConfigs.getEdgeConfigs()); } @Override @@ -143,8 +151,8 @@ public class KafkaTbRuleEngineQueueFactory implements TbRuleEngineQueueFactory { } @Override - public TbQueueProducer> createToOtaPackageStateServiceMsgProducer() { - TbKafkaProducerTemplate.TbKafkaProducerTemplateBuilder> requestBuilder = TbKafkaProducerTemplate.builder(); + public TbQueueProducer> createToOtaPackageStateServiceMsgProducer() { + TbKafkaProducerTemplate.TbKafkaProducerTemplateBuilder> requestBuilder = TbKafkaProducerTemplate.builder(); requestBuilder.settings(kafkaSettings); requestBuilder.clientId("tb-rule-engine-ota-producer-" + serviceInfoProvider.getServiceId()); requestBuilder.defaultTopic(topicService.buildTopicName(coreSettings.getOtaPackageTopic())); @@ -162,6 +170,26 @@ public class KafkaTbRuleEngineQueueFactory implements TbRuleEngineQueueFactory { return requestBuilder.build(); } + @Override + public TbQueueProducer> createEdgeMsgProducer() { + TbKafkaProducerTemplate.TbKafkaProducerTemplateBuilder> requestBuilder = TbKafkaProducerTemplate.builder(); + requestBuilder.settings(kafkaSettings); + requestBuilder.clientId("tb-rule-engine-to-edge-" + serviceInfoProvider.getServiceId()); + requestBuilder.defaultTopic(topicService.buildTopicName(edgeSettings.getTopic())); + requestBuilder.admin(edgeAdmin); + return requestBuilder.build(); + } + + @Override + public TbQueueProducer> createEdgeNotificationsMsgProducer() { + TbKafkaProducerTemplate.TbKafkaProducerTemplateBuilder> requestBuilder = TbKafkaProducerTemplate.builder(); + requestBuilder.settings(kafkaSettings); + requestBuilder.clientId("tb-rule-engine-to-edge-notifications-" + serviceInfoProvider.getServiceId()); + requestBuilder.defaultTopic(topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName()); + requestBuilder.admin(notificationAdmin); + return requestBuilder.build(); + } + @Override public TbQueueConsumer> createToRuleEngineMsgConsumer(Queue configuration) { throw new UnsupportedOperationException("Rule engine consumer should use a partitionId"); diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/PubSubMonolithQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/PubSubMonolithQueueFactory.java index 00f4a1ec4e..3df48e8fb8 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/PubSubMonolithQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/PubSubMonolithQueueFactory.java @@ -24,15 +24,17 @@ import org.thingsboard.server.common.data.queue.Queue; import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.gen.js.JsInvokeProtos.RemoteJsRequest; import org.thingsboard.server.gen.js.JsInvokeProtos.RemoteJsResponse; -import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeNotificationMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToVersionControlServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg; import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg; import org.thingsboard.server.queue.TbQueueAdmin; @@ -50,6 +52,7 @@ import org.thingsboard.server.queue.pubsub.TbPubSubProducerTemplate; import org.thingsboard.server.queue.pubsub.TbPubSubSettings; import org.thingsboard.server.queue.pubsub.TbPubSubSubscriptionSettings; import org.thingsboard.server.queue.settings.TbQueueCoreSettings; +import org.thingsboard.server.queue.settings.TbQueueEdgeSettings; import org.thingsboard.server.queue.settings.TbQueueRemoteJsInvokeSettings; import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; @@ -71,6 +74,7 @@ public class PubSubMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEng private final TbServiceInfoProvider serviceInfoProvider; private final TbQueueRemoteJsInvokeSettings jsInvokeSettings; private final TbQueueVersionControlSettings vcSettings; + private final TbQueueEdgeSettings edgeSettings; private final TbQueueAdmin coreAdmin; private final TbQueueAdmin ruleEngineAdmin; @@ -78,6 +82,7 @@ public class PubSubMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEng private final TbQueueAdmin transportApiAdmin; private final TbQueueAdmin notificationAdmin; private final TbQueueAdmin vcAdmin; + private final TbQueueAdmin edgeAdmin; public PubSubMonolithQueueFactory(TbPubSubSettings pubSubSettings, TbQueueCoreSettings coreSettings, @@ -88,7 +93,8 @@ public class PubSubMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEng TbServiceInfoProvider serviceInfoProvider, TbPubSubSubscriptionSettings pubSubSubscriptionSettings, TbQueueRemoteJsInvokeSettings jsInvokeSettings, - TbQueueVersionControlSettings vcSettings) { + TbQueueVersionControlSettings vcSettings, + TbQueueEdgeSettings edgeSettings) { this.pubSubSettings = pubSubSettings; this.coreSettings = coreSettings; this.ruleEngineSettings = ruleEngineSettings; @@ -97,6 +103,7 @@ public class PubSubMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEng this.topicService = topicService; this.serviceInfoProvider = serviceInfoProvider; this.vcSettings = vcSettings; + this.edgeSettings = edgeSettings; this.coreAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getCoreSettings()); this.ruleEngineAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getRuleEngineSettings()); @@ -104,6 +111,7 @@ public class PubSubMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEng this.transportApiAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getTransportApiSettings()); this.notificationAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getNotificationsSettings()); this.vcAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getVcSettings()); + this.edgeAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getEdgeSettings()); this.jsInvokeSettings = jsInvokeSettings; } @@ -135,9 +143,9 @@ public class PubSubMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEng } @Override - public TbQueueConsumer> createToVersionControlMsgConsumer() { + public TbQueueConsumer> createToVersionControlMsgConsumer() { return new TbPubSubConsumerTemplate<>(vcAdmin, pubSubSettings, topicService.buildTopicName(vcSettings.getTopic()), - msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportProtos.ToVersionControlServiceMsg.parseFrom(msg.getData()), msg.getHeaders()) + msg -> new TbProtoQueueMsg<>(msg.getKey(), ToVersionControlServiceMsg.parseFrom(msg.getData()), msg.getHeaders()) ); } @@ -224,7 +232,7 @@ public class PubSubMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEng } @Override - public TbQueueProducer> createVersionControlMsgProducer() { + public TbQueueProducer> createVersionControlMsgProducer() { return new TbPubSubProducerTemplate<>(vcAdmin, pubSubSettings, topicService.buildTopicName(vcSettings.getTopic())); } @@ -250,6 +258,30 @@ public class PubSubMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEng msg -> new TbProtoQueueMsg<>(msg.getKey(), ToHousekeeperServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); } + @Override + public TbQueueProducer> createEdgeMsgProducer() { + return new TbPubSubProducerTemplate<>(edgeAdmin, pubSubSettings, topicService.buildTopicName(edgeSettings.getTopic())); + } + + @Override + public TbQueueConsumer> createEdgeMsgConsumer() { + return new TbPubSubConsumerTemplate<>(edgeAdmin, pubSubSettings, topicService.buildTopicName(edgeSettings.getTopic()), + msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeMsg.parseFrom(msg.getData()), msg.getHeaders())); + } + + @Override + public TbQueueConsumer> createToEdgeNotificationsMsgConsumer() { + return new TbPubSubConsumerTemplate<>(notificationAdmin, pubSubSettings, + topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName(), + msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); + } + + @Override + public TbQueueProducer> createEdgeNotificationsMsgProducer() { + return new TbPubSubProducerTemplate<>(notificationAdmin, pubSubSettings, + topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName()); + } + @PreDestroy private void destroy() { if (coreAdmin != null) { @@ -270,5 +302,8 @@ public class PubSubMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEng if (vcAdmin != null) { vcAdmin.destroy(); } + if (edgeAdmin != null) { + edgeAdmin.destroy(); + } } } diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/PubSubTbCoreQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/PubSubTbCoreQueueFactory.java index 091909d8f2..919d895a97 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/PubSubTbCoreQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/PubSubTbCoreQueueFactory.java @@ -22,15 +22,17 @@ import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Component; import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.gen.js.JsInvokeProtos; -import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeNotificationMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToVersionControlServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg; import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg; import org.thingsboard.server.queue.TbQueueAdmin; @@ -48,6 +50,7 @@ import org.thingsboard.server.queue.pubsub.TbPubSubProducerTemplate; import org.thingsboard.server.queue.pubsub.TbPubSubSettings; import org.thingsboard.server.queue.pubsub.TbPubSubSubscriptionSettings; import org.thingsboard.server.queue.settings.TbQueueCoreSettings; +import org.thingsboard.server.queue.settings.TbQueueEdgeSettings; import org.thingsboard.server.queue.settings.TbQueueRemoteJsInvokeSettings; import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; @@ -67,12 +70,14 @@ public class PubSubTbCoreQueueFactory implements TbCoreQueueFactory { private final TbQueueRemoteJsInvokeSettings jsInvokeSettings; private final TbQueueTransportNotificationSettings transportNotificationSettings; private final TbQueueRuleEngineSettings ruleEngineSettings; + private final TbQueueEdgeSettings edgeSettings; private final TbQueueAdmin coreAdmin; private final TbQueueAdmin jsExecutorAdmin; private final TbQueueAdmin transportApiAdmin; private final TbQueueAdmin notificationAdmin; private final TbQueueAdmin ruleEngineAdmin; + private final TbQueueAdmin edgeAdmin; public PubSubTbCoreQueueFactory(TbPubSubSettings pubSubSettings, TbQueueCoreSettings coreSettings, @@ -82,6 +87,7 @@ public class PubSubTbCoreQueueFactory implements TbCoreQueueFactory { TbQueueRemoteJsInvokeSettings jsInvokeSettings, TbQueueTransportNotificationSettings transportNotificationSettings, TbQueueRuleEngineSettings ruleEngineSettings, + TbQueueEdgeSettings edgeSettings, TbPubSubSubscriptionSettings pubSubSubscriptionSettings) { this.pubSubSettings = pubSubSettings; this.coreSettings = coreSettings; @@ -91,12 +97,14 @@ public class PubSubTbCoreQueueFactory implements TbCoreQueueFactory { this.jsInvokeSettings = jsInvokeSettings; this.transportNotificationSettings = transportNotificationSettings; this.ruleEngineSettings = ruleEngineSettings; + this.edgeSettings = edgeSettings; this.coreAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getCoreSettings()); this.jsExecutorAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getJsExecutorSettings()); this.transportApiAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getTransportApiSettings()); this.notificationAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getNotificationsSettings()); this.ruleEngineAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getRuleEngineSettings()); + this.edgeAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getEdgeSettings()); } @Override @@ -121,7 +129,8 @@ public class PubSubTbCoreQueueFactory implements TbCoreQueueFactory { @Override public TbQueueProducer> createTbCoreNotificationsMsgProducer() { - return new TbPubSubProducerTemplate<>(notificationAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getTopic())); + return new TbPubSubProducerTemplate<>(notificationAdmin, pubSubSettings, + topicService.getNotificationsTopic(ServiceType.TB_CORE, serviceInfoProvider.getServiceId()).getFullTopicName()); } @Override @@ -194,7 +203,7 @@ public class PubSubTbCoreQueueFactory implements TbCoreQueueFactory { } @Override - public TbQueueProducer> createVersionControlMsgProducer() { + public TbQueueProducer> createVersionControlMsgProducer() { //TODO: version-control return null; } @@ -221,6 +230,30 @@ public class PubSubTbCoreQueueFactory implements TbCoreQueueFactory { msg -> new TbProtoQueueMsg<>(msg.getKey(), ToHousekeeperServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); } + @Override + public TbQueueConsumer> createEdgeMsgConsumer() { + return new TbPubSubConsumerTemplate<>(edgeAdmin, pubSubSettings, topicService.buildTopicName(edgeSettings.getTopic()), + msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeMsg.parseFrom(msg.getData()), msg.getHeaders())); + } + + @Override + public TbQueueProducer> createEdgeMsgProducer() { + return new TbPubSubProducerTemplate<>(edgeAdmin, pubSubSettings, topicService.buildTopicName(edgeSettings.getTopic())); + } + + @Override + public TbQueueConsumer> createToEdgeNotificationsMsgConsumer() { + return new TbPubSubConsumerTemplate<>(notificationAdmin, pubSubSettings, + topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName(), + msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); + } + + @Override + public TbQueueProducer> createEdgeNotificationsMsgProducer() { + return new TbPubSubProducerTemplate<>(notificationAdmin, pubSubSettings, + topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName()); + } + @PreDestroy private void destroy() { if (coreAdmin != null) { @@ -238,5 +271,8 @@ public class PubSubTbCoreQueueFactory implements TbCoreQueueFactory { if (ruleEngineAdmin != null) { ruleEngineAdmin.destroy(); } + if (edgeAdmin != null) { + edgeAdmin.destroy(); + } } } diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/PubSubTbRuleEngineQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/PubSubTbRuleEngineQueueFactory.java index 3e607d0bf9..bb46610de5 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/PubSubTbRuleEngineQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/PubSubTbRuleEngineQueueFactory.java @@ -23,8 +23,10 @@ import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.queue.Queue; import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.gen.js.JsInvokeProtos; +import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; @@ -46,6 +48,7 @@ import org.thingsboard.server.queue.pubsub.TbPubSubProducerTemplate; import org.thingsboard.server.queue.pubsub.TbPubSubSettings; import org.thingsboard.server.queue.pubsub.TbPubSubSubscriptionSettings; import org.thingsboard.server.queue.settings.TbQueueCoreSettings; +import org.thingsboard.server.queue.settings.TbQueueEdgeSettings; import org.thingsboard.server.queue.settings.TbQueueRemoteJsInvokeSettings; import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; @@ -63,11 +66,13 @@ public class PubSubTbRuleEngineQueueFactory implements TbRuleEngineQueueFactory private final TbServiceInfoProvider serviceInfoProvider; private final TbQueueRemoteJsInvokeSettings jsInvokeSettings; private final TbQueueTransportNotificationSettings transportNotificationSettings; + private final TbQueueEdgeSettings edgeSettings; private final TbQueueAdmin coreAdmin; private final TbQueueAdmin ruleEngineAdmin; private final TbQueueAdmin jsExecutorAdmin; private final TbQueueAdmin notificationAdmin; + private final TbQueueAdmin edgeAdmin; public PubSubTbRuleEngineQueueFactory(TbPubSubSettings pubSubSettings, TbQueueCoreSettings coreSettings, @@ -76,7 +81,8 @@ public class PubSubTbRuleEngineQueueFactory implements TbRuleEngineQueueFactory TbServiceInfoProvider serviceInfoProvider, TbQueueRemoteJsInvokeSettings jsInvokeSettings, TbQueueTransportNotificationSettings transportNotificationSettings, - TbPubSubSubscriptionSettings pubSubSubscriptionSettings) { + TbPubSubSubscriptionSettings pubSubSubscriptionSettings, + TbQueueEdgeSettings edgeSettings) { this.pubSubSettings = pubSubSettings; this.coreSettings = coreSettings; this.ruleEngineSettings = ruleEngineSettings; @@ -84,11 +90,13 @@ public class PubSubTbRuleEngineQueueFactory implements TbRuleEngineQueueFactory this.serviceInfoProvider = serviceInfoProvider; this.jsInvokeSettings = jsInvokeSettings; this.transportNotificationSettings = transportNotificationSettings; + this.edgeSettings = edgeSettings; this.coreAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getCoreSettings()); this.ruleEngineAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getRuleEngineSettings()); this.jsExecutorAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getJsExecutorSettings()); this.notificationAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getNotificationsSettings()); + this.edgeAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getEdgeSettings()); } @Override @@ -116,6 +124,16 @@ public class PubSubTbRuleEngineQueueFactory implements TbRuleEngineQueueFactory return new TbPubSubProducerTemplate<>(notificationAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getTopic())); } + @Override + public TbQueueProducer> createEdgeMsgProducer() { + return new TbPubSubProducerTemplate<>(edgeAdmin, pubSubSettings, topicService.buildTopicName(edgeSettings.getTopic())); + } + + @Override + public TbQueueProducer> createEdgeNotificationsMsgProducer() { + return new TbPubSubProducerTemplate<>(notificationAdmin, pubSubSettings, topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName()); + } + @Override public TbQueueConsumer> createToRuleEngineMsgConsumer(Queue configuration) { return new TbPubSubConsumerTemplate<>(ruleEngineAdmin, pubSubSettings, topicService.buildTopicName(configuration.getTopic()), diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqMonolithQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqMonolithQueueFactory.java index cf60012449..8ad400d9e3 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqMonolithQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqMonolithQueueFactory.java @@ -24,15 +24,17 @@ import org.thingsboard.server.common.data.queue.Queue; import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.gen.js.JsInvokeProtos.RemoteJsRequest; import org.thingsboard.server.gen.js.JsInvokeProtos.RemoteJsResponse; -import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeNotificationMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToVersionControlServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg; import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg; import org.thingsboard.server.queue.TbQueueAdmin; @@ -50,6 +52,7 @@ import org.thingsboard.server.queue.rabbitmq.TbRabbitMqProducerTemplate; import org.thingsboard.server.queue.rabbitmq.TbRabbitMqQueueArguments; import org.thingsboard.server.queue.rabbitmq.TbRabbitMqSettings; import org.thingsboard.server.queue.settings.TbQueueCoreSettings; +import org.thingsboard.server.queue.settings.TbQueueEdgeSettings; import org.thingsboard.server.queue.settings.TbQueueRemoteJsInvokeSettings; import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; @@ -71,6 +74,7 @@ public class RabbitMqMonolithQueueFactory implements TbCoreQueueFactory, TbRuleE private final TbRabbitMqSettings rabbitMqSettings; private final TbQueueRemoteJsInvokeSettings jsInvokeSettings; private final TbQueueVersionControlSettings vcSettings; + private final TbQueueEdgeSettings edgeSettings; private final TbQueueAdmin coreAdmin; private final TbQueueAdmin ruleEngineAdmin; @@ -78,6 +82,7 @@ public class RabbitMqMonolithQueueFactory implements TbCoreQueueFactory, TbRuleE private final TbQueueAdmin transportApiAdmin; private final TbQueueAdmin notificationAdmin; private final TbQueueAdmin vcAdmin; + private final TbQueueAdmin edgeAdmin; public RabbitMqMonolithQueueFactory(TopicService topicService, TbQueueCoreSettings coreSettings, TbQueueRuleEngineSettings ruleEngineSettings, @@ -87,7 +92,8 @@ public class RabbitMqMonolithQueueFactory implements TbCoreQueueFactory, TbRuleE TbRabbitMqSettings rabbitMqSettings, TbRabbitMqQueueArguments queueArguments, TbQueueRemoteJsInvokeSettings jsInvokeSettings, - TbQueueVersionControlSettings vcSettings) { + TbQueueVersionControlSettings vcSettings, + TbQueueEdgeSettings edgeSettings) { this.topicService = topicService; this.coreSettings = coreSettings; this.serviceInfoProvider = serviceInfoProvider; @@ -97,6 +103,7 @@ public class RabbitMqMonolithQueueFactory implements TbCoreQueueFactory, TbRuleE this.rabbitMqSettings = rabbitMqSettings; this.jsInvokeSettings = jsInvokeSettings; this.vcSettings = vcSettings; + this.edgeSettings = edgeSettings; this.coreAdmin = new TbRabbitMqAdmin(rabbitMqSettings, queueArguments.getCoreArgs()); this.ruleEngineAdmin = new TbRabbitMqAdmin(rabbitMqSettings, queueArguments.getRuleEngineArgs()); @@ -104,6 +111,7 @@ public class RabbitMqMonolithQueueFactory implements TbCoreQueueFactory, TbRuleE this.transportApiAdmin = new TbRabbitMqAdmin(rabbitMqSettings, queueArguments.getTransportApiArgs()); this.notificationAdmin = new TbRabbitMqAdmin(rabbitMqSettings, queueArguments.getNotificationsArgs()); this.vcAdmin = new TbRabbitMqAdmin(rabbitMqSettings, queueArguments.getVcArgs()); + this.edgeAdmin = new TbRabbitMqAdmin(rabbitMqSettings, queueArguments.getEdgeArgs()); } @Override @@ -128,13 +136,14 @@ public class RabbitMqMonolithQueueFactory implements TbCoreQueueFactory, TbRuleE @Override public TbQueueProducer> createTbCoreNotificationsMsgProducer() { - return new TbRabbitMqProducerTemplate<>(notificationAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getTopic())); + return new TbRabbitMqProducerTemplate<>(notificationAdmin, rabbitMqSettings, + topicService.getNotificationsTopic(ServiceType.TB_CORE, serviceInfoProvider.getServiceId()).getFullTopicName()); } @Override - public TbQueueConsumer> createToVersionControlMsgConsumer() { + public TbQueueConsumer> createToVersionControlMsgConsumer() { return new TbRabbitMqConsumerTemplate<>(vcAdmin, rabbitMqSettings, topicService.buildTopicName(vcSettings.getTopic()), - msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportProtos.ToVersionControlServiceMsg.parseFrom(msg.getData()), msg.getHeaders()) + msg -> new TbProtoQueueMsg<>(msg.getKey(), ToVersionControlServiceMsg.parseFrom(msg.getData()), msg.getHeaders()) ); } @@ -221,7 +230,7 @@ public class RabbitMqMonolithQueueFactory implements TbCoreQueueFactory, TbRuleE } @Override - public TbQueueProducer> createVersionControlMsgProducer() { + public TbQueueProducer> createVersionControlMsgProducer() { return new TbRabbitMqProducerTemplate<>(vcAdmin, rabbitMqSettings, topicService.buildTopicName(vcSettings.getTopic())); } @@ -247,6 +256,30 @@ public class RabbitMqMonolithQueueFactory implements TbCoreQueueFactory, TbRuleE msg -> new TbProtoQueueMsg<>(msg.getKey(), ToHousekeeperServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); } + @Override + public TbQueueConsumer> createEdgeMsgConsumer() { + return new TbRabbitMqConsumerTemplate<>(edgeAdmin, rabbitMqSettings, topicService.buildTopicName(edgeSettings.getTopic()), + msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeMsg.parseFrom(msg.getData()), msg.getHeaders())); + } + + @Override + public TbQueueProducer> createEdgeMsgProducer() { + return new TbRabbitMqProducerTemplate<>(edgeAdmin, rabbitMqSettings, topicService.buildTopicName(edgeSettings.getTopic())); + } + + @Override + public TbQueueConsumer> createToEdgeNotificationsMsgConsumer() { + return new TbRabbitMqConsumerTemplate<>(notificationAdmin, rabbitMqSettings, + topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName(), + msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); + } + + @Override + public TbQueueProducer> createEdgeNotificationsMsgProducer() { + return new TbRabbitMqProducerTemplate<>(notificationAdmin, rabbitMqSettings, + topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName()); + } + @PreDestroy private void destroy() { if (coreAdmin != null) { @@ -267,5 +300,8 @@ public class RabbitMqMonolithQueueFactory implements TbCoreQueueFactory, TbRuleE if (vcAdmin != null) { vcAdmin.destroy(); } + if (edgeAdmin != null) { + edgeAdmin.destroy(); + } } } diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqTbCoreQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqTbCoreQueueFactory.java index 57440422be..16f9838384 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqTbCoreQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqTbCoreQueueFactory.java @@ -22,14 +22,17 @@ import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Component; import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.gen.js.JsInvokeProtos; -import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeNotificationMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToVersionControlServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg; import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg; import org.thingsboard.server.queue.TbQueueAdmin; @@ -47,6 +50,7 @@ import org.thingsboard.server.queue.rabbitmq.TbRabbitMqProducerTemplate; import org.thingsboard.server.queue.rabbitmq.TbRabbitMqQueueArguments; import org.thingsboard.server.queue.rabbitmq.TbRabbitMqSettings; import org.thingsboard.server.queue.settings.TbQueueCoreSettings; +import org.thingsboard.server.queue.settings.TbQueueEdgeSettings; import org.thingsboard.server.queue.settings.TbQueueRemoteJsInvokeSettings; import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; @@ -66,12 +70,14 @@ public class RabbitMqTbCoreQueueFactory implements TbCoreQueueFactory { private final TbServiceInfoProvider serviceInfoProvider; private final TbQueueRemoteJsInvokeSettings jsInvokeSettings; private final TbQueueTransportNotificationSettings transportNotificationSettings; + private final TbQueueEdgeSettings edgeSettings; private final TbQueueAdmin coreAdmin; private final TbQueueAdmin ruleEngineAdmin; private final TbQueueAdmin jsExecutorAdmin; private final TbQueueAdmin transportApiAdmin; private final TbQueueAdmin notificationAdmin; + private final TbQueueAdmin edgeAdmin; public RabbitMqTbCoreQueueFactory(TbRabbitMqSettings rabbitMqSettings, TbQueueCoreSettings coreSettings, @@ -81,6 +87,7 @@ public class RabbitMqTbCoreQueueFactory implements TbCoreQueueFactory { TbServiceInfoProvider serviceInfoProvider, TbQueueRemoteJsInvokeSettings jsInvokeSettings, TbQueueTransportNotificationSettings transportNotificationSettings, + TbQueueEdgeSettings edgeSettings, TbRabbitMqQueueArguments queueArguments) { this.rabbitMqSettings = rabbitMqSettings; this.coreSettings = coreSettings; @@ -90,12 +97,14 @@ public class RabbitMqTbCoreQueueFactory implements TbCoreQueueFactory { this.serviceInfoProvider = serviceInfoProvider; this.jsInvokeSettings = jsInvokeSettings; this.transportNotificationSettings = transportNotificationSettings; + this.edgeSettings = edgeSettings; this.coreAdmin = new TbRabbitMqAdmin(rabbitMqSettings, queueArguments.getCoreArgs()); this.ruleEngineAdmin = new TbRabbitMqAdmin(rabbitMqSettings, queueArguments.getRuleEngineArgs()); this.jsExecutorAdmin = new TbRabbitMqAdmin(rabbitMqSettings, queueArguments.getJsExecutorArgs()); this.transportApiAdmin = new TbRabbitMqAdmin(rabbitMqSettings, queueArguments.getTransportApiArgs()); this.notificationAdmin = new TbRabbitMqAdmin(rabbitMqSettings, queueArguments.getNotificationsArgs()); + this.edgeAdmin = new TbRabbitMqAdmin(rabbitMqSettings, queueArguments.getEdgeArgs()); } @Override @@ -120,7 +129,8 @@ public class RabbitMqTbCoreQueueFactory implements TbCoreQueueFactory { @Override public TbQueueProducer> createTbCoreNotificationsMsgProducer() { - return new TbRabbitMqProducerTemplate<>(notificationAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getTopic())); + return new TbRabbitMqProducerTemplate<>(notificationAdmin, rabbitMqSettings, + topicService.getNotificationsTopic(ServiceType.TB_CORE, serviceInfoProvider.getServiceId()).getFullTopicName()); } @Override @@ -136,6 +146,30 @@ public class RabbitMqTbCoreQueueFactory implements TbCoreQueueFactory { msg -> new TbProtoQueueMsg<>(msg.getKey(), ToCoreNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); } + @Override + public TbQueueProducer> createEdgeMsgProducer() { + return new TbRabbitMqProducerTemplate<>(edgeAdmin, rabbitMqSettings, topicService.buildTopicName(edgeSettings.getTopic())); + } + + @Override + public TbQueueConsumer> createEdgeMsgConsumer() { + return new TbRabbitMqConsumerTemplate<>(edgeAdmin, rabbitMqSettings, topicService.buildTopicName(edgeSettings.getTopic()), + msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeMsg.parseFrom(msg.getData()), msg.getHeaders())); + } + + @Override + public TbQueueConsumer> createToEdgeNotificationsMsgConsumer() { + return new TbRabbitMqConsumerTemplate<>(notificationAdmin, rabbitMqSettings, + topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName(), + msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); + } + + @Override + public TbQueueProducer> createEdgeNotificationsMsgProducer() { + return new TbRabbitMqProducerTemplate<>(notificationAdmin, rabbitMqSettings, + topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName()); + } + @Override public TbQueueConsumer> createTransportApiRequestConsumer() { return new TbRabbitMqConsumerTemplate<>(transportApiAdmin, rabbitMqSettings, topicService.buildTopicName(transportApiSettings.getRequestsTopic()), @@ -171,7 +205,7 @@ public class RabbitMqTbCoreQueueFactory implements TbCoreQueueFactory { } @Override - public TbQueueProducer> createVersionControlMsgProducer() { + public TbQueueProducer> createVersionControlMsgProducer() { //TODO: version-control return null; } @@ -199,25 +233,25 @@ public class RabbitMqTbCoreQueueFactory implements TbCoreQueueFactory { } @Override - public TbQueueProducer> createHousekeeperMsgProducer() { + public TbQueueProducer> createHousekeeperMsgProducer() { return new TbRabbitMqProducerTemplate<>(coreAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic())); } @Override - public TbQueueConsumer> createHousekeeperMsgConsumer() { + public TbQueueConsumer> createHousekeeperMsgConsumer() { return new TbRabbitMqConsumerTemplate<>(coreAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic()), - msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportProtos.ToHousekeeperServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); + msg -> new TbProtoQueueMsg<>(msg.getKey(), ToHousekeeperServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); } @Override - public TbQueueProducer> createHousekeeperReprocessingMsgProducer() { + public TbQueueProducer> createHousekeeperReprocessingMsgProducer() { return new TbRabbitMqProducerTemplate<>(coreAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getHousekeeperReprocessingTopic())); } @Override - public TbQueueConsumer> createHousekeeperReprocessingMsgConsumer() { + public TbQueueConsumer> createHousekeeperReprocessingMsgConsumer() { return new TbRabbitMqConsumerTemplate<>(coreAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getHousekeeperReprocessingTopic()), - msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportProtos.ToHousekeeperServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); + msg -> new TbProtoQueueMsg<>(msg.getKey(), ToHousekeeperServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); } @PreDestroy @@ -237,5 +271,8 @@ public class RabbitMqTbCoreQueueFactory implements TbCoreQueueFactory { if (notificationAdmin != null) { notificationAdmin.destroy(); } + if (edgeAdmin != null) { + edgeAdmin.destroy(); + } } } diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqTbRuleEngineQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqTbRuleEngineQueueFactory.java index a0a87714ca..3dabaf100b 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqTbRuleEngineQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqTbRuleEngineQueueFactory.java @@ -26,6 +26,9 @@ import org.thingsboard.server.gen.js.JsInvokeProtos; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; @@ -45,6 +48,7 @@ import org.thingsboard.server.queue.rabbitmq.TbRabbitMqProducerTemplate; import org.thingsboard.server.queue.rabbitmq.TbRabbitMqQueueArguments; import org.thingsboard.server.queue.rabbitmq.TbRabbitMqSettings; import org.thingsboard.server.queue.settings.TbQueueCoreSettings; +import org.thingsboard.server.queue.settings.TbQueueEdgeSettings; import org.thingsboard.server.queue.settings.TbQueueRemoteJsInvokeSettings; import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; @@ -62,11 +66,13 @@ public class RabbitMqTbRuleEngineQueueFactory implements TbRuleEngineQueueFactor private final TbRabbitMqSettings rabbitMqSettings; private final TbQueueRemoteJsInvokeSettings jsInvokeSettings; private final TbQueueTransportNotificationSettings transportNotificationSettings; + private final TbQueueEdgeSettings edgeSettings; private final TbQueueAdmin coreAdmin; private final TbQueueAdmin ruleEngineAdmin; private final TbQueueAdmin jsExecutorAdmin; private final TbQueueAdmin notificationAdmin; + private final TbQueueAdmin edgeAdmin; public RabbitMqTbRuleEngineQueueFactory(TopicService topicService, TbQueueCoreSettings coreSettings, TbQueueRuleEngineSettings ruleEngineSettings, @@ -74,6 +80,7 @@ public class RabbitMqTbRuleEngineQueueFactory implements TbRuleEngineQueueFactor TbRabbitMqSettings rabbitMqSettings, TbQueueRemoteJsInvokeSettings jsInvokeSettings, TbQueueTransportNotificationSettings transportNotificationSettings, + TbQueueEdgeSettings edgeSettings, TbRabbitMqQueueArguments queueArguments) { this.topicService = topicService; this.coreSettings = coreSettings; @@ -82,11 +89,13 @@ public class RabbitMqTbRuleEngineQueueFactory implements TbRuleEngineQueueFactor this.rabbitMqSettings = rabbitMqSettings; this.jsInvokeSettings = jsInvokeSettings; this.transportNotificationSettings = transportNotificationSettings; + this.edgeSettings = edgeSettings; this.coreAdmin = new TbRabbitMqAdmin(rabbitMqSettings, queueArguments.getCoreArgs()); this.ruleEngineAdmin = new TbRabbitMqAdmin(rabbitMqSettings, queueArguments.getRuleEngineArgs()); this.jsExecutorAdmin = new TbRabbitMqAdmin(rabbitMqSettings, queueArguments.getJsExecutorArgs()); this.notificationAdmin = new TbRabbitMqAdmin(rabbitMqSettings, queueArguments.getNotificationsArgs()); + this.edgeAdmin = new TbRabbitMqAdmin(rabbitMqSettings, queueArguments.getEdgeArgs()); } @Override @@ -114,6 +123,16 @@ public class RabbitMqTbRuleEngineQueueFactory implements TbRuleEngineQueueFactor return new TbRabbitMqProducerTemplate<>(notificationAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getTopic())); } + @Override + public TbQueueProducer> createEdgeMsgProducer() { + return new TbRabbitMqProducerTemplate<>(edgeAdmin, rabbitMqSettings, topicService.buildTopicName(edgeSettings.getTopic())); + } + + @Override + public TbQueueProducer> createEdgeNotificationsMsgProducer() { + return new TbRabbitMqProducerTemplate<>(notificationAdmin, rabbitMqSettings, topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName()); + } + @Override public TbQueueConsumer> createToRuleEngineMsgConsumer(Queue configuration) { return new TbRabbitMqConsumerTemplate<>(ruleEngineAdmin, rabbitMqSettings, topicService.buildTopicName(configuration.getTopic()), @@ -156,12 +175,12 @@ public class RabbitMqTbRuleEngineQueueFactory implements TbRuleEngineQueueFactor } @Override - public TbQueueProducer> createToOtaPackageStateServiceMsgProducer() { + public TbQueueProducer> createToOtaPackageStateServiceMsgProducer() { return new TbRabbitMqProducerTemplate<>(coreAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getOtaPackageTopic())); } @Override - public TbQueueProducer> createHousekeeperMsgProducer() { + public TbQueueProducer> createHousekeeperMsgProducer() { return new TbRabbitMqProducerTemplate<>(coreAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic())); } diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqTransportQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqTransportQueueFactory.java index 9b8a3d3c49..ea922557bd 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqTransportQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqTransportQueueFactory.java @@ -19,9 +19,9 @@ import jakarta.annotation.PreDestroy; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.stereotype.Component; -import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg; @@ -132,7 +132,7 @@ public class RabbitMqTransportQueueFactory implements TbTransportQueueFactory { } @Override - public TbQueueProducer> createHousekeeperMsgProducer() { + public TbQueueProducer> createHousekeeperMsgProducer() { return new TbRabbitMqProducerTemplate<>(coreAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic())); } diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/ServiceBusMonolithQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/ServiceBusMonolithQueueFactory.java index 2ec807498c..fa7e73b879 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/ServiceBusMonolithQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/ServiceBusMonolithQueueFactory.java @@ -23,15 +23,17 @@ import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.queue.Queue; import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.gen.js.JsInvokeProtos; -import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeNotificationMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToVersionControlServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg; import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg; import org.thingsboard.server.queue.TbQueueAdmin; @@ -49,6 +51,7 @@ import org.thingsboard.server.queue.common.TbProtoQueueMsg; import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; import org.thingsboard.server.queue.discovery.TopicService; import org.thingsboard.server.queue.settings.TbQueueCoreSettings; +import org.thingsboard.server.queue.settings.TbQueueEdgeSettings; import org.thingsboard.server.queue.settings.TbQueueRemoteJsInvokeSettings; import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; @@ -70,6 +73,7 @@ public class ServiceBusMonolithQueueFactory implements TbCoreQueueFactory, TbRul private final TbServiceBusSettings serviceBusSettings; private final TbQueueRemoteJsInvokeSettings jsInvokeSettings; private final TbQueueVersionControlSettings vcSettings; + private final TbQueueEdgeSettings edgeSettings; private final TbQueueAdmin coreAdmin; private final TbQueueAdmin ruleEngineAdmin; @@ -77,6 +81,7 @@ public class ServiceBusMonolithQueueFactory implements TbCoreQueueFactory, TbRul private final TbQueueAdmin transportApiAdmin; private final TbQueueAdmin notificationAdmin; private final TbQueueAdmin vcAdmin; + private final TbQueueAdmin edgeAdmin; public ServiceBusMonolithQueueFactory(TopicService topicService, TbQueueCoreSettings coreSettings, TbQueueRuleEngineSettings ruleEngineSettings, @@ -86,6 +91,7 @@ public class ServiceBusMonolithQueueFactory implements TbCoreQueueFactory, TbRul TbServiceBusSettings serviceBusSettings, TbQueueRemoteJsInvokeSettings jsInvokeSettings, TbQueueVersionControlSettings vcSettings, + TbQueueEdgeSettings edgeSettings, TbServiceBusQueueConfigs serviceBusQueueConfigs) { this.topicService = topicService; this.coreSettings = coreSettings; @@ -96,6 +102,7 @@ public class ServiceBusMonolithQueueFactory implements TbCoreQueueFactory, TbRul this.serviceBusSettings = serviceBusSettings; this.jsInvokeSettings = jsInvokeSettings; this.vcSettings = vcSettings; + this.edgeSettings = edgeSettings; this.coreAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getCoreConfigs()); this.ruleEngineAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getRuleEngineConfigs()); @@ -103,6 +110,7 @@ public class ServiceBusMonolithQueueFactory implements TbCoreQueueFactory, TbRul this.transportApiAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getTransportApiConfigs()); this.notificationAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getNotificationsConfigs()); this.vcAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getVcConfigs()); + this.edgeAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getEdgeConfigs()); } @Override @@ -127,13 +135,14 @@ public class ServiceBusMonolithQueueFactory implements TbCoreQueueFactory, TbRul @Override public TbQueueProducer> createTbCoreNotificationsMsgProducer() { - return new TbServiceBusProducerTemplate<>(notificationAdmin, serviceBusSettings, topicService.buildTopicName(coreSettings.getTopic())); + return new TbServiceBusProducerTemplate<>(notificationAdmin, serviceBusSettings, + topicService.getNotificationsTopic(ServiceType.TB_CORE, serviceInfoProvider.getServiceId()).getFullTopicName()); } @Override - public TbQueueConsumer> createToVersionControlMsgConsumer() { + public TbQueueConsumer> createToVersionControlMsgConsumer() { return new TbServiceBusConsumerTemplate<>(vcAdmin, serviceBusSettings, topicService.buildTopicName(vcSettings.getTopic()), - msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportProtos.ToVersionControlServiceMsg.parseFrom(msg.getData()), msg.getHeaders()) + msg -> new TbProtoQueueMsg<>(msg.getKey(), ToVersionControlServiceMsg.parseFrom(msg.getData()), msg.getHeaders()) ); } @@ -220,7 +229,7 @@ public class ServiceBusMonolithQueueFactory implements TbCoreQueueFactory, TbRul } @Override - public TbQueueProducer> createVersionControlMsgProducer() { + public TbQueueProducer> createVersionControlMsgProducer() { return new TbServiceBusProducerTemplate<>(vcAdmin, serviceBusSettings, topicService.buildTopicName(vcSettings.getTopic())); } @@ -246,6 +255,30 @@ public class ServiceBusMonolithQueueFactory implements TbCoreQueueFactory, TbRul msg -> new TbProtoQueueMsg<>(msg.getKey(), ToHousekeeperServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); } + @Override + public TbQueueConsumer> createEdgeMsgConsumer() { + return new TbServiceBusConsumerTemplate<>(edgeAdmin, serviceBusSettings, topicService.buildTopicName(edgeSettings.getTopic()), + msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeMsg.parseFrom(msg.getData()), msg.getHeaders())); + } + + @Override + public TbQueueProducer> createEdgeMsgProducer() { + return new TbServiceBusProducerTemplate<>(edgeAdmin, serviceBusSettings, topicService.buildTopicName(edgeSettings.getTopic())); + } + + @Override + public TbQueueConsumer> createToEdgeNotificationsMsgConsumer() { + return new TbServiceBusConsumerTemplate<>(notificationAdmin, serviceBusSettings, + topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName(), + msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); + } + + @Override + public TbQueueProducer> createEdgeNotificationsMsgProducer() { + return new TbServiceBusProducerTemplate<>(notificationAdmin, serviceBusSettings, + topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName()); + } + @PreDestroy private void destroy() { if (coreAdmin != null) { @@ -266,5 +299,8 @@ public class ServiceBusMonolithQueueFactory implements TbCoreQueueFactory, TbRul if (vcAdmin != null) { vcAdmin.destroy(); } + if (edgeAdmin != null) { + edgeAdmin.destroy(); + } } } diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/ServiceBusTbCoreQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/ServiceBusTbCoreQueueFactory.java index 493e58dba7..71a7efe50b 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/ServiceBusTbCoreQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/ServiceBusTbCoreQueueFactory.java @@ -22,15 +22,17 @@ import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Component; import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.gen.js.JsInvokeProtos; -import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeNotificationMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToVersionControlServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg; import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg; import org.thingsboard.server.queue.TbQueueAdmin; @@ -48,6 +50,7 @@ import org.thingsboard.server.queue.common.TbProtoQueueMsg; import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; import org.thingsboard.server.queue.discovery.TopicService; import org.thingsboard.server.queue.settings.TbQueueCoreSettings; +import org.thingsboard.server.queue.settings.TbQueueEdgeSettings; import org.thingsboard.server.queue.settings.TbQueueRemoteJsInvokeSettings; import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; @@ -67,12 +70,14 @@ public class ServiceBusTbCoreQueueFactory implements TbCoreQueueFactory { private final TbServiceInfoProvider serviceInfoProvider; private final TbQueueRemoteJsInvokeSettings jsInvokeSettings; private final TbQueueTransportNotificationSettings transportNotificationSettings; + private final TbQueueEdgeSettings edgeSettings; private final TbQueueAdmin coreAdmin; private final TbQueueAdmin ruleEngineAdmin; private final TbQueueAdmin jsExecutorAdmin; private final TbQueueAdmin transportApiAdmin; private final TbQueueAdmin notificationAdmin; + private final TbQueueAdmin edgeAdmin; public ServiceBusTbCoreQueueFactory(TbServiceBusSettings serviceBusSettings, TbQueueCoreSettings coreSettings, @@ -82,6 +87,7 @@ public class ServiceBusTbCoreQueueFactory implements TbCoreQueueFactory { TbServiceInfoProvider serviceInfoProvider, TbQueueRemoteJsInvokeSettings jsInvokeSettings, TbQueueTransportNotificationSettings transportNotificationSettings, + TbQueueEdgeSettings edgeSettings, TbServiceBusQueueConfigs serviceBusQueueConfigs) { this.serviceBusSettings = serviceBusSettings; this.coreSettings = coreSettings; @@ -91,12 +97,14 @@ public class ServiceBusTbCoreQueueFactory implements TbCoreQueueFactory { this.serviceInfoProvider = serviceInfoProvider; this.jsInvokeSettings = jsInvokeSettings; this.transportNotificationSettings = transportNotificationSettings; + this.edgeSettings = edgeSettings; this.coreAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getCoreConfigs()); this.ruleEngineAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getRuleEngineConfigs()); this.jsExecutorAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getJsExecutorConfigs()); this.transportApiAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getTransportApiConfigs()); this.notificationAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getNotificationsConfigs()); + this.edgeAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getEdgeConfigs()); } @Override @@ -121,7 +129,8 @@ public class ServiceBusTbCoreQueueFactory implements TbCoreQueueFactory { @Override public TbQueueProducer> createTbCoreNotificationsMsgProducer() { - return new TbServiceBusProducerTemplate<>(notificationAdmin, serviceBusSettings, topicService.buildTopicName(coreSettings.getTopic())); + return new TbServiceBusProducerTemplate<>(notificationAdmin, serviceBusSettings, + topicService.getNotificationsTopic(ServiceType.TB_CORE, serviceInfoProvider.getServiceId()).getFullTopicName()); } @Override @@ -194,7 +203,7 @@ public class ServiceBusTbCoreQueueFactory implements TbCoreQueueFactory { } @Override - public TbQueueProducer> createVersionControlMsgProducer() { + public TbQueueProducer> createVersionControlMsgProducer() { //TODO: version-control return null; } @@ -221,6 +230,30 @@ public class ServiceBusTbCoreQueueFactory implements TbCoreQueueFactory { msg -> new TbProtoQueueMsg<>(msg.getKey(), ToHousekeeperServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); } + @Override + public TbQueueConsumer> createEdgeMsgConsumer() { + return new TbServiceBusConsumerTemplate<>(edgeAdmin, serviceBusSettings, topicService.buildTopicName(edgeSettings.getTopic()), + msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeMsg.parseFrom(msg.getData()), msg.getHeaders())); + } + + @Override + public TbQueueProducer> createEdgeMsgProducer() { + return new TbServiceBusProducerTemplate<>(edgeAdmin, serviceBusSettings, topicService.buildTopicName(edgeSettings.getTopic())); + } + + @Override + public TbQueueConsumer> createToEdgeNotificationsMsgConsumer() { + return new TbServiceBusConsumerTemplate<>(notificationAdmin, serviceBusSettings, + topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName(), + msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); + } + + @Override + public TbQueueProducer> createEdgeNotificationsMsgProducer() { + return new TbServiceBusProducerTemplate<>(notificationAdmin, serviceBusSettings, + topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName()); + } + @PreDestroy private void destroy() { if (coreAdmin != null) { @@ -238,5 +271,8 @@ public class ServiceBusTbCoreQueueFactory implements TbCoreQueueFactory { if (notificationAdmin != null) { notificationAdmin.destroy(); } + if (edgeAdmin != null) { + edgeAdmin.destroy(); + } } } diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/ServiceBusTbRuleEngineQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/ServiceBusTbRuleEngineQueueFactory.java index 92ef01fa00..643a9dee3b 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/ServiceBusTbRuleEngineQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/ServiceBusTbRuleEngineQueueFactory.java @@ -26,6 +26,9 @@ import org.thingsboard.server.gen.js.JsInvokeProtos; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; @@ -45,6 +48,7 @@ import org.thingsboard.server.queue.common.TbProtoQueueMsg; import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; import org.thingsboard.server.queue.discovery.TopicService; import org.thingsboard.server.queue.settings.TbQueueCoreSettings; +import org.thingsboard.server.queue.settings.TbQueueEdgeSettings; import org.thingsboard.server.queue.settings.TbQueueRemoteJsInvokeSettings; import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; @@ -62,11 +66,13 @@ public class ServiceBusTbRuleEngineQueueFactory implements TbRuleEngineQueueFact private final TbServiceBusSettings serviceBusSettings; private final TbQueueRemoteJsInvokeSettings jsInvokeSettings; private final TbQueueTransportNotificationSettings transportNotificationSettings; + private final TbQueueEdgeSettings edgeSettings; private final TbQueueAdmin coreAdmin; private final TbQueueAdmin ruleEngineAdmin; private final TbQueueAdmin jsExecutorAdmin; private final TbQueueAdmin notificationAdmin; + private final TbQueueAdmin edgeAdmin; public ServiceBusTbRuleEngineQueueFactory(TopicService topicService, TbQueueCoreSettings coreSettings, TbQueueRuleEngineSettings ruleEngineSettings, @@ -74,6 +80,7 @@ public class ServiceBusTbRuleEngineQueueFactory implements TbRuleEngineQueueFact TbServiceBusSettings serviceBusSettings, TbQueueRemoteJsInvokeSettings jsInvokeSettings, TbQueueTransportNotificationSettings transportNotificationSettings, + TbQueueEdgeSettings edgeSettings, TbServiceBusQueueConfigs serviceBusQueueConfigs) { this.topicService = topicService; this.coreSettings = coreSettings; @@ -82,11 +89,13 @@ public class ServiceBusTbRuleEngineQueueFactory implements TbRuleEngineQueueFact this.serviceBusSettings = serviceBusSettings; this.jsInvokeSettings = jsInvokeSettings; this.transportNotificationSettings = transportNotificationSettings; + this.edgeSettings = edgeSettings; this.coreAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getCoreConfigs()); this.ruleEngineAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getRuleEngineConfigs()); this.jsExecutorAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getJsExecutorConfigs()); this.notificationAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getNotificationsConfigs()); + this.edgeAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getEdgeConfigs()); } @Override @@ -114,6 +123,16 @@ public class ServiceBusTbRuleEngineQueueFactory implements TbRuleEngineQueueFact return new TbServiceBusProducerTemplate<>(notificationAdmin, serviceBusSettings, topicService.buildTopicName(coreSettings.getTopic())); } + @Override + public TbQueueProducer> createEdgeMsgProducer() { + return new TbServiceBusProducerTemplate<>(edgeAdmin, serviceBusSettings, topicService.buildTopicName(edgeSettings.getTopic())); + } + + @Override + public TbQueueProducer> createEdgeNotificationsMsgProducer() { + return new TbServiceBusProducerTemplate<>(notificationAdmin, serviceBusSettings, topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName()); + } + @Override public TbQueueConsumer> createToRuleEngineMsgConsumer(Queue configuration) { return new TbServiceBusConsumerTemplate<>(ruleEngineAdmin, serviceBusSettings, topicService.buildTopicName(configuration.getTopic()), @@ -156,12 +175,12 @@ public class ServiceBusTbRuleEngineQueueFactory implements TbRuleEngineQueueFact } @Override - public TbQueueProducer> createToOtaPackageStateServiceMsgProducer() { + public TbQueueProducer> createToOtaPackageStateServiceMsgProducer() { return new TbServiceBusProducerTemplate<>(coreAdmin, serviceBusSettings, topicService.buildTopicName(coreSettings.getOtaPackageTopic())); } @Override - public TbQueueProducer> createHousekeeperMsgProducer() { + public TbQueueProducer> createHousekeeperMsgProducer() { return new TbServiceBusProducerTemplate<>(coreAdmin, serviceBusSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic())); } diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/ServiceBusTransportQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/ServiceBusTransportQueueFactory.java index fd493eb2e1..7f3e246eec 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/ServiceBusTransportQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/ServiceBusTransportQueueFactory.java @@ -19,9 +19,9 @@ import jakarta.annotation.PreDestroy; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.stereotype.Component; -import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg; @@ -133,7 +133,7 @@ public class ServiceBusTransportQueueFactory implements TbTransportQueueFactory } @Override - public TbQueueProducer> createHousekeeperMsgProducer() { + public TbQueueProducer> createHousekeeperMsgProducer() { return new TbServiceBusProducerTemplate<>(coreAdmin, serviceBusSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic())); } diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbCoreQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbCoreQueueFactory.java index 20a67c2e09..cecfddf7a7 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbCoreQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbCoreQueueFactory.java @@ -18,6 +18,8 @@ package org.thingsboard.server.queue.provider; import org.thingsboard.server.gen.js.JsInvokeProtos; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeNotificationMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; @@ -138,4 +140,12 @@ public interface TbCoreQueueFactory extends TbUsageStatsClientQueueFactory, Hous TbQueueConsumer> createHousekeeperReprocessingMsgConsumer(); + TbQueueConsumer> createEdgeMsgConsumer(); + + TbQueueProducer> createEdgeMsgProducer(); + + TbQueueConsumer> createToEdgeNotificationsMsgConsumer(); + + TbQueueProducer> createEdgeNotificationsMsgProducer(); + } diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbCoreQueueProducerProvider.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbCoreQueueProducerProvider.java index 3fcb49f47c..cf94bf68d0 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbCoreQueueProducerProvider.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbCoreQueueProducerProvider.java @@ -19,6 +19,8 @@ import jakarta.annotation.PostConstruct; import org.springframework.stereotype.Service; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeNotificationMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; @@ -39,6 +41,8 @@ public class TbCoreQueueProducerProvider implements TbQueueProducerProvider { private TbQueueProducer> toTbCore; private TbQueueProducer> toRuleEngineNotifications; private TbQueueProducer> toTbCoreNotifications; + private TbQueueProducer> toEdge; + private TbQueueProducer> toEdgeNotifications; private TbQueueProducer> toUsageStats; private TbQueueProducer> toVersionControl; private TbQueueProducer> toHousekeeper; @@ -57,6 +61,8 @@ public class TbCoreQueueProducerProvider implements TbQueueProducerProvider { this.toUsageStats = tbQueueProvider.createToUsageStatsServiceMsgProducer(); this.toVersionControl = tbQueueProvider.createVersionControlMsgProducer(); this.toHousekeeper = tbQueueProvider.createHousekeeperMsgProducer(); + this.toEdge = tbQueueProvider.createEdgeMsgProducer(); + this.toEdgeNotifications = tbQueueProvider.createEdgeNotificationsMsgProducer(); } @Override @@ -99,4 +105,15 @@ public class TbCoreQueueProducerProvider implements TbQueueProducerProvider { return toHousekeeper; } + + @Override + public TbQueueProducer> getTbEdgeMsgProducer() { + return toEdge; + } + + @Override + public TbQueueProducer> getTbEdgeNotificationsMsgProducer() { + return toEdgeNotifications; + } + } diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbQueueProducerProvider.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbQueueProducerProvider.java index a752301cd8..a0c43a9e4b 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbQueueProducerProvider.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbQueueProducerProvider.java @@ -17,6 +17,8 @@ package org.thingsboard.server.queue.provider; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeNotificationMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; @@ -73,7 +75,7 @@ public interface TbQueueProducerProvider { */ TbQueueProducer> getTbUsageStatsMsgProducer(); - /** + /** * Used to push messages to other instances of TB Core Service * * @return @@ -82,4 +84,8 @@ public interface TbQueueProducerProvider { TbQueueProducer> getHousekeeperMsgProducer(); + TbQueueProducer> getTbEdgeMsgProducer(); + + TbQueueProducer> getTbEdgeNotificationsMsgProducer(); + } diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbRuleEngineProducerProvider.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbRuleEngineProducerProvider.java index 908369ea15..8797064204 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbRuleEngineProducerProvider.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbRuleEngineProducerProvider.java @@ -18,14 +18,16 @@ package org.thingsboard.server.queue.provider; import jakarta.annotation.PostConstruct; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.stereotype.Service; -import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeNotificationMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToVersionControlServiceMsg; import org.thingsboard.server.queue.TbQueueProducer; import org.thingsboard.server.queue.common.TbProtoQueueMsg; @@ -41,6 +43,8 @@ public class TbRuleEngineProducerProvider implements TbQueueProducerProvider { private TbQueueProducer> toTbCoreNotifications; private TbQueueProducer> toUsageStats; private TbQueueProducer> toHousekeeper; + private TbQueueProducer> toEdge; + private TbQueueProducer> toEdgeNotifications; public TbRuleEngineProducerProvider(TbRuleEngineQueueFactory tbQueueProvider) { this.tbQueueProvider = tbQueueProvider; @@ -55,6 +59,8 @@ public class TbRuleEngineProducerProvider implements TbQueueProducerProvider { this.toTbCoreNotifications = tbQueueProvider.createTbCoreNotificationsMsgProducer(); this.toUsageStats = tbQueueProvider.createToUsageStatsServiceMsgProducer(); this.toHousekeeper = tbQueueProvider.createHousekeeperMsgProducer(); + this.toEdge = tbQueueProvider.createEdgeMsgProducer(); + this.toEdgeNotifications = tbQueueProvider.createEdgeNotificationsMsgProducer(); } @Override @@ -82,13 +88,23 @@ public class TbRuleEngineProducerProvider implements TbQueueProducerProvider { return toTbCoreNotifications; } + @Override + public TbQueueProducer> getTbEdgeMsgProducer() { + return toEdge; + } + + @Override + public TbQueueProducer> getTbEdgeNotificationsMsgProducer() { + return toEdgeNotifications; + } + @Override public TbQueueProducer> getTbUsageStatsMsgProducer() { return toUsageStats; } @Override - public TbQueueProducer> getTbVersionControlMsgProducer() { + public TbQueueProducer> getTbVersionControlMsgProducer() { throw new RuntimeException("Not Implemented! Should not be used by Rule Engine!"); } diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbRuleEngineQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbRuleEngineQueueFactory.java index e49074f92d..dda3f33ed4 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbRuleEngineQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbRuleEngineQueueFactory.java @@ -19,6 +19,9 @@ import org.thingsboard.server.common.data.queue.Queue; import org.thingsboard.server.gen.js.JsInvokeProtos; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; @@ -67,14 +70,18 @@ public interface TbRuleEngineQueueFactory extends TbUsageStatsClientQueueFactory * * @return */ - TbQueueProducer> createTbCoreNotificationsMsgProducer(); + TbQueueProducer> createTbCoreNotificationsMsgProducer(); + + TbQueueProducer> createEdgeMsgProducer(); + + TbQueueProducer> createEdgeNotificationsMsgProducer(); /** * Used to consume messages about firmware update notifications to TB Core Service * * @return */ - TbQueueProducer> createToOtaPackageStateServiceMsgProducer(); + TbQueueProducer> createToOtaPackageStateServiceMsgProducer(); /** * Used to consume messages by TB Rule Engine Service diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbTransportQueueProducerProvider.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbTransportQueueProducerProvider.java index df394cd997..b2c7856b20 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbTransportQueueProducerProvider.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbTransportQueueProducerProvider.java @@ -18,14 +18,16 @@ package org.thingsboard.server.queue.provider; import jakarta.annotation.PostConstruct; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.stereotype.Service; -import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeNotificationMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToVersionControlServiceMsg; import org.thingsboard.server.queue.TbQueueProducer; import org.thingsboard.server.queue.common.TbProtoQueueMsg; @@ -79,7 +81,17 @@ public class TbTransportQueueProducerProvider implements TbQueueProducerProvider } @Override - public TbQueueProducer> getTbVersionControlMsgProducer() { + public TbQueueProducer> getTbEdgeMsgProducer() { + throw new RuntimeException("Not Implemented! Should not be used Transport!"); + } + + @Override + public TbQueueProducer> getTbEdgeNotificationsMsgProducer() { + throw new RuntimeException("Not Implemented! Should not be used by Transport!"); + } + + @Override + public TbQueueProducer> getTbVersionControlMsgProducer() { throw new RuntimeException("Not Implemented! Should not be used by Transport!"); } diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbVersionControlProducerProvider.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbVersionControlProducerProvider.java index 7547c73f71..a8f3b124e2 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbVersionControlProducerProvider.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbVersionControlProducerProvider.java @@ -18,14 +18,16 @@ package org.thingsboard.server.queue.provider; import jakarta.annotation.PostConstruct; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.stereotype.Service; -import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeNotificationMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToVersionControlServiceMsg; import org.thingsboard.server.queue.TbQueueProducer; import org.thingsboard.server.queue.common.TbProtoQueueMsg; @@ -75,7 +77,17 @@ public class TbVersionControlProducerProvider implements TbQueueProducerProvider } @Override - public TbQueueProducer> getTbVersionControlMsgProducer() { + public TbQueueProducer> getTbEdgeMsgProducer() { + throw new RuntimeException("Not Implemented! Should not be used by Version Control Service!"); + } + + @Override + public TbQueueProducer> getTbEdgeNotificationsMsgProducer() { + throw new RuntimeException("Not Implemented! Should not be used by Version Control Service!"); + } + + @Override + public TbQueueProducer> getTbVersionControlMsgProducer() { throw new RuntimeException("Not Implemented! Should not be used by Version Control Service!"); } diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/pubsub/TbPubSubSubscriptionSettings.java b/common/queue/src/main/java/org/thingsboard/server/queue/pubsub/TbPubSubSubscriptionSettings.java index 2faf4b1985..14aa67a4f0 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/pubsub/TbPubSubSubscriptionSettings.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/pubsub/TbPubSubSubscriptionSettings.java @@ -27,6 +27,7 @@ import java.util.Map; @Component @ConditionalOnExpression("'${queue.type:null}'=='pubsub'") public class TbPubSubSubscriptionSettings { + @Value("${queue.pubsub.queue-properties.core:}") private String coreProperties; @Value("${queue.pubsub.queue-properties.rule-engine:}") @@ -39,6 +40,8 @@ public class TbPubSubSubscriptionSettings { private String jsExecutorProperties; @Value("${queue.pubsub.queue-properties.version-control:}") private String vcProperties; + @Value("${queue.pubsub.queue-properties.edge:}") + private String edgeProperties; @Getter private Map coreSettings; @@ -52,6 +55,8 @@ public class TbPubSubSubscriptionSettings { private Map jsExecutorSettings; @Getter private Map vcSettings; + @Getter + private Map edgeSettings; @PostConstruct private void init() { @@ -61,6 +66,7 @@ public class TbPubSubSubscriptionSettings { notificationsSettings = PropertyUtils.getProps(notificationsProperties); jsExecutorSettings = PropertyUtils.getProps(jsExecutorProperties); vcSettings = PropertyUtils.getProps(vcProperties); + edgeSettings = PropertyUtils.getProps(edgeProperties); } } diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqQueueArguments.java b/common/queue/src/main/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqQueueArguments.java index acd008fb1d..06613d5617 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqQueueArguments.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqQueueArguments.java @@ -41,6 +41,8 @@ public class TbRabbitMqQueueArguments { private String jsExecutorProperties; @Value("${queue.rabbitmq.queue-properties.version-control:}") private String vcProperties; + @Value("${queue.rabbitmq.queue-properties.edge:}") + private String edgeProperties; @Getter private Map coreArgs; @@ -54,6 +56,8 @@ public class TbRabbitMqQueueArguments { private Map jsExecutorArgs; @Getter private Map vcArgs; + @Getter + private Map edgeArgs; @PostConstruct private void init() { @@ -63,6 +67,7 @@ public class TbRabbitMqQueueArguments { notificationsArgs = getArgs(notificationsProperties); jsExecutorArgs = getArgs(jsExecutorProperties); vcArgs = getArgs(vcProperties); + edgeArgs = getArgs(edgeProperties); } public static Map getArgs(String properties) { diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/settings/TbQueueEdgeSettings.java b/common/queue/src/main/java/org/thingsboard/server/queue/settings/TbQueueEdgeSettings.java new file mode 100644 index 0000000000..87fefc8113 --- /dev/null +++ b/common/queue/src/main/java/org/thingsboard/server/queue/settings/TbQueueEdgeSettings.java @@ -0,0 +1,31 @@ +/** + * Copyright © 2016-2024 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.queue.settings; + +import lombok.Data; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; + +@Lazy +@Data +@Component +public class TbQueueEdgeSettings { + + @Value("${queue.edge.topic}") + private String topic; + +} diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/sqs/TbAwsSqsQueueAttributes.java b/common/queue/src/main/java/org/thingsboard/server/queue/sqs/TbAwsSqsQueueAttributes.java index 0c61c2d2eb..2c1b8793eb 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/sqs/TbAwsSqsQueueAttributes.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/sqs/TbAwsSqsQueueAttributes.java @@ -43,6 +43,8 @@ public class TbAwsSqsQueueAttributes { private String otaProperties; @Value("${queue.aws-sqs.queue-properties.version-control:}") private String vcProperties; + @Value("${queue.aws-sqs.queue-properties.edge:}") + private String edgeProperties; @Getter private Map coreAttributes; @@ -58,6 +60,8 @@ public class TbAwsSqsQueueAttributes { private Map otaAttributes; @Getter private Map vcAttributes; + @Getter + private Map edgeAttributes; private final Map defaultAttributes = new HashMap<>(); @@ -72,6 +76,7 @@ public class TbAwsSqsQueueAttributes { jsExecutorAttributes = getConfigs(jsExecutorProperties); otaAttributes = getConfigs(otaProperties); vcAttributes = getConfigs(vcProperties); + edgeAttributes = getConfigs(edgeProperties); } private Map getConfigs(String properties) { diff --git a/common/stats/src/main/java/org/thingsboard/server/common/stats/StatsType.java b/common/stats/src/main/java/org/thingsboard/server/common/stats/StatsType.java index 6c854ac8d6..3833155c05 100644 --- a/common/stats/src/main/java/org/thingsboard/server/common/stats/StatsType.java +++ b/common/stats/src/main/java/org/thingsboard/server/common/stats/StatsType.java @@ -21,9 +21,10 @@ public enum StatsType { TRANSPORT("transport"), JS_INVOKE("jsInvoke"), RATE_EXECUTOR("rateExecutor"), - HOUSEKEEPER("housekeeper"); + HOUSEKEEPER("housekeeper"), + EDGE("edge"); - private String name; + private final String name; StatsType(String name) { this.name = name; diff --git a/common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/DefaultClusterVersionControlService.java b/common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/DefaultClusterVersionControlService.java index 99401bbdf0..138505bd8d 100644 --- a/common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/DefaultClusterVersionControlService.java +++ b/common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/DefaultClusterVersionControlService.java @@ -79,6 +79,7 @@ import org.thingsboard.server.queue.util.TbVersionControlComponent; import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -174,7 +175,7 @@ public class DefaultClusterVersionControlService extends TbApplicationEventListe } } } - consumer.subscribe(event.getPartitions()); + consumer.subscribe(event.getPartitionsMap().values().stream().findAny().orElse(Collections.emptySet())); } @Override diff --git a/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java index 6a9536d8ac..1e0202bf79 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java @@ -17,11 +17,9 @@ package org.thingsboard.server.dao.edge; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; -import com.google.common.base.Function; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; -import jakarta.annotation.Nullable; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.hibernate.exception.ConstraintViolationException; @@ -54,6 +52,7 @@ import org.thingsboard.server.common.data.id.TenantProfileId; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.kv.KvEntry; import org.thingsboard.server.common.data.page.PageData; +import org.thingsboard.server.common.data.page.PageDataIterable; import org.thingsboard.server.common.data.page.PageDataIterableByTenantIdEntityId; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.relation.EntityRelation; @@ -97,8 +96,7 @@ public class EdgeServiceImpl extends AbstractCachedEntityService() { - @Nullable - @Override - public List apply(@Nullable List edgeList) { - return edgeList == null ? - Collections.emptyList() : - edgeList.stream().filter(edge -> query.getEdgeTypes().contains(edge.getType())).collect(Collectors.toList()); - } - }, MoreExecutors.directExecutor()); - + edges = Futures.transform(edges, edgeList -> edgeList == null ? + Collections.emptyList() : + edgeList.stream().filter(edge -> query.getEdgeTypes().contains(edge.getType())).collect(Collectors.toList()), MoreExecutors.directExecutor()); return edges; } @@ -417,19 +408,11 @@ public class EdgeServiceImpl extends AbstractCachedEntityService pageData; - do { - pageData = ruleChainService.findAutoAssignToEdgeRuleChainsByTenantId(tenantId, pageLink); - if (pageData.getData().size() > 0) { - for (RuleChain ruleChain : pageData.getData()) { - ruleChainService.assignRuleChainToEdge(tenantId, ruleChain.getId(), edgeId); - } - } - if (pageData.hasNext()) { - pageLink = pageLink.nextPageLink(); - } - } while (pageData.hasNext()); + PageDataIterable ruleChains = new PageDataIterable<>( + link -> ruleChainService.findAutoAssignToEdgeRuleChainsByTenantId(tenantId, link), 1024); + for (RuleChain ruleChain : ruleChains) { + ruleChainService.assignRuleChainToEdge(tenantId, ruleChain.getId(), edgeId); + } } @Override @@ -580,6 +563,17 @@ public class EdgeServiceImpl extends AbstractCachedEntityService isEdgeActiveAsync(TenantId tenantId, EdgeId edgeId, String key) { ListenableFuture> futureKvEntry; @@ -594,17 +588,11 @@ public class EdgeServiceImpl extends AbstractCachedEntityService findEdgeRuleChains(TenantId tenantId, EdgeId edgeId) { List result = new ArrayList<>(); - PageLink pageLink = new PageLink(DEFAULT_PAGE_SIZE); - PageData pageData; - do { - pageData = ruleChainService.findRuleChainsByTenantIdAndEdgeId(tenantId, edgeId, pageLink); - if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { - result.addAll(pageData.getData()); - if (pageData.hasNext()) { - pageLink = pageLink.nextPageLink(); - } - } - } while (pageData != null && pageData.hasNext()); + PageDataIterable ruleChains = new PageDataIterable<>( + link -> ruleChainService.findRuleChainsByTenantIdAndEdgeId(tenantId, edgeId, link), 1024); + for (RuleChain ruleChain : ruleChains) { + result.add(ruleChain); + } return result; } diff --git a/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeSessionCaffeineCache.java b/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeSessionCaffeineCache.java new file mode 100644 index 0000000000..948b860649 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeSessionCaffeineCache.java @@ -0,0 +1,33 @@ +/** + * Copyright © 2016-2024 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.dao.edge; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.cache.CacheManager; +import org.springframework.stereotype.Service; +import org.thingsboard.server.cache.CaffeineTbTransactionalCache; +import org.thingsboard.server.common.data.CacheConstants; +import org.thingsboard.server.common.data.id.EdgeId; + +@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "caffeine", matchIfMissing = true) +@Service("EdgeSessionCache") +public class EdgeSessionCaffeineCache extends CaffeineTbTransactionalCache { + + public EdgeSessionCaffeineCache(CacheManager cacheManager) { + super(cacheManager, CacheConstants.EDGE_SESSIONS_CACHE); + } + +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeSessionRedisCache.java b/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeSessionRedisCache.java new file mode 100644 index 0000000000..518c0c0b32 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeSessionRedisCache.java @@ -0,0 +1,36 @@ +/** + * Copyright © 2016-2024 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.dao.edge; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.stereotype.Service; +import org.thingsboard.server.cache.CacheSpecsMap; +import org.thingsboard.server.cache.RedisTbTransactionalCache; +import org.thingsboard.server.cache.TBRedisCacheConfiguration; +import org.thingsboard.server.cache.TbJsonRedisSerializer; +import org.thingsboard.server.common.data.CacheConstants; +import org.thingsboard.server.common.data.id.EdgeId; + +@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis") +@Service("EdgeSessionCache") +public class EdgeSessionRedisCache extends RedisTbTransactionalCache { + + public EdgeSessionRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) { + super(CacheConstants.EDGE_SESSIONS_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbJsonRedisSerializer<>(String.class)); + } + +} diff --git a/dao/src/test/resources/application-test.properties b/dao/src/test/resources/application-test.properties index 48f7c92b1d..e71c6b1294 100644 --- a/dao/src/test/resources/application-test.properties +++ b/dao/src/test/resources/application-test.properties @@ -75,6 +75,9 @@ cache.specs.otaPackagesData.maxSize=100000 cache.specs.edges.timeToLiveInMinutes=1440 cache.specs.edges.maxSize=100000 +cache.specs.edgeSessions.timeToLiveInMinutes=1440 +cache.specs.edgeSessions.maxSize=100000 + cache.specs.relatedEdges.timeToLiveInMinutes=1440 cache.specs.relatedEdges.maxSize=100000