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 6c12b5f753..ebbfae0f05 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 @@ -19,16 +19,18 @@ import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.AlarmInfo; import org.thingsboard.server.common.data.alarm.AlarmQuery; +import org.thingsboard.server.common.data.alarm.AlarmSeverity; +import org.thingsboard.server.common.data.alarm.AlarmStatus; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.query.AlarmData; -import org.thingsboard.server.common.data.query.AlarmDataPageLink; import org.thingsboard.server.common.data.query.AlarmDataQuery; import org.thingsboard.server.dao.Dao; import java.util.Collection; +import java.util.Set; import java.util.UUID; /** @@ -48,4 +50,6 @@ public interface AlarmDao extends Dao { PageData findAlarmDataByQueryForEntities(TenantId tenantId, CustomerId customerId, AlarmDataQuery query, Collection orderedEntityIds); + + Set findAlarmSeverities(TenantId tenantId, EntityId entityId, Set status); } 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 45478ce146..b239b8e9f8 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 @@ -39,10 +39,10 @@ import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.EntityId; 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.common.data.query.AlarmData; import org.thingsboard.server.common.data.query.AlarmDataPageLink; import org.thingsboard.server.common.data.query.AlarmDataQuery; +import org.thingsboard.server.common.data.query.DeviceTypeFilter; import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.EntityRelationsQuery; import org.thingsboard.server.common.data.relation.EntitySearchDirection; @@ -60,7 +60,6 @@ import javax.annotation.PreDestroy; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import java.util.Comparator; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; @@ -316,37 +315,16 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ @Override public AlarmSeverity findHighestAlarmSeverity(TenantId tenantId, EntityId entityId, AlarmSearchStatus alarmSearchStatus, AlarmStatus alarmStatus) { - TimePageLink nextPageLink = new TimePageLink(100); - boolean hasNext = true; - AlarmSeverity highestSeverity = null; - AlarmQuery query; - while (hasNext && AlarmSeverity.CRITICAL != highestSeverity) { - query = new AlarmQuery(entityId, nextPageLink, alarmSearchStatus, alarmStatus, false, null); - PageData alarms = alarmDao.findAlarms(tenantId, query); - if (alarms.hasNext()) { - nextPageLink = nextPageLink.nextPageLink(); - } - AlarmSeverity severity = detectHighestSeverity(alarms.getData()); - if (severity == null) { - continue; - } - if (severity == AlarmSeverity.CRITICAL || highestSeverity == null) { - highestSeverity = severity; - } else { - highestSeverity = highestSeverity.compareTo(severity) < 0 ? highestSeverity : severity; - } + Set statusList = null; + if (alarmSearchStatus != null) { + statusList = alarmSearchStatus.getStatuses(); + } else if (alarmStatus != null) { + statusList = Collections.singleton(alarmStatus); } - return highestSeverity; - } - private AlarmSeverity detectHighestSeverity(List alarms) { - if (!alarms.isEmpty()) { - List sorted = new ArrayList(alarms); - sorted.sort(Comparator.comparing(Alarm::getSeverity)); - return sorted.get(0).getSeverity(); - } else { - return null; - } + Set alarmSeverities = alarmDao.findAlarmSeverities(tenantId, entityId, statusList); + + return alarmSeverities.stream().min(AlarmSeverity::compareTo).orElse(null); } private void deleteRelation(TenantId tenantId, EntityRelation alarmRelation) { diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/AlarmRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/AlarmRepository.java index f3206f30de..f34048c5ad 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/AlarmRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/AlarmRepository.java @@ -20,6 +20,7 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.query.Param; +import org.thingsboard.server.common.data.alarm.AlarmSeverity; import org.thingsboard.server.common.data.alarm.AlarmStatus; import org.thingsboard.server.dao.model.sql.AlarmEntity; import org.thingsboard.server.dao.model.sql.AlarmInfoEntity; @@ -75,4 +76,12 @@ public interface AlarmRepository extends CrudRepository { @Param("searchText") String searchText, Pageable pageable); + @Query("SELECT alarm.severity FROM AlarmEntity alarm" + + " WHERE alarm.tenantId = :tenantId" + + " AND alarm.originatorId = :entityId" + + " AND ((:status) IS NULL OR alarm.status in (:status))") + Set findAlarmSeverities(@Param("tenantId") UUID tenantId, + @Param("entityId") UUID entityId, + @Param("status") Set status); + } 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 d74092ac95..722928e1b8 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 @@ -24,6 +24,7 @@ import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.AlarmInfo; import org.thingsboard.server.common.data.alarm.AlarmQuery; +import org.thingsboard.server.common.data.alarm.AlarmSeverity; import org.thingsboard.server.common.data.alarm.AlarmStatus; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.EntityId; @@ -120,4 +121,9 @@ public class JpaAlarmDao extends JpaAbstractDao implements A public PageData findAlarmDataByQueryForEntities(TenantId tenantId, CustomerId customerId, AlarmDataQuery query, Collection orderedEntityIds) { return alarmQueryRepository.findAlarmDataByQueryForEntities(tenantId, customerId, query, orderedEntityIds); } + + @Override + public Set findAlarmSeverities(TenantId tenantId, EntityId entityId, Set status) { + return alarmRepository.findAlarmSeverities(tenantId.getId(), entityId.getId(), status); + } } diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/BaseAlarmServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/BaseAlarmServiceTest.java index 3536b6066f..a885ac38de 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/BaseAlarmServiceTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/BaseAlarmServiceTest.java @@ -354,6 +354,62 @@ public abstract class BaseAlarmServiceTest extends AbstractServiceTest { return new AlarmDataQuery(new DeviceTypeFilter(), pageLink, null, null, null, alarmFields); } + @Test + public void testFindHighestAlarmSeverity() throws ExecutionException, InterruptedException { + Customer customer = new Customer(); + customer.setTitle("TestCustomer"); + customer.setTenantId(tenantId); + customer = customerService.saveCustomer(customer); + + Device customerDevice = new Device(); + customerDevice.setName("TestCustomerDevice"); + customerDevice.setType("default"); + customerDevice.setTenantId(tenantId); + customerDevice.setCustomerId(customer.getId()); + customerDevice = deviceService.saveDevice(customerDevice); + + // no one alarms was created + Assert.assertNull(alarmService.findHighestAlarmSeverity(tenantId, customerDevice.getId(), null, null)); + + Alarm alarm1 = Alarm.builder() + .tenantId(tenantId) + .originator(customerDevice.getId()) + .type(TEST_ALARM) + .severity(AlarmSeverity.MAJOR) + .status(AlarmStatus.ACTIVE_UNACK) + .startTs(System.currentTimeMillis()) + .build(); + alarm1 = alarmService.createOrUpdateAlarm(alarm1).getAlarm(); + alarmService.clearAlarm(tenantId, alarm1.getId(), null, System.currentTimeMillis()).get(); + + Alarm alarm2 = Alarm.builder() + .tenantId(tenantId) + .originator(customerDevice.getId()) + .type(TEST_ALARM) + .severity(AlarmSeverity.MINOR) + .status(AlarmStatus.ACTIVE_ACK) + .startTs(System.currentTimeMillis()) + .build(); + alarm2 = alarmService.createOrUpdateAlarm(alarm2).getAlarm(); + alarmService.clearAlarm(tenantId, alarm2.getId(), null, System.currentTimeMillis()).get(); + + Alarm alarm3 = Alarm.builder() + .tenantId(tenantId) + .originator(customerDevice.getId()) + .type(TEST_ALARM) + .severity(AlarmSeverity.CRITICAL) + .status(AlarmStatus.ACTIVE_ACK) + .startTs(System.currentTimeMillis()) + .build(); + alarm3 = alarmService.createOrUpdateAlarm(alarm3).getAlarm(); + + Assert.assertEquals(AlarmSeverity.MAJOR, alarmService.findHighestAlarmSeverity(tenantId, customerDevice.getId(), AlarmSearchStatus.UNACK, null)); + Assert.assertEquals(AlarmSeverity.CRITICAL, alarmService.findHighestAlarmSeverity(tenantId, customerDevice.getId(), null, null)); + Assert.assertEquals(AlarmSeverity.MAJOR, alarmService.findHighestAlarmSeverity(tenantId, customerDevice.getId(), null, AlarmStatus.CLEARED_UNACK)); + Assert.assertEquals(AlarmSeverity.CRITICAL, alarmService.findHighestAlarmSeverity(tenantId, customerDevice.getId(), AlarmSearchStatus.ACTIVE, null)); + Assert.assertEquals(AlarmSeverity.MINOR, alarmService.findHighestAlarmSeverity(tenantId, customerDevice.getId(), null, AlarmStatus.CLEARED_ACK)); + } + @Test public void testFindAlarmUsingAlarmDataQuery() throws ExecutionException, InterruptedException { AssetId parentId = new AssetId(Uuids.timeBased());