added restriction for number of cfs/arguments/ts rolling values
This commit is contained in:
parent
19f6f32326
commit
481753b8f0
@ -52,4 +52,7 @@ public interface ArgumentEntry {
|
||||
collect(Collectors.toMap(TsKvEntry::getTs, TsKvEntry::getValue, (oldValue, newValue) -> newValue, TreeMap::new)));
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
ArgumentEntry copy();
|
||||
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
});
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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…
x
Reference in New Issue
Block a user