|
|
|
@ -21,6 +21,7 @@ import com.google.common.util.concurrent.Futures; |
|
|
|
import com.google.common.util.concurrent.ListenableFuture; |
|
|
|
import com.google.common.util.concurrent.MoreExecutors; |
|
|
|
import lombok.extern.slf4j.Slf4j; |
|
|
|
import org.apache.commons.collections.CollectionUtils; |
|
|
|
import org.springframework.beans.factory.annotation.Autowired; |
|
|
|
import org.springframework.context.annotation.Profile; |
|
|
|
import org.springframework.stereotype.Service; |
|
|
|
@ -31,14 +32,12 @@ import org.thingsboard.rule.engine.profile.TbDeviceProfileNode; |
|
|
|
import org.thingsboard.rule.engine.profile.TbDeviceProfileNodeConfiguration; |
|
|
|
import org.thingsboard.server.common.data.EntityView; |
|
|
|
import org.thingsboard.server.common.data.Tenant; |
|
|
|
import org.thingsboard.server.common.data.TenantProfile; |
|
|
|
import org.thingsboard.server.common.data.alarm.Alarm; |
|
|
|
import org.thingsboard.server.common.data.alarm.AlarmInfo; |
|
|
|
import org.thingsboard.server.common.data.alarm.AlarmQuery; |
|
|
|
import org.thingsboard.server.common.data.alarm.AlarmSeverity; |
|
|
|
import org.thingsboard.server.common.data.id.EntityViewId; |
|
|
|
import org.thingsboard.server.common.data.id.RuleChainId; |
|
|
|
import org.thingsboard.server.common.data.id.RuleNodeId; |
|
|
|
import org.thingsboard.server.common.data.id.TenantId; |
|
|
|
import org.thingsboard.server.common.data.id.*; |
|
|
|
import org.thingsboard.server.common.data.kv.BaseReadTsKvQuery; |
|
|
|
import org.thingsboard.server.common.data.kv.ReadTsKvQuery; |
|
|
|
import org.thingsboard.server.common.data.kv.TsKvEntry; |
|
|
|
@ -47,12 +46,14 @@ import org.thingsboard.server.common.data.page.PageLink; |
|
|
|
import org.thingsboard.server.common.data.page.TimePageLink; |
|
|
|
import org.thingsboard.server.common.data.query.DynamicValue; |
|
|
|
import org.thingsboard.server.common.data.query.FilterPredicateValue; |
|
|
|
import org.thingsboard.server.common.data.queue.*; |
|
|
|
import org.thingsboard.server.common.data.relation.EntityRelation; |
|
|
|
import org.thingsboard.server.common.data.relation.RelationTypeGroup; |
|
|
|
import org.thingsboard.server.common.data.rule.RuleChain; |
|
|
|
import org.thingsboard.server.common.data.rule.RuleChainMetaData; |
|
|
|
import org.thingsboard.server.common.data.rule.RuleChainType; |
|
|
|
import org.thingsboard.server.common.data.rule.RuleNode; |
|
|
|
import org.thingsboard.server.common.data.tenant.profile.TenantProfileQueueConfiguration; |
|
|
|
import org.thingsboard.server.dao.DaoUtil; |
|
|
|
import org.thingsboard.server.dao.alarm.AlarmDao; |
|
|
|
import org.thingsboard.server.dao.alarm.AlarmService; |
|
|
|
@ -61,16 +62,22 @@ import org.thingsboard.server.dao.entityview.EntityViewService; |
|
|
|
import org.thingsboard.server.dao.model.sql.DeviceProfileEntity; |
|
|
|
import org.thingsboard.server.dao.model.sql.RelationEntity; |
|
|
|
import org.thingsboard.server.dao.oauth2.OAuth2Service; |
|
|
|
import org.thingsboard.server.dao.queue.QueueService; |
|
|
|
import org.thingsboard.server.dao.relation.RelationService; |
|
|
|
import org.thingsboard.server.dao.rule.RuleChainService; |
|
|
|
import org.thingsboard.server.dao.sql.device.DeviceProfileRepository; |
|
|
|
import org.thingsboard.server.dao.tenant.TenantProfileService; |
|
|
|
import org.thingsboard.server.dao.tenant.TenantService; |
|
|
|
import org.thingsboard.server.dao.timeseries.TimeseriesService; |
|
|
|
import org.thingsboard.server.queue.settings.TbRuleEngineQueueConfiguration; |
|
|
|
import org.thingsboard.server.service.install.InstallScripts; |
|
|
|
import org.thingsboard.server.service.install.SystemDataLoaderService; |
|
|
|
import org.thingsboard.server.service.install.TbRuleEngineQueueConfigService; |
|
|
|
|
|
|
|
import java.util.ArrayList; |
|
|
|
import java.util.Collections; |
|
|
|
import java.util.List; |
|
|
|
import java.util.Map; |
|
|
|
import java.util.concurrent.ExecutionException; |
|
|
|
import java.util.concurrent.atomic.AtomicLong; |
|
|
|
import java.util.stream.Collectors; |
|
|
|
@ -115,6 +122,18 @@ public class DefaultDataUpdateService implements DataUpdateService { |
|
|
|
@Autowired |
|
|
|
private OAuth2Service oAuth2Service; |
|
|
|
|
|
|
|
@Autowired |
|
|
|
private TenantProfileService tenantProfileService; |
|
|
|
|
|
|
|
@Autowired |
|
|
|
private QueueService queueService; |
|
|
|
|
|
|
|
@Autowired |
|
|
|
private TbRuleEngineQueueConfigService queueConfig; |
|
|
|
|
|
|
|
@Autowired |
|
|
|
private SystemDataLoaderService systemDataLoaderService; |
|
|
|
|
|
|
|
@Override |
|
|
|
public void updateData(String fromVersion) throws Exception { |
|
|
|
switch (fromVersion) { |
|
|
|
@ -141,6 +160,26 @@ public class DefaultDataUpdateService implements DataUpdateService { |
|
|
|
log.info("Updating data from version 3.3.2 to 3.3.3 ..."); |
|
|
|
updateNestedRuleChains(); |
|
|
|
break; |
|
|
|
case "3.3.4": |
|
|
|
log.info("Updating data from version 3.3.4 to 3.4.0 ..."); |
|
|
|
log.info("Loading queues..."); |
|
|
|
try { |
|
|
|
if (!CollectionUtils.isEmpty(queueConfig.getQueues())) { |
|
|
|
queueConfig.getQueues().forEach(queueSettings -> { |
|
|
|
Queue queue = queueConfigToQueue(queueSettings); |
|
|
|
Queue existing = queueService.findQueueByTenantIdAndName(queue.getTenantId(), queue.getName()); |
|
|
|
if (existing == null) { |
|
|
|
queueService.saveQueue(queue); |
|
|
|
} |
|
|
|
}); |
|
|
|
} else { |
|
|
|
systemDataLoaderService.createQueues(); |
|
|
|
} |
|
|
|
} catch (Exception e) { |
|
|
|
} |
|
|
|
tenantsProfileQueueConfigurationUpdater.updateEntities(null); |
|
|
|
checkPointRuleNodesUpdater.updateEntities(null); |
|
|
|
break; |
|
|
|
default: |
|
|
|
throw new RuntimeException("Unable to update data, unsupported fromVersion: " + fromVersion); |
|
|
|
} |
|
|
|
@ -547,4 +586,133 @@ public class DefaultDataUpdateService implements DataUpdateService { |
|
|
|
log.warn("CAUTION: Update of Oauth2 parameters from 3.2.2 to 3.3.0 available only in ThingsBoard versions 3.3.0/3.3.1"); |
|
|
|
} |
|
|
|
|
|
|
|
private final PaginatedUpdater<String, TenantProfile> tenantsProfileQueueConfigurationUpdater = |
|
|
|
new PaginatedUpdater<>() { |
|
|
|
|
|
|
|
@Override |
|
|
|
protected String getName() { |
|
|
|
return "Tenant profiles queue configuration updater"; |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
protected boolean forceReportTotal() { |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
protected PageData<TenantProfile> findEntities(String id, PageLink pageLink) { |
|
|
|
return tenantProfileService.findTenantProfiles(TenantId.SYS_TENANT_ID, pageLink); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
protected void updateEntity(TenantProfile tenantProfile) { |
|
|
|
updateTenantProfileQueueConfiguration(tenantProfile); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
private void updateTenantProfileQueueConfiguration(TenantProfile profile) { |
|
|
|
try { |
|
|
|
List<TenantProfileQueueConfiguration> queueConfiguration = profile.getProfileData().getQueueConfiguration(); |
|
|
|
if (profile.isIsolatedTbRuleEngine() && (queueConfiguration == null || queueConfiguration.isEmpty())) { |
|
|
|
TenantProfileQueueConfiguration mainQueueConfig = getMainQueueConfiguration(); |
|
|
|
profile.getProfileData().setQueueConfiguration(Collections.singletonList((mainQueueConfig))); |
|
|
|
tenantProfileService.saveTenantProfile(TenantId.SYS_TENANT_ID, profile); |
|
|
|
List<TenantId> isolatedTenants = tenantService.findTenantIdsByTenantProfileId(profile.getId()); |
|
|
|
isolatedTenants.forEach(tenantId -> { |
|
|
|
queueService.saveQueue(new Queue(tenantId, mainQueueConfig)); |
|
|
|
}); |
|
|
|
} |
|
|
|
} catch (Exception e) { |
|
|
|
log.error("Failed to update tenant profile queue configuration name=["+profile.getName()+"], id=["+ profile.getId().getId() +"]", e); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private TenantProfileQueueConfiguration getMainQueueConfiguration() { |
|
|
|
TenantProfileQueueConfiguration mainQueueConfiguration = new TenantProfileQueueConfiguration(); |
|
|
|
mainQueueConfiguration.setName("Main"); |
|
|
|
mainQueueConfiguration.setTopic("tb_rule_engine.main"); |
|
|
|
mainQueueConfiguration.setPollInterval(25); |
|
|
|
mainQueueConfiguration.setPartitions(10); |
|
|
|
mainQueueConfiguration.setConsumerPerPartition(true); |
|
|
|
mainQueueConfiguration.setPackProcessingTimeout(2000); |
|
|
|
SubmitStrategy mainQueueSubmitStrategy = new SubmitStrategy(); |
|
|
|
mainQueueSubmitStrategy.setType(SubmitStrategyType.BURST); |
|
|
|
mainQueueSubmitStrategy.setBatchSize(1000); |
|
|
|
mainQueueConfiguration.setSubmitStrategy(mainQueueSubmitStrategy); |
|
|
|
ProcessingStrategy mainQueueProcessingStrategy = new ProcessingStrategy(); |
|
|
|
mainQueueProcessingStrategy.setType(ProcessingStrategyType.SKIP_ALL_FAILURES); |
|
|
|
mainQueueProcessingStrategy.setRetries(3); |
|
|
|
mainQueueProcessingStrategy.setFailurePercentage(0); |
|
|
|
mainQueueProcessingStrategy.setPauseBetweenRetries(3); |
|
|
|
mainQueueProcessingStrategy.setMaxPauseBetweenRetries(3); |
|
|
|
mainQueueConfiguration.setProcessingStrategy(mainQueueProcessingStrategy); |
|
|
|
return mainQueueConfiguration; |
|
|
|
} |
|
|
|
|
|
|
|
private Queue queueConfigToQueue(TbRuleEngineQueueConfiguration queueSettings) { |
|
|
|
Queue queue = new Queue(); |
|
|
|
queue.setTenantId(TenantId.SYS_TENANT_ID); |
|
|
|
queue.setName(queueSettings.getName()); |
|
|
|
queue.setTopic(queueSettings.getTopic()); |
|
|
|
queue.setPollInterval(queueSettings.getPollInterval()); |
|
|
|
queue.setPartitions(queueSettings.getPartitions()); |
|
|
|
queue.setPackProcessingTimeout(queueSettings.getPackProcessingTimeout()); |
|
|
|
SubmitStrategy submitStrategy = new SubmitStrategy(); |
|
|
|
submitStrategy.setBatchSize(queueSettings.getSubmitStrategy().getBatchSize()); |
|
|
|
submitStrategy.setType(SubmitStrategyType.valueOf(queueSettings.getSubmitStrategy().getType())); |
|
|
|
queue.setSubmitStrategy(submitStrategy); |
|
|
|
ProcessingStrategy processingStrategy = new ProcessingStrategy(); |
|
|
|
processingStrategy.setType(ProcessingStrategyType.valueOf(queueSettings.getProcessingStrategy().getType())); |
|
|
|
processingStrategy.setRetries(queueSettings.getProcessingStrategy().getRetries()); |
|
|
|
processingStrategy.setFailurePercentage(queueSettings.getProcessingStrategy().getFailurePercentage()); |
|
|
|
processingStrategy.setPauseBetweenRetries(queueSettings.getProcessingStrategy().getPauseBetweenRetries()); |
|
|
|
processingStrategy.setMaxPauseBetweenRetries(queueSettings.getProcessingStrategy().getMaxPauseBetweenRetries()); |
|
|
|
queue.setProcessingStrategy(processingStrategy); |
|
|
|
queue.setConsumerPerPartition(queueSettings.isConsumerPerPartition()); |
|
|
|
return queue; |
|
|
|
} |
|
|
|
|
|
|
|
private final PaginatedUpdater<String, RuleNode> checkPointRuleNodesUpdater = |
|
|
|
new PaginatedUpdater<>() { |
|
|
|
|
|
|
|
@Override |
|
|
|
protected String getName() { |
|
|
|
return "Checkpoint rule nodes updater"; |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
protected boolean forceReportTotal() { |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
protected PageData<RuleNode> findEntities(String id, PageLink pageLink) { |
|
|
|
return ruleChainService.findAllRuleNodesByType("org.thingsboard.rule.engine.flow.TbCheckpointNode", pageLink); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
protected void updateEntity(RuleNode ruleNode) { |
|
|
|
updateCheckPointRuleNodeConfiguration(ruleNode); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
private void updateCheckPointRuleNodeConfiguration(RuleNode node) { |
|
|
|
try { |
|
|
|
ObjectNode configuration = (ObjectNode) node.getConfiguration(); |
|
|
|
JsonNode queueNameNode = configuration.remove("queueName"); |
|
|
|
if (queueNameNode != null) { |
|
|
|
RuleChain ruleChain = this.ruleChainService.findRuleChainById(TenantId.SYS_TENANT_ID, node.getRuleChainId()); |
|
|
|
TenantId tenantId = ruleChain.getTenantId(); |
|
|
|
Map<String, QueueId> queues = |
|
|
|
queueService.findQueuesByTenantId(tenantId).stream().collect(Collectors.toMap(Queue::getName, Queue::getId)); |
|
|
|
String queueName = queueNameNode.asText(); |
|
|
|
QueueId queueId = queues.get(queueName); |
|
|
|
configuration.put("queueId", queueId != null ? queueId.toString() : ""); |
|
|
|
ruleChainService.saveRuleNode(tenantId, node); |
|
|
|
} |
|
|
|
} catch (Exception e) { |
|
|
|
log.error("Failed to update checkpoint rule node configuration name=["+node.getName()+"], id=["+ node.getId().getId() +"]", e); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|