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.context.annotation.Profile;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.thingsboard.common.util.JacksonUtil;
|
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.TbRuleChainInputNode;
|
||||||
import org.thingsboard.rule.engine.flow.TbRuleChainInputNodeConfiguration;
|
import org.thingsboard.rule.engine.flow.TbRuleChainInputNodeConfiguration;
|
||||||
import org.thingsboard.rule.engine.profile.TbDeviceProfileNode;
|
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.RuleChainType;
|
||||||
import org.thingsboard.server.common.data.rule.RuleNode;
|
import org.thingsboard.server.common.data.rule.RuleNode;
|
||||||
import org.thingsboard.server.common.data.tenant.profile.TenantProfileQueueConfiguration;
|
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.DaoUtil;
|
||||||
import org.thingsboard.server.dao.alarm.AlarmDao;
|
import org.thingsboard.server.dao.alarm.AlarmDao;
|
||||||
import org.thingsboard.server.dao.audit.AuditLogDao;
|
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.component.RuleNodeClassInfo;
|
||||||
import org.thingsboard.server.service.install.InstallScripts;
|
import org.thingsboard.server.service.install.InstallScripts;
|
||||||
import org.thingsboard.server.service.install.SystemDataLoaderService;
|
import org.thingsboard.server.service.install.SystemDataLoaderService;
|
||||||
|
import org.thingsboard.server.utils.TbNodeUpgradeUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -291,16 +290,12 @@ public class DefaultDataUpdateService implements DataUpdateService {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var ruleNodeId = ruleNode.getId();
|
var ruleNodeId = ruleNode.getId();
|
||||||
var oldConfiguration = ruleNode.getConfiguration();
|
|
||||||
int fromVersion = ruleNode.getConfigurationVersion();
|
int fromVersion = ruleNode.getConfigurationVersion();
|
||||||
log.debug("Going to upgrade rule node with id: {} type: {} fromVersion: {} toVersion: {}",
|
log.debug("Going to upgrade rule node with id: {} type: {} fromVersion: {} toVersion: {}",
|
||||||
ruleNodeId, ruleNodeType, fromVersion, toVersion);
|
ruleNodeId, ruleNodeType, fromVersion, toVersion);
|
||||||
try {
|
try {
|
||||||
var tbVersionedNode = (TbNode) ruleNodeClassInfo.getClazz().getDeclaredConstructor().newInstance();
|
ruleNode.setConfiguration(TbNodeUpgradeUtils.upgradeRuleNodeConfiguration(ruleNode, ruleNodeClassInfo.getAnnotation(),
|
||||||
TbPair<Boolean, JsonNode> upgradeRuleNodeConfigurationResult = tbVersionedNode.upgrade(fromVersion, oldConfiguration);
|
ruleNodeClassInfo.getClazz()));
|
||||||
if (upgradeRuleNodeConfigurationResult.getFirst()) {
|
|
||||||
ruleNode.setConfiguration(upgradeRuleNodeConfigurationResult.getSecond());
|
|
||||||
}
|
|
||||||
ruleNode.setConfigurationVersion(toVersion);
|
ruleNode.setConfigurationVersion(toVersion);
|
||||||
saveFutures.add(jpaExecutorService.submit(() -> {
|
saveFutures.add(jpaExecutorService.submit(() -> {
|
||||||
ruleChainService.saveRuleNode(TenantId.SYS_TENANT_ID, ruleNode);
|
ruleChainService.saveRuleNode(TenantId.SYS_TENANT_ID, ruleNode);
|
||||||
|
|||||||
@ -15,12 +15,10 @@
|
|||||||
*/
|
*/
|
||||||
package org.thingsboard.server.service.rule;
|
package org.thingsboard.server.service.rule;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.thingsboard.common.util.JacksonUtil;
|
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.TbNodeException;
|
||||||
import org.thingsboard.rule.engine.flow.TbRuleChainInputNode;
|
import org.thingsboard.rule.engine.flow.TbRuleChainInputNode;
|
||||||
import org.thingsboard.rule.engine.flow.TbRuleChainInputNodeConfiguration;
|
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.RuleChainUpdateResult;
|
||||||
import org.thingsboard.server.common.data.rule.RuleNode;
|
import org.thingsboard.server.common.data.rule.RuleNode;
|
||||||
import org.thingsboard.server.common.data.rule.RuleNodeUpdateResult;
|
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.relation.RelationService;
|
||||||
import org.thingsboard.server.dao.rule.RuleChainService;
|
import org.thingsboard.server.dao.rule.RuleChainService;
|
||||||
import org.thingsboard.server.queue.util.TbCoreComponent;
|
import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||||
import org.thingsboard.server.service.component.ComponentDiscoveryService;
|
import org.thingsboard.server.service.component.ComponentDiscoveryService;
|
||||||
import org.thingsboard.server.service.entitiy.AbstractTbEntityService;
|
import org.thingsboard.server.service.entitiy.AbstractTbEntityService;
|
||||||
import org.thingsboard.server.service.install.InstallScripts;
|
import org.thingsboard.server.service.install.InstallScripts;
|
||||||
|
import org.thingsboard.server.utils.TbNodeUpgradeUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -402,17 +400,14 @@ public class DefaultTbRuleChainService extends AbstractTbEntityService implement
|
|||||||
var ruleNodeClass = componentDiscoveryService.getRuleNodeInfo(ruleNodeType)
|
var ruleNodeClass = componentDiscoveryService.getRuleNodeInfo(ruleNodeType)
|
||||||
.orElseThrow(() -> new RuntimeException("Rule node " + ruleNodeType + " is not supported!"));
|
.orElseThrow(() -> new RuntimeException("Rule node " + ruleNodeType + " is not supported!"));
|
||||||
if (ruleNodeClass.isVersioned()) {
|
if (ruleNodeClass.isVersioned()) {
|
||||||
TbNode tbVersionedNode = (TbNode) ruleNodeClass.getClazz().getDeclaredConstructor().newInstance();
|
|
||||||
int fromVersion = node.getConfigurationVersion();
|
int fromVersion = node.getConfigurationVersion();
|
||||||
int toVersion = ruleNodeClass.getCurrentVersion();
|
int toVersion = ruleNodeClass.getCurrentVersion();
|
||||||
if (fromVersion < toVersion) {
|
if (fromVersion < toVersion) {
|
||||||
log.debug("Going to upgrade rule node with id: {} type: {} fromVersion: {} toVersion: {}",
|
log.debug("Going to upgrade rule node with id: {} type: {} fromVersion: {} toVersion: {}",
|
||||||
ruleNodeId, ruleNodeType, fromVersion, toVersion);
|
ruleNodeId, ruleNodeType, fromVersion, toVersion);
|
||||||
try {
|
try {
|
||||||
TbPair<Boolean, JsonNode> upgradeResult = tbVersionedNode.upgrade(fromVersion, node.getConfiguration());
|
node.setConfiguration(TbNodeUpgradeUtils.upgradeRuleNodeConfiguration(node, ruleNodeClass.getAnnotation(),
|
||||||
if (upgradeResult.getFirst()) {
|
ruleNodeClass.getClazz()));
|
||||||
node.setConfiguration(upgradeResult.getSecond());
|
|
||||||
}
|
|
||||||
node.setConfigurationVersion(toVersion);
|
node.setConfigurationVersion(toVersion);
|
||||||
log.debug("Successfully upgrade rule node with id: {} type: {}, rule chain id: {} fromVersion: {} toVersion: {}",
|
log.debug("Successfully upgrade rule node with id: {} type: {}, rule chain id: {} fromVersion: {} toVersion: {}",
|
||||||
ruleNodeId, ruleNodeType, ruleChainId, 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;
|
package org.thingsboard.rule.engine.api.util;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
import org.thingsboard.common.util.JacksonUtil;
|
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) {
|
public static List<String> processPatterns(List<String> patterns, TbMsgMetaData metaData) {
|
||||||
if (!CollectionUtils.isEmpty(patterns)) {
|
if (!CollectionUtils.isEmpty(patterns)) {
|
||||||
return patterns.stream().map(p -> processPattern(p, metaData)).collect(Collectors.toList());
|
return patterns.stream().map(p -> processPattern(p, metaData)).collect(Collectors.toList());
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user