diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/AbstractTbEntityService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/AbstractTbEntityService.java index ff8dd52ec5..9af65c0965 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/AbstractTbEntityService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/AbstractTbEntityService.java @@ -25,15 +25,10 @@ import org.springframework.context.annotation.Lazy; import org.thingsboard.server.cluster.TbClusterService; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.User; -import org.thingsboard.server.common.data.alarm.AlarmInfo; -import org.thingsboard.server.common.data.alarm.AlarmQuery; import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityIdFactory; -import org.thingsboard.server.common.data.id.TenantId; -import org.thingsboard.server.common.data.page.PageData; -import org.thingsboard.server.common.data.page.TimePageLink; import org.thingsboard.server.dao.alarm.AlarmService; import org.thingsboard.server.dao.customer.CustomerService; import org.thingsboard.server.dao.edge.EdgeService; @@ -72,13 +67,6 @@ public abstract class AbstractTbEntityService { @Lazy private EntitiesVersionControlService vcService; - protected void removeAlarmsByEntityId(TenantId tenantId, EntityId entityId) { - PageData alarms = - alarmService.findAlarms(tenantId, new AlarmQuery(entityId, new TimePageLink(Integer.MAX_VALUE), null, null, null, false)); - - alarms.getData().stream().map(AlarmInfo::getId).forEach(alarmId -> alarmService.delAlarm(tenantId, alarmId)); - } - protected T checkNotNull(T reference) throws ThingsboardException { return checkNotNull(reference, "Requested item wasn't found!"); } diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/asset/DefaultTbAssetService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/asset/DefaultTbAssetService.java index 58940318be..e30f6f9922 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/asset/DefaultTbAssetService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/asset/DefaultTbAssetService.java @@ -78,7 +78,6 @@ public class DefaultTbAssetService extends AbstractTbEntityService implements Tb TenantId tenantId = asset.getTenantId(); AssetId assetId = asset.getId(); try { - removeAlarmsByEntityId(tenantId, assetId); assetService.deleteAsset(tenantId, assetId); notificationEntityService.logEntityAction(tenantId, assetId, asset, asset.getCustomerId(), actionType, user, assetId.toString()); tbClusterService.broadcastEntityStateChangeEvent(tenantId, assetId, ComponentLifecycleEvent.DELETED); diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/device/DefaultTbDeviceService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/device/DefaultTbDeviceService.java index 8d43a43cbc..f7d11e88d0 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/device/DefaultTbDeviceService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/device/DefaultTbDeviceService.java @@ -97,7 +97,6 @@ public class DefaultTbDeviceService extends AbstractTbEntityService implements T TenantId tenantId = device.getTenantId(); DeviceId deviceId = device.getId(); try { - removeAlarmsByEntityId(tenantId, deviceId); deviceService.deleteDevice(tenantId, deviceId); notificationEntityService.notifyDeleteDevice(tenantId, deviceId, device.getCustomerId(), device, user, deviceId.toString()); diff --git a/application/src/main/java/org/thingsboard/server/service/housekeeper/HousekeeperService.java b/application/src/main/java/org/thingsboard/server/service/housekeeper/HousekeeperService.java index 4c0c0e72d5..fa59eae4c9 100644 --- a/application/src/main/java/org/thingsboard/server/service/housekeeper/HousekeeperService.java +++ b/application/src/main/java/org/thingsboard/server/service/housekeeper/HousekeeperService.java @@ -130,7 +130,7 @@ public class HousekeeperService { } if (log.isDebugEnabled()) { - log.debug("[{}] {} task {}", task.getTenantId(), isNew(msg.getTask()) ? "Processing" : "Reprocessing", msg.getTask().getValue()); + log.debug("[{}] {} {}", task.getTenantId(), isNew(msg.getTask()) ? "Processing" : "Reprocessing", task.getDescription()); } try { Future future = executor.submit(() -> { @@ -140,7 +140,6 @@ public class HousekeeperService { future.get(taskProcessingTimeout, TimeUnit.MILLISECONDS); statsService.ifPresent(statsService -> statsService.reportProcessed(task.getTaskType(), msg)); - log.debug("[{}] Successfully {} task {}", task.getTenantId(), isNew(msg.getTask()) ? "processed" : "reprocessed", msg.getTask().getValue()); } catch (InterruptedException e) { throw e; } catch (Throwable e) { diff --git a/application/src/main/java/org/thingsboard/server/service/housekeeper/processor/EntityAlarmsDeletionTaskProcessor.java b/application/src/main/java/org/thingsboard/server/service/housekeeper/processor/AlarmsDeletionTaskProcessor.java similarity index 57% rename from application/src/main/java/org/thingsboard/server/service/housekeeper/processor/EntityAlarmsDeletionTaskProcessor.java rename to application/src/main/java/org/thingsboard/server/service/housekeeper/processor/AlarmsDeletionTaskProcessor.java index 0827ce2441..2d7cf690d9 100644 --- a/application/src/main/java/org/thingsboard/server/service/housekeeper/processor/EntityAlarmsDeletionTaskProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/housekeeper/processor/AlarmsDeletionTaskProcessor.java @@ -16,27 +16,35 @@ package org.thingsboard.server.service.housekeeper.processor; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; -import org.thingsboard.server.dao.alarm.AlarmService; +import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.housekeeper.HousekeeperTask; import org.thingsboard.server.common.data.housekeeper.HousekeeperTaskType; +import org.thingsboard.server.dao.alarm.AlarmService; @Component @RequiredArgsConstructor -public class EntityAlarmsDeletionTaskProcessor implements HousekeeperTaskProcessor { +@Slf4j +public class AlarmsDeletionTaskProcessor implements HousekeeperTaskProcessor { private final AlarmService alarmService; @Override public void process(HousekeeperTask task) throws Exception { - alarmService.deleteEntityAlarmRecords(task.getTenantId(), task.getEntityId()); - // fixme: do we need to remove alarms by originator ??? - // fixme: why alarm comments are not deleted ?? + EntityType entityType = task.getEntityId().getEntityType(); + if (entityType == EntityType.DEVICE || entityType == EntityType.ASSET) { + int count = alarmService.deleteAlarmsByEntityId(task.getTenantId(), task.getEntityId()); + log.debug("[{}][{}][{}] Deleted {} alarms", task.getTenantId(), task.getEntityId().getEntityType(), task.getEntityId(), count); + } else { + int count = alarmService.deleteEntityAlarmRecords(task.getTenantId(), task.getEntityId()); + log.debug("[{}][{}][{}] Deleted {} entity alarms", task.getTenantId(), task.getEntityId().getEntityType(), task.getEntityId(), count); + } } @Override public HousekeeperTaskType getTaskType() { - return HousekeeperTaskType.DELETE_ENTITY_ALARMS; + return HousekeeperTaskType.DELETE_ALARMS; } } diff --git a/application/src/main/java/org/thingsboard/server/service/ttl/AlarmsCleanUpService.java b/application/src/main/java/org/thingsboard/server/service/ttl/AlarmsCleanUpService.java index 76de56cf13..c0f3158c61 100644 --- a/application/src/main/java/org/thingsboard/server/service/ttl/AlarmsCleanUpService.java +++ b/application/src/main/java/org/thingsboard/server/service/ttl/AlarmsCleanUpService.java @@ -56,7 +56,6 @@ public class AlarmsCleanUpService { private final TenantService tenantService; private final AlarmDao alarmDao; private final AlarmService alarmService; - private final RelationService relationService; private final EntityActionService entityActionService; private final PartitionService partitionService; private final TbTenantProfileCache tenantProfileCache; diff --git a/application/src/test/java/org/thingsboard/server/service/housekeeper/HousekeeperServiceTest.java b/application/src/test/java/org/thingsboard/server/service/housekeeper/HousekeeperServiceTest.java index daf363467d..1204e36184 100644 --- a/application/src/test/java/org/thingsboard/server/service/housekeeper/HousekeeperServiceTest.java +++ b/application/src/test/java/org/thingsboard/server/service/housekeeper/HousekeeperServiceTest.java @@ -32,12 +32,17 @@ import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.EventInfo; import org.thingsboard.server.common.data.alarm.Alarm; +import org.thingsboard.server.common.data.alarm.AlarmQuery; import org.thingsboard.server.common.data.alarm.AlarmSeverity; +import org.thingsboard.server.common.data.alarm.EntityAlarm; +import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.event.EventType; import org.thingsboard.server.common.data.event.LifecycleEvent; import org.thingsboard.server.common.data.housekeeper.HousekeeperTask; import org.thingsboard.server.common.data.housekeeper.HousekeeperTaskType; import org.thingsboard.server.common.data.id.AlarmId; +import org.thingsboard.server.common.data.id.AssetId; +import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.RuleNodeId; @@ -52,15 +57,19 @@ import org.thingsboard.server.common.data.kv.TsKvEntry; import org.thingsboard.server.common.data.msg.TbNodeConnectionType; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.TimePageLink; +import org.thingsboard.server.common.data.relation.EntityRelation; +import org.thingsboard.server.common.data.relation.RelationTypeGroup; import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.common.data.rule.RuleChainMetaData; import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.data.rule.RuleNode; import org.thingsboard.server.common.msg.housekeeper.HousekeeperClient; import org.thingsboard.server.controller.AbstractControllerTest; +import org.thingsboard.server.dao.alarm.AlarmDao; import org.thingsboard.server.dao.alarm.AlarmService; import org.thingsboard.server.dao.attributes.AttributesService; import org.thingsboard.server.dao.event.EventService; +import org.thingsboard.server.dao.relation.RelationService; import org.thingsboard.server.dao.rule.RuleChainService; import org.thingsboard.server.dao.service.DaoSqlTest; import org.thingsboard.server.dao.timeseries.TimeseriesService; @@ -115,6 +124,10 @@ public class HousekeeperServiceTest extends AbstractControllerTest { private RuleChainService ruleChainService; @Autowired private AlarmService alarmService; + @Autowired + private AlarmDao alarmDao; + @Autowired + private RelationService relationService; @SpyBean private TelemetryDeletionTaskProcessor telemetryDeletionTaskProcessor; @@ -200,6 +213,11 @@ public class HousekeeperServiceTest extends AbstractControllerTest { Device device = createDevice("oi324rujoi", "oi324rujoi"); createRelatedData(device.getId()); + Asset asset = createAsset(); + createRelatedData(asset.getId()); + createRelation(device.getId(), asset.getId()); + createAlarm(device.getId(), asset.getId()); + RuleChainMetaData ruleChainMetaData = createRuleChain(); RuleChainId ruleChainId = ruleChainMetaData.getRuleChainId(); RuleNodeId ruleNode1Id = ruleChainMetaData.getNodes().get(0).getId(); @@ -216,6 +234,7 @@ public class HousekeeperServiceTest extends AbstractControllerTest { await().atMost(30, TimeUnit.SECONDS).untilAsserted(() -> { verifyNoRelatedData(device.getId()); + verifyNoRelatedData(asset.getId()); verifyNoRelatedData(ruleNode1Id); verifyNoRelatedData(ruleNode2Id); verifyNoRelatedData(ruleChainId); @@ -301,7 +320,7 @@ public class HousekeeperServiceTest extends AbstractControllerTest { } private void verifyNoRelatedData(EntityId entityId) throws Exception { - List expectedTaskTypes = List.of(HousekeeperTaskType.DELETE_TELEMETRY, HousekeeperTaskType.DELETE_ATTRIBUTES, HousekeeperTaskType.DELETE_EVENTS, HousekeeperTaskType.DELETE_ENTITY_ALARMS); + List expectedTaskTypes = List.of(HousekeeperTaskType.DELETE_TELEMETRY, HousekeeperTaskType.DELETE_ATTRIBUTES, HousekeeperTaskType.DELETE_EVENTS, HousekeeperTaskType.DELETE_ALARMS); for (HousekeeperTaskType taskType : expectedTaskTypes) { verify(housekeeperClient).submitTask(argThat(task -> task.getTaskType() == taskType && task.getEntityId().equals(entityId))); } @@ -312,6 +331,11 @@ public class HousekeeperServiceTest extends AbstractControllerTest { assertThat(getAttribute(entityId, scope, scope + ATTRIBUTE_KEY)).isNull(); } assertThat(getEvents(entityId)).isEmpty(); + assertThat(alarmDao.findEntityAlarmRecordsByEntityId(tenantId, entityId)).isEmpty(); + assertThat(alarmService.findAlarms(tenantId, AlarmQuery.builder().pageLink(new TimePageLink(100)).build()).getData()) + .filteredOn(alarm -> alarm.getOriginator().equals(entityId)).isEmpty(); + assertThat(relationService.findByTo(tenantId, entityId, RelationTypeGroup.COMMON)).isEmpty(); + assertThat(relationService.findByFrom(tenantId, entityId, RelationTypeGroup.COMMON)).isEmpty(); } private void createAttribute(EntityId entityId, String scope, String key) throws Exception { @@ -336,6 +360,27 @@ public class HousekeeperServiceTest extends AbstractControllerTest { } + private void createRelation(DeviceId to, AssetId from) { + EntityRelation relation = new EntityRelation(from, to, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON); + relationService.saveRelation(tenantId, relation); + } + + private void createAlarm(DeviceId deviceId, EntityId propagatedEntityId) { + Alarm alarm = doPost("/api/alarm", Alarm.builder() + .tenantId(tenantId) + .originator(deviceId) + .severity(AlarmSeverity.CRITICAL) + .type("test alarm for " + deviceId) + .propagate(true) + .build(), Alarm.class); + + List entityAlarms = alarmDao.findEntityAlarmRecords(tenantId, alarm.getId()); + assertThat(entityAlarms).anyMatch(entityAlarm -> entityAlarm.getEntityId().equals(deviceId) && entityAlarm.getAlarmType().equals(alarm.getType())); + assertThat(entityAlarms).anyMatch(entityAlarm -> entityAlarm.getEntityId().equals(propagatedEntityId) && entityAlarm.getAlarmType().equals(alarm.getType())); + assertThat(alarmService.findAlarms(tenantId, AlarmQuery.builder().pageLink(new TimePageLink(100)).build()).getData()) + .filteredOn(a -> a.getOriginator().equals(deviceId)).isNotEmpty(); + } + private TsKvEntry getLatestTelemetry(EntityId entityId) throws Exception { return timeseriesService.findLatest(tenantId, entityId, HousekeeperServiceTest.TELEMETRY_KEY).get().orElse(null); } @@ -355,6 +400,13 @@ public class HousekeeperServiceTest extends AbstractControllerTest { .collect(Collectors.toList()); } + private Asset createAsset() { + Asset asset = new Asset(); + asset.setName("test"); + asset.setType("test"); + return doPost("/api/asset", asset, Asset.class); + } + private RuleChainMetaData createRuleChain() { RuleChain ruleChain = new RuleChain(); ruleChain.setTenantId(tenantId); diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmService.java index 7a55348bed..5607e4ff50 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmService.java @@ -81,6 +81,8 @@ public interface AlarmService extends EntityDaoService { void delAlarmTypes(TenantId tenantId, Set types); + int deleteAlarmsByEntityId(TenantId tenantId, EntityId entityId); + // Other API Alarm findAlarmById(TenantId tenantId, AlarmId alarmId); @@ -106,7 +108,7 @@ public interface AlarmService extends EntityDaoService { PageData findAlarmIdsByAssigneeId(TenantId tenantId, UserId userId, PageLink pageLink); - void deleteEntityAlarmRecords(TenantId tenantId, EntityId entityId); + int deleteEntityAlarmRecords(TenantId tenantId, EntityId entityId); void deleteEntityAlarmRecordsByTenantId(TenantId tenantId); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/housekeeper/HousekeeperTask.java b/common/data/src/main/java/org/thingsboard/server/common/data/housekeeper/HousekeeperTask.java index 44598d511c..bc41f553ad 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/housekeeper/HousekeeperTask.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/housekeeper/HousekeeperTask.java @@ -69,8 +69,8 @@ public class HousekeeperTask implements Serializable { return new AlarmsUnassignHousekeeperTask(user); } - public static HousekeeperTask deleteEntityAlarms(TenantId tenantId, EntityId entityId) { - return new HousekeeperTask(tenantId, entityId, HousekeeperTaskType.DELETE_ENTITY_ALARMS); + public static HousekeeperTask deleteAlarms(TenantId tenantId, EntityId entityId) { + return new HousekeeperTask(tenantId, entityId, HousekeeperTaskType.DELETE_ALARMS); } public static HousekeeperTask deleteEntities(TenantId tenantId, EntityType entityType) { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/housekeeper/HousekeeperTaskType.java b/common/data/src/main/java/org/thingsboard/server/common/data/housekeeper/HousekeeperTaskType.java index 4f30f94a45..eb5833b06f 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/housekeeper/HousekeeperTaskType.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/housekeeper/HousekeeperTaskType.java @@ -26,8 +26,8 @@ public enum HousekeeperTaskType { DELETE_ATTRIBUTES("attributes deletion"), DELETE_TELEMETRY("telemetry deletion"), DELETE_EVENTS("events deletion"), - UNASSIGN_ALARMS("alarms unassigning"), - DELETE_ENTITY_ALARMS("entity alarms deletion"); + DELETE_ALARMS("alarms deletion"), + UNASSIGN_ALARMS("alarms unassigning"); private final String description; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/page/PageData.java b/common/data/src/main/java/org/thingsboard/server/common/data/page/PageData.java index 9042e4865f..02129ea31b 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/page/PageData.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/page/PageData.java @@ -20,6 +20,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.EqualsAndHashCode; +import lombok.ToString; import java.io.Serializable; import java.util.Collections; @@ -29,6 +30,7 @@ import java.util.stream.Collectors; @ApiModel @EqualsAndHashCode +@ToString public class PageData implements Serializable { public static final PageData EMPTY_PAGE_DATA = new PageData<>(); diff --git a/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmDao.java b/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmDao.java index c752ae706d..339c8fd988 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmDao.java @@ -84,7 +84,9 @@ public interface AlarmDao extends Dao { List findEntityAlarmRecords(TenantId tenantId, AlarmId id); - void deleteEntityAlarmRecords(TenantId tenantId, EntityId entityId); + List findEntityAlarmRecordsByEntityId(TenantId tenantId, EntityId entityId); + + int deleteEntityAlarmRecords(TenantId tenantId, EntityId entityId); void deleteEntityAlarmRecordsByTenantId(TenantId tenantId); diff --git a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java index a14c172a57..9b7004042d 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java @@ -51,6 +51,7 @@ import org.thingsboard.server.common.data.id.UserId; 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.data.query.AlarmCountQuery; import org.thingsboard.server.common.data.query.AlarmData; import org.thingsboard.server.common.data.query.AlarmDataQuery; @@ -183,16 +184,23 @@ public class BaseAlarmService extends AbstractCachedEntityService alarms; + int count = 0; + do { + alarms = findAlarms(tenantId, AlarmQuery.builder() + .affectedEntityId(entityId) + .pageLink(new TimePageLink(pageLink, null, null)) + .build()); + for (AlarmInfo alarm : alarms.getData()) { + deleteAlarm(tenantId, alarm, true); + count++; + } + } while (alarms.hasNext()); + return count; + } + private List createEntityAlarmRecords(Alarm alarm) throws ExecutionException, InterruptedException { Set propagatedEntitiesSet = new LinkedHashSet<>(); propagatedEntitiesSet.add(alarm.getOriginator()); @@ -322,9 +348,9 @@ public class BaseAlarmService extends AbstractCachedEntityService findAllByEntityId(UUID entityId); + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java index 9430773ff9..1483cf8a8e 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java @@ -309,8 +309,13 @@ public class JpaAlarmDao extends JpaAbstractDao implements A } @Override - public void deleteEntityAlarmRecords(TenantId tenantId, EntityId entityId) { - entityAlarmRepository.deleteByEntityId(entityId.getId()); + public List findEntityAlarmRecordsByEntityId(TenantId tenantId, EntityId entityId) { + return DaoUtil.convertDataList(entityAlarmRepository.findAllByEntityId(entityId.getId())); + } + + @Override + public int deleteEntityAlarmRecords(TenantId tenantId, EntityId entityId) { + return entityAlarmRepository.deleteByEntityId(entityId.getId()); } @Override