added TbNodeUpgradeUtils && fixed upgrade when config is null or NullNode
This commit is contained in:
		
							parent
							
								
									c42599c0d9
								
							
						
					
					
						commit
						92178384ea
					
				@ -27,7 +27,6 @@ import org.springframework.context.annotation.Lazy;
 | 
			
		||||
import org.springframework.context.annotation.Profile;
 | 
			
		||||
import org.springframework.stereotype.Service;
 | 
			
		||||
import org.thingsboard.common.util.JacksonUtil;
 | 
			
		||||
import org.thingsboard.rule.engine.api.TbNode;
 | 
			
		||||
import org.thingsboard.rule.engine.flow.TbRuleChainInputNode;
 | 
			
		||||
import org.thingsboard.rule.engine.flow.TbRuleChainInputNodeConfiguration;
 | 
			
		||||
import org.thingsboard.rule.engine.profile.TbDeviceProfileNode;
 | 
			
		||||
@ -67,7 +66,6 @@ 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;
 | 
			
		||||
@ -90,6 +88,7 @@ import org.thingsboard.server.service.component.ComponentDiscoveryService;
 | 
			
		||||
import org.thingsboard.server.service.component.RuleNodeClassInfo;
 | 
			
		||||
import org.thingsboard.server.service.install.InstallScripts;
 | 
			
		||||
import org.thingsboard.server.service.install.SystemDataLoaderService;
 | 
			
		||||
