Browse Source

simplified logic for readinessStatus

pull/14208/head
dshvaika 11 months ago
parent
commit
de514ff4d0
  1. 2
      application/src/main/java/org/thingsboard/server/actors/calculatedField/CalculatedFieldEntityMessageProcessor.java
  2. 26
      application/src/main/java/org/thingsboard/server/service/cf/ctx/state/BaseCalculatedFieldState.java
  3. 42
      application/src/main/java/org/thingsboard/server/service/cf/ctx/state/CalculatedFieldState.java
  4. 1
      application/src/main/java/org/thingsboard/server/service/cf/ctx/state/propagation/PropagationCalculatedFieldState.java
  5. 8
      application/src/test/java/org/thingsboard/server/service/cf/ctx/state/GeofencingCalculatedFieldStateTest.java
  6. 8
      application/src/test/java/org/thingsboard/server/service/cf/ctx/state/PropagationCalculatedFieldStateTest.java
  7. 7
      application/src/test/java/org/thingsboard/server/service/cf/ctx/state/ScriptCalculatedFieldStateTest.java
  8. 8
      application/src/test/java/org/thingsboard/server/service/cf/ctx/state/SimpleCalculatedFieldStateTest.java

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

@ -416,7 +416,7 @@ public class CalculatedFieldEntityMessageProcessor extends AbstractContextAwareM
} }
} else { } else {
if (DebugModeUtil.isDebugFailuresAvailable(ctx.getCalculatedField())) { if (DebugModeUtil.isDebugFailuresAvailable(ctx.getCalculatedField())) {
String errorMsg = ctx.isInitialized() ? state.getReadinessStatus().stringValue() : "Calculated field state is not initialized!"; String errorMsg = ctx.isInitialized() && state.getReadinessStatus() != null ? state.getReadinessStatus().stringValue() : "Calculated field state is not initialized!";
systemContext.persistCalculatedFieldDebugEvent(tenantId, ctx.getCfId(), entityId, state.getArguments(), tbMsgId, tbMsgType, null, errorMsg); systemContext.persistCalculatedFieldDebugEvent(tenantId, ctx.getCfId(), entityId, state.getArguments(), tbMsgId, tbMsgType, null, errorMsg);
} }
callback.onSuccess(); callback.onSuccess();

26
application/src/main/java/org/thingsboard/server/service/cf/ctx/state/BaseCalculatedFieldState.java

@ -26,11 +26,11 @@ import org.thingsboard.server.service.cf.ctx.CalculatedFieldEntityCtxId;
import org.thingsboard.server.utils.CalculatedFieldUtils; import org.thingsboard.server.utils.CalculatedFieldUtils;
import java.io.Closeable; import java.io.Closeable;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
@Getter @Getter
public abstract class BaseCalculatedFieldState implements CalculatedFieldState, Closeable { public abstract class BaseCalculatedFieldState implements CalculatedFieldState, Closeable {
@ -57,7 +57,6 @@ public abstract class BaseCalculatedFieldState implements CalculatedFieldState,
this.ctx = ctx; this.ctx = ctx;
this.actorCtx = actorCtx; this.actorCtx = actorCtx;
this.requiredArguments = ctx.getArgNames(); this.requiredArguments = ctx.getArgNames();
this.readinessStatus = ReadinessStatus.initialState(requiredArguments, arguments);
} }
@Override @Override
@ -91,12 +90,15 @@ public abstract class BaseCalculatedFieldState implements CalculatedFieldState,
} }
updatedArguments.put(key, newEntry); updatedArguments.put(key, newEntry);
updateLastUpdateTimestamp(newEntry); updateLastUpdateTimestamp(newEntry);
readinessStatus.onArgumentUpdate(key, newEntry);
} }
} }
return Objects.requireNonNullElse(updatedArguments, Collections.emptyMap()); if (updatedArguments != null) {
readinessStatus = checkReadiness(requiredArguments, arguments);
return updatedArguments;
}
return Collections.emptyMap();
} }
@Override @Override
@ -109,7 +111,7 @@ public abstract class BaseCalculatedFieldState implements CalculatedFieldState,
@Override @Override
public boolean isReady() { public boolean isReady() {
return readinessStatus.isReady(); return readinessStatus != null && readinessStatus.isReady();
} }
@Override @Override
@ -150,4 +152,18 @@ public abstract class BaseCalculatedFieldState implements CalculatedFieldState,
this.latestTimestamp = Math.max(this.latestTimestamp, newTs); this.latestTimestamp = Math.max(this.latestTimestamp, newTs);
} }
public ReadinessStatus checkReadiness(List<String> requiredArguments, Map<String, ArgumentEntry> currentArguments) {
List<String> emptyArguments = null;
for (String requiredArgumentKey : requiredArguments) {
ArgumentEntry argumentEntry = currentArguments.get(requiredArgumentKey);
if (argumentEntry == null || argumentEntry.isEmpty()) {
if (emptyArguments == null) {
emptyArguments = new ArrayList<>();
}
emptyArguments.add(requiredArgumentKey);
}
}
return new ReadinessStatus(emptyArguments);
}
} }

