Commit ef0182414fd39fc534a1b1a277dcea4bcc5e1671

Authored by Igor Kulikov
Committed by GitHub
2 parents 06420d2b 82ae2eb3

Merge pull request #3991 from AndrewVolosytnykhThingsboard/andrewdev

#3966 highestAlarmSeverity fixed
@@ -19,16 +19,18 @@ import com.google.common.util.concurrent.ListenableFuture; @@ -19,16 +19,18 @@ import com.google.common.util.concurrent.ListenableFuture;
19 import org.thingsboard.server.common.data.alarm.Alarm; 19 import org.thingsboard.server.common.data.alarm.Alarm;
20 import org.thingsboard.server.common.data.alarm.AlarmInfo; 20 import org.thingsboard.server.common.data.alarm.AlarmInfo;
21 import org.thingsboard.server.common.data.alarm.AlarmQuery; 21 import org.thingsboard.server.common.data.alarm.AlarmQuery;
  22 +import org.thingsboard.server.common.data.alarm.AlarmSeverity;
  23 +import org.thingsboard.server.common.data.alarm.AlarmStatus;
22 import org.thingsboard.server.common.data.id.CustomerId; 24 import org.thingsboard.server.common.data.id.CustomerId;
23 import org.thingsboard.server.common.data.id.EntityId; 25 import org.thingsboard.server.common.data.id.EntityId;
24 import org.thingsboard.server.common.data.id.TenantId; 26 import org.thingsboard.server.common.data.id.TenantId;
25 import org.thingsboard.server.common.data.page.PageData; 27 import org.thingsboard.server.common.data.page.PageData;
26 import org.thingsboard.server.common.data.query.AlarmData; 28 import org.thingsboard.server.common.data.query.AlarmData;
27 -import org.thingsboard.server.common.data.query.AlarmDataPageLink;  
28 import org.thingsboard.server.common.data.query.AlarmDataQuery; 29 import org.thingsboard.server.common.data.query.AlarmDataQuery;
29 import org.thingsboard.server.dao.Dao; 30 import org.thingsboard.server.dao.Dao;
30 31
31 import java.util.Collection; 32 import java.util.Collection;
  33 +import java.util.Set;
