Browse Source

added produceIntermediateResult flag to handle updates during the current interval and changed default value for min deduplication interval

pull/14474/head
IrynaMatveieva 10 months ago
parent
commit
b9952d7d27
  1. 8
      application/src/main/data/upgrade/basic/schema_update.sql
  2. 1
      application/src/main/java/org/thingsboard/server/controller/SystemInfoController.java
  3. 7
      application/src/main/java/org/thingsboard/server/controller/TenantProfileController.java
  4. 9
      application/src/main/java/org/thingsboard/server/service/cf/ctx/state/CalculatedFieldCtx.java
  5. 29
      application/src/main/java/org/thingsboard/server/service/cf/ctx/state/aggregation/single/EntityAggregationCalculatedFieldState.java
  6. 2
      application/src/main/resources/thingsboard.yml
  7. 1
      common/data/src/main/java/org/thingsboard/server/common/data/SystemParams.java
  8. 1
      common/data/src/main/java/org/thingsboard/server/common/data/cf/configuration/aggregation/single/EntityAggregationCalculatedFieldConfiguration.java
  9. 6
      common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/DefaultTenantProfileConfiguration.java
  10. 4
      dao/src/main/java/org/thingsboard/server/dao/service/validator/CalculatedFieldDataValidator.java
  11. 2
      ui-ngx/src/app/shared/models/tenant.model.ts

8
application/src/main/data/upgrade/basic/schema_update.sql

@ -24,8 +24,9 @@ SET profile_data = jsonb_set(
'minAllowedScheduledUpdateIntervalInSecForCF', 60, 'minAllowedScheduledUpdateIntervalInSecForCF', 60,
'maxRelationLevelPerCfArgument', 10, 'maxRelationLevelPerCfArgument', 10,
'maxRelatedEntitiesToReturnPerCfArgument', 100, 'maxRelatedEntitiesToReturnPerCfArgument', 100,
'minAllowedDeduplicationIntervalInSecForCF', 60, 'minAllowedDeduplicationIntervalInSecForCF', 10,
'minAllowedAggregationIntervalInSecForCF', 60 'minAllowedAggregationIntervalInSecForCF', 60,
'minAllowedRealtimeAggregationIntervalInSecForCF', 300
) )
|| ||
jsonb_strip_nulls(profile_data -> 'configuration') jsonb_strip_nulls(profile_data -> 'configuration')
@ -36,7 +37,8 @@ WHERE NOT (
'maxRelationLevelPerCfArgument', 'maxRelationLevelPerCfArgument',
'maxRelatedEntitiesToReturnPerCfArgument', 'maxRelatedEntitiesToReturnPerCfArgument',
'minAllowedDeduplicationIntervalInSecForCF', 'minAllowedDeduplicationIntervalInSecForCF',
'minAllowedAggregationIntervalInSecForCF' 'minAllowedAggregationIntervalInSecForCF',
'minAllowedRealtimeAggregationIntervalInSecForCF'
] ]
); );

1
application/src/main/java/org/thingsboard/server/controller/SystemInfoController.java

