added logic update to the rule nodes upgrade script

This commit is contained in:
ShvaykaD 2023-05-17 18:03:35 +03:00
parent 5831876b8e
commit 21e5a1a130
28 changed files with 241 additions and 232 deletions

View File

@ -258,6 +258,7 @@ public class ThingsboardInstallService {
installScripts.loadSystemLwm2mResources();
case "3.5.0":
log.info("Upgrading ThingsBoard from version 3.5.0 to 3.5.1 ...");
databaseEntitiesUpgradeService.upgradeDatabase("3.5.0");
dataUpdateService.updateData("3.5.0");
log.info("Updating system data...");
systemDataLoaderService.updateSystemWidgets();

View File

@ -713,6 +713,25 @@ public class SqlDatabaseUpgradeService implements DatabaseEntitiesUpgradeService
log.error("Failed updating schema!!!", e);
}
break;
case "3.5.0":
try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword)) {
log.info("Updating schema ...");
if (isOldSchema(conn, 3005000)) {
try {
conn.createStatement().execute("ALTER TABLE rule_node ADD COLUMN IF NOT EXISTS configuration_version int DEFAULT 0;");
} catch (Exception e) {
}
try {
conn.createStatement().execute("CREATE INDEX IF NOT EXISTS idx_rule_node_type_configuration_version ON rule_node(type, configuration_version);");
} catch (Exception e) {
}
conn.createStatement().execute("UPDATE tb_schema_settings SET schema_version = 3005001;");
}
log.info("Schema updated.");
} catch (Exception e) {
log.error("Failed updating schema!!!", e);
}
break;
default:
throw new RuntimeException("Unable to upgrade SQL database, unsupported fromVersion: " + fromVersion);
}

View File

