From 84ba42908b9e50d7977886edf453d26dc24a3081 Mon Sep 17 00:00:00 2001 From: ShvaykaD Date: Thu, 23 Nov 2023 11:43:59 +0200 Subject: [PATCH] moved save attributes node upgrade to sql file && minor changes to tests --- .../3.6.1/save_attributes_node_update.sql | 26 +++++++++++++++++++ .../install/SqlDatabaseUpgradeService.java | 10 ++----- .../engine/telemetry/TbMsgAttributesNode.java | 7 +++-- .../TbMsgAttributesNodeConfigurationTest.java | 2 +- .../telemetry/TbMsgAttributesNodeTest.java | 20 ++++++-------- 5 files changed, 40 insertions(+), 25 deletions(-) create mode 100644 application/src/main/data/upgrade/3.6.1/save_attributes_node_update.sql diff --git a/application/src/main/data/upgrade/3.6.1/save_attributes_node_update.sql b/application/src/main/data/upgrade/3.6.1/save_attributes_node_update.sql new file mode 100644 index 0000000000..dd1003ffe4 --- /dev/null +++ b/application/src/main/data/upgrade/3.6.1/save_attributes_node_update.sql @@ -0,0 +1,26 @@ +-- +-- 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. +-- + +UPDATE rule_node SET + configuration = (configuration::jsonb || jsonb_build_object( + 'notifyDevice', + CASE WHEN configuration::jsonb ->> 'notifyDevice' = 'false' THEN false ELSE true END, + 'sendAttributesUpdatedNotification', + CASE WHEN configuration::jsonb ->> 'sendAttributesUpdatedNotification' = 'true' THEN true ELSE false END, + 'updateAttributesOnlyOnValueChange', + CASE WHEN configuration::jsonb ->> 'updateAttributesOnlyOnValueChange' = 'false' THEN false ELSE true END)::jsonb)::varchar, + configuration_version = 2 +WHERE type = 'org.thingsboard.rule.engine.telemetry.TbMsgAttributesNode' AND configuration_version = 1; \ No newline at end of file diff --git a/application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java b/application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java index 3527822c4a..be337aa2c7 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java +++ b/application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java @@ -797,14 +797,8 @@ public class SqlDatabaseUpgradeService implements DatabaseEntitiesUpgradeService if (isOldSchema(conn, 3006001)) { log.info("Updating schema ..."); try { - conn.createStatement().execute("UPDATE rule_node SET " + - "configuration = (configuration::jsonb || jsonb_build_object(" + - "'notifyDevice', CASE WHEN configuration::jsonb ->> 'notifyDevice' = 'false' THEN false ELSE true END, " + - "'sendAttributesUpdatedNotification', CASE WHEN configuration::jsonb ->> 'sendAttributesUpdatedNotification' = 'true' THEN true ELSE false END, " + - "'updateAttributesOnlyOnValueChange', CASE WHEN configuration::jsonb ->> 'updateAttributesOnlyOnValueChange' = 'false' THEN false ELSE true END" + - ")::jsonb)::varchar, " + - "configuration_version = 2 " + - "WHERE type = 'org.thingsboard.rule.engine.telemetry.TbMsgAttributesNode' AND configuration_version = 1;"); + Path saveAttributesNodeUpdateFile = Paths.get(installScripts.getDataDir(), "upgrade", "3.6.1", "save_attributes_node_update.sql"); + loadSql(saveAttributesNodeUpdateFile, conn); } catch (Exception e) { log.warn("Failed to execute update script for save attributes rule nodes due to: ", e); } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java index 66fb0fbde9..da24485f18 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java @@ -120,7 +120,7 @@ public class TbMsgAttributesNode implements TbNode { msg.getOriginator(), scope, attributes, - config.isNotifyDevice() || checkNotifyDeviceMdValue(msg.getMetaData()), + config.isNotifyDevice() || checkNotifyDeviceMdValue(msg.getMetaData().getValue(NOTIFY_DEVICE_METADATA_KEY)), sendAttributesUpdateNotification ? new AttributesUpdateNodeCallback(ctx, msg, scope, attributes) : new TelemetryNodeCallback(ctx, msg) @@ -149,10 +149,9 @@ public class TbMsgAttributesNode implements TbNode { return config.isSendAttributesUpdatedNotification() && !CLIENT_SCOPE.equals(scope); } - private boolean checkNotifyDeviceMdValue(TbMsgMetaData md) { - var notifyDeviceMdStr = md.getValue(NOTIFY_DEVICE_METADATA_KEY); + private boolean checkNotifyDeviceMdValue(String notifyDeviceMdValue) { // Check for empty string for backward-compatibility. A while ago node always notified devices. - return StringUtils.isEmpty(notifyDeviceMdStr) || Boolean.parseBoolean(notifyDeviceMdStr); + return StringUtils.isEmpty(notifyDeviceMdValue) || Boolean.parseBoolean(notifyDeviceMdValue); } private String getScope(String mdScopeValue) { diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNodeConfigurationTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNodeConfigurationTest.java index 2bc2c0ba0e..07833607d4 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNodeConfigurationTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNodeConfigurationTest.java @@ -22,7 +22,7 @@ import static org.assertj.core.api.Assertions.assertThat; class TbMsgAttributesNodeConfigurationTest { @Test - void testDefaultConfig_givenupdateAttributesOnlyOnValueChange_thenTrue_sinceVersion1() { + void testDefaultConfig_givenUpdateAttributesOnlyOnValueChange_thenTrue_sinceVersion1() { assertThat(new TbMsgAttributesNodeConfiguration().defaultConfiguration().isUpdateAttributesOnlyOnValueChange()).isTrue(); } diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNodeTest.java index 60f31bd134..fe2edc941b 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNodeTest.java @@ -67,19 +67,19 @@ import static org.thingsboard.server.common.data.DataConstants.NOTIFY_DEVICE_MET @Slf4j class TbMsgAttributesNodeTest { - private static final DeviceId ORIGINATOR_ID = new DeviceId(UUID.randomUUID()); - private static final TenantId TENANT_ID = new TenantId(UUID.randomUUID()); - - TbMsgAttributesNode node; + private TenantId tenantId; + private DeviceId deviceId; + private TbMsgAttributesNode node; @BeforeEach void setUp() { + tenantId = new TenantId(UUID.fromString("6c18691e-4470-4766-9739-aface71d761f")); + deviceId = new DeviceId(UUID.fromString("b66159d7-c77e-45e8-bb41-a8f557f434c1")); node = spy(TbMsgAttributesNode.class); } @Test void testFilterChangedAttr_whenCurrentAttributesEmpty_thenReturnNewAttributes() { - node = spy(TbMsgAttributesNode.class); List newAttributes = new ArrayList<>(); List filtered = node.filterChangedAttr(Collections.emptyList(), newAttributes); @@ -88,7 +88,6 @@ class TbMsgAttributesNodeTest { @Test void testFilterChangedAttr_whenCurrentAttributesContainsInAnyOrderNewAttributes_thenReturnEmptyList() { - node = spy(TbMsgAttributesNode.class); List currentAttributes = List.of( new BaseAttributeKvEntry(1694000000L, new StringDataEntry("address", "Peremohy ave 1")), new BaseAttributeKvEntry(1694000000L, new BooleanDataEntry("valid", true)), @@ -109,7 +108,6 @@ class TbMsgAttributesNodeTest { @Test void testFilterChangedAttr_whenCurrentAttributesContainsInAnyOrderNewAttributes_thenReturnExpectedList() { - node = spy(TbMsgAttributesNode.class); List currentAttributes = List.of( new BaseAttributeKvEntry(1694000000L, new StringDataEntry("address", "Peremohy ave 1")), new BaseAttributeKvEntry(1694000000L, new BooleanDataEntry("valid", true)), @@ -148,7 +146,6 @@ class TbMsgAttributesNodeTest { @ParameterizedTest @MethodSource void givenNotifyDeviceMdValue_whenSaveAndNotify_thenVerifyExpectedArgumentForNotifyDeviceInSaveAndNotifyMethod(String mdValue, boolean expectedArgumentValue) throws TbNodeException { - node = spy(TbMsgAttributesNode.class); var ctxMock = mock(TbContext.class); var telemetryServiceMock = mock(RuleEngineTelemetryService.class); ObjectNode defaultConfig = (ObjectNode) JacksonUtil.valueToTree(new TbMsgAttributesNodeConfiguration().defaultConfiguration()); @@ -157,7 +154,7 @@ class TbMsgAttributesNodeTest { assertThat(defaultConfig.has("notifyDevice")).as("pre condition has notifyDevice").isTrue(); - when(ctxMock.getTenantId()).thenReturn(TENANT_ID); + when(ctxMock.getTenantId()).thenReturn(tenantId); when(ctxMock.getTelemetryService()).thenReturn(telemetryServiceMock); willCallRealMethod().given(node).init(any(TbContext.class), any(TbNodeConfiguration.class)); willCallRealMethod().given(node).saveAttr(any(), eq(ctxMock), any(TbMsg.class), anyString(), anyBoolean()); @@ -169,7 +166,7 @@ class TbMsgAttributesNodeTest { md.putValue(NOTIFY_DEVICE_METADATA_KEY, mdValue); } // dummy list with one ts kv to pass the empty list check. - var testTbMsg = TbMsg.newMsg(TbMsgType.POST_TELEMETRY_REQUEST, ORIGINATOR_ID, md, TbMsg.EMPTY_STRING); + var testTbMsg = TbMsg.newMsg(TbMsgType.POST_TELEMETRY_REQUEST, deviceId, md, TbMsg.EMPTY_STRING); List testAttrList = List.of(new BaseAttributeKvEntry(0L, new StringDataEntry("testKey", "testValue"))); node.saveAttr(testAttrList, ctxMock, testTbMsg, DataConstants.SHARED_SCOPE, false); @@ -177,7 +174,7 @@ class TbMsgAttributesNodeTest { ArgumentCaptor notifyDeviceCaptor = ArgumentCaptor.forClass(Boolean.class); verify(telemetryServiceMock, times(1)).saveAndNotify( - eq(TENANT_ID), eq(ORIGINATOR_ID), eq(DataConstants.SHARED_SCOPE), + eq(tenantId), eq(deviceId), eq(DataConstants.SHARED_SCOPE), eq(testAttrList), notifyDeviceCaptor.capture(), any() ); boolean notifyDevice = notifyDeviceCaptor.getValue(); @@ -230,7 +227,6 @@ class TbMsgAttributesNodeTest { @MethodSource void givenFromVersionAndConfig_whenUpgrade_thenVerifyHasChangesAndConfig(int givenVersion, String givenConfigStr, boolean hasChanges, String expectedConfigStr) throws TbNodeException { // GIVEN - node = spy(TbMsgAttributesNode.class); willCallRealMethod().given(node).upgrade(anyInt(), any()); JsonNode givenConfig = JacksonUtil.toJsonNode(givenConfigStr); JsonNode expectedConfig = JacksonUtil.toJsonNode(expectedConfigStr);