42
application/src/main/java/org/thingsboard/server/service/cf/ctx/state/CalculatedFieldState.java

@ -36,10 +36,8 @@ import org.thingsboard.server.service.cf.ctx.state.geofencing.GeofencingCalculat
import org.thingsboard.server.service.cf.ctx.state.propagation.PropagationCalculatedFieldState; import org.thingsboard.server.service.cf.ctx.state.propagation.PropagationCalculatedFieldState;
import java.io.Closeable; import java.io.Closeable;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import static org.thingsboard.server.utils.CalculatedFieldUtils.toSingleValueArgumentProto; import static org.thingsboard.server.utils.CalculatedFieldUtils.toSingleValueArgumentProto;
@ -103,52 +101,20 @@ public interface CalculatedFieldState extends Closeable {
@Data @Data
@AllArgsConstructor @AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_EMPTY) @JsonInclude(JsonInclude.Include.NON_NULL)
class ReadinessStatus { class ReadinessStatus {
private Set<String> missingArguments; private List<String> emptyArguments;
private Set<String> emptyArguments;
public static ReadinessStatus initialState(List<String> requiredArguments, Map<String, ArgumentEntry> arguments) {
if (arguments.isEmpty()) {
return new ReadinessStatus(new HashSet<>(requiredArguments), new HashSet<>());
}
Set<String> missingArguments = new HashSet<>(requiredArguments.size());
Set<String> emptyArguments = new HashSet<>(requiredArguments.size());
requiredArguments.forEach(requiredArgumentKey -> {
ArgumentEntry argumentEntry = arguments.get(requiredArgumentKey);
if (argumentEntry == null) {
missingArguments.add(requiredArgumentKey);
return;
}
if (argumentEntry.isEmpty()) {
emptyArguments.add(requiredArgumentKey);
}
});
return new ReadinessStatus(missingArguments, emptyArguments);
}
public void onArgumentUpdate(String key, ArgumentEntry newEntry) {
if (newEntry == null) {
missingArguments.add(key);
return;
}
missingArguments.remove(key);
if (newEntry.isEmpty()) {
emptyArguments.add(key);
} else {
emptyArguments.remove(key);
}
}
public boolean isReady() { public boolean isReady() {
return missingArguments.isEmpty() && emptyArguments.isEmpty(); return emptyArguments == null || emptyArguments.isEmpty();
} }
public String stringValue() { public String stringValue() {
return JacksonUtil.toString(this); return JacksonUtil.toString(this);
} }
} }
} }

1
application/src/main/java/org/thingsboard/server/service/cf/ctx/state/propagation/PropagationCalculatedFieldState.java

@ -50,7 +50,6 @@ public class PropagationCalculatedFieldState extends ScriptCalculatedFieldState
this.actorCtx = actorCtx; this.actorCtx = actorCtx;
this.requiredArguments = new ArrayList<>(ctx.getArgNames()); this.requiredArguments = new ArrayList<>(ctx.getArgNames());
requiredArguments.add(PROPAGATION_CONFIG_ARGUMENT); requiredArguments.add(PROPAGATION_CONFIG_ARGUMENT);
this.readinessStatus = ReadinessStatus.initialState(requiredArguments, arguments);
if (ctx.isApplyExpressionForResolvedArguments()) { if (ctx.isApplyExpressionForResolvedArguments()) {
this.tbelExpression = ctx.getTbelExpressions().get(ctx.getExpression()); this.tbelExpression = ctx.getTbelExpressions().get(ctx.getExpression());
} }