import org.thingsboard.server.utils.TbNodeUpgradeUtils;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
@ -291,16 +290,12 @@ public class DefaultDataUpdateService implements DataUpdateService {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            var ruleNodeId = ruleNode.getId();
 | 
			
		||||
            var oldConfiguration = ruleNode.getConfiguration();
 | 
			
		||||
            int fromVersion = ruleNode.getConfigurationVersion();
 | 
			
		||||
            log.debug("Going to upgrade rule node with id: {} type: {} fromVersion: {} toVersion: {}",
 | 
			
		||||
                    ruleNodeId, ruleNodeType, fromVersion, toVersion);
 | 
			
		||||
            try {
 | 
			
		||||
                var tbVersionedNode = (TbNode) ruleNodeClassInfo.getClazz().getDeclaredConstructor().newInstance();
 | 
			
		||||
                TbPair<Boolean, JsonNode> upgradeRuleNodeConfigurationResult = tbVersionedNode.upgrade(fromVersion, oldConfiguration);
 | 
			
		||||
                if (upgradeRuleNodeConfigurationResult.getFirst()) {
 | 
			
		||||
                    ruleNode.setConfiguration(upgradeRuleNodeConfigurationResult.getSecond());
 | 
			
		||||
                }
 | 
			
		||||
                ruleNode.setConfiguration(TbNodeUpgradeUtils.upgradeRuleNodeConfiguration(ruleNode, ruleNodeClassInfo.getAnnotation(),
 | 
			
		||||
                        ruleNodeClassInfo.getClazz()));
 | 
			
		||||
                ruleNode.setConfigurationVersion(toVersion);
 | 
			
		||||
                saveFutures.add(jpaExecutorService.submit(() -> {
 | 
			
		||||
                    ruleChainService.saveRuleNode(TenantId.SYS_TENANT_ID, ruleNode);
 | 
			
		||||
 | 
			
		||||
@ -15,12 +15,10 @@
 | 
			
		||||
 */
 | 
			
		||||
package org.thingsboard.server.service.rule;
 | 
			
		||||
 | 
			
		||||
import com.fasterxml.jackson.databind.JsonNode;
 | 
			
		||||
import lombok.RequiredArgsConstructor;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
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.flow.TbRuleChainInputNode;
 | 
			
		||||
import org.thingsboard.rule.engine.flow.TbRuleChainInputNodeConfiguration;
 | 
			
		||||
@ -44,13 +42,13 @@ import org.thingsboard.server.common.data.rule.RuleChainType;
 | 
			
		||||
import org.thingsboard.server.common.data.rule.RuleChainUpdateResult;
 | 
			
		||||
import org.thingsboard.server.common.data.rule.RuleNode;
 | 
			
		||||
import org.thingsboard.server.common.data.rule.RuleNodeUpdateResult;
 | 
			
		||||
import org.thingsboard.server.common.data.util.TbPair;
 | 
			
		||||
import org.thingsboard.server.dao.relation.RelationService;
 | 
			
		||||
import org.thingsboard.server.dao.rule.RuleChainService;
 | 
			
		||||
import org.thingsboard.server.queue.util.TbCoreComponent;
 | 
			
		||||
import org.thingsboard.server.service.component.ComponentDiscoveryService;
 | 
			
		||||
import org.thingsboard.server.service.entitiy.AbstractTbEntityService;
 | 
			
		||||
import org.thingsboard.server.service.install.InstallScripts;
 | 
			
		||||
import org.thingsboard.server.utils.TbNodeUpgradeUtils;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
@ -402,17 +400,14 @@ public class DefaultTbRuleChainService extends AbstractTbEntityService implement
 | 
			
		||||
            var ruleNodeClass = componentDiscoveryService.getRuleNodeInfo(ruleNodeType)
 | 
			
		||||
                    .orElseThrow(() -> new RuntimeException("Rule node " + ruleNodeType + " is not supported!"));
 | 
			
		||||
            if (ruleNodeClass.isVersioned()) {
 | 
			
		||||
                TbNode tbVersionedNode = (TbNode) ruleNodeClass.getClazz().getDeclaredConstructor().newInstance();
 | 
			
		||||
                int fromVersion = node.getConfigurationVersion();
 | 
			
		||||
                int toVersion = ruleNodeClass.getCurrentVersion();
 | 
			
		||||
                if (fromVersion < toVersion) {
 | 
			
		||||
                    log.debug("Going to upgrade rule node with id: {} type: {} fromVersion: {} toVersion: {}",
 | 
			
		||||
                            ruleNodeId, ruleNodeType, fromVersion, toVersion);
 | 
			
		||||
                    try {
 | 
			
		||||
                        TbPair<Boolean, JsonNode> upgradeResult = tbVersionedNode.upgrade(fromVersion, node.getConfiguration());
 | 
			
		||||
                        if (upgradeResult.getFirst()) {
 | 
			
		||||
                            node.setConfiguration(upgradeResult.getSecond());
 | 
			
		||||
                        }
 | 
			
		||||
                        node.setConfiguration(TbNodeUpgradeUtils.upgradeRuleNodeConfiguration(node, ruleNodeClass.getAnnotation(),
 | 
			
		||||
                                ruleNodeClass.getClazz()));
 | 
			
		||||
                        node.setConfigurationVersion(toVersion);
 | 
			
		||||
                        log.debug("Successfully upgrade rule node with id: {} type: {}, rule chain id: {} fromVersion: {} toVersion: {}",
 | 
			
		||||
                                ruleNodeId, ruleNodeType, ruleChainId, fromVersion, toVersion);
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,39 @@
 | 
			
		||||
/**
 | 
			
		||||
 * 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.server.utils;
 | 
			
		||||
 | 
			
		||||
import com.fasterxml.jackson.databind.JsonNode;
 | 
			
		||||
import org.thingsboard.common.util.JacksonUtil;
 | 
			
		||||
import org.thingsboard.rule.engine.api.TbNode;
 | 
			
		||||
import org.thingsboard.server.common.data.rule.RuleNode;
 | 
			
		||||
import org.thingsboard.server.common.data.util.TbPair;
 | 
			
		||||
 | 
			
		||||
public class TbNodeUpgradeUtils {
 | 
			
		||||
 | 
			
		||||
    public static JsonNode upgradeRuleNodeConfiguration(RuleNode node,
 | 
			
		||||
                                                        org.thingsboard.rule.engine.api.RuleNode annotation,
 | 
			
		||||
                                                        Class<?> nodeClass) throws Exception {
 | 
			
		||||
        JsonNode oldConfiguration = node.getConfiguration();
 | 
			
		||||
        if (oldConfiguration == null || !oldConfiguration.isObject()) {
 | 
			
		||||
            var configClass = annotation.configClazz();
 | 
			
		||||
            return JacksonUtil.valueToTree(configClass.getDeclaredConstructor().newInstance().defaultConfiguration());
 | 
			
		||||
        }
 | 
			
		||||
        var tbVersionedNode = (TbNode) nodeClass.getDeclaredConstructor().newInstance();
 | 
			
		||||
        TbPair<Boolean, JsonNode> upgradeResult = tbVersionedNode.upgrade(node.getConfigurationVersion(), oldConfiguration);
 | 
			
		||||
        return upgradeResult.getFirst() ? upgradeResult.getSecond() : oldConfiguration;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,111 @@
 | 
			
		||||
/**
 | 
			
		||||
 * 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.server.utils;
 | 
			
		||||
 | 
			
		||||
import com.fasterxml.jackson.databind.node.NullNode;
 | 
			
		||||
import org.assertj.core.api.Assertions;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
import org.thingsboard.common.util.JacksonUtil;
 | 
			
		||||
import org.thingsboard.rule.engine.api.TbNode;
 | 
			
		||||
import org.thingsboard.rule.engine.metadata.TbGetAttributesNode;
 | 
			
		||||
import org.thingsboard.rule.engine.metadata.TbGetAttributesNodeConfiguration;
 | 
			
		||||
import org.thingsboard.server.common.data.rule.RuleNode;
 | 
			
		||||
import org.thingsboard.server.common.data.util.TbPair;
 | 
			
		||||
 | 
			
		||||
import static org.mockito.Mockito.mock;
 | 
			
		||||
import static org.mockito.Mockito.when;
 | 
			
		||||
 | 
			
		||||
public class TbNodeUpgradeUtilsTest {
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testUpgradeRuleNodeConfigurationWithNullConfig() throws Exception {
 | 
			
		||||
        // GIVEN
 | 
			
		||||
        var node = mock(RuleNode.class);
 | 
			
		||||
        var nodeClass = TbGetAttributesNode.class;
 | 
			
		||||
        var nodeConfigClazz = TbGetAttributesNodeConfiguration.class;
 | 
			
		||||
 | 
			
		||||
        var annotation = mock(org.thingsboard.rule.engine.api.RuleNode.class);
 | 
			
		||||
 | 
			
		||||
        var defaultConfig = JacksonUtil.valueToTree(nodeConfigClazz.getDeclaredConstructor().newInstance().defaultConfiguration());
 | 
			
		||||
 | 
			
		||||
        when(node.getConfiguration()).thenReturn(null);
 | 
			
		||||
        when(node.getConfigurationVersion()).thenReturn(0);
 | 
			
		||||
        when(annotation.configClazz()).thenReturn((Class) nodeConfigClazz);
 | 
			
		||||
        // WHEN
 | 
			
		||||
        var upgradedConfig = TbNodeUpgradeUtils.upgradeRuleNodeConfiguration(node, annotation, nodeClass);
 | 
			
		||||
 | 
			
		||||
        // THEN
 | 
			
		||||
        Assertions.assertThat(upgradedConfig).isEqualTo(defaultConfig);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testUpgradeRuleNodeConfigurationWithNullNodeConfig() throws Exception {
 | 
			
		||||
        // GIVEN
 | 
			
		||||
        var node = mock(RuleNode.class);
 | 
			
		||||
        var nodeClass = TbGetAttributesNode.class;
 | 
			
		||||
        var nodeConfigClazz = TbGetAttributesNodeConfiguration.class;
 | 
			
		||||
 | 
			
		||||
        var annotation = mock(org.thingsboard.rule.engine.api.RuleNode.class);
 | 
			
		||||
 | 
			
		||||
        var defaultConfig = JacksonUtil.valueToTree(nodeConfigClazz.getDeclaredConstructor().newInstance().defaultConfiguration());
 | 
			
		||||
 | 
			
		||||
        when(node.getConfiguration()).thenReturn(NullNode.instance);
 | 
			
		||||
        when(node.getConfigurationVersion()).thenReturn(0);
 | 
			
		||||
        when(annotation.configClazz()).thenReturn((Class) nodeConfigClazz);
 | 
			
		||||
        // WHEN
 | 
			
		||||
        var upgradedConfig = TbNodeUpgradeUtils.upgradeRuleNodeConfiguration(node, annotation, nodeClass);
 | 
			
		||||
 | 
			
		||||
        // THEN
 | 
			
		||||
        Assertions.assertThat(upgradedConfig).isEqualTo(defaultConfig);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testUpgradeRuleNodeConfigurationWithNonNullConfig() throws Exception {
 | 
			
		||||
        // GIVEN
 | 
			
		||||
        var node = mock(RuleNode.class);
 | 
			
		||||
        var nodeClass = TbGetAttributesNode.class;
 | 
			
		||||
        var nodeConfigClazz = TbGetAttributesNodeConfiguration.class;
 | 
			
		||||
 | 
			
		||||
        var annotation = mock(org.thingsboard.rule.engine.api.RuleNode.class);
 | 
			
		||||
 | 
			
		||||
        String versionZeroDefaultConfigStr = "{\"fetchToData\":false," +
 | 
			
		||||
                "\"clientAttributeNames\":[]," +
 | 
			
		||||
                "\"sharedAttributeNames\":[]," +
 | 
			
		||||
                "\"serverAttributeNames\":[]," +
 | 
			
		||||
                "\"latestTsKeyNames\":[]," +
 | 
			
		||||
                "\"tellFailureIfAbsent\":true," +
 | 
			
		||||
                "\"getLatestValueWithTs\":false}";
 | 
			
		||||
 | 
			
		||||
        var existingConfig = JacksonUtil.toJsonNode(versionZeroDefaultConfigStr);
 | 
			
		||||
        int fromVersion = 0;
 | 
			
		||||
        var currentDefaultConfig = JacksonUtil.valueToTree(nodeConfigClazz.getDeclaredConstructor().newInstance().defaultConfiguration());
 | 
			
		||||
 | 
			
		||||
        when(node.getConfiguration()).thenReturn(existingConfig);
 | 
			
		||||
        when(node.getConfigurationVersion()).thenReturn(fromVersion);
 | 
			
		||||
        when(annotation.configClazz()).thenReturn((Class) nodeConfigClazz);
 | 
			
		||||
 | 
			
		||||
        TbNode tbVersionedNodeMock = mock(nodeClass);
 | 
			
		||||
 | 
			
		||||
        when(tbVersionedNodeMock.upgrade(fromVersion, existingConfig)).thenReturn(new TbPair<>(true, currentDefaultConfig));
 | 
			
		||||
 | 
			
		||||
        // WHEN
 | 
			
		||||
        var upgradedConfig = TbNodeUpgradeUtils.upgradeRuleNodeConfiguration(node, annotation, nodeClass);
 | 
			
		||||
 | 
			
		||||
        // THEN
 | 
			
		||||
        Assertions.assertThat(upgradedConfig).isEqualTo(currentDefaultConfig);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -15,7 +15,6 @@
 | 
			
		||||
 */
 | 
			
		||||
package org.thingsboard.rule.engine.api.util;
 | 
			
		||||
 | 
			
		||||
import com.fasterxml.jackson.core.JsonProcessingException;
 | 
			
		||||
import com.fasterxml.jackson.databind.JsonNode;
 | 
			
		||||
import org.springframework.util.CollectionUtils;
 | 
			
		||||
import org.thingsboard.common.util.JacksonUtil;
 | 
			
		||||
@ -85,6 +84,7 @@ public class TbNodeUtils {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Deprecated(since = "3.6.1", forRemoval = true)
 | 
			
		||||
    public static List<String> processPatterns(List<String> patterns, TbMsgMetaData metaData) {
 | 
			
		||||
        if (!CollectionUtils.isEmpty(patterns)) {
 | 
			
		||||
            return patterns.stream().map(p -> processPattern(p, metaData)).collect(Collectors.toList());
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user