Browse Source

added restriction for number of cfs/arguments/ts rolling values

pull/12266/head
IrynaMatveieva 2 years ago
parent
commit
481753b8f0
  1. 3
      application/src/main/java/org/thingsboard/server/service/cf/ctx/state/ArgumentEntry.java
  2. 9
      application/src/main/java/org/thingsboard/server/service/cf/ctx/state/BaseCalculatedFieldState.java
  3. 8
      application/src/main/java/org/thingsboard/server/service/cf/ctx/state/SingleValueArgumentEntry.java
  4. 37
      application/src/main/java/org/thingsboard/server/service/cf/ctx/state/TsRollingArgumentEntry.java
  5. 18
      application/src/main/java/org/thingsboard/server/service/entitiy/cf/DefaultTbCalculatedFieldService.java

3
application/src/main/java/org/thingsboard/server/service/cf/ctx/state/ArgumentEntry.java

@ -52,4 +52,7 @@ public interface ArgumentEntry {
collect(Collectors.toMap(TsKvEntry::getTs, TsKvEntry::getValue, (oldValue, newValue) -> newValue, TreeMap::new)));
}
@JsonIgnore
ArgumentEntry copy();
}

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

@ -42,25 +42,24 @@ public abstract class BaseCalculatedFieldState implements CalculatedFieldState {
if (existingArgumentEntry != null) {
if (existingArgumentEntry instanceof SingleValueArgumentEntry) {
if (existingArgumentEntry.hasUpdatedValue(argumentEntry)) {
arguments.put(key, argumentEntry);
arguments.put(key, argumentEntry.copy());
stateUpdated.set(true);
}
} else if (existingArgumentEntry instanceof TsRollingArgumentEntry existingTsRollingArgumentEntry) {
if (argumentEntry instanceof TsRollingArgumentEntry tsRollingArgumentEntry) {
if (existingArgumentEntry.hasUpdatedValue(argumentEntry)) {
existingTsRollingArgumentEntry.getTsRecords().putAll(tsRollingArgumentEntry.getTsRecords());
existingTsRollingArgumentEntry.addAllTsRecords(tsRollingArgumentEntry.getTsRecords());
stateUpdated.set(true);
}
} else if (argumentEntry instanceof SingleValueArgumentEntry singleValueArgumentEntry) {
if (existingArgumentEntry.hasUpdatedValue(argumentEntry)) {
existingTsRollingArgumentEntry.getTsRecords().put(singleValueArgumentEntry.getTs(), singleValueArgumentEntry.getValue());
existingTsRollingArgumentEntry.addTsRecord(singleValueArgumentEntry.getTs(), singleValueArgumentEntry.getValue());
stateUpdated.set(true);
}
}
}
} else {
arguments.put(key, argumentEntry);
arguments.put(key, argumentEntry.copy());
stateUpdated.set(true);
}
});

8
application/src/main/java/org/thingsboard/server/service/cf/ctx/state/SingleValueArgumentEntry.java

