|
|
|
@ -24,11 +24,14 @@ import org.thingsboard.server.actors.ActorSystemContext; |
|
|
|
import org.thingsboard.server.actors.TbActorCtx; |
|
|
|
import org.thingsboard.server.actors.shared.AbstractContextAwareMsgProcessor; |
|
|
|
import org.thingsboard.server.common.data.AttributeScope; |
|
|
|
import org.thingsboard.server.common.data.StringUtils; |
|
|
|
import org.thingsboard.server.common.data.cf.configuration.Argument; |
|
|
|
import org.thingsboard.server.common.data.cf.configuration.ArgumentType; |
|
|
|
import org.thingsboard.server.common.data.cf.configuration.ReferencedEntityKey; |
|
|
|
import org.thingsboard.server.common.data.id.CalculatedFieldId; |
|
|
|
import org.thingsboard.server.common.data.id.EntityId; |
|
|
|
import org.thingsboard.server.common.data.id.TenantId; |
|
|
|
import org.thingsboard.server.common.data.kv.StringDataEntry; |
|
|
|
import org.thingsboard.server.common.data.msg.TbMsgType; |
|
|
|
import org.thingsboard.server.common.msg.cf.CalculatedFieldPartitionChangeMsg; |
|
|
|
import org.thingsboard.server.common.msg.queue.TbCallback; |
|
|
|
@ -56,6 +59,7 @@ import java.util.Map; |
|
|
|
import java.util.Set; |
|
|
|
import java.util.UUID; |
|
|
|
import java.util.concurrent.TimeUnit; |
|
|
|
import java.util.stream.Collectors; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
@ -171,6 +175,10 @@ public class CalculatedFieldEntityMessageProcessor extends AbstractContextAwareM |
|
|
|
processArgumentValuesUpdate(ctx, cfIds, callback, mapToArguments(ctx, msg.getEntityId(), proto.getTsDataList()), toTbMsgId(proto), toTbMsgType(proto)); |
|
|
|
} else if (proto.getAttrDataCount() > 0) { |
|
|
|
processArgumentValuesUpdate(ctx, cfIds, callback, mapToArguments(ctx, msg.getEntityId(), proto.getScope(), proto.getAttrDataList()), toTbMsgId(proto), toTbMsgType(proto)); |
|
|
|
} else if (proto.getRemovedTsKeysCount() > 0) { |
|
|
|
processArgumentValuesUpdate(ctx, cfIds, callback, mapToArgumentsWithFetchedValue(ctx, proto.getRemovedTsKeysList()), toTbMsgId(proto), toTbMsgType(proto)); |
|
|
|
} else if (proto.getRemovedAttrKeysCount() > 0) { |
|
|
|
processArgumentValuesUpdate(ctx, cfIds, callback, mapToArgumentsWithDefaultValue(ctx, msg.getEntityId(), proto.getScope(), proto.getRemovedAttrKeysList()), toTbMsgId(proto), toTbMsgType(proto)); |
|
|
|
} else { |
|
|
|
callback.onSuccess(CALLBACKS_PER_CF); |
|
|
|
} |
|
|
|
@ -189,6 +197,10 @@ public class CalculatedFieldEntityMessageProcessor extends AbstractContextAwareM |
|
|
|
processTelemetry(ctx, proto, cfIdList, callback); |
|
|
|
} else if (proto.getAttrDataCount() > 0) { |
|
|
|
processAttributes(ctx, proto, cfIdList, callback); |
|
|
|
} else if (proto.getRemovedTsKeysCount() > 0) { |
|
|
|
processRemovedTelemetry(ctx, proto, cfIdList, callback); |
|
|
|
} else if (proto.getRemovedAttrKeysCount() > 0) { |
|
|
|
processRemovedAttributes(ctx, proto, cfIdList, callback); |
|
|
|
} else { |
|
|
|
callback.onSuccess(CALLBACKS_PER_CF); |
|
|
|
} |
|
|
|
@ -209,6 +221,14 @@ public class CalculatedFieldEntityMessageProcessor extends AbstractContextAwareM |
|
|
|
processArgumentValuesUpdate(ctx, cfIdList, callback, mapToArguments(ctx, proto.getScope(), proto.getAttrDataList()), toTbMsgId(proto), toTbMsgType(proto)); |
|
|
|
} |
|
|
|
|
|
|
|
private void processRemovedTelemetry(CalculatedFieldCtx ctx, CalculatedFieldTelemetryMsgProto proto, List<CalculatedFieldId> cfIdList, MultipleTbCallback callback) throws CalculatedFieldException { |
|
|
|
processArgumentValuesUpdate(ctx, cfIdList, callback, mapToArgumentsWithFetchedValue(ctx, proto.getRemovedTsKeysList()), toTbMsgId(proto), toTbMsgType(proto)); |
|
|
|
} |
|
|
|
|
|
|
|
private void processRemovedAttributes(CalculatedFieldCtx ctx, CalculatedFieldTelemetryMsgProto proto, List<CalculatedFieldId> cfIdList, MultipleTbCallback callback) throws CalculatedFieldException { |
|
|
|
processArgumentValuesUpdate(ctx, cfIdList, callback, mapToArgumentsWithDefaultValue(ctx, proto.getScope(), proto.getRemovedAttrKeysList()), toTbMsgId(proto), toTbMsgType(proto)); |
|
|
|
} |
|
|
|
|
|
|
|
private void processArgumentValuesUpdate(CalculatedFieldCtx ctx, List<CalculatedFieldId> cfIdList, MultipleTbCallback callback, |
|
|
|
Map<String, ArgumentEntry> newArgValues, UUID tbMsgId, TbMsgType tbMsgType) throws CalculatedFieldException { |
|
|
|
if (newArgValues.isEmpty()) { |
|
|
|
@ -310,7 +330,7 @@ public class CalculatedFieldEntityMessageProcessor extends AbstractContextAwareM |
|
|
|
return mapToArguments(argNames, data); |
|
|
|
} |
|
|
|
|
|
|
|
private static Map<String, ArgumentEntry> mapToArguments(Map<ReferencedEntityKey, String> argNames, List<TsKvProto> data) { |
|
|
|
private Map<String, ArgumentEntry> mapToArguments(Map<ReferencedEntityKey, String> argNames, List<TsKvProto> data) { |
|
|
|
if (argNames.isEmpty()) { |
|
|
|
return Collections.emptyMap(); |
|
|
|
} |
|
|
|
@ -342,7 +362,7 @@ public class CalculatedFieldEntityMessageProcessor extends AbstractContextAwareM |
|
|
|
return mapToArguments(argNames, scope, attrDataList); |
|
|
|
} |
|
|
|
|
|
|
|
private static Map<String, ArgumentEntry> mapToArguments(Map<ReferencedEntityKey, String> argNames, AttributeScopeProto scope, List<AttributeValueProto> attrDataList) { |
|
|
|
private Map<String, ArgumentEntry> mapToArguments(Map<ReferencedEntityKey, String> argNames, AttributeScopeProto scope, List<AttributeValueProto> attrDataList) { |
|
|
|
Map<String, ArgumentEntry> arguments = new HashMap<>(); |
|
|
|
for (AttributeValueProto item : attrDataList) { |
|
|
|
ReferencedEntityKey key = new ReferencedEntityKey(item.getKey(), ArgumentType.ATTRIBUTE, AttributeScope.valueOf(scope.name())); |
|
|
|
@ -354,6 +374,46 @@ public class CalculatedFieldEntityMessageProcessor extends AbstractContextAwareM |
|
|
|
return arguments; |
|
|
|
} |
|
|
|
|
|
|
|
private Map<String, ArgumentEntry> mapToArgumentsWithDefaultValue(CalculatedFieldCtx ctx, EntityId entityId, AttributeScopeProto scope, List<String> removedAttrKeys) { |
|
|
|
var argNames = ctx.getLinkedEntityArguments().get(entityId); |
|
|
|
if (argNames.isEmpty()) { |
|
|
|
return Collections.emptyMap(); |
|
|
|
} |
|
|
|
return mapToArgumentsWithDefaultValue(argNames, ctx.getArguments(), scope, removedAttrKeys); |
|
|
|
} |
|
|
|
|
|
|
|
private Map<String, ArgumentEntry> mapToArgumentsWithDefaultValue(CalculatedFieldCtx ctx, AttributeScopeProto scope, List<String> removedAttrKeys) { |
|
|
|
return mapToArgumentsWithDefaultValue(ctx.getMainEntityArguments(), ctx.getArguments(), scope, removedAttrKeys); |
|
|
|
} |
|
|
|
|
|
|
|
private Map<String, ArgumentEntry> mapToArgumentsWithDefaultValue(Map<ReferencedEntityKey, String> argNames, Map<String, Argument> configArguments, AttributeScopeProto scope, List<String> removedAttrKeys) { |
|
|
|
Map<String, ArgumentEntry> arguments = new HashMap<>(); |
|
|
|
for (String removedKey : removedAttrKeys) { |
|
|
|
ReferencedEntityKey key = new ReferencedEntityKey(removedKey, ArgumentType.ATTRIBUTE, AttributeScope.valueOf(scope.name())); |
|
|
|
String argName = argNames.get(key); |
|
|
|
if (argName != null) { |
|
|
|
Argument argument = configArguments.get(argName); |
|
|
|
String defaultValue = (argument != null) ? argument.getDefaultValue() : null; |
|
|
|
arguments.put(argName, StringUtils.isNotEmpty(defaultValue) |
|
|
|
? new SingleValueArgumentEntry(System.currentTimeMillis(), new StringDataEntry(removedKey, defaultValue), null) |
|
|
|
: new SingleValueArgumentEntry()); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
return arguments; |
|
|
|
} |
|
|
|
|
|
|
|
private Map<String, ArgumentEntry> mapToArgumentsWithFetchedValue(CalculatedFieldCtx ctx, List<String> removedTelemetryKeys) { |
|
|
|
Map<String, Argument> deletedArguments = ctx.getArguments().entrySet().stream() |
|
|
|
.filter(entry -> removedTelemetryKeys.contains(entry.getKey())) |
|
|
|
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); |
|
|
|
|
|
|
|
Map<String, ArgumentEntry> fetchedArgs = cfService.fetchArgsFromDb(tenantId, entityId, deletedArguments); |
|
|
|
|
|
|
|
fetchedArgs.values().forEach(arg -> arg.setForceResetPrevious(true)); |
|
|
|
return fetchedArgs; |
|
|
|
} |
|
|
|
|
|
|
|
private static List<CalculatedFieldId> getCalculatedFieldIds(CalculatedFieldTelemetryMsgProto proto) { |
|
|
|
List<CalculatedFieldId> cfIds = new LinkedList<>(); |
|
|
|
for (var cfId : proto.getPreviousCalculatedFieldsList()) { |
|
|
|
|