Commit 581bb536f5e2281981815e338d48f05e41bb2592

Authored by AndrewVolostnykhThingsboard
1 parent 3c558a7d

findHighestAlarmStatus: fixed using Repository Query

@@ -28,26 +28,43 @@ import org.springframework.util.CollectionUtils; @@ -28,26 +28,43 @@ import org.springframework.util.CollectionUtils;
28 import org.springframework.util.StringUtils; 28 import org.springframework.util.StringUtils;
29 import org.thingsboard.common.util.ThingsBoardThreadFactory; 29 import org.thingsboard.common.util.ThingsBoardThreadFactory;
30 import org.thingsboard.server.common.data.Tenant; 30 import org.thingsboard.server.common.data.Tenant;
31 -import org.thingsboard.server.common.data.alarm.*; 31 +import org.thingsboard.server.common.data.alarm.Alarm;
  32 +import org.thingsboard.server.common.data.alarm.AlarmInfo;
  33 +import org.thingsboard.server.common.data.alarm.AlarmQuery;
  34 +import org.thingsboard.server.common.data.alarm.AlarmSearchStatus;
  35 +import org.thingsboard.server.common.data.alarm.AlarmSeverity;
  36 +import org.thingsboard.server.common.data.alarm.AlarmStatus;
32 import org.thingsboard.server.common.data.id.AlarmId; 37 import org.thingsboard.server.common.data.id.AlarmId;
33 import org.thingsboard.server.common.data.id.CustomerId; 38 import org.thingsboard.server.common.data.id.CustomerId;
34 import org.thingsboard.server.common.data.id.EntityId; 39 import org.thingsboard.server.common.data.id.EntityId;
35 import org.thingsboard.server.common.data.id.TenantId; 40 import org.thingsboard.server.common.data.id.TenantId;
36 import org.thingsboard.server.common.data.page.PageData; 41 import org.thingsboard.server.common.data.page.PageData;
37 -import org.thingsboard.server.common.data.page.TimePageLink;  
38 import org.thingsboard.server.common.data.query.AlarmData; 42 import org.thingsboard.server.common.data.query.AlarmData;
  43 +import org.thingsboard.server.common.data.query.AlarmDataPageLink;
39 import org.thingsboard.server.common.data.query.AlarmDataQuery; 44 import org.thingsboard.server.common.data.query.AlarmDataQuery;
40 -import org.thingsboard.server.common.data.relation.*; 45 +import org.thingsboard.server.common.data.query.DeviceTypeFilter;
  46 +import org.thingsboard.server.common.data.relation.EntityRelation;
  47 +import org.thingsboard.server.common.data.relation.EntityRelationsQuery;
  48 +import org.thingsboard.server.common.data.relation.EntitySearchDirection;
  49 +import org.thingsboard.server.common.data.relation.RelationTypeGroup;
  50 +import org.thingsboard.server.common.data.relation.RelationsSearchParameters;
41 import org.thingsboard.server.dao.entity.AbstractEntityService; 51 import org.thingsboard.server.dao.entity.AbstractEntityService;
42 import org.thingsboard.server.dao.entity.EntityService; 52 import org.thingsboard.server.dao.entity.EntityService;
43 import org.thingsboard.server.dao.exception.DataValidationException; 53 import org.thingsboard.server.dao.exception.DataValidationException;
44 import org.thingsboard.server.dao.service.DataValidator; 54 import org.thingsboard.server.dao.service.DataValidator;
  55 +import org.thingsboard.server.dao.sql.alarm.AlarmRepository;
45 import org.thingsboard.server.dao.tenant.TenantDao; 56 import org.thingsboard.server.dao.tenant.TenantDao;
46 57
47 import javax.annotation.Nullable; 58 import javax.annotation.Nullable;
48 import javax.annotation.PostConstruct; 59 import javax.annotation.PostConstruct;
49 import javax.annotation.PreDestroy; 60 import javax.annotation.PreDestroy;
50 -import java.util.*; 61 +import java.util.ArrayList;
  62 +import java.util.Collection;
  63 +import java.util.Collections;
  64 +import java.util.Comparator;
  65 +import java.util.LinkedHashSet;
  66 +import java.util.List;
  67 +import java.util.Set;
51 import java.util.concurrent.ExecutionException; 68 import java.util.concurrent.ExecutionException;
52 import java.util.concurrent.ExecutorService; 69 import java.util.concurrent.ExecutorService;
53 import java.util.concurrent.Executors; 70 import java.util.concurrent.Executors;
@@ -72,6 +89,9 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ @@ -72,6 +89,9 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
72 @Autowired 89 @Autowired
73 private EntityService entityService; 90 private EntityService entityService;
74 91
  92 + @Autowired
  93 + private AlarmRepository alarmRepository;
  94 +