32 import java.util.UUID; 34 import java.util.UUID;
33 35
34 /** 36 /**
@@ -48,4 +50,6 @@ public interface AlarmDao extends Dao<Alarm> { @@ -48,4 +50,6 @@ public interface AlarmDao extends Dao<Alarm> {
48 50
49 PageData<AlarmData> findAlarmDataByQueryForEntities(TenantId tenantId, CustomerId customerId, 51 PageData<AlarmData> findAlarmDataByQueryForEntities(TenantId tenantId, CustomerId customerId,
50 AlarmDataQuery query, Collection<EntityId> orderedEntityIds); 52 AlarmDataQuery query, Collection<EntityId> orderedEntityIds);
  53 +
  54 + Set<AlarmSeverity> findAlarmSeverities(TenantId tenantId, EntityId entityId, Set<AlarmStatus> status);
51 } 55 }
@@ -39,10 +39,10 @@ import org.thingsboard.server.common.data.id.CustomerId; @@ -39,10 +39,10 @@ import org.thingsboard.server.common.data.id.CustomerId;
39 import org.thingsboard.server.common.data.id.EntityId; 39 import org.thingsboard.server.common.data.id.EntityId;
40 import org.thingsboard.server.common.data.id.TenantId; 40 import org.thingsboard.server.common.data.id.TenantId;
41 import org.thingsboard.server.common.data.page.PageData; 41 import org.thingsboard.server.common.data.page.PageData;
42 -import org.thingsboard.server.common.data.page.TimePageLink;  
43 import org.thingsboard.server.common.data.query.AlarmData; 42 import org.thingsboard.server.common.data.query.AlarmData;
44 import org.thingsboard.server.common.data.query.AlarmDataPageLink; 43 import org.thingsboard.server.common.data.query.AlarmDataPageLink;
45 import org.thingsboard.server.common.data.query.AlarmDataQuery; 44 import org.thingsboard.server.common.data.query.AlarmDataQuery;
  45 +import org.thingsboard.server.common.data.query.DeviceTypeFilter;
46 import org.thingsboard.server.common.data.relation.EntityRelation; 46 import org.thingsboard.server.common.data.relation.EntityRelation;
47 import org.thingsboard.server.common.data.relation.EntityRelationsQuery; 47 import org.thingsboard.server.common.data.relation.EntityRelationsQuery;
48 import org.thingsboard.server.common.data.relation.EntitySearchDirection; 48 import org.thingsboard.server.common.data.relation.EntitySearchDirection;
@@ -60,7 +60,6 @@ import javax.annotation.PreDestroy; @@ -60,7 +60,6 @@ import javax.annotation.PreDestroy;
60 import java.util.ArrayList; 60 import java.util.ArrayList;
61 import java.util.Collection; 61 import java.util.Collection;
62 import java.util.Collections; 62 import java.util.Collections;
63 -import java.util.Comparator;  
64 import java.util.LinkedHashSet; 63 import java.util.LinkedHashSet;
65 import java.util.List; 64 import java.util.List;
66 import java.util.Set; 65 import java.util.Set;
@@ -316,37 +315,16 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ @@ -316,37 +315,16 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
316 @Override 315 @Override
317 public AlarmSeverity findHighestAlarmSeverity(TenantId tenantId, EntityId entityId, AlarmSearchStatus alarmSearchStatus, 316 public AlarmSeverity findHighestAlarmSeverity(TenantId tenantId, EntityId entityId, AlarmSearchStatus alarmSearchStatus,
318 AlarmStatus alarmStatus) { 317 AlarmStatus alarmStatus) {
319 - TimePageLink nextPageLink = new TimePageLink(100);  
320 - boolean hasNext = true;  
321 - AlarmSeverity highestSeverity = null;  
322 - AlarmQuery query;  
323 - while (hasNext && AlarmSeverity.CRITICAL != highestSeverity) {  
324 - query = new AlarmQuery(entityId, nextPageLink, alarmSearchStatus, alarmStatus, false, null);  
325 - PageData<AlarmInfo> alarms = alarmDao.findAlarms(tenantId, query);  
326 - if (alarms.hasNext()) {  
327 - nextPageLink = nextPageLink.nextPageLink();  
328 - }  
329 - AlarmSeverity severity = detectHighestSeverity(alarms.getData());  
330 - if (severity == null) {  
331 - continue;  
332 - }  
333 - if (severity == AlarmSeverity.CRITICAL || highestSeverity == null) {  
334 - highestSeverity = severity;  
335 - } else {  
336 - highestSeverity = highestSeverity.compareTo(severity) < 0 ? highestSeverity : severity;  
337 - } 318 + Set<AlarmStatus> statusList = null;
  319 + if (alarmSearchStatus != null) {
  320 + statusList = alarmSearchStatus.getStatuses();
  321 + } else if (alarmStatus != null) {
  322 + statusList = Collections.singleton(alarmStatus);
338 } 323 }
339 - return highestSeverity;  
340 - }  
341 324
342 - private AlarmSeverity detectHighestSeverity(List<AlarmInfo> alarms) {  
343 - if (!alarms.isEmpty()) {  
344 - List<AlarmInfo> sorted = new ArrayList(alarms);  
345 - sorted.sort(Comparator.comparing(Alarm::getSeverity));  
346 - return sorted.get(0).getSeverity();  
347 - } else {  
348 - return null;  
349 - } 325 + Set<AlarmSeverity> alarmSeverities = alarmDao.findAlarmSeverities(tenantId, entityId, statusList);
  326 +
  327 + return alarmSeverities.stream().min(AlarmSeverity::compareTo).orElse(null);
350 } 328 }
351 329
352 private void deleteRelation(TenantId tenantId, EntityRelation alarmRelation) { 330 private void deleteRelation(TenantId tenantId, EntityRelation alarmRelation) {
@@ -20,6 +20,7 @@ import org.springframework.data.domain.Pageable; @@ -20,6 +20,7 @@ import org.springframework.data.domain.Pageable;
20 import org.springframework.data.jpa.repository.Query; 20 import org.springframework.data.jpa.repository.Query;
21 import org.springframework.data.repository.CrudRepository; 21 import org.springframework.data.repository.CrudRepository;
22 import org.springframework.data.repository.query.Param; 22 import org.springframework.data.repository.query.Param;
  23 +import org.thingsboard.server.common.data.alarm.AlarmSeverity;
23 import org.thingsboard.server.common.data.alarm.AlarmStatus; 24 import org.thingsboard.server.common.data.alarm.AlarmStatus;
24 import org.thingsboard.server.dao.model.sql.AlarmEntity; 25 import org.thingsboard.server.dao.model.sql.AlarmEntity;
25 import org.thingsboard.server.dao.model.sql.AlarmInfoEntity; 26 import org.thingsboard.server.dao.model.sql.AlarmInfoEntity;
@@ -75,4 +76,12 @@ public interface AlarmRepository extends CrudRepository<AlarmEntity, UUID> { @@ -75,4 +76,12 @@ public interface AlarmRepository extends CrudRepository<AlarmEntity, UUID> {
75 @Param("searchText") String searchText, 76 @Param("searchText") String searchText,
76 Pageable pageable); 77 Pageable pageable);
77 78
  79 + @Query("SELECT alarm.severity FROM AlarmEntity alarm" +
  80 + " WHERE alarm.tenantId = :tenantId" +
  81 + " AND alarm.originatorId = :entityId" +
  82 + " AND ((:status) IS NULL OR alarm.status in (:status))")
  83 + Set<AlarmSeverity> findAlarmSeverities(@Param("tenantId") UUID tenantId,
  84 + @Param("entityId") UUID entityId,
  85 + @Param("status") Set<AlarmStatus> status);
  86 +
78 } 87 }
@@ -24,6 +24,7 @@ import org.springframework.stereotype.Component; @@ -24,6 +24,7 @@ import org.springframework.stereotype.Component;
24 import org.thingsboard.server.common.data.alarm.Alarm; 24 import org.thingsboard.server.common.data.alarm.Alarm;
25 import org.thingsboard.server.common.data.alarm.AlarmInfo; 25 import org.thingsboard.server.common.data.alarm.AlarmInfo;
26 import org.thingsboard.server.common.data.alarm.AlarmQuery; 26 import org.thingsboard.server.common.data.alarm.AlarmQuery;
  27 +import org.thingsboard.server.common.data.alarm.AlarmSeverity;
27 import org.thingsboard.server.common.data.alarm.AlarmStatus; 28 import org.thingsboard.server.common.data.alarm.AlarmStatus;
28 import org.thingsboard.server.common.data.id.CustomerId; 29 import org.thingsboard.server.common.data.id.CustomerId;
29 import org.thingsboard.server.common.data.id.EntityId; 30 import org.thingsboard.server.common.data.id.EntityId;
@@ -120,4 +121,9 @@ public class JpaAlarmDao extends JpaAbstractDao<AlarmEntity, Alarm> implements A @@ -120,4 +121,9 @@ public class JpaAlarmDao extends JpaAbstractDao<AlarmEntity, Alarm> implements A
120 public PageData<AlarmData> findAlarmDataByQueryForEntities(TenantId tenantId, CustomerId customerId, AlarmDataQuery query, Collection<EntityId> orderedEntityIds) { 121 public PageData<AlarmData> findAlarmDataByQueryForEntities(TenantId tenantId, CustomerId customerId, AlarmDataQuery query, Collection<EntityId> orderedEntityIds) {
121 return alarmQueryRepository.findAlarmDataByQueryForEntities(tenantId, customerId, query, orderedEntityIds); 122 return alarmQueryRepository.findAlarmDataByQueryForEntities(tenantId, customerId, query, orderedEntityIds);
122 } 123 }
  124 +
  125 + @Override
  126 + public Set<AlarmSeverity> findAlarmSeverities(TenantId tenantId, EntityId entityId, Set<AlarmStatus> status) {
  127 + return alarmRepository.findAlarmSeverities(tenantId.getId(), entityId.getId(), status);
  128 + }
123 } 129 }
@@ -355,6 +355,62 @@ public abstract class BaseAlarmServiceTest extends AbstractServiceTest { @@ -355,6 +355,62 @@ public abstract class BaseAlarmServiceTest extends AbstractServiceTest {
355 } 355 }
356 356
357 @Test 357 @Test
  358 + public void testFindHighestAlarmSeverity() throws ExecutionException, InterruptedException {
  359 + Customer customer = new Customer();
  360 + customer.setTitle("TestCustomer");
  361 + customer.setTenantId(tenantId);
  362 + customer = customerService.saveCustomer(customer);
  363 +
  364 + Device customerDevice = new Device();
  365 + customerDevice.setName("TestCustomerDevice");
  366 + customerDevice.setType("default");
  367 + customerDevice.setTenantId(tenantId);
  368 + customerDevice.setCustomerId(customer.getId());
  369 + customerDevice = deviceService.saveDevice(customerDevice);
  370 +
  371 + // no one alarms was created
  372 + Assert.assertNull(alarmService.findHighestAlarmSeverity(tenantId, customerDevice.getId(), null, null));
  373 +
  374 + Alarm alarm1 = Alarm.builder()
  375 + .tenantId(tenantId)
  376 + .originator(customerDevice.getId())
  377 + .type(TEST_ALARM)
  378 + .severity(AlarmSeverity.MAJOR)
  379 + .status(AlarmStatus.ACTIVE_UNACK)
  380 + .startTs(System.currentTimeMillis())
  381 + .build();
  382 + alarm1 = alarmService.createOrUpdateAlarm(alarm1).getAlarm();
  383 + alarmService.clearAlarm(tenantId, alarm1.getId(), null, System.currentTimeMillis()).get();
  384 +
  385 + Alarm alarm2 = Alarm.builder()
  386 + .tenantId(tenantId)
  387 + .originator(customerDevice.getId())
  388 + .type(TEST_ALARM)
  389 + .severity(AlarmSeverity.MINOR)
  390 + .status(AlarmStatus.ACTIVE_ACK)
  391 + .startTs(System.currentTimeMillis())
  392 + .build();
  393 + alarm2 = alarmService.createOrUpdateAlarm(alarm2).getAlarm();
  394 + alarmService.clearAlarm(tenantId, alarm2.getId(), null, System.currentTimeMillis()).get();
  395 +
  396 + Alarm alarm3 = Alarm.builder()
  397 + .tenantId(tenantId)
  398 + .originator(customerDevice.getId())
  399 + .type(TEST_ALARM)
  400 + .severity(AlarmSeverity.CRITICAL)
  401 + .status(AlarmStatus.ACTIVE_ACK)
  402 + .startTs(System.currentTimeMillis())
  403 + .build();
  404 + alarm3 = alarmService.createOrUpdateAlarm(alarm3).getAlarm();
  405 +
  406 + Assert.assertEquals(AlarmSeverity.MAJOR, alarmService.findHighestAlarmSeverity(tenantId, customerDevice.getId(), AlarmSearchStatus.UNACK, null));
  407 + Assert.assertEquals(AlarmSeverity.CRITICAL, alarmService.findHighestAlarmSeverity(tenantId, customerDevice.getId(), null, null));
  408 + Assert.assertEquals(AlarmSeverity.MAJOR, alarmService.findHighestAlarmSeverity(tenantId, customerDevice.getId(), null, AlarmStatus.CLEARED_UNACK));
  409 + Assert.assertEquals(AlarmSeverity.CRITICAL, alarmService.findHighestAlarmSeverity(tenantId, customerDevice.getId(), AlarmSearchStatus.ACTIVE, null));
  410 + Assert.assertEquals(AlarmSeverity.MINOR, alarmService.findHighestAlarmSeverity(tenantId, customerDevice.getId(), null, AlarmStatus.CLEARED_ACK));
  411 + }
  412 +
  413 + @Test
358 public void testFindAlarmUsingAlarmDataQuery() throws ExecutionException, InterruptedException { 414 public void testFindAlarmUsingAlarmDataQuery() throws ExecutionException, InterruptedException {
359 AssetId parentId = new AssetId(Uuids.timeBased()); 415 AssetId parentId = new AssetId(Uuids.timeBased());
360 AssetId parentId2 = new AssetId(Uuids.timeBased()); 416 AssetId parentId2 = new AssetId(Uuids.timeBased());