Commit 26e84f7b1834955648ab54acd4ea7bf15941282e
Committed by
Andrew Shvayka
1 parent
158436b1
refactoring & added alarmCanBeClearedWithAlarmOriginator test
Showing
2 changed files
with
57 additions
and
29 deletions
... | ... | @@ -57,38 +57,15 @@ public class TbClearAlarmNode extends TbAbstractAlarmNode<TbClearAlarmNodeConfig |
57 | 57 | @Override |
58 | 58 | protected ListenableFuture<AlarmResult> processAlarm(TbContext ctx, TbMsg msg) { |
59 | 59 | String alarmType = TbNodeUtils.processPattern(this.config.getAlarmType(), msg.getMetaData()); |
60 | + ListenableFuture<Alarm> alarmFuture; | |
60 | 61 | if (msg.getOriginator().getEntityType().equals(EntityType.ALARM)) { |
61 | - return clearAlarmByAlarmOriginator(ctx, msg); | |
62 | + alarmFuture = ctx.getAlarmService().findAlarmByIdAsync(ctx.getTenantId(), new AlarmId(msg.getOriginator().getId())); | |
62 | 63 | } else { |
63 | - ListenableFuture<Alarm> latest = ctx.getAlarmService().findLatestByOriginatorAndType(ctx.getTenantId(), msg.getOriginator(), alarmType); | |
64 | - return Futures.transformAsync(latest, a -> { | |
65 | - if (a != null && !a.getStatus().isCleared()) { | |
66 | - return clearAlarm(ctx, msg, a); | |
67 | - } | |
68 | - return Futures.immediateFuture(new AlarmResult(false, false, false, null)); | |
69 | - }, ctx.getDbCallbackExecutor()); | |
64 | + alarmFuture = ctx.getAlarmService().findLatestByOriginatorAndType(ctx.getTenantId(), msg.getOriginator(), alarmType); | |
70 | 65 | } |
71 | - } | |
72 | - | |
73 | - private ListenableFuture<AlarmResult> clearAlarmByAlarmOriginator(TbContext ctx, TbMsg msg) { | |
74 | - ListenableFuture<Alarm> alarmByIdAsync = ctx.getAlarmService().findAlarmByIdAsync(ctx.getTenantId(), new AlarmId(msg.getOriginator().getId())); | |
75 | - return Futures.transformAsync(alarmByIdAsync, alarm -> { | |
76 | - if (alarm != null && !alarm.getStatus().isCleared()) { | |
77 | - ctx.logJsEvalRequest(); | |
78 | - ListenableFuture<JsonNode> asyncDetails = buildAlarmDetails(ctx, msg, alarm.getDetails()); | |
79 | - return Futures.transformAsync(asyncDetails, details -> { | |
80 | - ctx.logJsEvalRequest(); | |
81 | - long clearTs = System.currentTimeMillis(); | |
82 | - ListenableFuture<Boolean> clearAlarmFuture = ctx.getAlarmService().clearAlarm(ctx.getTenantId(), alarm.getId(), details, clearTs); | |
83 | - return Futures.transformAsync(clearAlarmFuture, cleared -> { | |
84 | - if (cleared) { | |
85 | - alarm.setClearTs(clearTs); | |
86 | - alarm.setDetails(details); | |
87 | - } | |
88 | - alarm.setStatus(alarm.getStatus().isAck() ? AlarmStatus.CLEARED_ACK : AlarmStatus.CLEARED_UNACK); | |
89 | - return Futures.immediateFuture(new AlarmResult(false, false, true, alarm)); | |
90 | - }, ctx.getDbCallbackExecutor()); | |
91 | - }, ctx.getDbCallbackExecutor()); | |
66 | + return Futures.transformAsync(alarmFuture, a -> { | |
67 | + if (a != null && !a.getStatus().isCleared()) { | |
68 | + return clearAlarm(ctx, msg, a); | |
92 | 69 | } |
93 | 70 | return Futures.immediateFuture(new AlarmResult(false, false, false, null)); |
94 | 71 | }, ctx.getDbCallbackExecutor()); | ... | ... |
... | ... | @@ -35,6 +35,7 @@ import org.thingsboard.rule.engine.api.TbContext; |
35 | 35 | import org.thingsboard.rule.engine.api.TbNodeConfiguration; |
36 | 36 | import org.thingsboard.rule.engine.api.TbNodeException; |
37 | 37 | import org.thingsboard.server.common.data.alarm.Alarm; |
38 | +import org.thingsboard.server.common.data.id.AlarmId; | |
38 | 39 | import org.thingsboard.server.common.data.id.DeviceId; |
39 | 40 | import org.thingsboard.server.common.data.id.EntityId; |
40 | 41 | import org.thingsboard.server.common.data.id.RuleChainId; |
... | ... | @@ -95,6 +96,7 @@ public class TbAlarmNodeTest { |
95 | 96 | private ListeningExecutor dbExecutor; |
96 | 97 | |
97 | 98 | private EntityId originator = new DeviceId(UUIDs.timeBased()); |
99 | + private EntityId alarmOriginator = new AlarmId(UUIDs.timeBased()); | |
98 | 100 | private TenantId tenantId = new TenantId(UUIDs.timeBased()); |
99 | 101 | private TbMsgMetaData metaData = new TbMsgMetaData(); |
100 | 102 | private String rawJson = "{\"name\": \"Vit\", \"passed\": 5}"; |
... | ... | @@ -325,6 +327,55 @@ public class TbAlarmNodeTest { |
325 | 327 | assertEquals(expectedAlarm, actualAlarm); |
326 | 328 | } |
327 | 329 | |
330 | + @Test | |
331 | + public void alarmCanBeClearedWithAlarmOriginator() throws ScriptException, IOException { | |
332 | + initWithClearAlarmScript(); | |
333 | + metaData.putValue("key", "value"); | |
334 | + TbMsg msg = TbMsg.newMsg( "USER", alarmOriginator, metaData, TbMsgDataType.JSON, rawJson, ruleChainId, ruleNodeId); | |
335 | + | |
336 | + long oldEndDate = System.currentTimeMillis(); | |
337 | + AlarmId id = new AlarmId(alarmOriginator.getId()); | |
338 | + Alarm activeAlarm = Alarm.builder().type("SomeType").tenantId(tenantId).originator(originator).status(ACTIVE_UNACK).severity(WARNING).endTs(oldEndDate).build(); | |
339 | + activeAlarm.setId(id); | |
340 | + | |
341 | + when(detailsJs.executeJsonAsync(msg)).thenReturn(Futures.immediateFuture(null)); | |
342 | + when(alarmService.findAlarmByIdAsync(tenantId, id)).thenReturn(Futures.immediateFuture(activeAlarm)); | |
343 | + when(alarmService.clearAlarm(eq(activeAlarm.getTenantId()), eq(activeAlarm.getId()), org.mockito.Mockito.any(JsonNode.class), anyLong())).thenReturn(Futures.immediateFuture(true)); | |
344 | +// doAnswer((Answer<Alarm>) invocationOnMock -> (Alarm) (invocationOnMock.getArguments())[0]).when(alarmService).createOrUpdateAlarm(activeAlarm); | |
345 | + | |
346 | + node.onMsg(ctx, msg); | |
347 | + | |
348 | + verify(ctx).tellNext(any(), eq("Cleared")); | |
349 | + | |
350 | + ArgumentCaptor<TbMsg> msgCaptor = ArgumentCaptor.forClass(TbMsg.class); | |
351 | + ArgumentCaptor<String> typeCaptor = ArgumentCaptor.forClass(String.class); | |
352 | + ArgumentCaptor<EntityId> originatorCaptor = ArgumentCaptor.forClass(EntityId.class); | |
353 | + ArgumentCaptor<TbMsgMetaData> metadataCaptor = ArgumentCaptor.forClass(TbMsgMetaData.class); | |
354 | + ArgumentCaptor<String> dataCaptor = ArgumentCaptor.forClass(String.class); | |
355 | + verify(ctx).transformMsg(msgCaptor.capture(), typeCaptor.capture(), originatorCaptor.capture(), metadataCaptor.capture(), dataCaptor.capture()); | |
356 | + | |
357 | + assertEquals("ALARM", typeCaptor.getValue()); | |
358 | + assertEquals(alarmOriginator, originatorCaptor.getValue()); | |
359 | + assertEquals("value", metadataCaptor.getValue().getValue("key")); | |
360 | + assertEquals(Boolean.TRUE.toString(), metadataCaptor.getValue().getValue(IS_CLEARED_ALARM)); | |
361 | + assertNotSame(metaData, metadataCaptor.getValue()); | |
362 | + | |
363 | + Alarm actualAlarm = new ObjectMapper().readValue(dataCaptor.getValue().getBytes(), Alarm.class); | |
364 | + Alarm expectedAlarm = Alarm.builder() | |
365 | + .tenantId(tenantId) | |
366 | + .originator(originator) | |
367 | + .status(CLEARED_UNACK) | |
368 | + .severity(WARNING) | |
369 | + .propagate(false) | |
370 | + .type("SomeType") | |
371 | + .details(null) | |
372 | + .endTs(oldEndDate) | |
373 | + .build(); | |
374 | + expectedAlarm.setId(id); | |
375 | + | |
376 | + assertEquals(expectedAlarm, actualAlarm); | |
377 | + } | |
378 | + | |
328 | 379 | private void initWithCreateAlarmScript() { |
329 | 380 | try { |
330 | 381 | TbCreateAlarmNodeConfiguration config = new TbCreateAlarmNodeConfiguration(); | ... | ... |