From 394075c9df75b9528ef69206544d09e3f3a9580c Mon Sep 17 00:00:00 2001 From: Nikita Mazurenko Date: Fri, 28 Nov 2025 15:11:32 +0200 Subject: [PATCH] Handle entity view removal from edge event in EntityViewEdgeProcessor --- .../entityview/BaseEntityViewProcessor.java | 13 +++++++ .../entityview/EntityViewEdgeProcessor.java | 34 +++++++------------ .../server/edge/EntityViewEdgeTest.java | 15 +++----- 3 files changed, 30 insertions(+), 32 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/entityview/BaseEntityViewProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/entityview/BaseEntityViewProcessor.java index 4ee532a33b..97f712c5ac 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/entityview/BaseEntityViewProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/entityview/BaseEntityViewProcessor.java @@ -21,9 +21,11 @@ import org.springframework.data.util.Pair; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.EntityView; import org.thingsboard.server.common.data.StringUtils; +import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.EntityViewId; import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.msg.TbMsgType; import org.thingsboard.server.dao.service.DataValidator; import org.thingsboard.server.gen.edge.v1.EntityViewUpdateMsg; import org.thingsboard.server.service.edge.rpc.processor.BaseEdgeProcessor; @@ -69,4 +71,15 @@ public abstract class BaseEntityViewProcessor extends BaseEdgeProcessor { protected abstract void setCustomerId(TenantId tenantId, CustomerId customerId, EntityView entityView, EntityViewUpdateMsg entityViewUpdateMsg); + protected void deleteEntityView(TenantId tenantId, EntityViewId entityViewId) { + deleteEntityView(tenantId, null, entityViewId); + } + + protected void deleteEntityView(TenantId tenantId, Edge edge, EntityViewId entityViewId) { + EntityView entityViewById = edgeCtx.getEntityViewService().findEntityViewById(tenantId, entityViewId); + if (entityViewById != null) { + edgeCtx.getEntityViewService().deleteEntityView(tenantId, entityViewId); + pushEntityEventToRuleEngine(tenantId, edge, entityViewById, TbMsgType.ENTITY_DELETED); + } + } } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/entityview/EntityViewEdgeProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/entityview/EntityViewEdgeProcessor.java index 56785f9ac0..42757764db 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/entityview/EntityViewEdgeProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/entityview/EntityViewEdgeProcessor.java @@ -54,21 +54,17 @@ public class EntityViewEdgeProcessor extends BaseEntityViewProcessor implements try { edgeSynchronizationManager.getEdgeId().set(edge.getId()); - switch (entityViewUpdateMsg.getMsgType()) { - case ENTITY_CREATED_RPC_MESSAGE: - case ENTITY_UPDATED_RPC_MESSAGE: + return switch (entityViewUpdateMsg.getMsgType()) { + case ENTITY_CREATED_RPC_MESSAGE, ENTITY_UPDATED_RPC_MESSAGE -> { saveOrUpdateEntityView(tenantId, entityViewId, entityViewUpdateMsg, edge); - return Futures.immediateFuture(null); - case ENTITY_DELETED_RPC_MESSAGE: - EntityView entityViewToDelete = edgeCtx.getEntityViewService().findEntityViewById(tenantId, entityViewId); - if (entityViewToDelete != null) { - edgeCtx.getEntityViewService().unassignEntityViewFromEdge(tenantId, entityViewId, edge.getId()); - } - return Futures.immediateFuture(null); - case UNRECOGNIZED: - default: - return handleUnsupportedMsgType(entityViewUpdateMsg.getMsgType()); - } + yield Futures.immediateFuture(null); + } + case ENTITY_DELETED_RPC_MESSAGE -> { + deleteEntityView(tenantId, entityViewId); + yield Futures.immediateFuture(null); + } + default -> handleUnsupportedMsgType(entityViewUpdateMsg.getMsgType()); + }; } catch (DataValidationException e) { if (e.getMessage().contains("limit reached")) { log.warn("[{}] Number of allowed entity views violated {}", tenantId, entityViewUpdateMsg, e); @@ -96,14 +92,8 @@ public class EntityViewEdgeProcessor extends BaseEntityViewProcessor implements } private void pushEntityViewCreatedEventToRuleEngine(TenantId tenantId, Edge edge, EntityViewId entityViewId) { - try { - EntityView entityView = edgeCtx.getEntityViewService().findEntityViewById(tenantId, entityViewId); - String entityViewAsString = JacksonUtil.toString(entityView); - TbMsgMetaData msgMetaData = getEdgeActionTbMsgMetaData(edge, entityView.getCustomerId()); - pushEntityEventToRuleEngine(tenantId, entityViewId, entityView.getCustomerId(), TbMsgType.ENTITY_CREATED, entityViewAsString, msgMetaData); - } catch (Exception e) { - log.warn("[{}][{}] Failed to push entity view action to rule engine: {}", tenantId, entityViewId, TbMsgType.ENTITY_CREATED.name(), e); - } + EntityView entityView = edgeCtx.getEntityViewService().findEntityViewById(tenantId, entityViewId); + pushEntityEventToRuleEngine(tenantId, edge, entityView, TbMsgType.ENTITY_CREATED); } @Override diff --git a/application/src/test/java/org/thingsboard/server/edge/EntityViewEdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/EntityViewEdgeTest.java index 875a83e3f5..2ff52d1c4d 100644 --- a/application/src/test/java/org/thingsboard/server/edge/EntityViewEdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/EntityViewEdgeTest.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.edge; -import com.fasterxml.jackson.core.type.TypeReference; import com.google.protobuf.AbstractMessage; import com.google.protobuf.InvalidProtocolBufferException; import org.junit.Assert; @@ -31,8 +30,6 @@ import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityViewId; -import org.thingsboard.server.common.data.page.PageData; -import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.dao.service.DaoSqlTest; import org.thingsboard.server.gen.edge.v1.EntityViewUpdateMsg; import org.thingsboard.server.gen.edge.v1.EntityViewsRequestMsg; @@ -40,10 +37,11 @@ import org.thingsboard.server.gen.edge.v1.UpdateMsgType; import org.thingsboard.server.gen.edge.v1.UplinkMsg; import org.thingsboard.server.gen.edge.v1.UplinkResponseMsg; -import java.util.List; import java.util.Optional; import java.util.UUID; +import java.util.concurrent.TimeUnit; +import static org.awaitility.Awaitility.await; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @DaoSqlTest @@ -256,12 +254,9 @@ public class EntityViewEdgeTest extends AbstractEdgeTest { edgeImitator.expectResponsesAmount(1); edgeImitator.sendUplinkMsg(upLinkMsgBuilder.build()); Assert.assertTrue(edgeImitator.waitForResponses()); - EntityViewInfo entityViewInfo = doGet("/api/entityView/info/" + savedEntityView.getUuidId(), EntityViewInfo.class); - Assert.assertNotNull(entityViewInfo); - List edgeAssets = doGetTypedWithPageLink("/api/edge/" + edge.getUuidId() + "/entityViews?", - new TypeReference>() { - }, new PageLink(100)).getData(); - Assert.assertFalse(edgeAssets.contains(entityViewInfo)); + await().atMost(30, TimeUnit.SECONDS).untilAsserted(() -> + doGet("/api/entityView/info/" + savedEntityView.getUuidId(), EntityViewInfo.class, status().isNotFound()) + ); } private void verifyEntityViewUpdateMsg(EntityView entityView, Device device) throws InvalidProtocolBufferException {