Browse Source

Merge pull request #15439 from zzzeebra/fix/alarm-duration-static-to-dynamic-reinit

Fixed alarm rule crash on duration source change
pull/15563/head
Viacheslav Klimov 6 months ago
committed by GitHub
parent
commit
300089ac71
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 2
      application/src/main/java/org/thingsboard/server/actors/calculatedField/CalculatedFieldEntityMessageProcessor.java
  2. 52
      application/src/test/java/org/thingsboard/server/cf/AlarmRulesTest.java

2
application/src/main/java/org/thingsboard/server/actors/calculatedField/CalculatedFieldEntityMessageProcessor.java

@ -485,7 +485,6 @@ public class CalculatedFieldEntityMessageProcessor extends AbstractContextAwareM
private void initState(CalculatedFieldState state, CalculatedFieldCtx ctx) {
state.setCtx(ctx, actorCtx);
state.init(false);
if (ctx.getCfType() == CalculatedFieldType.GEOFENCING && ctx.isCfHasRelationPathQuerySource()) {
GeofencingCalculatedFieldState geofencingState = (GeofencingCalculatedFieldState) state;
@ -494,6 +493,7 @@ public class CalculatedFieldEntityMessageProcessor extends AbstractContextAwareM
Map<String, ArgumentEntry> arguments = fetchArguments(ctx);
state.update(arguments, ctx);
state.init(false);
state.checkStateSize(new CalculatedFieldEntityCtxId(tenantId, ctx.getCfId(), entityId), ctx.getMaxStateSize());
states.put(ctx.getCfId(), state);

52
application/src/test/java/org/thingsboard/server/cf/AlarmRulesTest.java

@ -401,6 +401,58 @@ public class AlarmRulesTest extends AbstractControllerTest {
});
}
@Test
public void testChangeDurationConditionFromStaticToDynamic() throws Exception {
Argument temperatureArgument = new Argument();
temperatureArgument.setRefEntityKey(new ReferencedEntityKey("temperature", ArgumentType.TS_LATEST, null));
temperatureArgument.setDefaultValue("0");
Map<String, Argument> arguments = Map.of(
"temperature", temperatureArgument
);
long staticDurationMs = 5000L;
Map<AlarmSeverity, Condition> createRules = Map.of(
AlarmSeverity.CRITICAL, new Condition("return temperature >= 50;", null, staticDurationMs)
);
CalculatedField calculatedField = createAlarmCf(deviceId, "High Temperature Alarm",
arguments, createRules, null);
// post telemetry to trigger condition and wait for the static-phase eval to produce a debug event,
// which guarantees firstEventTs > 0 in AlarmRuleState before we trigger REINIT
postTelemetry(deviceId, "{\"temperature\":50}");
CalculatedFieldId cfId = calculatedField.getId();
await().atMost(TIMEOUT, TimeUnit.SECONDS)
.until(() -> getDebugEvents(cfId, 1),
events -> !events.isEmpty() && !events.get(0).getId().equals(latestEventId));
// update CF: add attribute argument and switch duration from static to dynamic
AlarmCalculatedFieldConfiguration configuration =
(AlarmCalculatedFieldConfiguration) calculatedField.getConfiguration();
Argument durationArgument = new Argument();
durationArgument.setRefEntityKey(new ReferencedEntityKey("durationThreshold",
ArgumentType.ATTRIBUTE, AttributeScope.SERVER_SCOPE));
durationArgument.setDefaultValue("-1");
configuration.getArguments().put("durationThreshold", durationArgument);
DurationAlarmCondition durationCondition = (DurationAlarmCondition)
configuration.getCreateRules().get(AlarmSeverity.CRITICAL).getCondition();
durationCondition.setValue(new AlarmConditionValue<>(null, "durationThreshold"));
calculatedField = saveCalculatedField(calculatedField);
long dynamicDurationMs = 3000L;
postAttributes(deviceId, AttributeScope.SERVER_SCOPE,
"{\"durationThreshold\":" + dynamicDurationMs + "}");
checkAlarmResult(calculatedField, alarmResult -> {
assertThat(alarmResult.isCreated()).isTrue();
assertThat(alarmResult.getAlarm().getSeverity()).isEqualTo(AlarmSeverity.CRITICAL);
assertThat(alarmResult.getAlarm().getStatus()).isEqualTo(AlarmStatus.ACTIVE_UNACK);
});
}
@Test
public void testCreateAlarm_currentOwnerArgument() throws Exception {
Argument temperatureArgument = new Argument();

Loading…
Cancel
Save