75 protected ExecutorService readResultsProcessingExecutor; 95 protected ExecutorService readResultsProcessingExecutor;
76 96
77 @PostConstruct 97 @PostConstruct
@@ -300,35 +320,23 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ @@ -300,35 +320,23 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
300 @Override 320 @Override
301 public AlarmSeverity findHighestAlarmSeverity(TenantId tenantId, EntityId entityId, AlarmSearchStatus alarmSearchStatus, 321 public AlarmSeverity findHighestAlarmSeverity(TenantId tenantId, EntityId entityId, AlarmSearchStatus alarmSearchStatus,
302 AlarmStatus alarmStatus) { 322 AlarmStatus alarmStatus) {
303 - TimePageLink nextPageLink = new TimePageLink(100);  
304 - boolean hasNext = true;  
305 - AlarmSeverity highestSeverity = null;  
306 - AlarmQuery query;  
307 - while (hasNext && AlarmSeverity.CRITICAL != highestSeverity) {  
308 - query = new AlarmQuery(entityId, nextPageLink, alarmSearchStatus, alarmStatus, false, null);  
309 - PageData<AlarmInfo> alarms = alarmDao.findAlarms(tenantId, query);  
310 -  
311 - if (alarms.hasNext()) {  
312 - nextPageLink = nextPageLink.nextPageLink();  
313 - } else {  
314 - hasNext = false;  
315 - } 323 + Set<AlarmStatus> statusList = null;
  324 + if (alarmSearchStatus != null) {
  325 + statusList = alarmSearchStatus.getStatuses();
  326 + } else if (alarmStatus != null) {
  327 + statusList = Collections.singleton(alarmStatus);
  328 + }
316 329
317 - AlarmSeverity severity = detectHighestSeverity(alarms.getData());  
318 - if (severity == null) {  
319 - continue;  
320 - } 330 + List<AlarmSeverity> alarmSeverities = alarmRepository.findHighestAlarmSeverity(tenantId.getId(), entityId.getId(), statusList);
321 331
322 - if (severity == AlarmSeverity.CRITICAL || highestSeverity == null) {  
323 - highestSeverity = severity;  
324 - } else {  
325 - highestSeverity = highestSeverity.compareTo(severity) < 0 ? highestSeverity : severity;  
326 - }  
327 - }  
328 - return highestSeverity; 332 + return alarmSeverities.stream().min(AlarmSeverity::compareTo).orElse(null);
  333 + }
  334 +
  335 + private AlarmDataQuery toQuery(AlarmDataPageLink pageLink) {
  336 + return new AlarmDataQuery(new DeviceTypeFilter(), pageLink, null, null, null, Collections.EMPTY_LIST);
329 } 337 }
330 338
331 - private AlarmSeverity detectHighestSeverity(List<AlarmInfo> alarms) { 339 + private AlarmSeverity detectHighestSeverity(List<AlarmData> alarms) {
332 if (!alarms.isEmpty()) { 340 if (!alarms.isEmpty()) {
333 List<AlarmInfo> sorted = new ArrayList(alarms); 341 List<AlarmInfo> sorted = new ArrayList(alarms);
334 sorted.sort(Comparator.comparing(Alarm::getSeverity)); 342 sorted.sort(Comparator.comparing(Alarm::getSeverity));
@@ -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 + List<AlarmSeverity> findHighestAlarmSeverity(@Param("tenantId") UUID tenantId,
  84 + @Param("entityId") UUID entityId,
  85 + @Param("status") Set<AlarmStatus> status);
  86 +
78 } 87 }
@@ -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 + long ts = System.currentTimeMillis();
  372 + Alarm alarm1 = Alarm.builder()
  373 + .tenantId(tenantId)
  374 + .originator(customerDevice.getId())
  375 + .type(TEST_ALARM)
  376 + .severity(AlarmSeverity.MAJOR)
  377 + .status(AlarmStatus.ACTIVE_UNACK)
  378 + .startTs(ts)
  379 + .build();
  380 + alarm1 = alarmService.createOrUpdateAlarm(alarm1).getAlarm();
  381 + alarmService.clearAlarm(tenantId, alarm1.getId(), null, System.currentTimeMillis()).get();
  382 +
  383 + ts = System.currentTimeMillis();
  384 + Alarm alarm2 = Alarm.builder()
  385 + .tenantId(tenantId)
  386 + .originator(customerDevice.getId())
  387 + .type(TEST_ALARM)
  388 + .severity(AlarmSeverity.MINOR)
  389 + .status(AlarmStatus.ACTIVE_ACK)
  390 + .startTs(ts)
  391 + .build();
  392 + alarm2 = alarmService.createOrUpdateAlarm(alarm2).getAlarm();
  393 + alarmService.clearAlarm(tenantId, alarm2.getId(), null, System.currentTimeMillis()).get();
  394 +
  395 + ts = System.currentTimeMillis();
  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(ts)
  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());