8
application/src/test/java/org/thingsboard/server/service/cf/ctx/state/GeofencingCalculatedFieldStateTest.java

@ -200,9 +200,7 @@ public class GeofencingCalculatedFieldStateTest {
@Test @Test
void testIsReadyWhenNotAllArgPresent() { void testIsReadyWhenNotAllArgPresent() {
assertThat(state.isReady()).isFalse(); assertThat(state.isReady()).isFalse();
assertThat(state.getReadinessStatus().getMissingArguments()) assertThat(state.getReadinessStatus()).isNull();
.containsExactlyInAnyOrderElementsOf(state.requiredArguments);
assertThat(state.getReadinessStatus().getEmptyArguments()).isEmpty();
} }
@Test @Test
@ -214,8 +212,7 @@ public class GeofencingCalculatedFieldStateTest {
"restrictedZones", geofencingRestrictedZoneArgEntry "restrictedZones", geofencingRestrictedZoneArgEntry
), ctx); ), ctx);
assertThat(state.isReady()).isTrue(); assertThat(state.isReady()).isTrue();
assertThat(state.getReadinessStatus().getMissingArguments()).isEmpty(); assertThat(state.getReadinessStatus().getEmptyArguments()).isNull();
assertThat(state.getReadinessStatus().getEmptyArguments()).isEmpty();
} }
@Test @Test
@ -227,7 +224,6 @@ public class GeofencingCalculatedFieldStateTest {
"restrictedZones", new GeofencingArgumentEntry() "restrictedZones", new GeofencingArgumentEntry()
), ctx); ), ctx);
assertThat(state.isReady()).isFalse(); assertThat(state.isReady()).isFalse();
assertThat(state.getReadinessStatus().getMissingArguments()).isEmpty();
assertThat(state.getReadinessStatus().getEmptyArguments()).contains("restrictedZones"); assertThat(state.getReadinessStatus().getEmptyArguments()).contains("restrictedZones");
} }

8
application/src/test/java/org/thingsboard/server/service/cf/ctx/state/PropagationCalculatedFieldStateTest.java

@ -131,7 +131,7 @@ public class PropagationCalculatedFieldStateTest {
initCtxAndState(false); initCtxAndState(false);
state.update(Map.of(TEMPERATURE_ARGUMENT_NAME, singleValueArgEntry), ctx); state.update(Map.of(TEMPERATURE_ARGUMENT_NAME, singleValueArgEntry), ctx);
assertThat(state.isReady()).isFalse(); assertThat(state.isReady()).isFalse();
assertThat(state.getReadinessStatus().getMissingArguments()).containsExactly(PROPAGATION_CONFIG_ARGUMENT); assertThat(state.getReadinessStatus().getEmptyArguments()).containsExactly(PROPAGATION_CONFIG_ARGUMENT);
} }
@Test @Test
@ -139,9 +139,8 @@ public class PropagationCalculatedFieldStateTest {
initCtxAndState(false); initCtxAndState(false);
state.update(Map.of(TEMPERATURE_ARGUMENT_NAME, singleValueArgEntry, state.update(Map.of(TEMPERATURE_ARGUMENT_NAME, singleValueArgEntry,
PROPAGATION_CONFIG_ARGUMENT, new PropagationArgumentEntry(Collections.emptyList())), ctx); PROPAGATION_CONFIG_ARGUMENT, new PropagationArgumentEntry(Collections.emptyList())), ctx);
assertThat(state.getReadinessStatus().getMissingArguments()).isEmpty();
assertThat(state.getReadinessStatus().getEmptyArguments()).containsExactly(PROPAGATION_CONFIG_ARGUMENT);
assertThat(state.isReady()).isFalse(); assertThat(state.isReady()).isFalse();
assertThat(state.getReadinessStatus().getEmptyArguments()).containsExactly(PROPAGATION_CONFIG_ARGUMENT);
} }
@Test @Test
@ -149,8 +148,7 @@ public class PropagationCalculatedFieldStateTest {
initCtxAndState(false); initCtxAndState(false);
state.update(Map.of(TEMPERATURE_ARGUMENT_NAME, singleValueArgEntry, PROPAGATION_CONFIG_ARGUMENT, propagationArgEntry), ctx); state.update(Map.of(TEMPERATURE_ARGUMENT_NAME, singleValueArgEntry, PROPAGATION_CONFIG_ARGUMENT, propagationArgEntry), ctx);
assertThat(state.isReady()).isTrue(); assertThat(state.isReady()).isTrue();
assertThat(state.getReadinessStatus().getMissingArguments()).isEmpty(); assertThat(state.getReadinessStatus().getEmptyArguments()).isNull();
assertThat(state.getReadinessStatus().getEmptyArguments()).isEmpty();
} }