@ -15,6 +15,7 @@
*/
package org.thingsboard.server.service.cf.ctx.state;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.thingsboard.server.common.data.kv.AttributeKvEntry;
@ -23,6 +24,7 @@ import org.thingsboard.server.common.data.kv.TsKvEntry;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class SingleValueArgumentEntry implements ArgumentEntry {
private long ts;
@ -51,4 +53,10 @@ public class SingleValueArgumentEntry implements ArgumentEntry {
public boolean hasUpdatedValue(ArgumentEntry entry) {
return this.ts != ((SingleValueArgumentEntry) entry).getTs();
}
@Override
public ArgumentEntry copy() {
return new SingleValueArgumentEntry(this.ts, this.value);
}
}

37
application/src/main/java/org/thingsboard/server/service/cf/ctx/state/TsRollingArgumentEntry.java

@ -16,18 +16,26 @@
package org.thingsboard.server.service.cf.ctx.state;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.math.NumberUtils;
import java.util.Map;
import java.util.TreeMap;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Slf4j
public class TsRollingArgumentEntry implements ArgumentEntry {
private TreeMap<Long, Object> tsRecords;
private static final int MAX_ROLLING_ARGUMENT_ENTRY_SIZE = 1000;
private TreeMap<Long, Object> tsRecords = new TreeMap<>();
public TsRollingArgumentEntry(TreeMap<Long, Object> tsRecords) {
addAllTsRecords(tsRecords);
}
@Override
public ArgumentType getType() {
@ -44,4 +52,27 @@ public class TsRollingArgumentEntry implements ArgumentEntry {
public boolean hasUpdatedValue(ArgumentEntry entry) {
return !tsRecords.containsKey(((SingleValueArgumentEntry) entry).getTs());
}
@Override
public ArgumentEntry copy() {
return new TsRollingArgumentEntry(new TreeMap<>(tsRecords));
}
public void addTsRecord(Long key, Object value) {
if (NumberUtils.isParsable(value.toString())) {
tsRecords.put(key, value);
if (tsRecords.size() > MAX_ROLLING_ARGUMENT_ENTRY_SIZE) {
tsRecords.pollFirstEntry();
}
} else {
log.warn("Argument type 'TS_ROLLING' only supports numeric values.");
}
}
public void addAllTsRecords(Map<Long, Object> newRecords) {
for (Map.Entry<Long, Object> entry : newRecords.entrySet()) {
addTsRecord(entry.getKey(), entry.getValue());
}
}
}

18
application/src/main/java/org/thingsboard/server/service/entitiy/cf/DefaultTbCalculatedFieldService.java

@ -46,6 +46,9 @@ import static org.thingsboard.server.dao.service.Validator.validateEntityId;
@RequiredArgsConstructor
public class DefaultTbCalculatedFieldService extends AbstractTbEntityService implements TbCalculatedFieldService {
private static final int MAX_ARGUMENT_SIZE = 10;
private static final int MAX_CALCULATED_FIELD_NUMBER = 10;
private final CalculatedFieldService calculatedFieldService;
@Override
@ -53,7 +56,9 @@ public class DefaultTbCalculatedFieldService extends AbstractTbEntityService imp
ActionType actionType = calculatedField.getId() == null ? ActionType.ADDED : ActionType.UPDATED;
TenantId tenantId = calculatedField.getTenantId();
try {
checkCalculatedFieldNumber(tenantId, calculatedField.getEntityId());
checkEntityExistence(tenantId, calculatedField.getEntityId());
checkArgumentSize(calculatedField.getConfiguration());
checkReferencedEntities(calculatedField.getConfiguration(), user);
CalculatedField savedCalculatedField = checkNotNull(calculatedFieldService.save(calculatedField));
logEntityActionService.logEntityAction(tenantId, savedCalculatedField.getId(), savedCalculatedField, actionType, user);
@ -105,6 +110,19 @@ public class DefaultTbCalculatedFieldService extends AbstractTbEntityService imp
}
private void checkArgumentSize(CalculatedFieldConfiguration calculatedFieldConfig) {
if (calculatedFieldConfig.getArguments().size() > MAX_ARGUMENT_SIZE) {
throw new IllegalArgumentException("Too many arguments: " + calculatedFieldConfig.getArguments().size() + ". Max number of argument is " + MAX_ARGUMENT_SIZE);
}
}
private void checkCalculatedFieldNumber(TenantId tenantId, EntityId entityId) {
int numberOfCalculatedFieldsByEntityId = calculatedFieldService.findCalculatedFieldIdsByEntityId(tenantId, entityId).size();
if (numberOfCalculatedFieldsByEntityId >= MAX_CALCULATED_FIELD_NUMBER) {
throw new IllegalArgumentException("Max number of calculated fields for entity is " + MAX_CALCULATED_FIELD_NUMBER);
}
}
private <E extends HasId<I> & HasTenantId, I extends EntityId> E findEntity(TenantId tenantId, EntityId entityId) {
return switch (entityId.getEntityType()) {
case TENANT, CUSTOMER, ASSET, DEVICE -> (E) entityService.fetchEntity(tenantId, entityId).orElse(null);

Loading…
Cancel
Save