Browse Source

CF: expressions usage refactoring

pull/14193/head
VIacheslavKlimov 12 months ago
parent
commit
d16ee53bcd
  1. 27
      application/src/main/java/org/thingsboard/server/service/cf/ctx/state/CalculatedFieldCtx.java
  2. 15
      application/src/main/java/org/thingsboard/server/service/cf/ctx/state/ScriptCalculatedFieldState.java
  3. 32
      application/src/main/java/org/thingsboard/server/service/cf/ctx/state/SimpleCalculatedFieldState.java

27
application/src/main/java/org/thingsboard/server/service/cf/ctx/state/CalculatedFieldCtx.java

@ -176,13 +176,8 @@ public class CalculatedFieldCtx {
public void init() {
switch (cfType) {
case SCRIPT -> {
try {
initTbelExpression(expression);
initialized = true;
} catch (Exception e) {
initialized = false;
throw new RuntimeException("Failed to init calculated field ctx. Invalid expression syntax.", e);
}
initTbelExpression(expression);
initialized = true;
}
case GEOFENCING -> initialized = true;
case SIMPLE -> {
@ -205,8 +200,7 @@ public class CalculatedFieldCtx {
}
}
public double evaluateSimpleExpression(String expressionStr, CalculatedFieldState state) {
Expression expression = simpleExpressions.get(expressionStr).get();
public double evaluateSimpleExpression(Expression expression, CalculatedFieldState state) {
for (Map.Entry<String, ArgumentEntry> entry : state.getArguments().entrySet()) {
try {
BasicKvEntry kvEntry = ((SingleValueArgumentEntry) entry.getValue()).getKvEntryValue();
@ -225,6 +219,10 @@ public class CalculatedFieldCtx {
}
public ListenableFuture<Object> evaluateTbelExpression(String expression, CalculatedFieldState state) {
return evaluateTbelExpression(tbelExpressions.get(expression), state);
}
public ListenableFuture<Object> evaluateTbelExpression(CalculatedFieldScriptEngine expression, CalculatedFieldState state) {
Map<String, TbelCfArg> arguments = new LinkedHashMap<>();
List<Object> args = new ArrayList<>(argNames.size() + 1);
args.add(new Object()); // first element is a ctx, but we will set it later;
@ -239,7 +237,7 @@ public class CalculatedFieldCtx {
}
args.set(0, new TbelCfCtx(arguments, state.getLatestTimestamp()));
return tbelExpressions.get(expression).executeScriptAsync(args.toArray());
return expression.executeScriptAsync(args.toArray());
}
public ScheduledFuture<?> scheduleReevaluation(long delayMs, TbActorRef actorCtx) {
@ -258,8 +256,13 @@ public class CalculatedFieldCtx {
} else if (tbelExpressions.containsKey(expression)) {
return;
}
CalculatedFieldScriptEngine engine = initEngine(tenantId, expression, tbelInvokeService);
tbelExpressions.put(expression, engine);
try {
CalculatedFieldScriptEngine engine = initEngine(tenantId, expression, tbelInvokeService);
tbelExpressions.put(expression, engine);
} catch (Exception e) {
initialized = false;
throw new RuntimeException("Failed to init calculated field ctx. Invalid expression syntax.", e);
}
}
private void initSimpleExpression(String expression) {

15
application/src/main/java/org/thingsboard/server/service/cf/ctx/state/ScriptCalculatedFieldState.java

@ -21,6 +21,7 @@ import com.google.common.util.concurrent.MoreExecutors;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.actors.TbActorRef;
import org.thingsboard.server.common.data.cf.CalculatedFieldType;
import org.thingsboard.server.common.data.cf.configuration.Output;
import org.thingsboard.server.common.data.id.EntityId;
@ -33,18 +34,21 @@ import java.util.Map;
@EqualsAndHashCode(callSuper = true)
public class ScriptCalculatedFieldState extends BaseCalculatedFieldState {
private CalculatedFieldScriptEngine tbelExpression;
public ScriptCalculatedFieldState(EntityId entityId) {
super(entityId);
}
@Override
public CalculatedFieldType getType() {
return CalculatedFieldType.SCRIPT;
public void setCtx(CalculatedFieldCtx ctx, TbActorRef actorCtx) {
super.setCtx(ctx, actorCtx);
this.tbelExpression = ctx.getTbelExpressions().get(ctx.getExpression());
}
@Override
public ListenableFuture<CalculatedFieldResult> performCalculation(Map<String, ArgumentEntry> updatedArgs, CalculatedFieldCtx ctx) {
ListenableFuture<Object> resultFuture = ctx.evaluateTbelExpression(ctx.getExpression(), this);
ListenableFuture<Object> resultFuture = ctx.evaluateTbelExpression(tbelExpression, this);
Output output = ctx.getOutput();
return Futures.transform(resultFuture,
result -> TelemetryCalculatedFieldResult.builder()
@ -56,4 +60,9 @@ public class ScriptCalculatedFieldState extends BaseCalculatedFieldState {
);
}
@Override
public CalculatedFieldType getType() {
return CalculatedFieldType.SCRIPT;
}
}

32
application/src/main/java/org/thingsboard/server/service/cf/ctx/state/SimpleCalculatedFieldState.java

@ -20,8 +20,10 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import lombok.EqualsAndHashCode;
import net.objecthunter.exp4j.Expression;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.script.api.tbel.TbUtils;
import org.thingsboard.server.actors.TbActorRef;
import org.thingsboard.server.common.data.cf.CalculatedFieldType;
import org.thingsboard.server.common.data.cf.configuration.Output;
import org.thingsboard.server.common.data.id.EntityId;
@ -33,26 +35,21 @@ import java.util.Map;
@EqualsAndHashCode(callSuper = true)
public class SimpleCalculatedFieldState extends BaseCalculatedFieldState {
private ThreadLocal<Expression> expression;
public SimpleCalculatedFieldState(EntityId entityId) {
super(entityId);
}
@Override
public CalculatedFieldType getType() {
return CalculatedFieldType.SIMPLE;
}
@Override
protected void validateNewEntry(String key, ArgumentEntry newEntry) {
if (newEntry instanceof TsRollingArgumentEntry) {
throw new IllegalArgumentException("Unsupported argument type detected for argument: " + key + ". " +
"Rolling argument entry is not supported for simple calculated fields.");
}
public void setCtx(CalculatedFieldCtx ctx, TbActorRef actorCtx) {
super.setCtx(ctx, actorCtx);
this.expression = ctx.getSimpleExpressions().get(ctx.getExpression());
}
@Override
public ListenableFuture<CalculatedFieldResult> performCalculation(Map<String, ArgumentEntry> updatedArgs, CalculatedFieldCtx ctx) {
double expressionResult = ctx.evaluateSimpleExpression(ctx.getExpression(), this);
double expressionResult = ctx.evaluateSimpleExpression(expression.get(), this);
Output output = ctx.getOutput();
Object result = formatResult(expressionResult, output.getDecimalsByDefault());
@ -96,4 +93,17 @@ public class SimpleCalculatedFieldState extends BaseCalculatedFieldState {
}
}
@Override
protected void validateNewEntry(String key, ArgumentEntry newEntry) {
if (newEntry instanceof TsRollingArgumentEntry) {
throw new IllegalArgumentException("Unsupported argument type detected for argument: " + key + ". " +
"Rolling argument entry is not supported for simple calculated fields.");
}
}
@Override
public CalculatedFieldType getType() {
return CalculatedFieldType.SIMPLE;
}
}

Loading…
Cancel
Save