@ -166,6 +166,7 @@ public class SystemInfoController extends BaseController {
systemParams.setMaxRelationLevelPerCfArgument(tenantProfileConfiguration.getMaxRelationLevelPerCfArgument()); systemParams.setMaxRelationLevelPerCfArgument(tenantProfileConfiguration.getMaxRelationLevelPerCfArgument());
systemParams.setMinAllowedDeduplicationIntervalInSecForCF(tenantProfileConfiguration.getMinAllowedDeduplicationIntervalInSecForCF()); systemParams.setMinAllowedDeduplicationIntervalInSecForCF(tenantProfileConfiguration.getMinAllowedDeduplicationIntervalInSecForCF());
systemParams.setMinAllowedAggregationIntervalInSecForCF(tenantProfileConfiguration.getMinAllowedAggregationIntervalInSecForCF()); systemParams.setMinAllowedAggregationIntervalInSecForCF(tenantProfileConfiguration.getMinAllowedAggregationIntervalInSecForCF());
systemParams.setMinAllowedRealtimeAggregationIntervalInSecForCF(tenantProfileConfiguration.getMinAllowedRealtimeAggregationIntervalInSecForCF());
systemParams.setTrendzSettings(trendzSettingsService.findTrendzSettings(currentUser.getTenantId())); systemParams.setTrendzSettings(trendzSettingsService.findTrendzSettings(currentUser.getTenantId()));
} }
systemParams.setMobileQrEnabled(Optional.ofNullable(qrCodeSettingService.findQrCodeSettings(TenantId.SYS_TENANT_ID)) systemParams.setMobileQrEnabled(Optional.ofNullable(qrCodeSettingService.findQrCodeSettings(TenantId.SYS_TENANT_ID))

7
application/src/main/java/org/thingsboard/server/controller/TenantProfileController.java

@ -166,9 +166,10 @@ public class TenantProfileController extends BaseController {
" \"maxRelatedEntitiesToReturnPerCfArgument\": 100,\n" + " \"maxRelatedEntitiesToReturnPerCfArgument\": 100,\n" +
" \"maxDataPointsPerRollingArg\": 1000,\n" + " \"maxDataPointsPerRollingArg\": 1000,\n" +
" \"maxStateSizeInKBytes\": 32,\n" + " \"maxStateSizeInKBytes\": 32,\n" +
" \"maxSingleValueArgumentSizeInKBytes\": 2" + " \"maxSingleValueArgumentSizeInKBytes\": 2," +
" \"minAllowedDeduplicationIntervalInSecForCF\": 60" + " \"minAllowedDeduplicationIntervalInSecForCF\": 10," +
" \"minAllowedAggregationIntervalInSecForCF\": 60" + " \"minAllowedAggregationIntervalInSecForCF\": 60," +
" \"minAllowedRealtimeAggregationIntervalInSecForCF\": 300" +
" }\n" + " }\n" +
" },\n" + " },\n" +
" \"default\": false\n" + " \"default\": false\n" +

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

@ -115,6 +115,7 @@ public class CalculatedFieldCtx implements Closeable {
private long maxStateSize; private long maxStateSize;
private long maxSingleValueArgumentSize; private long maxSingleValueArgumentSize;
private long realtimeAggregationIntervalMillis;
private boolean relationQueryDynamicArguments; private boolean relationQueryDynamicArguments;
private List<String> mainEntityGeofencingArgumentNames; private List<String> mainEntityGeofencingArgumentNames;
@ -210,6 +211,7 @@ public class CalculatedFieldCtx implements Closeable {
this.maxStateSize = systemContext.getApiLimitService().getLimit(tenantId, DefaultTenantProfileConfiguration::getMaxStateSizeInKBytes) * 1024; this.maxStateSize = systemContext.getApiLimitService().getLimit(tenantId, DefaultTenantProfileConfiguration::getMaxStateSizeInKBytes) * 1024;
this.maxSingleValueArgumentSize = systemContext.getApiLimitService().getLimit(tenantId, DefaultTenantProfileConfiguration::getMaxSingleValueArgumentSizeInKBytes) * 1024; this.maxSingleValueArgumentSize = systemContext.getApiLimitService().getLimit(tenantId, DefaultTenantProfileConfiguration::getMaxSingleValueArgumentSizeInKBytes) * 1024;
this.realtimeAggregationIntervalMillis = TimeUnit.SECONDS.toMillis(systemContext.getApiLimitService().getLimit(tenantId, DefaultTenantProfileConfiguration::getMinAllowedRealtimeAggregationIntervalInSecForCF));
} }
public boolean requiresScheduledReevaluation() { public boolean requiresScheduledReevaluation() {
@ -223,6 +225,12 @@ public class CalculatedFieldCtx implements Closeable {
lastReevaluationTs = now; lastReevaluationTs = now;
return true; return true;
} }
if (entityAggregationConfig.isProduceIntermediateResult()) {
if (now - lastReevaluationTs >= realtimeAggregationIntervalMillis) {
lastReevaluationTs = now;
return true;
}
}
ZonedDateTime lastReevaluationTime = TimeUtils.toZonedDateTime(lastReevaluationTs, entityAggregationConfig.getInterval().getZoneId()); ZonedDateTime lastReevaluationTime = TimeUtils.toZonedDateTime(lastReevaluationTs, entityAggregationConfig.getInterval().getZoneId());
long previousIntervalEndTs = entityAggregationConfig.getInterval().getDateTimeIntervalEndTs(lastReevaluationTime); long previousIntervalEndTs = entityAggregationConfig.getInterval().getDateTimeIntervalEndTs(lastReevaluationTime);
if (now >= previousIntervalEndTs) { if (now >= previousIntervalEndTs) {
@ -291,6 +299,7 @@ public class CalculatedFieldCtx implements Closeable {
public void updateTenantProfileProperties() { public void updateTenantProfileProperties() {
this.maxStateSize = systemContext.getApiLimitService().getLimit(tenantId, DefaultTenantProfileConfiguration::getMaxStateSizeInKBytes) * 1024; this.maxStateSize = systemContext.getApiLimitService().getLimit(tenantId, DefaultTenantProfileConfiguration::getMaxStateSizeInKBytes) * 1024;
this.maxSingleValueArgumentSize = systemContext.getApiLimitService().getLimit(tenantId, DefaultTenantProfileConfiguration::getMaxSingleValueArgumentSizeInKBytes) * 1024; this.maxSingleValueArgumentSize = systemContext.getApiLimitService().getLimit(tenantId, DefaultTenantProfileConfiguration::getMaxSingleValueArgumentSizeInKBytes) * 1024;
this.realtimeAggregationIntervalMillis = TimeUnit.SECONDS.toMillis(systemContext.getApiLimitService().getLimit(tenantId, DefaultTenantProfileConfiguration::getMinAllowedRealtimeAggregationIntervalInSecForCF));
} }
public double evaluateSimpleExpression(Expression expression, CalculatedFieldState state) { public double evaluateSimpleExpression(Expression expression, CalculatedFieldState state) {

29
application/src/main/java/org/thingsboard/server/service/cf/ctx/state/aggregation/single/EntityAggregationCalculatedFieldState.java

@ -63,6 +63,8 @@ public class EntityAggregationCalculatedFieldState extends BaseCalculatedFieldSt
private long checkInterval; private long checkInterval;
private Map<String, AggMetric> metrics; private Map<String, AggMetric> metrics;
private boolean produceIntermediateResult;
private EntityAggregationDebugArgumentsTracker debugTracker; private EntityAggregationDebugArgumentsTracker debugTracker;
private CalculatedFieldProcessingService cfProcessingService; private CalculatedFieldProcessingService cfProcessingService;
@ -81,6 +83,7 @@ public class EntityAggregationCalculatedFieldState extends BaseCalculatedFieldSt
checkInterval = TimeUnit.SECONDS.toMillis(ctx.getSystemContext().getCfCheckInterval()); checkInterval = TimeUnit.SECONDS.toMillis(ctx.getSystemContext().getCfCheckInterval());
interval = configuration.getInterval(); interval = configuration.getInterval();
metrics = configuration.getMetrics(); metrics = configuration.getMetrics();
produceIntermediateResult = configuration.isProduceIntermediateResult();
} }
@Override @Override
@ -113,7 +116,7 @@ public class EntityAggregationCalculatedFieldState extends BaseCalculatedFieldSt
Map<AggIntervalEntry, Map<String, ArgumentEntry>> results = new HashMap<>(); Map<AggIntervalEntry, Map<String, ArgumentEntry>> results = new HashMap<>();
List<AggIntervalEntry> expiredIntervals = new ArrayList<>(); List<AggIntervalEntry> expiredIntervals = new ArrayList<>();
getIntervals().forEach((intervalEntry, argIntervalStatuses) -> { getIntervals().forEach((intervalEntry, argIntervalStatuses) -> {
processInterval(now, intervalEntry, argIntervalStatuses, expiredIntervals, results); processInterval(now, ctx, intervalEntry, argIntervalStatuses, expiredIntervals, results);
}); });
removeExpiredIntervals(expiredIntervals); removeExpiredIntervals(expiredIntervals);
@ -193,6 +196,7 @@ public class EntityAggregationCalculatedFieldState extends BaseCalculatedFieldSt
} }
private void processInterval(long now, private void processInterval(long now,
CalculatedFieldCtx ctx,
AggIntervalEntry intervalEntry, AggIntervalEntry intervalEntry,
Map<String, AggIntervalEntryStatus> args, Map<String, AggIntervalEntryStatus> args,
List<AggIntervalEntry> expiredIntervals, List<AggIntervalEntry> expiredIntervals,
@ -208,6 +212,10 @@ public class EntityAggregationCalculatedFieldState extends BaseCalculatedFieldSt
if (watermarkDuration == 0) { if (watermarkDuration == 0) {
expiredIntervals.add(intervalEntry); expiredIntervals.add(intervalEntry);
} }
} else if (now - startTs < intervalEntry.getIntervalDuration()) {
if (produceIntermediateResult) {
handleCurrentInterval(ctx, intervalEntry, args, results);
}
} }
} }
@ -242,6 +250,25 @@ public class EntityAggregationCalculatedFieldState extends BaseCalculatedFieldSt
}); });
} }
private void handleCurrentInterval(CalculatedFieldCtx ctx,
AggIntervalEntry intervalEntry,
Map<String, AggIntervalEntryStatus> args,
Map<AggIntervalEntry, Map<String, ArgumentEntry>> results) {
long realtimeAggregationInterval = ctx.getRealtimeAggregationIntervalMillis();
args.forEach((argName, argEntryIntervalStatus) -> {
if (argEntryIntervalStatus.intervalPassed(realtimeAggregationInterval)) {
if (argEntryIntervalStatus.argsUpdated()) {
argEntryIntervalStatus.setLastMetricsEvalTs(System.currentTimeMillis());
argEntryIntervalStatus.setLastArgsRefreshTs(-1);
processArgument(intervalEntry, argName, false, results);
} else if (argEntryIntervalStatus.getLastMetricsEvalTs() == -1) {// TODO: should we return default value when the interval has not ended
argEntryIntervalStatus.setLastMetricsEvalTs(System.currentTimeMillis());
processArgument(intervalEntry, argName, true, results);
}
}
});
}
private void processArgument(AggIntervalEntry intervalEntry, private void processArgument(AggIntervalEntry intervalEntry,
String argName, String argName,
boolean useDefault, boolean useDefault,

2
application/src/main/resources/thingsboard.yml

@ -541,7 +541,7 @@ actors:
# Interval in seconds to check calculated fields for re-evaluation interval. 1 minute by default. # Interval in seconds to check calculated fields for re-evaluation interval. 1 minute by default.
check_interval: "${ACTORS_CALCULATED_FIELDS_CHECK_INTERVAL_SEC:60}" check_interval: "${ACTORS_CALCULATED_FIELDS_CHECK_INTERVAL_SEC:60}"
alarms: alarms:
# Interval in seconds to re-evaluate Alarm rules that have a time schedule. 2 minutes by default. # Interval in seconds to re-evaluate Alarm rules that have a time schedule. 1 minute by default.
reevaluation_interval: "${ACTORS_ALARMS_REEVALUATION_INTERVAL_SEC:60}" reevaluation_interval: "${ACTORS_ALARMS_REEVALUATION_INTERVAL_SEC:60}"
debug: debug:

1
common/data/src/main/java/org/thingsboard/server/common/data/SystemParams.java

@ -42,5 +42,6 @@ public class SystemParams {
int maxRelationLevelPerCfArgument; int maxRelationLevelPerCfArgument;
long minAllowedDeduplicationIntervalInSecForCF; long minAllowedDeduplicationIntervalInSecForCF;
long minAllowedAggregationIntervalInSecForCF; long minAllowedAggregationIntervalInSecForCF;
long minAllowedRealtimeAggregationIntervalInSecForCF;
TrendzSettings trendzSettings; TrendzSettings trendzSettings;
} }

1
common/data/src/main/java/org/thingsboard/server/common/data/cf/configuration/aggregation/single/EntityAggregationCalculatedFieldConfiguration.java

@ -43,6 +43,7 @@ public class EntityAggregationCalculatedFieldConfiguration implements ArgumentsB
private AggInterval interval; private AggInterval interval;
@Valid @Valid
private Watermark watermark; private Watermark watermark;
private boolean produceIntermediateResult;
@Valid @Valid
@NotNull @NotNull
private Output output; private Output output;

6
common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/DefaultTenantProfileConfiguration.java

@ -190,10 +190,12 @@ public class DefaultTenantProfileConfiguration implements TenantProfileConfigura
private long maxStateSizeInKBytes = 32; private long maxStateSizeInKBytes = 32;
@Schema(example = "2") @Schema(example = "2")
private long maxSingleValueArgumentSizeInKBytes = 2; private long maxSingleValueArgumentSizeInKBytes = 2;
@Schema(example = "60") @Schema(example = "10")
private long minAllowedDeduplicationIntervalInSecForCF = 60; private long minAllowedDeduplicationIntervalInSecForCF = 10;
@Schema(example = "60") @Schema(example = "60")
private long minAllowedAggregationIntervalInSecForCF = 60; private long minAllowedAggregationIntervalInSecForCF = 60;
@Schema(example = "300")
private long minAllowedRealtimeAggregationIntervalInSecForCF = 300;
@Override @Override
public long getProfileThreshold(ApiUsageRecordKey key) { public long getProfileThreshold(ApiUsageRecordKey key) {

4
dao/src/main/java/org/thingsboard/server/dao/service/validator/CalculatedFieldDataValidator.java

@ -50,7 +50,7 @@ public class CalculatedFieldDataValidator extends DataValidator<CalculatedField>
validateCalculatedFieldConfiguration(calculatedField); validateCalculatedFieldConfiguration(calculatedField);
validateSchedulingConfiguration(tenantId, calculatedField); validateSchedulingConfiguration(tenantId, calculatedField);
validateRelationQuerySourceArguments(tenantId, calculatedField); validateRelationQuerySourceArguments(tenantId, calculatedField);
validateAggregationConfiguration(tenantId, calculatedField); validateRelatedAggregationConfiguration(tenantId, calculatedField);
validateEntityAggregationConfiguration(tenantId, calculatedField); validateEntityAggregationConfiguration(tenantId, calculatedField);
} }
@ -119,7 +119,7 @@ public class CalculatedFieldDataValidator extends DataValidator<CalculatedField>
wrapAsDataValidation(() -> relationQueryDynamicSourceConfiguration.validateMaxRelationLevel(argumentName, maxRelationLevel))); wrapAsDataValidation(() -> relationQueryDynamicSourceConfiguration.validateMaxRelationLevel(argumentName, maxRelationLevel)));
} }
private void validateAggregationConfiguration(TenantId tenantId, CalculatedField calculatedField) { private void validateRelatedAggregationConfiguration(TenantId tenantId, CalculatedField calculatedField) {
if (!(calculatedField.getConfiguration() instanceof RelatedEntitiesAggregationCalculatedFieldConfiguration aggConfiguration)) { if (!(calculatedField.getConfiguration() instanceof RelatedEntitiesAggregationCalculatedFieldConfiguration aggConfiguration)) {
return; return;
} }

2
ui-ngx/src/app/shared/models/tenant.model.ts

@ -176,7 +176,7 @@ export function createTenantProfileConfiguration(type: TenantProfileType): Tenan
maxArgumentsPerCF: 10, maxArgumentsPerCF: 10,
maxDataPointsPerRollingArg: 1000, maxDataPointsPerRollingArg: 1000,
maxRelationLevelPerCfArgument: 10, maxRelationLevelPerCfArgument: 10,
minAllowedDeduplicationIntervalInSecForCF: 60, minAllowedDeduplicationIntervalInSecForCF: 10,
minAllowedAggregationIntervalInSecForCF: 60, minAllowedAggregationIntervalInSecForCF: 60,
maxRelatedEntitiesToReturnPerCfArgument: 100, maxRelatedEntitiesToReturnPerCfArgument: 100,
minAllowedScheduledUpdateIntervalInSecForCF: 0, minAllowedScheduledUpdateIntervalInSecForCF: 0,

Loading…
Cancel
Save