@ -22,22 +22,19 @@ import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Profile;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.stereotype.Service;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.rule.engine.api.TbNode;
import org.thingsboard.rule.engine.api.TbNodeException;
import org.thingsboard.rule.engine.api.VersionedNode;
import org.thingsboard.rule.engine.flow.TbRuleChainInputNode;
import org.thingsboard.rule.engine.flow.TbRuleChainInputNodeConfiguration;
import org.thingsboard.rule.engine.metadata.TbFetchDeviceCredentialsNode;
import org.thingsboard.rule.engine.metadata.TbGetAttributesNode;
import org.thingsboard.rule.engine.metadata.TbGetCustomerAttributeNode;
import org.thingsboard.rule.engine.metadata.TbGetCustomerDetailsNode;
import org.thingsboard.rule.engine.metadata.TbGetDeviceAttrNode;
import org.thingsboard.rule.engine.metadata.TbGetOriginatorFieldsNode;
import org.thingsboard.rule.engine.metadata.TbGetRelatedAttributeNode;
import org.thingsboard.rule.engine.metadata.TbGetTenantAttributeNode;
import org.thingsboard.rule.engine.metadata.TbGetTenantDetailsNode;
import org.thingsboard.rule.engine.profile.TbDeviceProfileNode;
import org.thingsboard.rule.engine.profile.TbDeviceProfileNodeConfiguration;
import org.thingsboard.server.common.data.DataConstants;
@ -73,6 +70,7 @@ 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.common.data.util.TbPair;
import org.thingsboard.server.dao.DaoUtil;
import org.thingsboard.server.dao.alarm.AlarmDao;
import org.thingsboard.server.dao.audit.AuditLogDao;
@ -92,10 +90,13 @@ import org.thingsboard.server.service.install.InstallScripts;
import org.thingsboard.server.service.install.SystemDataLoaderService;
import org.thingsboard.server.service.install.TbRuleEngineQueueConfigService;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;
@ -107,6 +108,9 @@ import static org.thingsboard.server.common.data.StringUtils.isBlank;
@Slf4j
public class DefaultDataUpdateService implements DataUpdateService {
@Value("${plugins.scan_packages}")
private String[] scanPackages;
@Autowired
private TenantService tenantService;
@ -217,55 +221,96 @@ public class DefaultDataUpdateService implements DataUpdateService {
break;
case "3.5.0":
log.info("Updating data from version 3.5.0 to 3.5.1 ...");
log.info("Starting enrichment rule nodes update ...");
upgradeEnrichmentRuleNodesWithFetchTo();
log.info("Finished enrichment rule nodes update!");
upgradeRuleNodes();
break;
default:
throw new RuntimeException("Unable to update data, unsupported fromVersion: " + fromVersion);
}
}
private void upgradeEnrichmentRuleNodesWithFetchTo() {
private void upgradeRuleNodes() {
var ruleChainIdToTenantIdMap = new HashMap<RuleChainId, TenantId>();
try {
var ruleChainIdToTenantId = new HashMap<RuleChainId, TenantId>();
upgradeRuleNode(ruleChainIdToTenantId, new TbGetOriginatorFieldsNode());
upgradeRuleNode(ruleChainIdToTenantId, new TbGetRelatedAttributeNode());
upgradeRuleNode(ruleChainIdToTenantId, new TbGetTenantAttributeNode());
upgradeRuleNode(ruleChainIdToTenantId, new TbGetCustomerAttributeNode());
upgradeRuleNode(ruleChainIdToTenantId, new TbGetAttributesNode());
upgradeRuleNode(ruleChainIdToTenantId, new TbGetDeviceAttrNode());
upgradeRuleNode(ruleChainIdToTenantId, new TbGetCustomerDetailsNode());
upgradeRuleNode(ruleChainIdToTenantId, new TbGetTenantDetailsNode());
upgradeRuleNode(ruleChainIdToTenantId, new TbFetchDeviceCredentialsNode());
} catch (Exception e) {
log.error("Unexpected error during enrichment rule nodes updating!", e);
}
}
private void upgradeRuleNode(HashMap<RuleChainId, TenantId> ruleChainIdToTenantId, VersionedNode versionedNode) {
var ruleNodes = new PageDataIterable<>(
pageLink -> ruleChainService.findAllRuleNodesByType(versionedNode.getClass().getName(), pageLink), 1024
log.info("Starting rule nodes upgrade ...");
var ruleNodeDefinitions = getBeanDefinitions(
org.thingsboard.rule.engine.api.RuleNode.class
);
ruleNodes.forEach(ruleNode -> {
var upgradeRuleNodeConfigurationResult = versionedNode.upgrade(ruleNode.getId(), ruleNode.getConfiguration());
for (BeanDefinition def : ruleNodeDefinitions) {
String clazzName = def.getBeanClassName();
Class<?> clazz = Class.forName(clazzName);
TbNode tbNode = (TbNode) clazz.getDeclaredConstructor().newInstance();
if (tbNode instanceof VersionedNode) {
var versionedNode = (VersionedNode) tbNode;
var ruleNodeName = versionedNode.getClass().getName();
int currentVersion = versionedNode.getCurrentVersion();
var ruleNodesToUpdate = new PageDataIterable<>(
pageLink ->
ruleChainService.findAllRuleNodesByTypeAndVersionLessThan(ruleNodeName, currentVersion, pageLink),
1024
);
for (RuleNode ruleNode : ruleNodesToUpdate) {
RuleNodeId ruleNodeId = ruleNode.getId();
var oldConfiguration = ruleNode.getConfiguration();
int fromVersion = ruleNode.getConfigurationVersion();
log.info("Going to upgrade rule node with id: {} type: {} fromVersion: {} toVersion: {}",
ruleNodeId,
clazzName,
fromVersion,
currentVersion);
try {
TbPair<Boolean, JsonNode> upgradeRuleNodeConfigurationResult = versionedNode.upgrade(ruleNodeId, fromVersion, oldConfiguration);
if (upgradeRuleNodeConfigurationResult.getFirst()) {
ruleNode.setConfiguration(upgradeRuleNodeConfigurationResult.getSecond());
var ruleChainId = ruleNode.getRuleChainId();
var tenantId = ruleChainIdToTenantId.computeIfAbsent(ruleChainId,
var tenantId = getTenantId(ruleChainIdToTenantIdMap, ruleNodeId, ruleChainId);
if (tenantId == null) {
log.warn("Failed to find tenant id for rule chain with id: {}", ruleChainId);
continue;
}
ruleChainService.saveRuleNode(tenantId, ruleNode);
log.info("Successfully upgrade rule node with id: {} type: {} fromVersion: {} toVersion: {}",
ruleNodeId,
clazzName,
fromVersion,
currentVersion);
}
} catch (TbNodeException e) {
log.warn("Failed to upgrade rule node with id: {} type: {} fromVersion: {} toVersion: {} due to: ",
ruleNodeId,
clazzName,
fromVersion,
currentVersion,
e);
}
}
}
}
log.info("Finished rule nodes upgrade!");
} catch (Exception e) {
log.error("Unexpected error during rule nodes upgrade: ", e);
}
}
private TenantId getTenantId(HashMap<RuleChainId, TenantId> ruleChainIdToTenantId, RuleNodeId ruleNodeId, RuleChainId ruleChainId) {
return ruleChainIdToTenantId.computeIfAbsent(ruleChainId,
id -> {
RuleChain ruleChain = ruleChainService.findRuleChainById(TenantId.SYS_TENANT_ID, id);
if (ruleChain == null) {
log.error("Failed to find rule chain by id: [{}], ruleNodeId: [{}]", ruleChainId, ruleNode.getId());
log.warn("Failed to find rule chain by id: {} ruleNodeId: {}", ruleChainId, ruleNodeId);
return null;
}
return ruleChain.getTenantId();
});
if (tenantId != null) {
ruleChainService.saveRuleNode(tenantId, ruleNode);
}
private Set<BeanDefinition> getBeanDefinitions(Class<? extends Annotation> componentType) {
ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
scanner.addIncludeFilter(new AnnotationTypeFilter(componentType));
Set<BeanDefinition> defs = new HashSet<>();
for (String scanPackage : scanPackages) {
defs.addAll(scanner.findCandidateComponents(scanPackage));
}
});
return defs;
}
private final PaginatedUpdater<String, DeviceProfileEntity> deviceProfileEntityDynamicConditionsUpdater =

View File

@ -99,6 +99,8 @@ public interface RuleChainService extends EntityDaoService {
PageData<RuleNode> findAllRuleNodesByType(String type, PageLink pageLink);
PageData<RuleNode> findAllRuleNodesByTypeAndVersionLessThan(String type, int version, PageLink pageLink);
RuleNode saveRuleNode(TenantId tenantId, RuleNode ruleNode);
void deleteRuleNodes(TenantId tenantId, RuleChainId ruleChainId);

View File

@ -50,7 +50,9 @@ public class RuleNode extends SearchTextBasedWithAdditionalInfo<RuleNodeId> impl
private boolean debugMode;
@ApiModelProperty(position = 7, value = "Enable/disable singleton mode. ", example = "false")
private boolean singletonMode;
@ApiModelProperty(position = 8, value = "JSON with the rule node configuration. Structure depends on the rule node implementation.", dataType = "com.fasterxml.jackson.databind.JsonNode")
@ApiModelProperty(position = 8, value = "Version of rule node configuration. ", example = "0")
private int configurationVersion;
@ApiModelProperty(position = 9, value = "JSON with the rule node configuration. Structure depends on the rule node implementation.", dataType = "com.fasterxml.jackson.databind.JsonNode")
private transient JsonNode configuration;
@JsonIgnore
private byte[] configurationBytes;
@ -109,7 +111,7 @@ public class RuleNode extends SearchTextBasedWithAdditionalInfo<RuleNodeId> impl
return super.getCreatedTime();
}
@ApiModelProperty(position = 8, value = "Additional parameters of the rule node. Contains 'layoutX' and 'layoutY' properties for visualization.", dataType = "com.fasterxml.jackson.databind.JsonNode")
@ApiModelProperty(position = 10, value = "Additional parameters of the rule node. Contains 'layoutX' and 'layoutY' properties for visualization.", dataType = "com.fasterxml.jackson.databind.JsonNode")
@Override
public JsonNode getAdditionalInfo() {
return super.getAdditionalInfo();

View File

@ -477,6 +477,7 @@ public class ModelConstants {
public static final String RULE_NODE_CHAIN_ID_PROPERTY = "rule_chain_id";
public static final String RULE_NODE_TYPE_PROPERTY = "type";
public static final String RULE_NODE_NAME_PROPERTY = "name";
public static final String RULE_NODE_VERSION_PROPERTY = "configuration_version";
public static final String RULE_NODE_CONFIGURATION_PROPERTY = "configuration";
/**

View File

@ -53,6 +53,9 @@ public class RuleNodeEntity extends BaseSqlEntity<RuleNode> implements SearchTex
@Column(name = ModelConstants.SEARCH_TEXT_PROPERTY)
private String searchText;
@Column(name = ModelConstants.RULE_NODE_VERSION_PROPERTY)
private int configurationVersion;
@Type(type = "json")
@Column(name = ModelConstants.RULE_NODE_CONFIGURATION_PROPERTY)
private JsonNode configuration;
@ -86,6 +89,7 @@ public class RuleNodeEntity extends BaseSqlEntity<RuleNode> implements SearchTex
this.debugMode = ruleNode.isDebugMode();
this.singletonMode = ruleNode.isSingletonMode();
this.searchText = ruleNode.getName();
this.configurationVersion = ruleNode.getConfigurationVersion();
this.configuration = ruleNode.getConfiguration();
this.additionalInfo = ruleNode.getAdditionalInfo();
if (ruleNode.getExternalId() != null) {
@ -114,6 +118,7 @@ public class RuleNodeEntity extends BaseSqlEntity<RuleNode> implements SearchTex
ruleNode.setName(name);
ruleNode.setDebugMode(debugMode);
ruleNode.setSingletonMode(singletonMode);
ruleNode.setConfigurationVersion(configurationVersion);
ruleNode.setConfiguration(configuration);
ruleNode.setAdditionalInfo(additionalInfo);
if (externalId != null) {

View File

@ -27,6 +27,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.rule.engine.api.TbNodeException;
import org.thingsboard.rule.engine.api.VersionedNode;
import org.thingsboard.server.common.data.BaseData;
import org.thingsboard.server.common.data.EntityType;
@ -77,6 +78,7 @@ import java.util.stream.Collectors;
import static org.thingsboard.server.common.data.DataConstants.TENANT;
import static org.thingsboard.server.dao.service.Validator.validateId;
import static org.thingsboard.server.dao.service.Validator.validatePageLink;
import static org.thingsboard.server.dao.service.Validator.validatePositiveNumber;
import static org.thingsboard.server.dao.service.Validator.validateString;
/**
@ -189,11 +191,11 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
RuleNode savedNode = ruleNodeDao.save(tenantId, node);
relations.add(new EntityRelation(ruleChainMetaData.getRuleChainId(), savedNode.getId(),
EntityRelation.CONTAINS_TYPE, RelationTypeGroup.RULE_CHAIN));
TbPair<Boolean, JsonNode> upgradeResult = upgradeRuleNode(savedNode);
if (upgradeResult.getFirst()) {
savedNode.setConfiguration(upgradeResult.getSecond());
savedNode = ruleNodeDao.save(tenantId, savedNode);
}
// TbPair<Boolean, JsonNode> upgradeResult = upgradeRuleNode(savedNode);
// if (upgradeResult.getFirst()) {
// savedNode.setConfiguration(upgradeResult.getSecond());
// savedNode = ruleNodeDao.save(tenantId, savedNode);
// }
int index = nodes.indexOf(node);
nodes.set(index, savedNode);
ruleNodeIndexMap.put(savedNode.getId(), index);
@ -263,24 +265,38 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
return RuleChainUpdateResult.successful(updatedRuleNodes);
}
private TbPair<Boolean, JsonNode> upgradeRuleNode(RuleNode node) {
var configuration = node.getConfiguration();
String ruleNodeClassName = node.getType();
private TbPair<Boolean, JsonNode> upgradeRuleNode(RuleNode ruleNode) {
RuleNodeId ruleNodeId = ruleNode.getId();
String ruleNodeType = ruleNode.getType();
int fromVersion = ruleNode.getConfigurationVersion();
try {
var ruleNodeClass = Class.forName(ruleNodeClassName).getConstructor().newInstance();
var ruleNodeClass = Class.forName(ruleNodeType).getDeclaredConstructor().newInstance();
if (ruleNodeClass instanceof VersionedNode) {
VersionedNode versionedNode = (VersionedNode) ruleNodeClass;
return versionedNode.upgrade(node.getId(), configuration);
int toVersion = versionedNode.getCurrentVersion();
log.info("Going to upgrade rule node with id: {} type: {} fromVersion: {} toVersion: {}",
ruleNodeId,
ruleNodeType,
fromVersion,
toVersion);
try {
return versionedNode.upgrade(ruleNodeId, fromVersion, ruleNode.getConfiguration());
} catch (TbNodeException e) {
log.warn("Failed to upgrade rule node with id: {} fromVersion: {} toVersion: {} due to: ",
ruleNodeId,
fromVersion,
toVersion,
e);
}
} catch (InstantiationException |
IllegalAccessException |
}
} catch (ClassNotFoundException |
InvocationTargetException |
NoSuchMethodException |
ClassNotFoundException e
) {
log.warn("Failed to upgrade rule node due to: ", e);
InstantiationException |
IllegalAccessException |
NoSuchMethodException e) {
log.warn("Failed to create instance of rule node with id: {} and type: {}", ruleNodeId, ruleNodeType);
}
return new TbPair<>(false, node.getConfiguration());
return new TbPair<>(false, ruleNode.getConfiguration());
}
@Override
@ -728,6 +744,15 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
return ruleNodeDao.findAllRuleNodesByType(type, pageLink);
}
@Override
public PageData<RuleNode> findAllRuleNodesByTypeAndVersionLessThan(String type, int version, PageLink pageLink) {
log.trace("Executing findAllRuleNodesByTypeAndVersionLessThan, type {}, pageLink {}, version {}", type, pageLink, version);
validateString(type, "Incorrect type of the rule node");
validatePositiveNumber(version, "Incorrect version to compare with. Version should be greater than 0!");
validatePageLink(pageLink);
return ruleNodeDao.findAllRuleNodesByTypeAndVersionLessThan(type, version, pageLink);
}
@Override
public RuleNode saveRuleNode(TenantId tenantId, RuleNode ruleNode) {
return ruleNodeDao.save(tenantId, ruleNode);

View File

@ -34,6 +34,8 @@ public interface RuleNodeDao extends Dao<RuleNode> {
PageData<RuleNode> findAllRuleNodesByType(String type, PageLink pageLink);
PageData<RuleNode> findAllRuleNodesByTypeAndVersionLessThan(String type, int version, PageLink pageLink);
List<RuleNode> findByExternalIds(RuleChainId ruleChainId, List<RuleNodeId> externalIds);
void deleteByIdIn(List<RuleNodeId> ruleNodeIds);

View File

@ -61,7 +61,7 @@ public class Validator {
/**
* This method validate <code>String</code> string. If string is invalid than throw
* This method validate <code>long</code> value. If value isn't possitive than throw
* <code>IncorrectParameterException</code> exception
*
* @param val the val

View File

@ -69,6 +69,16 @@ public class JpaRuleNodeDao extends JpaAbstractSearchTextDao<RuleNodeEntity, Rul
DaoUtil.toPageable(pageLink)));
}
@Override
public PageData<RuleNode> findAllRuleNodesByTypeAndVersionLessThan(String type, int version, PageLink pageLink) {
return DaoUtil.toPageData(ruleNodeRepository
.findAllRuleNodesByTypeAndVersionLessThan(
type,
version,
Objects.toString(pageLink.getTextSearch(), ""),
DaoUtil.toPageable(pageLink)));
}
@Override
public List<RuleNode> findByExternalIds(RuleChainId ruleChainId, List<RuleNodeId> externalIds) {
return DaoUtil.convertDataList(ruleNodeRepository.findRuleNodesByRuleChainIdAndExternalIdIn(ruleChainId.getId(),

View File

@ -41,6 +41,12 @@ public interface RuleNodeRepository extends JpaRepository<RuleNodeEntity, UUID>
@Param("searchText") String searchText,
Pageable pageable);
@Query("SELECT r FROM RuleNodeEntity r WHERE r.type = :ruleType AND r.configurationVersion < :version AND LOWER(r.configuration) LIKE LOWER(CONCAT('%', :searchText, '%')) ")
Page<RuleNodeEntity> findAllRuleNodesByTypeAndVersionLessThan(@Param("ruleType") String ruleType,
@Param("version") int version,
@Param("searchText") String searchText,
Pageable pageable);
List<RuleNodeEntity> findRuleNodesByRuleChainIdAndExternalIdIn(UUID ruleChainId, List<UUID> externalIds);
@Transactional

View File

@ -89,6 +89,8 @@ CREATE INDEX IF NOT EXISTS idx_rule_node_external_id ON rule_node(rule_chain_id,
CREATE INDEX IF NOT EXISTS idx_rule_node_type ON rule_node(type);
CREATE INDEX IF NOT EXISTS idx_rule_node_type_configuration_version ON rule_node(type, configuration_version);
CREATE INDEX IF NOT EXISTS idx_api_usage_state_entity_id ON api_usage_state(entity_id);
CREATE INDEX IF NOT EXISTS idx_alarm_comment_alarm_id ON alarm_comment(alarm_id);

View File

@ -184,6 +184,7 @@ CREATE TABLE IF NOT EXISTS rule_node (
created_time bigint NOT NULL,
rule_chain_id uuid,
additional_info varchar,
configuration_version int DEFAULT 0,
configuration varchar(10000000),
type varchar(255),
name varchar(255),

View File

@ -19,25 +19,10 @@ import com.fasterxml.jackson.databind.JsonNode;
import org.thingsboard.server.common.data.id.RuleNodeId;
import org.thingsboard.server.common.data.util.TbPair;
public interface VersionedNode {
public interface VersionedNode extends TbNode {
String VERSION_PROPERTY_NAME = "version";
TbPair<Boolean, JsonNode> upgrade(RuleNodeId ruleNodeId, int fromVersion, JsonNode oldConfiguration) throws TbNodeException;
TbPair<Boolean, JsonNode> upgrade(RuleNodeId ruleNodeId, JsonNode oldConfiguration);
default int getVersionOrElseThrowTbNodeException(RuleNodeId ruleNodeId, JsonNode oldConfiguration) throws TbNodeException {
if (oldConfiguration == null) {
throw new TbNodeException("Rule node: [" + this.getClass().getName() + "] " +
"with id: [" + ruleNodeId + "] has null configuration!");
} else if (!oldConfiguration.isObject()) {
throw new TbNodeException("Rule node: [" + this.getClass().getName() + "] " +
"with id: [" + ruleNodeId + "] has non json object configuration!");
}
if (!oldConfiguration.has(VERSION_PROPERTY_NAME)) {
return 0;
}
return oldConfiguration.get(VERSION_PROPERTY_NAME).asInt();
}
int getCurrentVersion();
}

View File

@ -1,22 +0,0 @@
/**
* Copyright © 2016-2023 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.rule.engine.api;
public interface VersionedNodeConfiguration {
int getVersion();
}

View File

@ -16,12 +16,10 @@
package org.thingsboard.rule.engine.metadata;
import lombok.Data;
import org.thingsboard.rule.engine.api.VersionedNodeConfiguration;
@Data
public abstract class TbAbstractFetchToNodeConfiguration implements VersionedNodeConfiguration {
public abstract class TbAbstractFetchToNodeConfiguration {
private FetchTo fetchTo;
private int version = 1;
}

View File

@ -149,11 +149,10 @@ public abstract class TbAbstractGetEntityAttrNode<T extends EntityId> extends Tb
ctx.tellSuccess(transformMessage(msg, msgData, msgMetaData));
}
protected TbPair<Boolean, JsonNode> upgradeToUseFetchToAndDataToFetch(RuleNodeId ruleNodeId, JsonNode oldConfiguration) throws TbNodeException {
protected TbPair<Boolean, JsonNode> upgradeToUseFetchToAndDataToFetch(JsonNode oldConfiguration) throws TbNodeException {
var newConfigObjectNode = (ObjectNode) oldConfiguration;
if (!newConfigObjectNode.has(OLD_PROPERTY_NAME)) {
throw new TbNodeException("Rule node: [" + this.getClass().getName() + "] " +
"with id: [" + ruleNodeId + "] doesn't have property: [" + OLD_PROPERTY_NAME + "]");
throw new TbNodeException("property to update: '" + OLD_PROPERTY_NAME + "' doesn't exists in configuration!");
}
var value = newConfigObjectNode.get(OLD_PROPERTY_NAME).asText();
if ("true".equals(value)) {
@ -163,12 +162,9 @@ public abstract class TbAbstractGetEntityAttrNode<T extends EntityId> extends Tb
newConfigObjectNode.remove(OLD_PROPERTY_NAME);
newConfigObjectNode.put(DATA_TO_FETCH_PROPERTY_NAME, DataToFetch.ATTRIBUTES.name());
} else {
throw new TbNodeException("Rule node: [" + this.getClass().getName() + "] " +
"with id: [" + ruleNodeId + "] has property: [" + OLD_PROPERTY_NAME + "] " +
"with unexpected value: [" + value + "] Allowed values: true or false!");
throw new TbNodeException("property to update: '" + OLD_PROPERTY_NAME + "' has unexpected value: " + value + ". Allowed values: true or false!");
}
newConfigObjectNode.put(FETCH_TO_PROPERTY_NAME, FetchTo.METADATA.name());
newConfigObjectNode.put(VERSION_PROPERTY_NAME, 1);
return new TbPair<>(true, newConfigObjectNode);
}

View File

@ -36,13 +36,18 @@ import org.thingsboard.server.common.msg.TbMsgMetaData;
import java.util.NoSuchElementException;
@Slf4j
public abstract class TbAbstractNodeWithFetchTo<C extends TbAbstractFetchToNodeConfiguration> implements TbNode, VersionedNode {
public abstract class TbAbstractNodeWithFetchTo<C extends TbAbstractFetchToNodeConfiguration> implements VersionedNode {
protected final static String FETCH_TO_PROPERTY_NAME = "fetchTo";
protected C config;
protected FetchTo fetchTo;
@Override
public int getCurrentVersion() {
return 1;
}
@Override
public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException {
config = loadNodeConfiguration(configuration);
@ -93,7 +98,6 @@ public abstract class TbAbstractNodeWithFetchTo<C extends TbAbstractFetchToNodeC
}
protected TbPair<Boolean, JsonNode> upgradeRuleNodesWithOldPropertyToUseFetchTo(
RuleNodeId ruleNodeId,
JsonNode oldConfiguration,
String oldProperty,
String ifTrue,
@ -101,24 +105,19 @@ public abstract class TbAbstractNodeWithFetchTo<C extends TbAbstractFetchToNodeC
) throws TbNodeException {
var newConfigObjectNode = (ObjectNode) oldConfiguration;
if (!newConfigObjectNode.has(oldProperty)) {
throw new TbNodeException("Rule node: [" + this.getClass().getName() + "] " +
"with id: [" + ruleNodeId + "] doesn't have property: [" + oldProperty + "]");
throw new TbNodeException("property to update: '" + oldProperty + "' doesn't exists in configuration!");
}
var value = newConfigObjectNode.get(oldProperty).asText();
if ("true".equals(value)) {
newConfigObjectNode.remove(oldProperty);
newConfigObjectNode.put(FETCH_TO_PROPERTY_NAME, ifTrue);
newConfigObjectNode.put(VERSION_PROPERTY_NAME, 1);
return new TbPair<>(true, newConfigObjectNode);
} else if ("false".equals(value)) {
newConfigObjectNode.remove(oldProperty);
newConfigObjectNode.put(FETCH_TO_PROPERTY_NAME, ifFalse);
newConfigObjectNode.put(VERSION_PROPERTY_NAME, 1);
return new TbPair<>(true, newConfigObjectNode);
} else {
throw new TbNodeException("Rule node: [" + this.getClass().getName() + "] " +
"with id: [" + ruleNodeId + "] has property: [" + oldProperty + "] " +
"with unexpected value: [" + value + "] Allowed values: true or false!");
throw new TbNodeException("property to update: '" + oldProperty + "' has unexpected value: " + value + ". Allowed values: true or false!");
}
}

View File

@ -89,22 +89,14 @@ public class TbFetchDeviceCredentialsNode extends TbAbstractNodeWithFetchTo<TbFe
}
@Override
public TbPair<Boolean, JsonNode> upgrade(RuleNodeId ruleNodeId, JsonNode oldConfiguration) {
try {
int oldVersion = getVersionOrElseThrowTbNodeException(ruleNodeId, oldConfiguration);
if (oldVersion == 0) {
return upgradeRuleNodesWithOldPropertyToUseFetchTo(
ruleNodeId,
public TbPair<Boolean, JsonNode> upgrade(RuleNodeId ruleNodeId, int fromVersion, JsonNode oldConfiguration) throws TbNodeException {
return fromVersion == 0 ?
upgradeRuleNodesWithOldPropertyToUseFetchTo(
oldConfiguration,
"fetchToMetadata",
FetchTo.METADATA.name(),
FetchTo.DATA.name()
);
}
} catch (TbNodeException e) {
log.warn(e.getMessage());
}
return new TbPair<>(false, oldConfiguration);
FetchTo.DATA.name()) :
new TbPair<>(false, oldConfiguration);
}
}

View File

@ -57,22 +57,14 @@ public class TbGetAttributesNode extends TbAbstractGetAttributesNode<TbGetAttrib
}
@Override
public TbPair<Boolean, JsonNode> upgrade(RuleNodeId ruleNodeId, JsonNode oldConfiguration) {
try {
int oldVersion = getVersionOrElseThrowTbNodeException(ruleNodeId, oldConfiguration);
if (oldVersion == 0) {
return upgradeRuleNodesWithOldPropertyToUseFetchTo(
ruleNodeId,
public TbPair<Boolean, JsonNode> upgrade(RuleNodeId ruleNodeId, int fromVersion, JsonNode oldConfiguration) throws TbNodeException {
return fromVersion == 0 ?
upgradeRuleNodesWithOldPropertyToUseFetchTo(
oldConfiguration,
"fetchToData",
FetchTo.DATA.name(),
FetchTo.METADATA.name()
);
}
} catch (TbNodeException e) {
log.warn(e.getMessage());
}
return new TbPair<>(false, oldConfiguration);
FetchTo.METADATA.name()) :
new TbPair<>(false, oldConfiguration);
}
}

View File

@ -72,16 +72,10 @@ public class TbGetCustomerAttributeNode extends TbAbstractGetEntityAttrNode<Cust
}
@Override
public TbPair<Boolean, JsonNode> upgrade(RuleNodeId ruleNodeId, JsonNode oldConfiguration) {
try {
int oldVersion = getVersionOrElseThrowTbNodeException(ruleNodeId, oldConfiguration);
if (oldVersion == 0) {
return upgradeToUseFetchToAndDataToFetch(ruleNodeId, oldConfiguration);
}
} catch (TbNodeException e) {
log.warn(e.getMessage());
}
return new TbPair<>(false, oldConfiguration);
public TbPair<Boolean, JsonNode> upgrade(RuleNodeId ruleNodeId, int fromVersion, JsonNode oldConfiguration) throws TbNodeException {
return fromVersion == 0 ?
upgradeToUseFetchToAndDataToFetch(oldConfiguration) :
new TbPair<>(false, oldConfiguration);
}
}

View File

@ -107,22 +107,14 @@ public class TbGetCustomerDetailsNode extends TbAbstractGetEntityDetailsNode<TbG
}
@Override
public TbPair<Boolean, JsonNode> upgrade(RuleNodeId ruleNodeId, JsonNode oldConfiguration) {
try {
int oldVersion = getVersionOrElseThrowTbNodeException(ruleNodeId, oldConfiguration);
if (oldVersion == 0) {
return upgradeRuleNodesWithOldPropertyToUseFetchTo(
ruleNodeId,
public TbPair<Boolean, JsonNode> upgrade(RuleNodeId ruleNodeId, int fromVersion, JsonNode oldConfiguration) throws TbNodeException {
return fromVersion == 0 ?
upgradeRuleNodesWithOldPropertyToUseFetchTo(
oldConfiguration,
"addToMetadata",
FetchTo.METADATA.name(),
FetchTo.DATA.name()
);
}
} catch (TbNodeException e) {
log.warn(e.getMessage());
}
return new TbPair<>(false, oldConfiguration);
FetchTo.DATA.name()) :
new TbPair<>(false, oldConfiguration);
}
}

View File

@ -60,22 +60,14 @@ public class TbGetDeviceAttrNode extends TbAbstractGetAttributesNode<TbGetDevice
}
@Override
public TbPair<Boolean, JsonNode> upgrade(RuleNodeId ruleNodeId, JsonNode oldConfiguration) {
try {
int oldVersion = getVersionOrElseThrowTbNodeException(ruleNodeId, oldConfiguration);
if (oldVersion == 0) {
return upgradeRuleNodesWithOldPropertyToUseFetchTo(
ruleNodeId,
public TbPair<Boolean, JsonNode> upgrade(RuleNodeId ruleNodeId, int fromVersion, JsonNode oldConfiguration) throws TbNodeException {
return fromVersion == 0 ?
upgradeRuleNodesWithOldPropertyToUseFetchTo(
oldConfiguration,
"fetchToData",
FetchTo.DATA.name(),
FetchTo.METADATA.name()
);
}
} catch (TbNodeException e) {
log.warn(e.getMessage());
}
return new TbPair<>(false, oldConfiguration);
FetchTo.METADATA.name()) :
new TbPair<>(false, oldConfiguration);
}
}

View File

@ -102,18 +102,12 @@ public class TbGetOriginatorFieldsNode extends TbAbstractNodeWithFetchTo<TbGetOr
}
@Override
public TbPair<Boolean, JsonNode> upgrade(RuleNodeId ruleNodeId, JsonNode oldConfiguration) {
try {
int oldVersion = getVersionOrElseThrowTbNodeException(ruleNodeId, oldConfiguration);
if (oldVersion == 0) {
public TbPair<Boolean, JsonNode> upgrade(RuleNodeId ruleNodeId, int fromVersion, JsonNode oldConfiguration) {
if (fromVersion == 0) {
var newConfigObjectNode = (ObjectNode) oldConfiguration;
newConfigObjectNode.put(FETCH_TO_PROPERTY_NAME, FetchTo.METADATA.name());
newConfigObjectNode.put(VERSION_PROPERTY_NAME, 1);
return new TbPair<>(true, newConfigObjectNode);
}
} catch (TbNodeException e) {
log.warn(e.getMessage());
}
return new TbPair<>(false, oldConfiguration);
}

View File

@ -75,16 +75,8 @@ public class TbGetRelatedAttributeNode extends TbAbstractGetEntityAttrNode<Entit
}
@Override
public TbPair<Boolean, JsonNode> upgrade(RuleNodeId ruleNodeId, JsonNode oldConfiguration) {
try {
int oldVersion = getVersionOrElseThrowTbNodeException(ruleNodeId, oldConfiguration);
if (oldVersion == 0) {
return upgradeToUseFetchToAndDataToFetch(ruleNodeId, oldConfiguration);
}
} catch (TbNodeException e) {
log.warn(e.getMessage());
}
return new TbPair<>(false, oldConfiguration);
public TbPair<Boolean, JsonNode> upgrade(RuleNodeId ruleNodeId, int fromVersion, JsonNode oldConfiguration) throws TbNodeException {
return fromVersion == 0 ? upgradeToUseFetchToAndDataToFetch(oldConfiguration) : new TbPair<>(false, oldConfiguration);
}
}

View File

@ -66,16 +66,8 @@ public class TbGetTenantAttributeNode extends TbAbstractGetEntityAttrNode<Tenant
}
@Override
public TbPair<Boolean, JsonNode> upgrade(RuleNodeId ruleNodeId, JsonNode oldConfiguration) {
try {
int oldVersion = getVersionOrElseThrowTbNodeException(ruleNodeId, oldConfiguration);
if (oldVersion == 0) {
return upgradeToUseFetchToAndDataToFetch(ruleNodeId, oldConfiguration);
}
} catch (TbNodeException e) {
log.warn(e.getMessage());
}
return new TbPair<>(false, oldConfiguration);
public TbPair<Boolean, JsonNode> upgrade(RuleNodeId ruleNodeId, int fromVersion, JsonNode oldConfiguration) throws TbNodeException {
return fromVersion == 0 ? upgradeToUseFetchToAndDataToFetch(oldConfiguration) : new TbPair<>(false, oldConfiguration);
}
}

View File

@ -62,22 +62,14 @@ public class TbGetTenantDetailsNode extends TbAbstractGetEntityDetailsNode<TbGet
}
@Override
public TbPair<Boolean, JsonNode> upgrade(RuleNodeId ruleNodeId, JsonNode oldConfiguration) {
try {
int oldVersion = getVersionOrElseThrowTbNodeException(ruleNodeId, oldConfiguration);
if (oldVersion == 0) {
return upgradeRuleNodesWithOldPropertyToUseFetchTo(
ruleNodeId,
public TbPair<Boolean, JsonNode> upgrade(RuleNodeId ruleNodeId, int fromVersion, JsonNode oldConfiguration) throws TbNodeException {
return fromVersion == 0 ?
upgradeRuleNodesWithOldPropertyToUseFetchTo(
oldConfiguration,
"addToMetadata",
FetchTo.METADATA.name(),
FetchTo.DATA.name()
);
}
} catch (TbNodeException e) {
log.warn(e.getMessage());
}
return new TbPair<>(false, oldConfiguration);
FetchTo.DATA.name()) :
new TbPair<>(false, oldConfiguration);
}
}