7
application/src/test/java/org/thingsboard/server/service/cf/ctx/state/ScriptCalculatedFieldStateTest.java

@ -161,17 +161,14 @@ public class ScriptCalculatedFieldStateTest {
@Test @Test
void testIsReadyWhenNotAllArgPresent() { void testIsReadyWhenNotAllArgPresent() {
assertThat(state.isReady()).isFalse(); assertThat(state.isReady()).isFalse();
assertThat(state.getReadinessStatus().getMissingArguments()) assertThat(state.getReadinessStatus()).isNull();
.containsExactlyInAnyOrderElementsOf(state.requiredArguments);
assertThat(state.getReadinessStatus().getEmptyArguments()).isEmpty();
} }
@Test @Test
void testIsReadyWhenAllArgPresent() { void testIsReadyWhenAllArgPresent() {
state.update(Map.of("deviceTemperature", deviceTemperatureArgEntry, "assetHumidity", assetHumidityArgEntry), ctx); state.update(Map.of("deviceTemperature", deviceTemperatureArgEntry, "assetHumidity", assetHumidityArgEntry), ctx);
assertThat(state.isReady()).isTrue(); assertThat(state.isReady()).isTrue();
assertThat(state.getReadinessStatus().getMissingArguments()).isEmpty(); assertThat(state.getReadinessStatus().getEmptyArguments()).isNull();
assertThat(state.getReadinessStatus().getEmptyArguments()).isEmpty();
} }
@Test @Test

8
application/src/test/java/org/thingsboard/server/service/cf/ctx/state/SimpleCalculatedFieldStateTest.java

@ -204,9 +204,7 @@ public class SimpleCalculatedFieldStateTest {
@Test @Test
void testIsReadyWhenNotAllArgPresent() { void testIsReadyWhenNotAllArgPresent() {
assertThat(state.isReady()).isFalse(); assertThat(state.isReady()).isFalse();
assertThat(state.getReadinessStatus().getMissingArguments()) assertThat(state.getReadinessStatus()).isNull();
.containsExactlyInAnyOrderElementsOf(state.requiredArguments);
assertThat(state.getReadinessStatus().getEmptyArguments()).isEmpty();
} }
@Test @Test
@ -217,8 +215,7 @@ public class SimpleCalculatedFieldStateTest {
"key3", key3ArgEntry "key3", key3ArgEntry
), ctx); ), ctx);
assertThat(state.isReady()).isTrue(); assertThat(state.isReady()).isTrue();
assertThat(state.getReadinessStatus().getMissingArguments()).isEmpty(); assertThat(state.getReadinessStatus().getEmptyArguments()).isNull();
assertThat(state.getReadinessStatus().getEmptyArguments()).isEmpty();
} }
@Test @Test
@ -229,7 +226,6 @@ public class SimpleCalculatedFieldStateTest {
"key3", new SingleValueArgumentEntry() "key3", new SingleValueArgumentEntry()
), ctx); ), ctx);
assertThat(state.isReady()).isFalse(); assertThat(state.isReady()).isFalse();
assertThat(state.getReadinessStatus().getMissingArguments()).isEmpty();
assertThat(state.getReadinessStatus().getEmptyArguments()).containsExactly("key3"); assertThat(state.getReadinessStatus().getEmptyArguments()).containsExactly("key3");
} }

Loading…
Cancel
Save