Browse Source

Used debugFailures and debugAll params instead of DebugStrategies

pull/11861/head
YevhenBondarenko 2 years ago
parent
commit
637fe2a258
  1. 27
      application/src/main/data/json/edge/rule_chains/edge_root_rule_chain.json
  2. 21
      application/src/main/data/json/tenant/device_profile/rule_chain_template.json
  3. 30
      application/src/main/data/json/tenant/rule_chains/root_rule_chain.json
  4. 6
      application/src/main/data/upgrade/3.8.1/schema_update.sql
  5. 17
      application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java
  6. 9
      application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleChainActorMessageProcessor.java
  7. 3
      application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeActorMessageProcessor.java
  8. 5
      application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/rule/BaseRuleChainMetadataConstructor.java
  9. 251
      application/src/test/java/org/thingsboard/server/actors/rule/DefaultTbContextTest.java
  10. 6
      application/src/test/java/org/thingsboard/server/edge/AbstractEdgeTest.java
  11. 3
      application/src/test/java/org/thingsboard/server/edge/RuleChainEdgeTest.java
  12. 11
      application/src/test/java/org/thingsboard/server/rules/flow/AbstractRuleEngineFlowIntegrationTest.java
  13. 3
      application/src/test/java/org/thingsboard/server/rules/lifecycle/AbstractRuleEngineLifecycleIntegrationTest.java
  14. 5
      application/src/test/java/org/thingsboard/server/service/housekeeper/HousekeeperServiceTest.java
  15. 9
      application/src/test/java/org/thingsboard/server/service/sync/ie/ExportImportServiceSqlTest.java
  16. 9
      application/src/test/java/org/thingsboard/server/service/sync/vc/VersionControlTest.java
  17. 70
      common/data/src/main/java/org/thingsboard/server/common/data/rule/DebugStrategy.java
  18. 19
      common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleNode.java
  19. 45
      common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleNodeDebugUtil.java
  20. 5
      common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/DefaultTenantProfileConfiguration.java
  21. 11
      common/edge-api/src/main/proto/edge.proto
  22. 3
      dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java
  23. 20
      dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleNodeEntity.java
  24. 21
      dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java
  25. 4
      dao/src/main/resources/sql/schema-entities.sql
  26. 54
      monitoring/src/main/resources/root_rule_chain.json
  27. 9
      msa/black-box-tests/src/test/resources/MqttRuleNodeTestMetadata.json
  28. 9
      msa/black-box-tests/src/test/resources/RpcResponseRuleChainMetadata.json

27
application/src/main/data/json/edge/rule_chains/edge_root_rule_chain.json

@ -20,7 +20,8 @@
}, },
"type": "org.thingsboard.rule.engine.profile.TbDeviceProfileNode", "type": "org.thingsboard.rule.engine.profile.TbDeviceProfileNode",
"name": "Device Profile Node", "name": "Device Profile Node",
"debugStrategy": "DISABLED", "debugFailures": false,
"debugAll": false,
"configuration": { "configuration": {
"persistAlarmRulesState": false, "persistAlarmRulesState": false,
"fetchAlarmRulesStateOnStart": false "fetchAlarmRulesStateOnStart": false
@ -34,7 +35,8 @@
}, },
"type": "org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode", "type": "org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode",
"name": "Save Timeseries", "name": "Save Timeseries",
"debugStrategy": "DISABLED", "debugFailures": false,
"debugAll": false,
"configuration": { "configuration": {
"defaultTTL": 0 "defaultTTL": 0
}, },
@ -47,7 +49,8 @@
}, },
"type": "org.thingsboard.rule.engine.telemetry.TbMsgAttributesNode", "type": "org.thingsboard.rule.engine.telemetry.TbMsgAttributesNode",
"name": "Save Client Attributes", "name": "Save Client Attributes",
"debugStrategy": "DISABLED", "debugFailures": false,
"debugAll": false,
"configurationVersion": 2, "configurationVersion": 2,
"configuration": { "configuration": {
"scope": "CLIENT_SCOPE", "scope": "CLIENT_SCOPE",
@ -64,7 +67,8 @@
}, },
"type": "org.thingsboard.rule.engine.filter.TbMsgTypeSwitchNode", "type": "org.thingsboard.rule.engine.filter.TbMsgTypeSwitchNode",
"name": "Message Type Switch", "name": "Message Type Switch",
"debugStrategy": "DISABLED", "debugFailures": false,
"debugAll": false,
"configuration": { "configuration": {
"version": 0 "version": 0
}, },
@ -77,7 +81,8 @@
}, },
"type": "org.thingsboard.rule.engine.action.TbLogNode", "type": "org.thingsboard.rule.engine.action.TbLogNode",
"name": "Log RPC from Device", "name": "Log RPC from Device",
"debugStrategy": "DISABLED", "debugFailures": false,
"debugAll": false,
"configuration": { "configuration": {
"scriptLang": "TBEL", "scriptLang": "TBEL",
"jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);", "jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);",
@ -92,7 +97,8 @@
}, },
"type": "org.thingsboard.rule.engine.action.TbLogNode", "type": "org.thingsboard.rule.engine.action.TbLogNode",
"name": "Log Other", "name": "Log Other",
"debugStrategy": "DISABLED", "debugFailures": false,
"debugAll": false,
"configuration": { "configuration": {
"scriptLang": "TBEL", "scriptLang": "TBEL",
"jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);", "jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);",
@ -107,7 +113,8 @@
}, },
"type": "org.thingsboard.rule.engine.rpc.TbSendRPCRequestNode", "type": "org.thingsboard.rule.engine.rpc.TbSendRPCRequestNode",
"name": "RPC Call Request", "name": "RPC Call Request",
"debugStrategy": "DISABLED", "debugFailures": false,
"debugAll": false,
"configuration": { "configuration": {
"timeoutInSeconds": 60 "timeoutInSeconds": 60
}, },
@ -120,7 +127,8 @@
}, },
"type": "org.thingsboard.rule.engine.edge.TbMsgPushToCloudNode", "type": "org.thingsboard.rule.engine.edge.TbMsgPushToCloudNode",
"name": "Push to cloud", "name": "Push to cloud",
"debugStrategy": "DISABLED", "debugFailures": false,
"debugAll": false,
"configuration": { "configuration": {
"scope": "SERVER_SCOPE" "scope": "SERVER_SCOPE"
}, },
@ -133,7 +141,8 @@
}, },
"type": "org.thingsboard.rule.engine.edge.TbMsgPushToCloudNode", "type": "org.thingsboard.rule.engine.edge.TbMsgPushToCloudNode",
"name": "Push to cloud", "name": "Push to cloud",
"debugStrategy": "DISABLED", "debugFailures": false,
"debugAll": false,
"configuration": { "configuration": {
"scope": "SERVER_SCOPE" "scope": "SERVER_SCOPE"
}, },

21
application/src/main/data/json/tenant/device_profile/rule_chain_template.json

@ -19,7 +19,8 @@
}, },
"type": "org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode", "type": "org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode",
"name": "Save Timeseries", "name": "Save Timeseries",
"debugStrategy": "DISABLED", "debugFailures": false,
"debugAll": false,
"configuration": { "configuration": {
"defaultTTL": 0 "defaultTTL": 0
} }
@ -31,7 +32,8 @@
}, },
"type": "org.thingsboard.rule.engine.telemetry.TbMsgAttributesNode", "type": "org.thingsboard.rule.engine.telemetry.TbMsgAttributesNode",
"name": "Save Client Attributes", "name": "Save Client Attributes",
"debugStrategy": "DISABLED", "debugFailures": false,
"debugAll": false,
"configurationVersion": 2, "configurationVersion": 2,
"configuration": { "configuration": {
"scope": "CLIENT_SCOPE", "scope": "CLIENT_SCOPE",
@ -47,7 +49,8 @@
}, },
"type": "org.thingsboard.rule.engine.filter.TbMsgTypeSwitchNode", "type": "org.thingsboard.rule.engine.filter.TbMsgTypeSwitchNode",
"name": "Message Type Switch", "name": "Message Type Switch",
"debugStrategy": "DISABLED", "debugFailures": false,
"debugAll": false,
"configuration": { "configuration": {
"version": 0 "version": 0
} }
@ -59,7 +62,8 @@
}, },
"type": "org.thingsboard.rule.engine.action.TbLogNode", "type": "org.thingsboard.rule.engine.action.TbLogNode",
"name": "Log RPC from Device", "name": "Log RPC from Device",
"debugStrategy": "DISABLED", "debugFailures": false,
"debugAll": false,
"configuration": { "configuration": {
"scriptLang": "TBEL", "scriptLang": "TBEL",
"jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);", "jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);",
@ -73,7 +77,8 @@
}, },
"type": "org.thingsboard.rule.engine.action.TbLogNode", "type": "org.thingsboard.rule.engine.action.TbLogNode",
"name": "Log Other", "name": "Log Other",
"debugStrategy": "DISABLED", "debugFailures": false,
"debugAll": false,
"configuration": { "configuration": {
"scriptLang": "TBEL", "scriptLang": "TBEL",
"jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);", "jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);",
@ -87,7 +92,8 @@
}, },
"type": "org.thingsboard.rule.engine.rpc.TbSendRPCRequestNode", "type": "org.thingsboard.rule.engine.rpc.TbSendRPCRequestNode",
"name": "RPC Call Request", "name": "RPC Call Request",
"debugStrategy": "DISABLED", "debugFailures": false,
"debugAll": false,
"configuration": { "configuration": {
"timeoutInSeconds": 60 "timeoutInSeconds": 60
} }
@ -100,7 +106,8 @@
}, },
"type": "org.thingsboard.rule.engine.profile.TbDeviceProfileNode", "type": "org.thingsboard.rule.engine.profile.TbDeviceProfileNode",
"name": "Device Profile Node", "name": "Device Profile Node",
"debugStrategy": "DISABLED", "debugFailures": false,
"debugAll": false,
"configuration": { "configuration": {
"persistAlarmRulesState": false, "persistAlarmRulesState": false,
"fetchAlarmRulesStateOnStart": false "fetchAlarmRulesStateOnStart": false

30
application/src/main/data/json/tenant/rule_chains/root_rule_chain.json

@ -18,7 +18,9 @@
}, },
"type": "org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode", "type": "org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode",
"name": "Save Timeseries", "name": "Save Timeseries",
"debugStrategy": "DISABLED", "debugFailures": false,
"debugAll": false,
"debugAllUntil": 0,
"configuration": { "configuration": {
"defaultTTL": 0 "defaultTTL": 0
} }
@ -30,7 +32,9 @@
}, },
"type": "org.thingsboard.rule.engine.telemetry.TbMsgAttributesNode", "type": "org.thingsboard.rule.engine.telemetry.TbMsgAttributesNode",
"name": "Save Client Attributes", "name": "Save Client Attributes",
"debugStrategy": "DISABLED", "debugFailures": false,
"debugAll": false,
"debugAllUntil": 0,
"configurationVersion": 2, "configurationVersion": 2,
"configuration": { "configuration": {
"scope": "CLIENT_SCOPE", "scope": "CLIENT_SCOPE",
@ -46,7 +50,9 @@
}, },
"type": "org.thingsboard.rule.engine.filter.TbMsgTypeSwitchNode", "type": "org.thingsboard.rule.engine.filter.TbMsgTypeSwitchNode",
"name": "Message Type Switch", "name": "Message Type Switch",
"debugStrategy": "DISABLED", "debugFailures": false,
"debugAll": false,
"debugAllUntil": 0,
"configuration": { "configuration": {
"version": 0 "version": 0
} }
@ -58,7 +64,9 @@
}, },
"type": "org.thingsboard.rule.engine.action.TbLogNode", "type": "org.thingsboard.rule.engine.action.TbLogNode",
"name": "Log RPC from Device", "name": "Log RPC from Device",
"debugStrategy": "DISABLED", "debugFailures": false,
"debugAll": false,
"debugAllUntil": 0,
"configuration": { "configuration": {
"scriptLang": "TBEL", "scriptLang": "TBEL",
"jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);", "jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);",
@ -72,7 +80,9 @@
}, },
"type": "org.thingsboard.rule.engine.action.TbLogNode", "type": "org.thingsboard.rule.engine.action.TbLogNode",
"name": "Log Other", "name": "Log Other",
"debugStrategy": "DISABLED", "debugFailures": false,
"debugAll": false,
"debugAllUntil": 0,
"configuration": { "configuration": {
"scriptLang": "TBEL", "scriptLang": "TBEL",
"jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);", "jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);",
@ -86,7 +96,9 @@
}, },
"type": "org.thingsboard.rule.engine.rpc.TbSendRPCRequestNode", "type": "org.thingsboard.rule.engine.rpc.TbSendRPCRequestNode",
"name": "RPC Call Request", "name": "RPC Call Request",
"debugStrategy": "DISABLED", "debugFailures": false,
"debugAll": false,
"debugAllUntil": 0,
"configuration": { "configuration": {
"timeoutInSeconds": 60 "timeoutInSeconds": 60
} }
@ -99,7 +111,9 @@
}, },
"type": "org.thingsboard.rule.engine.profile.TbDeviceProfileNode", "type": "org.thingsboard.rule.engine.profile.TbDeviceProfileNode",
"name": "Device Profile Node", "name": "Device Profile Node",
"debugStrategy": "DISABLED", "debugFailures": false,
"debugAll": false,
"debugAllUntil": 0,
"configuration": { "configuration": {
"persistAlarmRulesState": false, "persistAlarmRulesState": false,
"fetchAlarmRulesStateOnStart": false "fetchAlarmRulesStateOnStart": false
@ -140,4 +154,4 @@
], ],
"ruleChainConnections": null "ruleChainConnections": null
} }
} }

6
application/src/main/data/upgrade/3.8.1/schema_update.sql

@ -28,9 +28,9 @@ UPDATE tb_user SET additional_info = (additional_info::jsonb - 'lastLoginTs' - '
-- UPDATE RULE NODE DEBUG MODE TO DEBUG STRATEGY START -- UPDATE RULE NODE DEBUG MODE TO DEBUG STRATEGY START
ALTER TABLE rule_node ALTER TABLE rule_node
ADD COLUMN IF NOT EXISTS debug_strategy varchar(32) DEFAULT 'DISABLED'; ADD COLUMN IF NOT EXISTS debug_failures boolean DEFAULT false;
ALTER TABLE rule_node ALTER TABLE rule_node
ADD COLUMN IF NOT EXISTS last_update_ts bigint NOT NULL DEFAULT extract(epoch from now()) * 1000; ADD COLUMN IF NOT EXISTS debug_all_until bigint NOT NULL DEFAULT 0;
DO DO
$$ $$
BEGIN BEGIN
@ -38,7 +38,7 @@ $$
FROM information_schema.columns FROM information_schema.columns
WHERE table_name = 'rule_node' AND column_name = 'debug_mode') THEN WHERE table_name = 'rule_node' AND column_name = 'debug_mode') THEN
UPDATE rule_node UPDATE rule_node
SET debug_strategy = CASE WHEN debug_mode = true THEN 'ALL_EVENTS' ELSE 'DISABLED' END; SET debug_all_until = CASE WHEN debug_mode = true THEN extract(epoch from now() + 3600) * 1000 ELSE 0 END;
ALTER TABLE rule_node ALTER TABLE rule_node
DROP COLUMN debug_mode; DROP COLUMN debug_mode;
END IF; END IF;

17
application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java

@ -63,8 +63,8 @@ import org.thingsboard.server.common.data.msg.TbMsgType;
import org.thingsboard.server.common.data.msg.TbNodeConnectionType; import org.thingsboard.server.common.data.msg.TbNodeConnectionType;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.rule.DebugStrategy;
import org.thingsboard.server.common.data.rule.RuleNode; import org.thingsboard.server.common.data.rule.RuleNode;
import org.thingsboard.server.common.data.rule.RuleNodeDebugUtil;
import org.thingsboard.server.common.data.rule.RuleNodeState; import org.thingsboard.server.common.data.rule.RuleNodeState;
import org.thingsboard.server.common.data.script.ScriptLanguage; import org.thingsboard.server.common.data.script.ScriptLanguage;
import org.thingsboard.server.common.msg.TbActorMsg; import org.thingsboard.server.common.msg.TbActorMsg;
@ -1002,22 +1002,11 @@ public class DefaultTbContext implements TbContext {
private void persistDebugOutput(TbMsg msg, Set<String> relationTypes, Throwable error, String failureMessage) { private void persistDebugOutput(TbMsg msg, Set<String> relationTypes, Throwable error, String failureMessage) {
RuleNode ruleNode = nodeCtx.getSelf(); RuleNode ruleNode = nodeCtx.getSelf();
DebugStrategy debugStrategy = ruleNode.getDebugStrategy(); if (RuleNodeDebugUtil.isDebugAllAvailable(ruleNode)) {
if (debugStrategy.shouldPersistDebugOutputForAllEvents(ruleNode.getLastUpdateTs(), msg.getTs(), getMaxRuleNodeDebugDurationMinutes())) {
relationTypes.forEach(relationType -> mainCtx.persistDebugOutput(getTenantId(), ruleNode.getId(), msg, relationType, error, failureMessage)); relationTypes.forEach(relationType -> mainCtx.persistDebugOutput(getTenantId(), ruleNode.getId(), msg, relationType, error, failureMessage));
} else if (debugStrategy.shouldPersistDebugForFailureEvent(relationTypes)) { } else if (RuleNodeDebugUtil.isDebugFailuresAvailable(ruleNode, relationTypes)) {
mainCtx.persistDebugOutput(getTenantId(), ruleNode.getId(), msg, TbNodeConnectionType.FAILURE, error, failureMessage); mainCtx.persistDebugOutput(getTenantId(), ruleNode.getId(), msg, TbNodeConnectionType.FAILURE, error, failureMessage);
} }
} }
private int getMaxRuleNodeDebugDurationMinutes() {
if (nodeCtx.getSelf().getDebugStrategy().isHasDuration()) {
var configuration = mainCtx.getTenantProfileCache()
.get(getTenantId()).getProfileData().getConfiguration();
int systemMaxRuleNodeDebugModeDurationMinutes = mainCtx.getMaxRuleNodeDebugModeDurationMinutes();
return configuration.getMaxRuleNodeDebugModeDurationMinutes(systemMaxRuleNodeDebugModeDurationMinutes);
}
return 0;
}
} }

9
application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleChainActorMessageProcessor.java

@ -35,6 +35,7 @@ import org.thingsboard.server.common.data.relation.EntityRelation;
import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.common.data.rule.RuleChain;
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.rule.RuleNodeDebugUtil;
import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg;
import org.thingsboard.server.common.msg.plugin.RuleNodeUpdatedMsg; import org.thingsboard.server.common.msg.plugin.RuleNodeUpdatedMsg;
@ -255,13 +256,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
var originatorNodeId = envelope.getTargetRuleNodeId(); var originatorNodeId = envelope.getTargetRuleNodeId();
RuleNodeCtx ruleNodeCtx = nodeActors.get(originatorNodeId); RuleNodeCtx ruleNodeCtx = nodeActors.get(originatorNodeId);
if (ruleNodeCtx != null) { if (ruleNodeCtx != null) {
var ruleNode = ruleNodeCtx.getSelf(); if (RuleNodeDebugUtil.isDebugAvailable(ruleNodeCtx.getSelf(), envelope.getRelationType())) {
var debugStrategy = ruleNode.getDebugStrategy();
int maxRuleNodeDebugModeDurationMinutes = getTenantProfileConfiguration()
.getMaxRuleNodeDebugModeDurationMinutes(systemContext.getMaxRuleNodeDebugModeDurationMinutes());
boolean shouldPersistDebugOutput = debugStrategy.shouldPersistDebugOutputForAllEvents(ruleNode.getLastUpdateTs(), tbMsg.getTs(), maxRuleNodeDebugModeDurationMinutes) ||
debugStrategy.shouldPersistDebugForFailureEvent(envelope.getRelationType());
if (shouldPersistDebugOutput) {
systemContext.persistDebugOutput(tenantId, originatorNodeId, tbMsg, envelope.getRelationType()); systemContext.persistDebugOutput(tenantId, originatorNodeId, tbMsg, envelope.getRelationType());
} }
} }

3
application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeActorMessageProcessor.java

@ -27,6 +27,7 @@ import org.thingsboard.server.common.data.id.RuleNodeId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.plugin.ComponentLifecycleState; import org.thingsboard.server.common.data.plugin.ComponentLifecycleState;
import org.thingsboard.server.common.data.rule.RuleNode; import org.thingsboard.server.common.data.rule.RuleNode;
import org.thingsboard.server.common.data.rule.RuleNodeDebugUtil;
import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; import org.thingsboard.server.common.msg.queue.PartitionChangeMsg;
import org.thingsboard.server.common.msg.queue.RuleNodeException; import org.thingsboard.server.common.msg.queue.RuleNodeException;
@ -218,7 +219,7 @@ public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor<RuleNod
} }
private void persistDebugInputIfAllowed(TbMsg msg, String fromNodeConnectionType, int debugModeDurationMinutes) { private void persistDebugInputIfAllowed(TbMsg msg, String fromNodeConnectionType, int debugModeDurationMinutes) {
if (ruleNode.getDebugStrategy().shouldPersistDebugInput(ruleNode.getLastUpdateTs(), msg.getTs(), debugModeDurationMinutes)) { if (RuleNodeDebugUtil.isDebugAllAvailable(ruleNode)) {
systemContext.persistDebugInput(tenantId, entityId, msg, fromNodeConnectionType); systemContext.persistDebugInput(tenantId, entityId, msg, fromNodeConnectionType);
} }
} }

5
application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/rule/BaseRuleChainMetadataConstructor.java

@ -24,7 +24,6 @@ import org.thingsboard.server.common.data.rule.NodeConnectionInfo;
import org.thingsboard.server.common.data.rule.RuleChainConnectionInfo; import org.thingsboard.server.common.data.rule.RuleChainConnectionInfo;
import org.thingsboard.server.common.data.rule.RuleChainMetaData; import org.thingsboard.server.common.data.rule.RuleChainMetaData;
import org.thingsboard.server.common.data.rule.RuleNode; import org.thingsboard.server.common.data.rule.RuleNode;
import org.thingsboard.server.gen.edge.v1.DebugStrategy;
import org.thingsboard.server.gen.edge.v1.EdgeVersion; import org.thingsboard.server.gen.edge.v1.EdgeVersion;
import org.thingsboard.server.gen.edge.v1.NodeConnectionInfoProto; import org.thingsboard.server.gen.edge.v1.NodeConnectionInfoProto;
import org.thingsboard.server.gen.edge.v1.RuleChainConnectionInfoProto; import org.thingsboard.server.gen.edge.v1.RuleChainConnectionInfoProto;
@ -89,8 +88,8 @@ public abstract class BaseRuleChainMetadataConstructor implements RuleChainMetad
.setIdLSB(node.getId().getId().getLeastSignificantBits()) .setIdLSB(node.getId().getId().getLeastSignificantBits())
.setType(node.getType()) .setType(node.getType())
.setName(node.getName()) .setName(node.getName())
.setLastUpdateTs(node.getLastUpdateTs()) .setDebugFailures(node.isDebugFailures())
.setDebugStrategy(DebugStrategy.forNumber(node.getDebugStrategy().getProtoNumber())) .setDebugAllUntil(node.getDebugAllUntil())
.setConfiguration(JacksonUtil.toString(node.getConfiguration())) .setConfiguration(JacksonUtil.toString(node.getConfiguration()))
.setAdditionalInfo(JacksonUtil.toString(node.getAdditionalInfo())) .setAdditionalInfo(JacksonUtil.toString(node.getAdditionalInfo()))
.setSingletonMode(node.isSingletonMode()) .setSingletonMode(node.isSingletonMode())

251
application/src/test/java/org/thingsboard/server/actors/rule/DefaultTbContextTest.java

@ -34,24 +34,19 @@ import org.thingsboard.server.actors.ruleChain.RuleNodeCtx;
import org.thingsboard.server.actors.ruleChain.RuleNodeToRuleChainTellNextMsg; import org.thingsboard.server.actors.ruleChain.RuleNodeToRuleChainTellNextMsg;
import org.thingsboard.server.cluster.TbClusterService; import org.thingsboard.server.cluster.TbClusterService;
import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.DataConstants;
import org.thingsboard.server.common.data.TenantProfile;
import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.id.RuleNodeId; import org.thingsboard.server.common.data.id.RuleNodeId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.msg.TbMsgType; import org.thingsboard.server.common.data.msg.TbMsgType;
import org.thingsboard.server.common.data.msg.TbNodeConnectionType; import org.thingsboard.server.common.data.msg.TbNodeConnectionType;
import org.thingsboard.server.common.data.rule.DebugStrategy;
import org.thingsboard.server.common.data.rule.RuleNode; import org.thingsboard.server.common.data.rule.RuleNode;
import org.thingsboard.server.common.data.tenant.profile.TenantProfileConfiguration;
import org.thingsboard.server.common.data.tenant.profile.TenantProfileData;
import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.TbMsgMetaData; import org.thingsboard.server.common.msg.TbMsgMetaData;
import org.thingsboard.server.common.msg.TbMsgProcessingStackItem; import org.thingsboard.server.common.msg.TbMsgProcessingStackItem;
import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.common.msg.queue.ServiceType;
import org.thingsboard.server.common.msg.queue.TbMsgCallback; import org.thingsboard.server.common.msg.queue.TbMsgCallback;
import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; import org.thingsboard.server.common.msg.queue.TopicPartitionInfo;
import org.thingsboard.server.dao.tenant.TbTenantProfileCache;
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg;
import org.thingsboard.server.queue.common.SimpleTbQueueCallback; import org.thingsboard.server.queue.common.SimpleTbQueueCallback;
@ -59,13 +54,13 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.ArgumentMatchers.isNull;
@ -75,7 +70,6 @@ import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.then; import static org.mockito.BDDMockito.then;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never; import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
@SuppressWarnings("ResultOfMethodCallIgnored") @SuppressWarnings("ResultOfMethodCallIgnored")
@ -104,13 +98,14 @@ class DefaultTbContextTest {
} }
@Test @Test
public void givenDebugStrategyOnlyFailureEvents_whenTellSuccess_thenVerifyDebugOutputNotPersisted() { public void givenDebugFailuresEvents_whenTellSuccess_thenVerifyDebugOutputNotPersisted() {
// GIVEN // GIVEN
var callbackMock = mock(TbMsgCallback.class); var callbackMock = mock(TbMsgCallback.class);
var msg = getTbMsgWithCallback(callbackMock); var msg = getTbMsgWithCallback(callbackMock);
var ruleNode = new RuleNode(RULE_NODE_ID); var ruleNode = new RuleNode(RULE_NODE_ID);
ruleNode.setRuleChainId(RULE_CHAIN_ID); ruleNode.setRuleChainId(RULE_CHAIN_ID);
ruleNode.setDebugStrategy(DebugStrategy.ONLY_FAILURE_EVENTS); ruleNode.setDebugFailures(true);
ruleNode.setDebugAllUntil(0);
given(nodeCtxMock.getSelf()).willReturn(ruleNode); given(nodeCtxMock.getSelf()).willReturn(ruleNode);
given(nodeCtxMock.getChainActor()).willReturn(chainActorMock); given(nodeCtxMock.getChainActor()).willReturn(chainActorMock);
@ -125,13 +120,14 @@ class DefaultTbContextTest {
} }
@Test @Test
public void givenDebugStrategyOnlyFailureEventsAndSuccessConnection_whenTellNext_thenVerifyDebugOutputNotPersisted() { public void givenDebugFailuresEventsAndSuccessConnection_whenTellNext_thenVerifyDebugOutputNotPersisted() {
// GIVEN // GIVEN
var callbackMock = mock(TbMsgCallback.class); var callbackMock = mock(TbMsgCallback.class);
var msg = getTbMsgWithCallback(callbackMock); var msg = getTbMsgWithCallback(callbackMock);
var ruleNode = new RuleNode(RULE_NODE_ID); var ruleNode = new RuleNode(RULE_NODE_ID);
ruleNode.setRuleChainId(RULE_CHAIN_ID); ruleNode.setRuleChainId(RULE_CHAIN_ID);
ruleNode.setDebugStrategy(DebugStrategy.ONLY_FAILURE_EVENTS); ruleNode.setDebugFailures(true);
ruleNode.setDebugAllUntil(0);
given(nodeCtxMock.getSelf()).willReturn(ruleNode); given(nodeCtxMock.getSelf()).willReturn(ruleNode);
given(nodeCtxMock.getChainActor()).willReturn(chainActorMock); given(nodeCtxMock.getChainActor()).willReturn(chainActorMock);
@ -147,13 +143,14 @@ class DefaultTbContextTest {
@MethodSource @MethodSource
@ParameterizedTest @ParameterizedTest
void givenDebugStrategyOnlyFailureEventsAndConnections_whenTellNext_thenVerifyDebugOutputPersisted(Set<String> connections) { void givenDebugFailuresEventsAndConnections_whenTellNext_thenVerifyDebugOutputPersisted(Set<String> connections) {
// GIVEN // GIVEN
var callbackMock = mock(TbMsgCallback.class); var callbackMock = mock(TbMsgCallback.class);
var msg = getTbMsgWithCallback(callbackMock); var msg = getTbMsgWithCallback(callbackMock);
var ruleNode = new RuleNode(RULE_NODE_ID); var ruleNode = new RuleNode(RULE_NODE_ID);
ruleNode.setRuleChainId(RULE_CHAIN_ID); ruleNode.setRuleChainId(RULE_CHAIN_ID);
ruleNode.setDebugStrategy(DebugStrategy.ONLY_FAILURE_EVENTS); ruleNode.setDebugFailures(true);
ruleNode.setDebugAllUntil(0);
given(nodeCtxMock.getTenantId()).willReturn(TENANT_ID); given(nodeCtxMock.getTenantId()).willReturn(TENANT_ID);
given(nodeCtxMock.getSelf()).willReturn(ruleNode); given(nodeCtxMock.getSelf()).willReturn(ruleNode);
given(nodeCtxMock.getChainActor()).willReturn(chainActorMock); given(nodeCtxMock.getChainActor()).willReturn(chainActorMock);
@ -169,7 +166,7 @@ class DefaultTbContextTest {
checkTellNextCommonLogic(callbackMock, connections, msg); checkTellNextCommonLogic(callbackMock, connections, msg);
} }
private static Stream<Set<String>> givenDebugStrategyOnlyFailureEventsAndConnections_whenTellNext_thenVerifyDebugOutputPersisted() { private static Stream<Set<String>> givenDebugFailuresEventsAndConnections_whenTellNext_thenVerifyDebugOutputPersisted() {
return Stream.of( return Stream.of(
Collections.singleton(TbNodeConnectionType.FAILURE), Collections.singleton(TbNodeConnectionType.FAILURE),
Set.of(TbNodeConnectionType.FAILURE, TbNodeConnectionType.SUCCESS) Set.of(TbNodeConnectionType.FAILURE, TbNodeConnectionType.SUCCESS)
@ -178,13 +175,14 @@ class DefaultTbContextTest {
@MethodSource @MethodSource
@ParameterizedTest @ParameterizedTest
void givenDebugStrategyDisabledAndConnections_whenTellNext_thenVerifyDebugOutputNotPersisted(Set<String> connections) { void givenDebugDisabledAndConnections_whenTellNext_thenVerifyDebugOutputNotPersisted(Set<String> connections) {
// GIVEN // GIVEN
var callbackMock = mock(TbMsgCallback.class); var callbackMock = mock(TbMsgCallback.class);
var msg = getTbMsgWithCallback(callbackMock); var msg = getTbMsgWithCallback(callbackMock);
var ruleNode = new RuleNode(RULE_NODE_ID); var ruleNode = new RuleNode(RULE_NODE_ID);
ruleNode.setRuleChainId(RULE_CHAIN_ID); ruleNode.setRuleChainId(RULE_CHAIN_ID);
ruleNode.setDebugStrategy(DebugStrategy.DISABLED); ruleNode.setDebugFailures(false);
ruleNode.setDebugAllUntil(0);
given(nodeCtxMock.getSelf()).willReturn(ruleNode); given(nodeCtxMock.getSelf()).willReturn(ruleNode);
given(nodeCtxMock.getChainActor()).willReturn(chainActorMock); given(nodeCtxMock.getChainActor()).willReturn(chainActorMock);
@ -198,7 +196,7 @@ class DefaultTbContextTest {
checkTellNextCommonLogic(callbackMock, connections, msg); checkTellNextCommonLogic(callbackMock, connections, msg);
} }
private static Stream<Set<String>> givenDebugStrategyDisabledAndConnections_whenTellNext_thenVerifyDebugOutputNotPersisted() { private static Stream<Set<String>> givenDebugDisabledAndConnections_whenTellNext_thenVerifyDebugOutputNotPersisted() {
return Stream.of( return Stream.of(
Collections.singleton(TbNodeConnectionType.FAILURE), Collections.singleton(TbNodeConnectionType.FAILURE),
Collections.singleton(TbNodeConnectionType.SUCCESS), Collections.singleton(TbNodeConnectionType.SUCCESS),
@ -208,18 +206,17 @@ class DefaultTbContextTest {
@MethodSource @MethodSource
@ParameterizedTest @ParameterizedTest
void givenDebugStrategyAllEventsAndConnection_whenTellNext_thenVerifyDebugOutputPersisted(String connection) { void givenDebugAllEventsAndConnection_whenTellNext_thenVerifyDebugOutputPersisted(String connection) {
// GIVEN // GIVEN
var callbackMock = mock(TbMsgCallback.class); var callbackMock = mock(TbMsgCallback.class);
var msg = getTbMsgWithCallback(callbackMock); var msg = getTbMsgWithCallback(callbackMock);
var ruleNode = new RuleNode(RULE_NODE_ID); var ruleNode = new RuleNode(RULE_NODE_ID);
ruleNode.setRuleChainId(RULE_CHAIN_ID); ruleNode.setRuleChainId(RULE_CHAIN_ID);
ruleNode.setLastUpdateTs(System.currentTimeMillis()); ruleNode.setDebugFailures(false);
ruleNode.setDebugStrategy(DebugStrategy.ALL_EVENTS); ruleNode.setDebugAllUntil(getUntilTime());
given(nodeCtxMock.getTenantId()).willReturn(TENANT_ID); given(nodeCtxMock.getTenantId()).willReturn(TENANT_ID);
given(nodeCtxMock.getSelf()).willReturn(ruleNode); given(nodeCtxMock.getSelf()).willReturn(ruleNode);
given(nodeCtxMock.getChainActor()).willReturn(chainActorMock); given(nodeCtxMock.getChainActor()).willReturn(chainActorMock);
mockGetMaxRuleNodeDebugModeDurationMinutes();
// WHEN // WHEN
defaultTbContext.tellNext(msg, connection); defaultTbContext.tellNext(msg, connection);
@ -227,30 +224,27 @@ class DefaultTbContextTest {
// THEN // THEN
then(nodeCtxMock).should().getChainActor(); then(nodeCtxMock).should().getChainActor();
then(nodeCtxMock).shouldHaveNoMoreInteractions(); then(nodeCtxMock).shouldHaveNoMoreInteractions();
then(mainCtxMock).should().getTenantProfileCache();
then(mainCtxMock).should().getMaxRuleNodeDebugModeDurationMinutes();
then(mainCtxMock).should().persistDebugOutput(TENANT_ID, RULE_NODE_ID, msg, connection, null, null); then(mainCtxMock).should().persistDebugOutput(TENANT_ID, RULE_NODE_ID, msg, connection, null, null);
then(mainCtxMock).shouldHaveNoMoreInteractions(); then(mainCtxMock).shouldHaveNoMoreInteractions();
checkTellNextCommonLogic(callbackMock, connection, msg); checkTellNextCommonLogic(callbackMock, connection, msg);
} }
private static Stream<String> givenDebugStrategyAllEventsAndConnection_whenTellNext_thenVerifyDebugOutputPersisted() { private static Stream<String> givenDebugAllEventsAndConnection_whenTellNext_thenVerifyDebugOutputPersisted() {
return failureAndSuccessConnection(); return failureAndSuccessConnection();
} }
@Test @Test
public void givenDebugStrategyAllEventsAndFailureAndSuccessConnection_whenTellNext_thenVerifyDebugOutputPersistedForAllEvents() { public void givenDebugAllEventsAndFailureAndSuccessConnection_whenTellNext_thenVerifyDebugOutputPersistedForAllEvents() {
// GIVEN // GIVEN
var callbackMock = mock(TbMsgCallback.class); var callbackMock = mock(TbMsgCallback.class);
var msg = getTbMsgWithCallback(callbackMock); var msg = getTbMsgWithCallback(callbackMock);
var ruleNode = new RuleNode(RULE_NODE_ID); var ruleNode = new RuleNode(RULE_NODE_ID);
ruleNode.setRuleChainId(RULE_CHAIN_ID); ruleNode.setRuleChainId(RULE_CHAIN_ID);
ruleNode.setLastUpdateTs(System.currentTimeMillis()); ruleNode.setDebugFailures(false);
ruleNode.setDebugStrategy(DebugStrategy.ALL_EVENTS); ruleNode.setDebugAllUntil(getUntilTime());
given(nodeCtxMock.getTenantId()).willReturn(TENANT_ID); given(nodeCtxMock.getTenantId()).willReturn(TENANT_ID);
given(nodeCtxMock.getSelf()).willReturn(ruleNode); given(nodeCtxMock.getSelf()).willReturn(ruleNode);
given(nodeCtxMock.getChainActor()).willReturn(chainActorMock); given(nodeCtxMock.getChainActor()).willReturn(chainActorMock);
mockGetMaxRuleNodeDebugModeDurationMinutes();
// WHEN // WHEN
Set<String> connections = failureAndSuccessConnection().collect(Collectors.toSet()); Set<String> connections = failureAndSuccessConnection().collect(Collectors.toSet());
@ -259,8 +253,6 @@ class DefaultTbContextTest {
// THEN // THEN
then(nodeCtxMock).should().getChainActor(); then(nodeCtxMock).should().getChainActor();
then(nodeCtxMock).shouldHaveNoMoreInteractions(); then(nodeCtxMock).shouldHaveNoMoreInteractions();
then(mainCtxMock).should().getTenantProfileCache();
then(mainCtxMock).should().getMaxRuleNodeDebugModeDurationMinutes();
var nodeConnectionsCaptor = ArgumentCaptor.forClass(String.class); var nodeConnectionsCaptor = ArgumentCaptor.forClass(String.class);
int wantedNumberOfInvocations = connections.size(); int wantedNumberOfInvocations = connections.size();
then(mainCtxMock).should(times(wantedNumberOfInvocations)).persistDebugOutput(eq(TENANT_ID), eq(RULE_NODE_ID), eq(msg), nodeConnectionsCaptor.capture(), nullable(Throwable.class), nullable(String.class)); then(mainCtxMock).should(times(wantedNumberOfInvocations)).persistDebugOutput(eq(TENANT_ID), eq(RULE_NODE_ID), eq(msg), nodeConnectionsCaptor.capture(), nullable(Throwable.class), nullable(String.class));
@ -272,18 +264,17 @@ class DefaultTbContextTest {
@MethodSource @MethodSource
@ParameterizedTest @ParameterizedTest
void givenDebugStrategyAllThenOnlyFailureEventsAndConnection_whenTellNext_thenVerifyDebugOutputPersisted(String connection) { void givenDebugAllThenOnlyFailureEventsAndConnection_whenTellNext_thenVerifyDebugOutputPersisted(String connection) {
// GIVEN // GIVEN
var callbackMock = mock(TbMsgCallback.class); var callbackMock = mock(TbMsgCallback.class);
var msg = getTbMsgWithCallback(callbackMock); var msg = getTbMsgWithCallback(callbackMock);
var ruleNode = new RuleNode(RULE_NODE_ID); var ruleNode = new RuleNode(RULE_NODE_ID);
ruleNode.setRuleChainId(RULE_CHAIN_ID); ruleNode.setRuleChainId(RULE_CHAIN_ID);
ruleNode.setLastUpdateTs(System.currentTimeMillis()); ruleNode.setDebugFailures(false);
ruleNode.setDebugStrategy(DebugStrategy.ALL_THEN_ONLY_FAILURE_EVENTS); ruleNode.setDebugAllUntil(getUntilTime());
given(nodeCtxMock.getTenantId()).willReturn(TENANT_ID); given(nodeCtxMock.getTenantId()).willReturn(TENANT_ID);
given(nodeCtxMock.getSelf()).willReturn(ruleNode); given(nodeCtxMock.getSelf()).willReturn(ruleNode);
given(nodeCtxMock.getChainActor()).willReturn(chainActorMock); given(nodeCtxMock.getChainActor()).willReturn(chainActorMock);
mockGetMaxRuleNodeDebugModeDurationMinutes();
// WHEN // WHEN
defaultTbContext.tellNext(msg, connection); defaultTbContext.tellNext(msg, connection);
@ -291,30 +282,27 @@ class DefaultTbContextTest {
// THEN // THEN
then(nodeCtxMock).should().getChainActor(); then(nodeCtxMock).should().getChainActor();
then(nodeCtxMock).shouldHaveNoMoreInteractions(); then(nodeCtxMock).shouldHaveNoMoreInteractions();
then(mainCtxMock).should().getTenantProfileCache();
then(mainCtxMock).should().getMaxRuleNodeDebugModeDurationMinutes();
then(mainCtxMock).should().persistDebugOutput(TENANT_ID, RULE_NODE_ID, msg, connection, null, null); then(mainCtxMock).should().persistDebugOutput(TENANT_ID, RULE_NODE_ID, msg, connection, null, null);
then(mainCtxMock).shouldHaveNoMoreInteractions(); then(mainCtxMock).shouldHaveNoMoreInteractions();
checkTellNextCommonLogic(callbackMock, connection, msg); checkTellNextCommonLogic(callbackMock, connection, msg);
} }
private static Stream<String> givenDebugStrategyAllThenOnlyFailureEventsAndConnection_whenTellNext_thenVerifyDebugOutputPersisted() { private static Stream<String> givenDebugAllThenOnlyFailureEventsAndConnection_whenTellNext_thenVerifyDebugOutputPersisted() {
return failureAndSuccessConnection(); return failureAndSuccessConnection();
} }
@Test @Test
public void givenDebugStrategyAllThenOnlyEventsAndFailureAndSuccessConnection_whenTellNext_thenVerifyDebugOutputPersistedForAllEvents() { public void givenDebugAllThenOnlyEventsAndFailureAndSuccessConnection_whenTellNext_thenVerifyDebugOutputPersistedForAllEvents() {
// GIVEN // GIVEN
var callbackMock = mock(TbMsgCallback.class); var callbackMock = mock(TbMsgCallback.class);
var msg = getTbMsgWithCallback(callbackMock); var msg = getTbMsgWithCallback(callbackMock);
var ruleNode = new RuleNode(RULE_NODE_ID); var ruleNode = new RuleNode(RULE_NODE_ID);
ruleNode.setRuleChainId(RULE_CHAIN_ID); ruleNode.setRuleChainId(RULE_CHAIN_ID);
ruleNode.setLastUpdateTs(System.currentTimeMillis()); ruleNode.setDebugFailures(true);
ruleNode.setDebugStrategy(DebugStrategy.ALL_THEN_ONLY_FAILURE_EVENTS); ruleNode.setDebugAllUntil(getUntilTime());
given(nodeCtxMock.getTenantId()).willReturn(TENANT_ID); given(nodeCtxMock.getTenantId()).willReturn(TENANT_ID);
given(nodeCtxMock.getSelf()).willReturn(ruleNode); given(nodeCtxMock.getSelf()).willReturn(ruleNode);
given(nodeCtxMock.getChainActor()).willReturn(chainActorMock); given(nodeCtxMock.getChainActor()).willReturn(chainActorMock);
mockGetMaxRuleNodeDebugModeDurationMinutes();
// WHEN // WHEN
Set<String> connections = failureAndSuccessConnection().collect(Collectors.toSet()); Set<String> connections = failureAndSuccessConnection().collect(Collectors.toSet());
@ -323,8 +311,6 @@ class DefaultTbContextTest {
// THEN // THEN
then(nodeCtxMock).should().getChainActor(); then(nodeCtxMock).should().getChainActor();
then(nodeCtxMock).shouldHaveNoMoreInteractions(); then(nodeCtxMock).shouldHaveNoMoreInteractions();
then(mainCtxMock).should().getTenantProfileCache();
then(mainCtxMock).should().getMaxRuleNodeDebugModeDurationMinutes();
var nodeConnectionsCaptor = ArgumentCaptor.forClass(String.class); var nodeConnectionsCaptor = ArgumentCaptor.forClass(String.class);
int wantedNumberOfInvocations = connections.size(); int wantedNumberOfInvocations = connections.size();
then(mainCtxMock).should(times(wantedNumberOfInvocations)).persistDebugOutput(eq(TENANT_ID), eq(RULE_NODE_ID), eq(msg), nodeConnectionsCaptor.capture(), nullable(Throwable.class), nullable(String.class)); then(mainCtxMock).should(times(wantedNumberOfInvocations)).persistDebugOutput(eq(TENANT_ID), eq(RULE_NODE_ID), eq(msg), nodeConnectionsCaptor.capture(), nullable(Throwable.class), nullable(String.class));
@ -339,12 +325,12 @@ class DefaultTbContextTest {
} }
@Test @Test
public void givenDebugStrategyOnlyFailureEventsAndFailureConnection_whenOutput_thenVerifyDebugOutputPersisted() { public void givenDebugFailuresEventsAndFailureConnection_whenOutput_thenVerifyDebugOutputPersisted() {
// GIVEN // GIVEN
var msgMock = mock(TbMsg.class); var msgMock = mock(TbMsg.class);
var ruleNode = new RuleNode(RULE_NODE_ID); var ruleNode = new RuleNode(RULE_NODE_ID);
ruleNode.setRuleChainId(RULE_CHAIN_ID); ruleNode.setRuleChainId(RULE_CHAIN_ID);
ruleNode.setDebugStrategy(DebugStrategy.ONLY_FAILURE_EVENTS); ruleNode.setDebugFailures(true);
given(msgMock.popFormStack()).willReturn(new TbMsgProcessingStackItem(RULE_CHAIN_ID, RULE_NODE_ID)); given(msgMock.popFormStack()).willReturn(new TbMsgProcessingStackItem(RULE_CHAIN_ID, RULE_NODE_ID));
given(nodeCtxMock.getTenantId()).willReturn(TENANT_ID); given(nodeCtxMock.getTenantId()).willReturn(TENANT_ID);
given(nodeCtxMock.getSelf()).willReturn(ruleNode); given(nodeCtxMock.getSelf()).willReturn(ruleNode);
@ -361,12 +347,12 @@ class DefaultTbContextTest {
} }
@Test @Test
public void givenDebugStrategyOnlyFailureEventsAndSuccessConnection_whenOutput_thenVerifyDebugOutputNotPersisted() { public void givenDebugFailuresEventsAndSuccessConnection_whenOutput_thenVerifyDebugOutputNotPersisted() {
// GIVEN // GIVEN
var msgMock = mock(TbMsg.class); var msgMock = mock(TbMsg.class);
var ruleNode = new RuleNode(RULE_NODE_ID); var ruleNode = new RuleNode(RULE_NODE_ID);
ruleNode.setRuleChainId(RULE_CHAIN_ID); ruleNode.setRuleChainId(RULE_CHAIN_ID);
ruleNode.setDebugStrategy(DebugStrategy.ONLY_FAILURE_EVENTS); ruleNode.setDebugFailures(true);
given(msgMock.popFormStack()).willReturn(new TbMsgProcessingStackItem(RULE_CHAIN_ID, RULE_NODE_ID)); given(msgMock.popFormStack()).willReturn(new TbMsgProcessingStackItem(RULE_CHAIN_ID, RULE_NODE_ID));
given(nodeCtxMock.getSelf()).willReturn(ruleNode); given(nodeCtxMock.getSelf()).willReturn(ruleNode);
given(nodeCtxMock.getChainActor()).willReturn(chainActorMock); given(nodeCtxMock.getChainActor()).willReturn(chainActorMock);
@ -382,12 +368,13 @@ class DefaultTbContextTest {
@ParameterizedTest @ParameterizedTest
@ValueSource(strings = {TbNodeConnectionType.SUCCESS, TbNodeConnectionType.FAILURE}) @ValueSource(strings = {TbNodeConnectionType.SUCCESS, TbNodeConnectionType.FAILURE})
void givenDebugStrategyDisabled_whenOutput_thenVerifyDebugOutputNotPersisted(String nodeConnection) { void givenDebugDisabled_whenOutput_thenVerifyDebugOutputNotPersisted(String nodeConnection) {
// GIVEN // GIVEN
var msgMock = mock(TbMsg.class); var msgMock = mock(TbMsg.class);
var ruleNode = new RuleNode(RULE_NODE_ID); var ruleNode = new RuleNode(RULE_NODE_ID);
ruleNode.setRuleChainId(RULE_CHAIN_ID); ruleNode.setRuleChainId(RULE_CHAIN_ID);
ruleNode.setDebugStrategy(DebugStrategy.DISABLED); ruleNode.setDebugFailures(false);
ruleNode.setDebugAllUntil(0);
given(msgMock.popFormStack()).willReturn(new TbMsgProcessingStackItem(RULE_CHAIN_ID, RULE_NODE_ID)); given(msgMock.popFormStack()).willReturn(new TbMsgProcessingStackItem(RULE_CHAIN_ID, RULE_NODE_ID));
given(nodeCtxMock.getSelf()).willReturn(ruleNode); given(nodeCtxMock.getSelf()).willReturn(ruleNode);
given(nodeCtxMock.getChainActor()).willReturn(chainActorMock); given(nodeCtxMock.getChainActor()).willReturn(chainActorMock);
@ -403,25 +390,23 @@ class DefaultTbContextTest {
@ParameterizedTest @ParameterizedTest
@ValueSource(strings = {TbNodeConnectionType.SUCCESS, TbNodeConnectionType.FAILURE}) @ValueSource(strings = {TbNodeConnectionType.SUCCESS, TbNodeConnectionType.FAILURE})
void givenDebugStrategyAllEvents_whenOutput_thenVerifyDebugOutputPersisted(String nodeConnection) { void givenDebugAllEvents_whenOutput_thenVerifyDebugOutputPersisted(String nodeConnection) {
// GIVEN // GIVEN
var msgMock = mock(TbMsg.class); var msgMock = mock(TbMsg.class);
var ruleNode = new RuleNode(RULE_NODE_ID); var ruleNode = new RuleNode(RULE_NODE_ID);
ruleNode.setRuleChainId(RULE_CHAIN_ID); ruleNode.setRuleChainId(RULE_CHAIN_ID);
ruleNode.setDebugStrategy(DebugStrategy.ALL_EVENTS); ruleNode.setDebugFailures(false);
ruleNode.setDebugAllUntil(getUntilTime());
given(msgMock.popFormStack()).willReturn(new TbMsgProcessingStackItem(RULE_CHAIN_ID, RULE_NODE_ID)); given(msgMock.popFormStack()).willReturn(new TbMsgProcessingStackItem(RULE_CHAIN_ID, RULE_NODE_ID));
given(nodeCtxMock.getTenantId()).willReturn(TENANT_ID); given(nodeCtxMock.getTenantId()).willReturn(TENANT_ID);
given(nodeCtxMock.getSelf()).willReturn(ruleNode); given(nodeCtxMock.getSelf()).willReturn(ruleNode);
given(nodeCtxMock.getChainActor()).willReturn(chainActorMock); given(nodeCtxMock.getChainActor()).willReturn(chainActorMock);
mockGetMaxRuleNodeDebugModeDurationMinutes();
// WHEN // WHEN
defaultTbContext.output(msgMock, nodeConnection); defaultTbContext.output(msgMock, nodeConnection);
// THEN // THEN
checkOutputCommonLogic(msgMock, nodeConnection); checkOutputCommonLogic(msgMock, nodeConnection);
then(mainCtxMock).should().getTenantProfileCache();
then(mainCtxMock).should().getMaxRuleNodeDebugModeDurationMinutes();
then(mainCtxMock).should().persistDebugOutput(TENANT_ID, RULE_NODE_ID, msgMock, nodeConnection, null, null); then(mainCtxMock).should().persistDebugOutput(TENANT_ID, RULE_NODE_ID, msgMock, nodeConnection, null, null);
then(mainCtxMock).shouldHaveNoMoreInteractions(); then(mainCtxMock).shouldHaveNoMoreInteractions();
then(nodeCtxMock).shouldHaveNoMoreInteractions(); then(nodeCtxMock).shouldHaveNoMoreInteractions();
@ -429,25 +414,23 @@ class DefaultTbContextTest {
@ParameterizedTest @ParameterizedTest
@ValueSource(strings = {TbNodeConnectionType.SUCCESS, TbNodeConnectionType.FAILURE}) @ValueSource(strings = {TbNodeConnectionType.SUCCESS, TbNodeConnectionType.FAILURE})
void givenDebugStrategyAllThenOnlyFailureEvents_whenOutput_thenVerifyDebugOutputPersisted(String nodeConnection) { void givenDebugAllThenOnlyFailureEvents_whenOutput_thenVerifyDebugOutputPersisted(String nodeConnection) {
// GIVEN // GIVEN
var msgMock = mock(TbMsg.class); var msgMock = mock(TbMsg.class);
var ruleNode = new RuleNode(RULE_NODE_ID); var ruleNode = new RuleNode(RULE_NODE_ID);
ruleNode.setRuleChainId(RULE_CHAIN_ID); ruleNode.setRuleChainId(RULE_CHAIN_ID);
ruleNode.setDebugStrategy(DebugStrategy.ALL_EVENTS); ruleNode.setDebugFailures(false);
ruleNode.setDebugAllUntil(getUntilTime());
given(msgMock.popFormStack()).willReturn(new TbMsgProcessingStackItem(RULE_CHAIN_ID, RULE_NODE_ID)); given(msgMock.popFormStack()).willReturn(new TbMsgProcessingStackItem(RULE_CHAIN_ID, RULE_NODE_ID));
given(nodeCtxMock.getTenantId()).willReturn(TENANT_ID); given(nodeCtxMock.getTenantId()).willReturn(TENANT_ID);
given(nodeCtxMock.getSelf()).willReturn(ruleNode); given(nodeCtxMock.getSelf()).willReturn(ruleNode);
given(nodeCtxMock.getChainActor()).willReturn(chainActorMock); given(nodeCtxMock.getChainActor()).willReturn(chainActorMock);
mockGetMaxRuleNodeDebugModeDurationMinutes();
// WHEN // WHEN
defaultTbContext.output(msgMock, nodeConnection); defaultTbContext.output(msgMock, nodeConnection);
// THEN // THEN
checkOutputCommonLogic(msgMock, nodeConnection); checkOutputCommonLogic(msgMock, nodeConnection);
then(mainCtxMock).should().getTenantProfileCache();
then(mainCtxMock).should().getMaxRuleNodeDebugModeDurationMinutes();
then(mainCtxMock).should().persistDebugOutput(TENANT_ID, RULE_NODE_ID, msgMock, nodeConnection, null, null); then(mainCtxMock).should().persistDebugOutput(TENANT_ID, RULE_NODE_ID, msgMock, nodeConnection, null, null);
then(mainCtxMock).shouldHaveNoMoreInteractions(); then(mainCtxMock).shouldHaveNoMoreInteractions();
then(nodeCtxMock).shouldHaveNoMoreInteractions(); then(nodeCtxMock).shouldHaveNoMoreInteractions();
@ -459,7 +442,8 @@ class DefaultTbContextTest {
var msgMock = mock(TbMsg.class); var msgMock = mock(TbMsg.class);
var ruleNode = new RuleNode(RULE_NODE_ID); var ruleNode = new RuleNode(RULE_NODE_ID);
ruleNode.setRuleChainId(RULE_CHAIN_ID); ruleNode.setRuleChainId(RULE_CHAIN_ID);
ruleNode.setDebugStrategy(DebugStrategy.DISABLED); ruleNode.setDebugFailures(false);
ruleNode.setDebugAllUntil(0);
given(msgMock.popFormStack()).willReturn(null); given(msgMock.popFormStack()).willReturn(null);
TbMsgCallback callbackMock = mock(TbMsgCallback.class); TbMsgCallback callbackMock = mock(TbMsgCallback.class);
given(msgMock.getCallback()).willReturn(callbackMock); given(msgMock.getCallback()).willReturn(callbackMock);
@ -476,19 +460,18 @@ class DefaultTbContextTest {
} }
@Test @Test
public void givenEmptyStackAndDebugStrategyAllEvents_whenOutput_thenVerifyMsgAckAndDebugOutputPersisted() { public void givenEmptyStackAndDebugAllEvents_whenOutput_thenVerifyMsgAckAndDebugOutputPersisted() {
// GIVEN // GIVEN
var msgMock = mock(TbMsg.class); var msgMock = mock(TbMsg.class);
var ruleNode = new RuleNode(RULE_NODE_ID); var ruleNode = new RuleNode(RULE_NODE_ID);
ruleNode.setRuleChainId(RULE_CHAIN_ID); ruleNode.setRuleChainId(RULE_CHAIN_ID);
ruleNode.setDebugStrategy(DebugStrategy.ALL_EVENTS); ruleNode.setDebugFailures(false);
ruleNode.setLastUpdateTs(System.currentTimeMillis()); ruleNode.setDebugAllUntil(getUntilTime());
given(msgMock.popFormStack()).willReturn(null); given(msgMock.popFormStack()).willReturn(null);
TbMsgCallback callbackMock = mock(TbMsgCallback.class); TbMsgCallback callbackMock = mock(TbMsgCallback.class);
given(msgMock.getCallback()).willReturn(callbackMock); given(msgMock.getCallback()).willReturn(callbackMock);
given(nodeCtxMock.getSelf()).willReturn(ruleNode); given(nodeCtxMock.getSelf()).willReturn(ruleNode);
given(nodeCtxMock.getTenantId()).willReturn(TENANT_ID); given(nodeCtxMock.getTenantId()).willReturn(TENANT_ID);
mockGetMaxRuleNodeDebugModeDurationMinutes();
// WHEN // WHEN
defaultTbContext.output(msgMock, TbNodeConnectionType.SUCCESS); defaultTbContext.output(msgMock, TbNodeConnectionType.SUCCESS);
@ -502,19 +485,18 @@ class DefaultTbContextTest {
} }
@Test @Test
public void givenEmptyStackAndDebugStrategyAllThenOnlyFailureEvents_whenOutput_thenVerifyMsgAckAndDebugOutputPersisted() { public void givenEmptyStackAndDebugAllThenOnlyFailureEvents_whenOutput_thenVerifyMsgAckAndDebugOutputPersisted() {
// GIVEN // GIVEN
var msgMock = mock(TbMsg.class); var msgMock = mock(TbMsg.class);
var ruleNode = new RuleNode(RULE_NODE_ID); var ruleNode = new RuleNode(RULE_NODE_ID);
ruleNode.setRuleChainId(RULE_CHAIN_ID); ruleNode.setRuleChainId(RULE_CHAIN_ID);
ruleNode.setDebugStrategy(DebugStrategy.ALL_THEN_ONLY_FAILURE_EVENTS); ruleNode.setDebugFailures(true);
ruleNode.setLastUpdateTs(System.currentTimeMillis()); ruleNode.setDebugAllUntil(getUntilTime());
given(msgMock.popFormStack()).willReturn(null); given(msgMock.popFormStack()).willReturn(null);
TbMsgCallback callbackMock = mock(TbMsgCallback.class); TbMsgCallback callbackMock = mock(TbMsgCallback.class);
given(msgMock.getCallback()).willReturn(callbackMock); given(msgMock.getCallback()).willReturn(callbackMock);
given(nodeCtxMock.getSelf()).willReturn(ruleNode); given(nodeCtxMock.getSelf()).willReturn(ruleNode);
given(nodeCtxMock.getTenantId()).willReturn(TENANT_ID); given(nodeCtxMock.getTenantId()).willReturn(TENANT_ID);
mockGetMaxRuleNodeDebugModeDurationMinutes();
// WHEN // WHEN
defaultTbContext.output(msgMock, TbNodeConnectionType.SUCCESS); defaultTbContext.output(msgMock, TbNodeConnectionType.SUCCESS);
@ -528,13 +510,13 @@ class DefaultTbContextTest {
} }
@Test @Test
public void givenDebugStrategyOnlyFailureEvents_whenEnqueueForTellFailure_thenVerifyDebugOutputPersisted() { public void givenDebugFailuresEvents_whenEnqueueForTellFailure_thenVerifyDebugOutputPersisted() {
// GIVEN // GIVEN
var msg = getTbMsgWithQueueName(); var msg = getTbMsgWithQueueName();
var tpi = new TopicPartitionInfo(DataConstants.MAIN_QUEUE_TOPIC, TENANT_ID, 0, true); var tpi = new TopicPartitionInfo(DataConstants.MAIN_QUEUE_TOPIC, TENANT_ID, 0, true);
var ruleNode = new RuleNode(RULE_NODE_ID); var ruleNode = new RuleNode(RULE_NODE_ID);
ruleNode.setRuleChainId(RULE_CHAIN_ID); ruleNode.setRuleChainId(RULE_CHAIN_ID);
ruleNode.setDebugStrategy(DebugStrategy.ONLY_FAILURE_EVENTS); ruleNode.setDebugFailures(true);
var tbClusterServiceMock = mock(TbClusterService.class); var tbClusterServiceMock = mock(TbClusterService.class);
given(nodeCtxMock.getTenantId()).willReturn(TENANT_ID); given(nodeCtxMock.getTenantId()).willReturn(TENANT_ID);
@ -561,13 +543,14 @@ class DefaultTbContextTest {
} }
@Test @Test
public void givenDebugStrategyDisabled_whenEnqueueForTellFailure_thenVerifyDebugOutputNotPersisted() { public void givenDebugDisabled_whenEnqueueForTellFailure_thenVerifyDebugOutputNotPersisted() {
// GIVEN // GIVEN
var msg = getTbMsgWithQueueName(); var msg = getTbMsgWithQueueName();
var tpi = new TopicPartitionInfo(DataConstants.MAIN_QUEUE_TOPIC, TENANT_ID, 0, true); var tpi = new TopicPartitionInfo(DataConstants.MAIN_QUEUE_TOPIC, TENANT_ID, 0, true);
var ruleNode = new RuleNode(RULE_NODE_ID); var ruleNode = new RuleNode(RULE_NODE_ID);
ruleNode.setRuleChainId(RULE_CHAIN_ID); ruleNode.setRuleChainId(RULE_CHAIN_ID);
ruleNode.setDebugStrategy(DebugStrategy.DISABLED); ruleNode.setDebugFailures(false);
ruleNode.setDebugAllUntil(0);
var tbClusterServiceMock = mock(TbClusterService.class); var tbClusterServiceMock = mock(TbClusterService.class);
given(nodeCtxMock.getTenantId()).willReturn(TENANT_ID); given(nodeCtxMock.getTenantId()).willReturn(TENANT_ID);
@ -588,21 +571,20 @@ class DefaultTbContextTest {
} }
@Test @Test
public void givenDebugStrategyAllEvents_whenEnqueueForTellFailure_thenVerifyDebugOutputPersisted() { public void givenDebugAllEvents_whenEnqueueForTellFailure_thenVerifyDebugOutputPersisted() {
// GIVEN // GIVEN
var msg = getTbMsgWithQueueName(); var msg = getTbMsgWithQueueName();
var tpi = new TopicPartitionInfo(DataConstants.MAIN_QUEUE_TOPIC, TENANT_ID, 0, true); var tpi = new TopicPartitionInfo(DataConstants.MAIN_QUEUE_TOPIC, TENANT_ID, 0, true);
var ruleNode = new RuleNode(RULE_NODE_ID); var ruleNode = new RuleNode(RULE_NODE_ID);
ruleNode.setRuleChainId(RULE_CHAIN_ID); ruleNode.setRuleChainId(RULE_CHAIN_ID);
ruleNode.setDebugStrategy(DebugStrategy.ALL_EVENTS); ruleNode.setDebugFailures(false);
ruleNode.setLastUpdateTs(System.currentTimeMillis()); ruleNode.setDebugAllUntil(getUntilTime());
var tbClusterServiceMock = mock(TbClusterService.class); var tbClusterServiceMock = mock(TbClusterService.class);
given(nodeCtxMock.getTenantId()).willReturn(TENANT_ID); given(nodeCtxMock.getTenantId()).willReturn(TENANT_ID);
given(nodeCtxMock.getSelf()).willReturn(ruleNode); given(nodeCtxMock.getSelf()).willReturn(ruleNode);
given(mainCtxMock.resolve(any(ServiceType.class), anyString(), any(TenantId.class), any(EntityId.class))).willReturn(tpi); given(mainCtxMock.resolve(any(ServiceType.class), anyString(), any(TenantId.class), any(EntityId.class))).willReturn(tpi);
given(mainCtxMock.getClusterService()).willReturn(tbClusterServiceMock); given(mainCtxMock.getClusterService()).willReturn(tbClusterServiceMock);
mockGetMaxRuleNodeDebugModeDurationMinutes();
// WHEN // WHEN
defaultTbContext.enqueueForTellFailure(msg, EXCEPTION); defaultTbContext.enqueueForTellFailure(msg, EXCEPTION);
@ -618,8 +600,6 @@ class DefaultTbContextTest {
.ignoringFields("id", "ctx") .ignoringFields("id", "ctx")
.isEqualTo(expectedTbMsg); .isEqualTo(expectedTbMsg);
then(mainCtxMock).should().getClusterService(); then(mainCtxMock).should().getClusterService();
then(mainCtxMock).should().getTenantProfileCache();
then(mainCtxMock).should().getMaxRuleNodeDebugModeDurationMinutes();
then(mainCtxMock).shouldHaveNoMoreInteractions(); then(mainCtxMock).shouldHaveNoMoreInteractions();
then(tbClusterServiceMock).shouldHaveNoMoreInteractions(); then(tbClusterServiceMock).shouldHaveNoMoreInteractions();
} }
@ -655,23 +635,20 @@ class DefaultTbContextTest {
@MethodSource @MethodSource
@ParameterizedTest @ParameterizedTest
void givenDebugStrategyOptions_whenEnqueueForTellNext_thenVerifyDebugOutputPersistedOnlyForAllEventsDebugStrategy(DebugStrategy debugStrategy, String connectionType) { void givenDebugOptions_whenEnqueueForTellNext_thenVerifyDebugOutputPersistedOnlyForDebugAll(boolean debugFailures, long debugAllUntil, String connectionType) {
// GIVEN // GIVEN
var msg = getTbMsgWithQueueName(); var msg = getTbMsgWithQueueName();
var tpi = new TopicPartitionInfo(DataConstants.MAIN_QUEUE_TOPIC, TENANT_ID, 0, true); var tpi = new TopicPartitionInfo(DataConstants.MAIN_QUEUE_TOPIC, TENANT_ID, 0, true);
var ruleNode = new RuleNode(RULE_NODE_ID); var ruleNode = new RuleNode(RULE_NODE_ID);
ruleNode.setRuleChainId(RULE_CHAIN_ID); ruleNode.setRuleChainId(RULE_CHAIN_ID);
ruleNode.setDebugStrategy(debugStrategy); ruleNode.setDebugFailures(debugFailures);
ruleNode.setLastUpdateTs(System.currentTimeMillis()); ruleNode.setDebugAllUntil(debugAllUntil);
var tbClusterServiceMock = mock(TbClusterService.class); var tbClusterServiceMock = mock(TbClusterService.class);
given(nodeCtxMock.getTenantId()).willReturn(TENANT_ID); given(nodeCtxMock.getTenantId()).willReturn(TENANT_ID);
given(nodeCtxMock.getSelf()).willReturn(ruleNode); given(nodeCtxMock.getSelf()).willReturn(ruleNode);
given(mainCtxMock.resolve(any(ServiceType.class), anyString(), any(TenantId.class), any(EntityId.class))).willReturn(tpi); given(mainCtxMock.resolve(any(ServiceType.class), anyString(), any(TenantId.class), any(EntityId.class))).willReturn(tpi);
given(mainCtxMock.getClusterService()).willReturn(tbClusterServiceMock); given(mainCtxMock.getClusterService()).willReturn(tbClusterServiceMock);
if (DebugStrategy.ALL_EVENTS.equals(debugStrategy) || DebugStrategy.ALL_THEN_ONLY_FAILURE_EVENTS.equals(debugStrategy)) {
mockGetMaxRuleNodeDebugModeDurationMinutes();
}
// WHEN // WHEN
defaultTbContext.enqueueForTellNext(msg, connectionType); defaultTbContext.enqueueForTellNext(msg, connectionType);
@ -697,9 +674,7 @@ class DefaultTbContextTest {
assertThat(simpleTbQueueCallback).isNotNull(); assertThat(simpleTbQueueCallback).isNotNull();
simpleTbQueueCallback.onSuccess(null); simpleTbQueueCallback.onSuccess(null);
if (DebugStrategy.ALL_EVENTS.equals(debugStrategy) || DebugStrategy.ALL_THEN_ONLY_FAILURE_EVENTS.equals(debugStrategy)) { if (debugAllUntil > 0) {
then(mainCtxMock).should().getTenantProfileCache();
then(mainCtxMock).should().getMaxRuleNodeDebugModeDurationMinutes();
ArgumentCaptor<TbMsg> tbMsgCaptor = ArgumentCaptor.forClass(TbMsg.class); ArgumentCaptor<TbMsg> tbMsgCaptor = ArgumentCaptor.forClass(TbMsg.class);
then(mainCtxMock).should().persistDebugOutput(eq(TENANT_ID), eq(RULE_NODE_ID), tbMsgCaptor.capture(), eq(connectionType), isNull(), isNull()); then(mainCtxMock).should().persistDebugOutput(eq(TENANT_ID), eq(RULE_NODE_ID), tbMsgCaptor.capture(), eq(connectionType), isNull(), isNull());
TbMsg actualTbMsg = tbMsgCaptor.getValue(); TbMsg actualTbMsg = tbMsgCaptor.getValue();
@ -714,24 +689,21 @@ class DefaultTbContextTest {
@MethodSource @MethodSource
@ParameterizedTest @ParameterizedTest
void givenDebugStrategyOptions_whenEnqueue_thenVerifyDebugOutputPersistedOnlyForAllEventsDebugStrategy(DebugStrategy debugStrategy) { void givenDebugOptions_whenEnqueue_thenVerifyDebugOutputPersistedOnlyForDebugAll(boolean debugFailures, long debugAllUntil) {
// GIVEN // GIVEN
var msg = getTbMsgWithQueueName(); var msg = getTbMsgWithQueueName();
var tpi = new TopicPartitionInfo(DataConstants.MAIN_QUEUE_TOPIC, TENANT_ID, 0, true); var tpi = new TopicPartitionInfo(DataConstants.MAIN_QUEUE_TOPIC, TENANT_ID, 0, true);
var ruleNode = new RuleNode(RULE_NODE_ID); var ruleNode = new RuleNode(RULE_NODE_ID);
ruleNode.setQueueName(DataConstants.MAIN_QUEUE_NAME); ruleNode.setQueueName(DataConstants.MAIN_QUEUE_NAME);
ruleNode.setRuleChainId(RULE_CHAIN_ID); ruleNode.setRuleChainId(RULE_CHAIN_ID);
ruleNode.setDebugStrategy(debugStrategy); ruleNode.setDebugFailures(debugFailures);
ruleNode.setLastUpdateTs(System.currentTimeMillis()); ruleNode.setDebugAllUntil(debugAllUntil);
var tbClusterServiceMock = mock(TbClusterService.class); var tbClusterServiceMock = mock(TbClusterService.class);
given(nodeCtxMock.getTenantId()).willReturn(TENANT_ID); given(nodeCtxMock.getTenantId()).willReturn(TENANT_ID);
given(nodeCtxMock.getSelf()).willReturn(ruleNode); given(nodeCtxMock.getSelf()).willReturn(ruleNode);
given(mainCtxMock.resolve(any(ServiceType.class), anyString(), any(TenantId.class), any(EntityId.class))).willReturn(tpi); given(mainCtxMock.resolve(any(ServiceType.class), anyString(), any(TenantId.class), any(EntityId.class))).willReturn(tpi);
given(mainCtxMock.getClusterService()).willReturn(tbClusterServiceMock); given(mainCtxMock.getClusterService()).willReturn(tbClusterServiceMock);
if (DebugStrategy.ALL_EVENTS.equals(debugStrategy) || DebugStrategy.ALL_THEN_ONLY_FAILURE_EVENTS.equals(debugStrategy)) {
mockGetMaxRuleNodeDebugModeDurationMinutes();
}
Consumer<Throwable> onFailure = mock(Consumer.class); Consumer<Throwable> onFailure = mock(Consumer.class);
Runnable onSuccess = mock(Runnable.class); Runnable onSuccess = mock(Runnable.class);
@ -760,9 +732,7 @@ class DefaultTbContextTest {
assertThat(simpleTbQueueCallback).isNotNull(); assertThat(simpleTbQueueCallback).isNotNull();
simpleTbQueueCallback.onSuccess(null); simpleTbQueueCallback.onSuccess(null);
if (debugStrategy.isHasDuration()) { if (debugAllUntil > 0) {
then(mainCtxMock).should().getTenantProfileCache();
then(mainCtxMock).should().getMaxRuleNodeDebugModeDurationMinutes();
then(mainCtxMock).should().persistDebugOutput(eq(TENANT_ID), eq(RULE_NODE_ID), eq(msg), eq(TbNodeConnectionType.TO_ROOT_RULE_CHAIN), nullable(Throwable.class), nullable(String.class)); then(mainCtxMock).should().persistDebugOutput(eq(TENANT_ID), eq(RULE_NODE_ID), eq(msg), eq(TbNodeConnectionType.TO_ROOT_RULE_CHAIN), nullable(Throwable.class), nullable(String.class));
} }
then(mainCtxMock).should().getClusterService(); then(mainCtxMock).should().getClusterService();
@ -771,12 +741,13 @@ class DefaultTbContextTest {
} }
@Test @Test
public void givenDebugStrategyOnlyFailures_whenTellFailure_thenVerifyDebugOutputPersisted() { public void givenDebugFailuress_whenTellFailure_thenVerifyDebugOutputPersisted() {
// GIVEN // GIVEN
var msg = getTbMsg(); var msg = getTbMsg();
var ruleNode = new RuleNode(RULE_NODE_ID); var ruleNode = new RuleNode(RULE_NODE_ID);
ruleNode.setRuleChainId(RULE_CHAIN_ID); ruleNode.setRuleChainId(RULE_CHAIN_ID);
ruleNode.setDebugStrategy(DebugStrategy.ONLY_FAILURE_EVENTS); ruleNode.setDebugFailures(true);
ruleNode.setDebugAllUntil(0);
given(nodeCtxMock.getTenantId()).willReturn(TENANT_ID); given(nodeCtxMock.getTenantId()).willReturn(TENANT_ID);
given(nodeCtxMock.getSelf()).willReturn(ruleNode); given(nodeCtxMock.getSelf()).willReturn(ruleNode);
given(nodeCtxMock.getChainActor()).willReturn(chainActorMock); given(nodeCtxMock.getChainActor()).willReturn(chainActorMock);
@ -801,12 +772,13 @@ class DefaultTbContextTest {
} }
@Test @Test
public void givenDebugStrategyDisabled_whenTellFailure_thenVerifyDebugOutputNotPersisted() { public void givenDebugDisabled_whenTellFailure_thenVerifyDebugOutputNotPersisted() {
// GIVEN // GIVEN
var msg = getTbMsg(); var msg = getTbMsg();
var ruleNode = new RuleNode(RULE_NODE_ID); var ruleNode = new RuleNode(RULE_NODE_ID);
ruleNode.setRuleChainId(RULE_CHAIN_ID); ruleNode.setRuleChainId(RULE_CHAIN_ID);
ruleNode.setDebugStrategy(DebugStrategy.DISABLED); ruleNode.setDebugFailures(false);
ruleNode.setDebugAllUntil(0);
given(nodeCtxMock.getSelf()).willReturn(ruleNode); given(nodeCtxMock.getSelf()).willReturn(ruleNode);
given(nodeCtxMock.getChainActor()).willReturn(chainActorMock); given(nodeCtxMock.getChainActor()).willReturn(chainActorMock);
@ -829,17 +801,16 @@ class DefaultTbContextTest {
} }
@Test @Test
public void givenDebugStrategyAllEvents_whenTellFailure_thenVerifyDebugOutputPersisted() { public void givenDebugAllEvents_whenTellFailure_thenVerifyDebugOutputPersisted() {
// GIVEN // GIVEN
var msg = getTbMsg(); var msg = getTbMsg();
var ruleNode = new RuleNode(RULE_NODE_ID); var ruleNode = new RuleNode(RULE_NODE_ID);
ruleNode.setRuleChainId(RULE_CHAIN_ID); ruleNode.setRuleChainId(RULE_CHAIN_ID);
ruleNode.setDebugStrategy(DebugStrategy.ALL_EVENTS); ruleNode.setDebugFailures(false);
ruleNode.setLastUpdateTs(System.currentTimeMillis()); ruleNode.setDebugAllUntil(getUntilTime());
given(nodeCtxMock.getTenantId()).willReturn(TENANT_ID); given(nodeCtxMock.getTenantId()).willReturn(TENANT_ID);
given(nodeCtxMock.getSelf()).willReturn(ruleNode); given(nodeCtxMock.getSelf()).willReturn(ruleNode);
given(nodeCtxMock.getChainActor()).willReturn(chainActorMock); given(nodeCtxMock.getChainActor()).willReturn(chainActorMock);
mockGetMaxRuleNodeDebugModeDurationMinutes();
// WHEN // WHEN
defaultTbContext.tellFailure(msg, EXCEPTION); defaultTbContext.tellFailure(msg, EXCEPTION);
@ -856,15 +827,14 @@ class DefaultTbContextTest {
then(chainActorMock).shouldHaveNoMoreInteractions(); then(chainActorMock).shouldHaveNoMoreInteractions();
then(nodeCtxMock).should().getChainActor(); then(nodeCtxMock).should().getChainActor();
then(mainCtxMock).should().persistDebugOutput(TENANT_ID, RULE_NODE_ID, msg, TbNodeConnectionType.FAILURE, EXCEPTION, null); then(mainCtxMock).should().persistDebugOutput(TENANT_ID, RULE_NODE_ID, msg, TbNodeConnectionType.FAILURE, EXCEPTION, null);
then(mainCtxMock).should().getTenantProfileCache();
then(mainCtxMock).should().getMaxRuleNodeDebugModeDurationMinutes();
then(mainCtxMock).shouldHaveNoMoreInteractions(); then(mainCtxMock).shouldHaveNoMoreInteractions();
then(nodeCtxMock).shouldHaveNoMoreInteractions(); then(nodeCtxMock).shouldHaveNoMoreInteractions();
} }
@MethodSource @MethodSource
@ParameterizedTest @ParameterizedTest
void givenDebugStrategyAndConnectionAndPersistedResultOptions_whenTellNext_thenVerifyDebugOutputPersistence(DebugStrategy debugStrategy, void givenDebugFailuresAndDebugAllAndConnectionAndPersistedResultOptions_whenTellNext_thenVerifyDebugOutputPersistence(boolean debugFailures,
long debugAllUntil,
String connection, String connection,
boolean shouldPersist, boolean shouldPersist,
boolean shouldPersistAfterDurationTime) { boolean shouldPersistAfterDurationTime) {
@ -873,16 +843,13 @@ class DefaultTbContextTest {
var msg = getTbMsgWithCallback(callbackMock); var msg = getTbMsgWithCallback(callbackMock);
var ruleNode = new RuleNode(RULE_NODE_ID); var ruleNode = new RuleNode(RULE_NODE_ID);
ruleNode.setRuleChainId(RULE_CHAIN_ID); ruleNode.setRuleChainId(RULE_CHAIN_ID);
ruleNode.setLastUpdateTs(System.currentTimeMillis()); ruleNode.setDebugFailures(debugFailures);
ruleNode.setDebugStrategy(debugStrategy); ruleNode.setDebugAllUntil(debugAllUntil);
if (shouldPersist) { if (shouldPersist) {
given(nodeCtxMock.getTenantId()).willReturn(TENANT_ID); given(nodeCtxMock.getTenantId()).willReturn(TENANT_ID);
} }
given(nodeCtxMock.getSelf()).willReturn(ruleNode); given(nodeCtxMock.getSelf()).willReturn(ruleNode);
given(nodeCtxMock.getChainActor()).willReturn(chainActorMock); given(nodeCtxMock.getChainActor()).willReturn(chainActorMock);
if (debugStrategy.isHasDuration()) {
mockGetMaxRuleNodeDebugModeDurationMinutes();
}
// WHEN // WHEN
defaultTbContext.tellNext(msg, connection); defaultTbContext.tellNext(msg, connection);
@ -894,9 +861,7 @@ class DefaultTbContextTest {
// GIVEN // GIVEN
Mockito.clearInvocations(mainCtxMock); Mockito.clearInvocations(mainCtxMock);
if (debugStrategy.isHasDuration()) { ruleNode.setDebugAllUntil(0);
mockGetMaxRuleNodeDebugModeDurationMinutes(0);
}
// WHEN // WHEN
defaultTbContext.tellNext(msg, connection); defaultTbContext.tellNext(msg, connection);
@ -956,34 +921,34 @@ class DefaultTbContextTest {
simpleTbQueueCallback.onSuccess(null); simpleTbQueueCallback.onSuccess(null);
} }
private static Stream<Arguments> givenDebugStrategyOptions_whenEnqueueForTellNext_thenVerifyDebugOutputPersistedOnlyForAllEventsDebugStrategy() { private static Stream<Arguments> givenDebugOptions_whenEnqueueForTellNext_thenVerifyDebugOutputPersistedOnlyForDebugAll() {
return Stream.of( return Stream.of(
Arguments.of(DebugStrategy.ALL_EVENTS, TbNodeConnectionType.OTHER), Arguments.of(false, getUntilTime(), TbNodeConnectionType.OTHER),
Arguments.of(DebugStrategy.ALL_THEN_ONLY_FAILURE_EVENTS, TbNodeConnectionType.OTHER), Arguments.of(true, getUntilTime(), TbNodeConnectionType.OTHER),
Arguments.of(DebugStrategy.ONLY_FAILURE_EVENTS, TbNodeConnectionType.TRUE), Arguments.of(true, 0, TbNodeConnectionType.TRUE),
Arguments.of(DebugStrategy.DISABLED, TbNodeConnectionType.FALSE) Arguments.of(false, 0, TbNodeConnectionType.FALSE)
); );
} }
private static Stream<Arguments> givenDebugStrategyOptions_whenEnqueue_thenVerifyDebugOutputPersistedOnlyForAllEventsDebugStrategy() { private static Stream<Arguments> givenDebugOptions_whenEnqueue_thenVerifyDebugOutputPersistedOnlyForDebugAll() {
return Stream.of( return Stream.of(
Arguments.of(DebugStrategy.ALL_EVENTS), Arguments.of(false, getUntilTime()),
Arguments.of(DebugStrategy.ALL_THEN_ONLY_FAILURE_EVENTS), Arguments.of(true, getUntilTime()),
Arguments.of(DebugStrategy.ONLY_FAILURE_EVENTS), Arguments.of(true, 0),
Arguments.of(DebugStrategy.DISABLED) Arguments.of(false, 0)
); );
} }
private static Stream<Arguments> givenDebugStrategyAndConnectionAndPersistedResultOptions_whenTellNext_thenVerifyDebugOutputPersistence() { private static Stream<Arguments> givenDebugFailuresAndDebugAllAndConnectionAndPersistedResultOptions_whenTellNext_thenVerifyDebugOutputPersistence() {
return Stream.of( return Stream.of(
Arguments.of(DebugStrategy.ALL_EVENTS, TbNodeConnectionType.SUCCESS, true, false), Arguments.of(false, getUntilTime(), TbNodeConnectionType.SUCCESS, true, false),
Arguments.of(DebugStrategy.ALL_EVENTS, TbNodeConnectionType.FAILURE, true, false), Arguments.of(false, getUntilTime(), TbNodeConnectionType.FAILURE, true, false),
Arguments.of(DebugStrategy.ALL_THEN_ONLY_FAILURE_EVENTS, TbNodeConnectionType.SUCCESS, true, false), Arguments.of(true, getUntilTime(), TbNodeConnectionType.SUCCESS, true, false),
Arguments.of(DebugStrategy.ALL_THEN_ONLY_FAILURE_EVENTS, TbNodeConnectionType.FAILURE, true, true), Arguments.of(true, getUntilTime(), TbNodeConnectionType.FAILURE, true, true),
Arguments.of(DebugStrategy.ONLY_FAILURE_EVENTS, TbNodeConnectionType.SUCCESS, false, false), Arguments.of(true, 0, TbNodeConnectionType.SUCCESS, false, false),
Arguments.of(DebugStrategy.ONLY_FAILURE_EVENTS, TbNodeConnectionType.FAILURE, true, true), Arguments.of(true, 0, TbNodeConnectionType.FAILURE, true, true),
Arguments.of(DebugStrategy.DISABLED, TbNodeConnectionType.SUCCESS, false, false), Arguments.of(false, 0, TbNodeConnectionType.SUCCESS, false, false),
Arguments.of(DebugStrategy.DISABLED, TbNodeConnectionType.FAILURE, false, false) Arguments.of(false, 0, TbNodeConnectionType.FAILURE, false, false)
); );
} }
@ -999,21 +964,11 @@ class DefaultTbContextTest {
return TbMsg.newMsg(TbMsgType.POST_TELEMETRY_REQUEST, TENANT_ID, TbMsgMetaData.EMPTY, TbMsg.EMPTY_STRING); return TbMsg.newMsg(TbMsgType.POST_TELEMETRY_REQUEST, TENANT_ID, TbMsgMetaData.EMPTY, TbMsg.EMPTY_STRING);
} }
private void mockGetMaxRuleNodeDebugModeDurationMinutes() { private static long getUntilTime() {
mockGetMaxRuleNodeDebugModeDurationMinutes(15); return getUntilTime(15);
} }
private void mockGetMaxRuleNodeDebugModeDurationMinutes(int maxRuleNodeDebugModeDurationMinutes) { private static long getUntilTime(int maxRuleNodeDebugModeDurationMinutes) {
var tbTenantProfileCacheMock = mock(TbTenantProfileCache.class); return System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(maxRuleNodeDebugModeDurationMinutes);
var tenantProfileMock = mock(TenantProfile.class);
var tenantProfileDataMock = mock(TenantProfileData.class);
var tenantProfileConfigurationMock = mock(TenantProfileConfiguration.class);
given(mainCtxMock.getTenantProfileCache()).willReturn(tbTenantProfileCacheMock);
given(tbTenantProfileCacheMock.get(TENANT_ID)).willReturn(tenantProfileMock);
given(tenantProfileMock.getProfileData()).willReturn(tenantProfileDataMock);
given(tenantProfileDataMock.getConfiguration()).willReturn(tenantProfileConfigurationMock);
given(tenantProfileConfigurationMock.getMaxRuleNodeDebugModeDurationMinutes(anyInt())).willReturn(maxRuleNodeDebugModeDurationMinutes);
} }
} }

6
application/src/test/java/org/thingsboard/server/edge/AbstractEdgeTest.java

@ -71,7 +71,6 @@ import org.thingsboard.server.common.data.query.EntityKeyValueType;
import org.thingsboard.server.common.data.query.FilterPredicateValue; import org.thingsboard.server.common.data.query.FilterPredicateValue;
import org.thingsboard.server.common.data.query.NumericFilterPredicate; import org.thingsboard.server.common.data.query.NumericFilterPredicate;
import org.thingsboard.server.common.data.queue.Queue; import org.thingsboard.server.common.data.queue.Queue;
import org.thingsboard.server.common.data.rule.DebugStrategy;
import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.common.data.rule.RuleChain;
import org.thingsboard.server.common.data.rule.RuleChainMetaData; import org.thingsboard.server.common.data.rule.RuleChainMetaData;
import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.data.rule.RuleChainType;
@ -164,7 +163,8 @@ abstract public class AbstractEdgeTest extends AbstractControllerTest {
} }
private RuleChainId getEdgeRootRuleChainId() throws Exception { private RuleChainId getEdgeRootRuleChainId() throws Exception {
return doGetTypedWithPageLink("/api/ruleChains?type={type}&", new TypeReference<PageData<RuleChain>>() {}, return doGetTypedWithPageLink("/api/ruleChains?type={type}&", new TypeReference<PageData<RuleChain>>() {
},
new PageLink(100, 0, "Edge Root Rule Chain"), new PageLink(100, 0, "Edge Root Rule Chain"),
"EDGE") "EDGE")
.getData().get(0).getId(); .getData().get(0).getId();
@ -208,7 +208,7 @@ abstract public class AbstractEdgeTest extends AbstractControllerTest {
protected void updateRootRuleChainMetadata() throws Exception { protected void updateRootRuleChainMetadata() throws Exception {
RuleChainId rootRuleChainId = getEdgeRootRuleChainId(); RuleChainId rootRuleChainId = getEdgeRootRuleChainId();
RuleChainMetaData rootRuleChainMetadata = doGet("/api/ruleChain/" + rootRuleChainId.getId().toString() + "/metadata", RuleChainMetaData.class); RuleChainMetaData rootRuleChainMetadata = doGet("/api/ruleChain/" + rootRuleChainId.getId().toString() + "/metadata", RuleChainMetaData.class);
rootRuleChainMetadata.getNodes().forEach(n -> n.setDebugStrategy(DebugStrategy.ALL_EVENTS)); rootRuleChainMetadata.getNodes().forEach(n -> n.setDebugAll(true));
doPost("/api/ruleChain/metadata", rootRuleChainMetadata, RuleChainMetaData.class); doPost("/api/ruleChain/metadata", rootRuleChainMetadata, RuleChainMetaData.class);
} }

3
application/src/test/java/org/thingsboard/server/edge/RuleChainEdgeTest.java

@ -23,7 +23,6 @@ import org.thingsboard.rule.engine.metadata.TbGetAttributesNodeConfiguration;
import org.thingsboard.rule.engine.util.TbMsgSource; import org.thingsboard.rule.engine.util.TbMsgSource;
import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.edge.Edge;
import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.rule.DebugStrategy;
import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.common.data.rule.RuleChain;
import org.thingsboard.server.common.data.rule.RuleChainMetaData; import org.thingsboard.server.common.data.rule.RuleChainMetaData;
import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.data.rule.RuleChainType;
@ -229,7 +228,7 @@ public class RuleChainEdgeTest extends AbstractEdgeTest {
// update metadata for root rule chain // update metadata for root rule chain
edgeImitator.expectMessageAmount(1); edgeImitator.expectMessageAmount(1);
metaData.getNodes().forEach(n -> n.setDebugStrategy(DebugStrategy.ALL_EVENTS)); metaData.getNodes().forEach(n -> n.setDebugAll(true));
doPost("/api/ruleChain/metadata", metaData, RuleChainMetaData.class); doPost("/api/ruleChain/metadata", metaData, RuleChainMetaData.class);
Assert.assertTrue(edgeImitator.waitForMessages()); Assert.assertTrue(edgeImitator.waitForMessages());
ruleChainUpdateMsgOpt = edgeImitator.findMessageByType(RuleChainUpdateMsg.class); ruleChainUpdateMsgOpt = edgeImitator.findMessageByType(RuleChainUpdateMsg.class);

11
application/src/test/java/org/thingsboard/server/rules/flow/AbstractRuleEngineFlowIntegrationTest.java

@ -43,7 +43,6 @@ import org.thingsboard.server.common.data.kv.StringDataEntry;
import org.thingsboard.server.common.data.msg.TbMsgType; import org.thingsboard.server.common.data.msg.TbMsgType;
import org.thingsboard.server.common.data.msg.TbNodeConnectionType; import org.thingsboard.server.common.data.msg.TbNodeConnectionType;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.rule.DebugStrategy;
import org.thingsboard.server.common.data.rule.NodeConnectionInfo; import org.thingsboard.server.common.data.rule.NodeConnectionInfo;
import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.common.data.rule.RuleChain;
import org.thingsboard.server.common.data.rule.RuleChainMetaData; import org.thingsboard.server.common.data.rule.RuleChainMetaData;
@ -143,7 +142,7 @@ public abstract class AbstractRuleEngineFlowIntegrationTest extends AbstractRule
ruleNode1.setName("Simple Rule Node 1"); ruleNode1.setName("Simple Rule Node 1");
ruleNode1.setType(org.thingsboard.rule.engine.metadata.TbGetAttributesNode.class.getName()); ruleNode1.setType(org.thingsboard.rule.engine.metadata.TbGetAttributesNode.class.getName());
ruleNode1.setConfigurationVersion(TbGetAttributesNode.class.getAnnotation(org.thingsboard.rule.engine.api.RuleNode.class).version()); ruleNode1.setConfigurationVersion(TbGetAttributesNode.class.getAnnotation(org.thingsboard.rule.engine.api.RuleNode.class).version());
ruleNode1.setDebugStrategy(DebugStrategy.ALL_EVENTS); ruleNode1.setDebugAll(true);
TbGetAttributesNodeConfiguration configuration1 = new TbGetAttributesNodeConfiguration(); TbGetAttributesNodeConfiguration configuration1 = new TbGetAttributesNodeConfiguration();
configuration1.setFetchTo(TbMsgSource.METADATA); configuration1.setFetchTo(TbMsgSource.METADATA);
configuration1.setServerAttributeNames(Collections.singletonList("serverAttributeKey1")); configuration1.setServerAttributeNames(Collections.singletonList("serverAttributeKey1"));
@ -153,7 +152,7 @@ public abstract class AbstractRuleEngineFlowIntegrationTest extends AbstractRule
ruleNode2.setName("Simple Rule Node 2"); ruleNode2.setName("Simple Rule Node 2");
ruleNode2.setType(org.thingsboard.rule.engine.metadata.TbGetAttributesNode.class.getName()); ruleNode2.setType(org.thingsboard.rule.engine.metadata.TbGetAttributesNode.class.getName());
ruleNode2.setConfigurationVersion(TbGetAttributesNode.class.getAnnotation(org.thingsboard.rule.engine.api.RuleNode.class).version()); ruleNode2.setConfigurationVersion(TbGetAttributesNode.class.getAnnotation(org.thingsboard.rule.engine.api.RuleNode.class).version());
ruleNode2.setDebugStrategy(DebugStrategy.ALL_EVENTS); ruleNode2.setDebugAll(true);
TbGetAttributesNodeConfiguration configuration2 = new TbGetAttributesNodeConfiguration(); TbGetAttributesNodeConfiguration configuration2 = new TbGetAttributesNodeConfiguration();
configuration2.setFetchTo(TbMsgSource.METADATA); configuration2.setFetchTo(TbMsgSource.METADATA);
configuration2.setServerAttributeNames(Collections.singletonList("serverAttributeKey2")); configuration2.setServerAttributeNames(Collections.singletonList("serverAttributeKey2"));
@ -249,7 +248,7 @@ public abstract class AbstractRuleEngineFlowIntegrationTest extends AbstractRule
ruleNode1.setName("Simple Rule Node 1"); ruleNode1.setName("Simple Rule Node 1");
ruleNode1.setType(org.thingsboard.rule.engine.metadata.TbGetAttributesNode.class.getName()); ruleNode1.setType(org.thingsboard.rule.engine.metadata.TbGetAttributesNode.class.getName());
ruleNode1.setConfigurationVersion(TbGetAttributesNode.class.getAnnotation(org.thingsboard.rule.engine.api.RuleNode.class).version()); ruleNode1.setConfigurationVersion(TbGetAttributesNode.class.getAnnotation(org.thingsboard.rule.engine.api.RuleNode.class).version());
ruleNode1.setDebugStrategy(DebugStrategy.ALL_EVENTS); ruleNode1.setDebugAll(true);
TbGetAttributesNodeConfiguration configuration1 = new TbGetAttributesNodeConfiguration(); TbGetAttributesNodeConfiguration configuration1 = new TbGetAttributesNodeConfiguration();
configuration1.setFetchTo(TbMsgSource.METADATA); configuration1.setFetchTo(TbMsgSource.METADATA);
configuration1.setServerAttributeNames(Collections.singletonList("serverAttributeKey1")); configuration1.setServerAttributeNames(Collections.singletonList("serverAttributeKey1"));
@ -258,7 +257,7 @@ public abstract class AbstractRuleEngineFlowIntegrationTest extends AbstractRule
RuleNode ruleNode12 = new RuleNode(); RuleNode ruleNode12 = new RuleNode();
ruleNode12.setName("Simple Rule Node 1"); ruleNode12.setName("Simple Rule Node 1");
ruleNode12.setType(org.thingsboard.rule.engine.flow.TbRuleChainInputNode.class.getName()); ruleNode12.setType(org.thingsboard.rule.engine.flow.TbRuleChainInputNode.class.getName());
ruleNode12.setDebugStrategy(DebugStrategy.ALL_EVENTS); ruleNode12.setDebugAll(true);
TbRuleChainInputNodeConfiguration configuration12 = new TbRuleChainInputNodeConfiguration(); TbRuleChainInputNodeConfiguration configuration12 = new TbRuleChainInputNodeConfiguration();
configuration12.setRuleChainId(secondaryRuleChain.getId().getId().toString()); configuration12.setRuleChainId(secondaryRuleChain.getId().getId().toString());
ruleNode12.setConfiguration(JacksonUtil.valueToTree(configuration12)); ruleNode12.setConfiguration(JacksonUtil.valueToTree(configuration12));
@ -283,7 +282,7 @@ public abstract class AbstractRuleEngineFlowIntegrationTest extends AbstractRule
ruleNode2.setName("Simple Rule Node 2"); ruleNode2.setName("Simple Rule Node 2");
ruleNode2.setType(org.thingsboard.rule.engine.metadata.TbGetAttributesNode.class.getName()); ruleNode2.setType(org.thingsboard.rule.engine.metadata.TbGetAttributesNode.class.getName());
ruleNode2.setConfigurationVersion(TbGetAttributesNode.class.getAnnotation(org.thingsboard.rule.engine.api.RuleNode.class).version()); ruleNode2.setConfigurationVersion(TbGetAttributesNode.class.getAnnotation(org.thingsboard.rule.engine.api.RuleNode.class).version());
ruleNode2.setDebugStrategy(DebugStrategy.ALL_EVENTS); ruleNode2.setDebugAll(true);
TbGetAttributesNodeConfiguration configuration2 = new TbGetAttributesNodeConfiguration(); TbGetAttributesNodeConfiguration configuration2 = new TbGetAttributesNodeConfiguration();
configuration2.setFetchTo(TbMsgSource.METADATA); configuration2.setFetchTo(TbMsgSource.METADATA);
configuration2.setServerAttributeNames(Collections.singletonList("serverAttributeKey2")); configuration2.setServerAttributeNames(Collections.singletonList("serverAttributeKey2"));

3
application/src/test/java/org/thingsboard/server/rules/lifecycle/AbstractRuleEngineLifecycleIntegrationTest.java

@ -36,7 +36,6 @@ import org.thingsboard.server.common.data.event.EventType;
import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry;
import org.thingsboard.server.common.data.kv.StringDataEntry; import org.thingsboard.server.common.data.kv.StringDataEntry;
import org.thingsboard.server.common.data.msg.TbMsgType; import org.thingsboard.server.common.data.msg.TbMsgType;
import org.thingsboard.server.common.data.rule.DebugStrategy;
import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.common.data.rule.RuleChain;
import org.thingsboard.server.common.data.rule.RuleChainMetaData; import org.thingsboard.server.common.data.rule.RuleChainMetaData;
import org.thingsboard.server.common.data.rule.RuleNode; import org.thingsboard.server.common.data.rule.RuleNode;
@ -98,7 +97,7 @@ public abstract class AbstractRuleEngineLifecycleIntegrationTest extends Abstrac
ruleNode.setName("Simple Rule Node"); ruleNode.setName("Simple Rule Node");
ruleNode.setType(org.thingsboard.rule.engine.metadata.TbGetAttributesNode.class.getName()); ruleNode.setType(org.thingsboard.rule.engine.metadata.TbGetAttributesNode.class.getName());
ruleNode.setConfigurationVersion(TbGetAttributesNode.class.getAnnotation(org.thingsboard.rule.engine.api.RuleNode.class).version()); ruleNode.setConfigurationVersion(TbGetAttributesNode.class.getAnnotation(org.thingsboard.rule.engine.api.RuleNode.class).version());
ruleNode.setDebugStrategy(DebugStrategy.ALL_EVENTS); ruleNode.setDebugAll(true);
TbGetAttributesNodeConfiguration configuration = new TbGetAttributesNodeConfiguration(); TbGetAttributesNodeConfiguration configuration = new TbGetAttributesNodeConfiguration();
configuration.setFetchTo(TbMsgSource.METADATA); configuration.setFetchTo(TbMsgSource.METADATA);
configuration.setServerAttributeNames(Collections.singletonList("serverAttributeKey")); configuration.setServerAttributeNames(Collections.singletonList("serverAttributeKey"));

5
application/src/test/java/org/thingsboard/server/service/housekeeper/HousekeeperServiceTest.java

@ -58,7 +58,6 @@ import org.thingsboard.server.common.data.msg.TbNodeConnectionType;
import org.thingsboard.server.common.data.page.TimePageLink; import org.thingsboard.server.common.data.page.TimePageLink;
import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.EntityRelation;
import org.thingsboard.server.common.data.relation.RelationTypeGroup; import org.thingsboard.server.common.data.relation.RelationTypeGroup;
import org.thingsboard.server.common.data.rule.DebugStrategy;
import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.common.data.rule.RuleChain;
import org.thingsboard.server.common.data.rule.RuleChainMetaData; import org.thingsboard.server.common.data.rule.RuleChainMetaData;
import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.data.rule.RuleChainType;
@ -463,7 +462,7 @@ public class HousekeeperServiceTest extends AbstractControllerTest {
ruleNode1.setName("Simple Rule Node 1"); ruleNode1.setName("Simple Rule Node 1");
ruleNode1.setType(org.thingsboard.rule.engine.metadata.TbGetAttributesNode.class.getName()); ruleNode1.setType(org.thingsboard.rule.engine.metadata.TbGetAttributesNode.class.getName());
ruleNode1.setConfigurationVersion(TbGetAttributesNode.class.getAnnotation(org.thingsboard.rule.engine.api.RuleNode.class).version()); ruleNode1.setConfigurationVersion(TbGetAttributesNode.class.getAnnotation(org.thingsboard.rule.engine.api.RuleNode.class).version());
ruleNode1.setDebugStrategy(DebugStrategy.ALL_EVENTS); ruleNode1.setDebugAll(true);
TbGetAttributesNodeConfiguration configuration1 = new TbGetAttributesNodeConfiguration(); TbGetAttributesNodeConfiguration configuration1 = new TbGetAttributesNodeConfiguration();
configuration1.setServerAttributeNames(Collections.singletonList("serverAttributeKey1")); configuration1.setServerAttributeNames(Collections.singletonList("serverAttributeKey1"));
ruleNode1.setConfiguration(JacksonUtil.valueToTree(configuration1)); ruleNode1.setConfiguration(JacksonUtil.valueToTree(configuration1));
@ -472,7 +471,7 @@ public class HousekeeperServiceTest extends AbstractControllerTest {
ruleNode2.setName("Simple Rule Node 2"); ruleNode2.setName("Simple Rule Node 2");
ruleNode2.setType(org.thingsboard.rule.engine.metadata.TbGetAttributesNode.class.getName()); ruleNode2.setType(org.thingsboard.rule.engine.metadata.TbGetAttributesNode.class.getName());
ruleNode2.setConfigurationVersion(TbGetAttributesNode.class.getAnnotation(org.thingsboard.rule.engine.api.RuleNode.class).version()); ruleNode2.setConfigurationVersion(TbGetAttributesNode.class.getAnnotation(org.thingsboard.rule.engine.api.RuleNode.class).version());
ruleNode2.setDebugStrategy(DebugStrategy.ALL_EVENTS); ruleNode2.setDebugAll(true);
TbGetAttributesNodeConfiguration configuration2 = new TbGetAttributesNodeConfiguration(); TbGetAttributesNodeConfiguration configuration2 = new TbGetAttributesNodeConfiguration();
configuration2.setServerAttributeNames(Collections.singletonList("serverAttributeKey2")); configuration2.setServerAttributeNames(Collections.singletonList("serverAttributeKey2"));
ruleNode2.setConfiguration(JacksonUtil.valueToTree(configuration2)); ruleNode2.setConfiguration(JacksonUtil.valueToTree(configuration2));

9
application/src/test/java/org/thingsboard/server/service/sync/ie/ExportImportServiceSqlTest.java

@ -65,7 +65,6 @@ import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;
import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.EntityRelation;
import org.thingsboard.server.common.data.relation.RelationTypeGroup; import org.thingsboard.server.common.data.relation.RelationTypeGroup;
import org.thingsboard.server.common.data.rule.DebugStrategy;
import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.common.data.rule.RuleChain;
import org.thingsboard.server.common.data.rule.RuleChainMetaData; import org.thingsboard.server.common.data.rule.RuleChainMetaData;
import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.data.rule.RuleChainType;
@ -472,7 +471,7 @@ public class ExportImportServiceSqlTest extends AbstractControllerTest {
RuleNode ruleNode1 = new RuleNode(); RuleNode ruleNode1 = new RuleNode();
ruleNode1.setName("Generator 1"); ruleNode1.setName("Generator 1");
ruleNode1.setType(TbMsgGeneratorNode.class.getName()); ruleNode1.setType(TbMsgGeneratorNode.class.getName());
ruleNode1.setDebugStrategy(DebugStrategy.ALL_EVENTS); ruleNode1.setDebugAllUntil(System.currentTimeMillis());
TbMsgGeneratorNodeConfiguration configuration1 = new TbMsgGeneratorNodeConfiguration(); TbMsgGeneratorNodeConfiguration configuration1 = new TbMsgGeneratorNodeConfiguration();
configuration1.setOriginatorType(originatorId.getEntityType()); configuration1.setOriginatorType(originatorId.getEntityType());
configuration1.setOriginatorId(originatorId.getId().toString()); configuration1.setOriginatorId(originatorId.getId().toString());
@ -482,7 +481,7 @@ public class ExportImportServiceSqlTest extends AbstractControllerTest {
ruleNode2.setName("Simple Rule Node 2"); ruleNode2.setName("Simple Rule Node 2");
ruleNode2.setType(org.thingsboard.rule.engine.metadata.TbGetAttributesNode.class.getName()); ruleNode2.setType(org.thingsboard.rule.engine.metadata.TbGetAttributesNode.class.getName());
ruleNode2.setConfigurationVersion(TbGetAttributesNode.class.getAnnotation(org.thingsboard.rule.engine.api.RuleNode.class).version()); ruleNode2.setConfigurationVersion(TbGetAttributesNode.class.getAnnotation(org.thingsboard.rule.engine.api.RuleNode.class).version());
ruleNode2.setDebugStrategy(DebugStrategy.ALL_EVENTS); ruleNode2.setDebugAllUntil(System.currentTimeMillis());
TbGetAttributesNodeConfiguration configuration2 = new TbGetAttributesNodeConfiguration(); TbGetAttributesNodeConfiguration configuration2 = new TbGetAttributesNodeConfiguration();
configuration2.setServerAttributeNames(Collections.singletonList("serverAttributeKey2")); configuration2.setServerAttributeNames(Collections.singletonList("serverAttributeKey2"));
ruleNode2.setConfiguration(JacksonUtil.valueToTree(configuration2)); ruleNode2.setConfiguration(JacksonUtil.valueToTree(configuration2));
@ -511,7 +510,7 @@ public class ExportImportServiceSqlTest extends AbstractControllerTest {
ruleNode1.setName("Simple Rule Node 1"); ruleNode1.setName("Simple Rule Node 1");
ruleNode1.setType(org.thingsboard.rule.engine.metadata.TbGetAttributesNode.class.getName()); ruleNode1.setType(org.thingsboard.rule.engine.metadata.TbGetAttributesNode.class.getName());
ruleNode1.setConfigurationVersion(TbGetAttributesNode.class.getAnnotation(org.thingsboard.rule.engine.api.RuleNode.class).version()); ruleNode1.setConfigurationVersion(TbGetAttributesNode.class.getAnnotation(org.thingsboard.rule.engine.api.RuleNode.class).version());
ruleNode1.setDebugStrategy(DebugStrategy.ALL_EVENTS); ruleNode1.setDebugAllUntil(System.currentTimeMillis());
TbGetAttributesNodeConfiguration configuration1 = new TbGetAttributesNodeConfiguration(); TbGetAttributesNodeConfiguration configuration1 = new TbGetAttributesNodeConfiguration();
configuration1.setServerAttributeNames(Collections.singletonList("serverAttributeKey1")); configuration1.setServerAttributeNames(Collections.singletonList("serverAttributeKey1"));
ruleNode1.setConfiguration(JacksonUtil.valueToTree(configuration1)); ruleNode1.setConfiguration(JacksonUtil.valueToTree(configuration1));
@ -520,7 +519,7 @@ public class ExportImportServiceSqlTest extends AbstractControllerTest {
ruleNode2.setName("Simple Rule Node 2"); ruleNode2.setName("Simple Rule Node 2");
ruleNode2.setType(org.thingsboard.rule.engine.metadata.TbGetAttributesNode.class.getName()); ruleNode2.setType(org.thingsboard.rule.engine.metadata.TbGetAttributesNode.class.getName());
ruleNode2.setConfigurationVersion(TbGetAttributesNode.class.getAnnotation(org.thingsboard.rule.engine.api.RuleNode.class).version()); ruleNode2.setConfigurationVersion(TbGetAttributesNode.class.getAnnotation(org.thingsboard.rule.engine.api.RuleNode.class).version());
ruleNode2.setDebugStrategy(DebugStrategy.ALL_EVENTS); ruleNode2.setDebugAllUntil(System.currentTimeMillis());
TbGetAttributesNodeConfiguration configuration2 = new TbGetAttributesNodeConfiguration(); TbGetAttributesNodeConfiguration configuration2 = new TbGetAttributesNodeConfiguration();
configuration2.setServerAttributeNames(Collections.singletonList("serverAttributeKey2")); configuration2.setServerAttributeNames(Collections.singletonList("serverAttributeKey2"));
ruleNode2.setConfiguration(JacksonUtil.valueToTree(configuration2)); ruleNode2.setConfiguration(JacksonUtil.valueToTree(configuration2));

9
application/src/test/java/org/thingsboard/server/service/sync/vc/VersionControlTest.java

@ -65,7 +65,6 @@ import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.EntityRelation;
import org.thingsboard.server.common.data.relation.RelationTypeGroup; import org.thingsboard.server.common.data.relation.RelationTypeGroup;
import org.thingsboard.server.common.data.rule.DebugStrategy;
import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.common.data.rule.RuleChain;
import org.thingsboard.server.common.data.rule.RuleChainMetaData; import org.thingsboard.server.common.data.rule.RuleChainMetaData;
import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.data.rule.RuleChainType;
@ -871,7 +870,7 @@ public class VersionControlTest extends AbstractControllerTest {
RuleNode ruleNode1 = new RuleNode(); RuleNode ruleNode1 = new RuleNode();
ruleNode1.setName("Generator 1"); ruleNode1.setName("Generator 1");
ruleNode1.setType(TbMsgGeneratorNode.class.getName()); ruleNode1.setType(TbMsgGeneratorNode.class.getName());
ruleNode1.setDebugStrategy(DebugStrategy.ALL_EVENTS); ruleNode1.setDebugAll(true);
TbMsgGeneratorNodeConfiguration configuration1 = new TbMsgGeneratorNodeConfiguration(); TbMsgGeneratorNodeConfiguration configuration1 = new TbMsgGeneratorNodeConfiguration();
configuration1.setOriginatorType(originatorId.getEntityType()); configuration1.setOriginatorType(originatorId.getEntityType());
configuration1.setOriginatorId(originatorId.getId().toString()); configuration1.setOriginatorId(originatorId.getId().toString());
@ -881,7 +880,7 @@ public class VersionControlTest extends AbstractControllerTest {
ruleNode2.setName("Simple Rule Node 2"); ruleNode2.setName("Simple Rule Node 2");
ruleNode2.setType(org.thingsboard.rule.engine.metadata.TbGetAttributesNode.class.getName()); ruleNode2.setType(org.thingsboard.rule.engine.metadata.TbGetAttributesNode.class.getName());
ruleNode2.setConfigurationVersion(TbGetAttributesNode.class.getAnnotation(org.thingsboard.rule.engine.api.RuleNode.class).version()); ruleNode2.setConfigurationVersion(TbGetAttributesNode.class.getAnnotation(org.thingsboard.rule.engine.api.RuleNode.class).version());
ruleNode2.setDebugStrategy(DebugStrategy.ALL_EVENTS); ruleNode2.setDebugAll(true);
TbGetAttributesNodeConfiguration configuration2 = new TbGetAttributesNodeConfiguration(); TbGetAttributesNodeConfiguration configuration2 = new TbGetAttributesNodeConfiguration();
configuration2.setServerAttributeNames(Collections.singletonList("serverAttributeKey2")); configuration2.setServerAttributeNames(Collections.singletonList("serverAttributeKey2"));
ruleNode2.setConfiguration(JacksonUtil.valueToTree(configuration2)); ruleNode2.setConfiguration(JacksonUtil.valueToTree(configuration2));
@ -909,7 +908,7 @@ public class VersionControlTest extends AbstractControllerTest {
ruleNode1.setName("Simple Rule Node 1"); ruleNode1.setName("Simple Rule Node 1");
ruleNode1.setType(org.thingsboard.rule.engine.metadata.TbGetAttributesNode.class.getName()); ruleNode1.setType(org.thingsboard.rule.engine.metadata.TbGetAttributesNode.class.getName());
ruleNode1.setConfigurationVersion(TbGetAttributesNode.class.getAnnotation(org.thingsboard.rule.engine.api.RuleNode.class).version()); ruleNode1.setConfigurationVersion(TbGetAttributesNode.class.getAnnotation(org.thingsboard.rule.engine.api.RuleNode.class).version());
ruleNode1.setDebugStrategy(DebugStrategy.ALL_EVENTS); ruleNode1.setDebugAll(true);
TbGetAttributesNodeConfiguration configuration1 = new TbGetAttributesNodeConfiguration(); TbGetAttributesNodeConfiguration configuration1 = new TbGetAttributesNodeConfiguration();
configuration1.setServerAttributeNames(Collections.singletonList("serverAttributeKey1")); configuration1.setServerAttributeNames(Collections.singletonList("serverAttributeKey1"));
ruleNode1.setConfiguration(JacksonUtil.valueToTree(configuration1)); ruleNode1.setConfiguration(JacksonUtil.valueToTree(configuration1));
@ -918,7 +917,7 @@ public class VersionControlTest extends AbstractControllerTest {
ruleNode2.setName("Simple Rule Node 2"); ruleNode2.setName("Simple Rule Node 2");
ruleNode2.setType(org.thingsboard.rule.engine.metadata.TbGetAttributesNode.class.getName()); ruleNode2.setType(org.thingsboard.rule.engine.metadata.TbGetAttributesNode.class.getName());
ruleNode2.setConfigurationVersion(TbGetAttributesNode.class.getAnnotation(org.thingsboard.rule.engine.api.RuleNode.class).version()); ruleNode2.setConfigurationVersion(TbGetAttributesNode.class.getAnnotation(org.thingsboard.rule.engine.api.RuleNode.class).version());
ruleNode2.setDebugStrategy(DebugStrategy.ALL_EVENTS); ruleNode2.setDebugAll(true);
TbGetAttributesNodeConfiguration configuration2 = new TbGetAttributesNodeConfiguration(); TbGetAttributesNodeConfiguration configuration2 = new TbGetAttributesNodeConfiguration();
configuration2.setServerAttributeNames(Collections.singletonList("serverAttributeKey2")); configuration2.setServerAttributeNames(Collections.singletonList("serverAttributeKey2"));
ruleNode2.setConfiguration(JacksonUtil.valueToTree(configuration2)); ruleNode2.setConfiguration(JacksonUtil.valueToTree(configuration2));

70
common/data/src/main/java/org/thingsboard/server/common/data/rule/DebugStrategy.java

@ -1,70 +0,0 @@
/**
* Copyright © 2016-2024 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.common.data.rule;
import lombok.Getter;
import org.thingsboard.server.common.data.msg.TbNodeConnectionType;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@Getter
public enum DebugStrategy {
DISABLED(0, false),
ALL_EVENTS(1, true),
ALL_THEN_ONLY_FAILURE_EVENTS(2, true),
ONLY_FAILURE_EVENTS(3, false);
private final int protoNumber;
private final boolean hasDuration;
DebugStrategy(int protoNumber, boolean hasDuration) {
this.protoNumber = protoNumber;
this.hasDuration = hasDuration;
}
public boolean shouldPersistDebugInput(long lastUpdateTs, long msgTs, int debugModeDurationMinutes) {
return isAllEventsStrategyAndMsgTsWithinDebugDuration(lastUpdateTs, msgTs, debugModeDurationMinutes);
}
public boolean shouldPersistDebugOutputForAllEvents(long lastUpdateTs, long msgTs, int debugModeDurationMinutes) {
return this.isAllEventsStrategyAndMsgTsWithinDebugDuration(lastUpdateTs, msgTs, debugModeDurationMinutes);
}
public boolean shouldPersistDebugForFailureEvent(Set<String> nodeConnections) {
return isFailureStrategy() && nodeConnections.contains(TbNodeConnectionType.FAILURE);
}
public boolean shouldPersistDebugForFailureEvent(String nodeConnection) {
return isFailureStrategy() && TbNodeConnectionType.FAILURE.equals(nodeConnection);
}
private boolean isFailureStrategy() {
return DebugStrategy.ONLY_FAILURE_EVENTS.equals(this) || DebugStrategy.ALL_THEN_ONLY_FAILURE_EVENTS.equals(this);
}
private boolean isAllEventsStrategyAndMsgTsWithinDebugDuration(long lastUpdateTs, long msgTs, int debugModeDurationMinutes) {
return this.hasDuration && isMsgTsWithinDebugDuration(lastUpdateTs, msgTs, debugModeDurationMinutes);
}
private boolean isMsgTsWithinDebugDuration(long lastUpdateTs, long msgCreationTs, int debugModeDurationMinutes) {
if (debugModeDurationMinutes <= 0) {
return true;
}
return msgCreationTs < lastUpdateTs + TimeUnit.MINUTES.toMillis(debugModeDurationMinutes);
}
}

19
common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleNode.java

@ -47,10 +47,12 @@ public class RuleNode extends BaseDataWithAdditionalInfo<RuleNodeId> implements
@Length(fieldName = "name") @Length(fieldName = "name")
@Schema(description = "User defined name of the rule node. Used on UI and for logging. ", example = "Process sensor reading") @Schema(description = "User defined name of the rule node. Used on UI and for logging. ", example = "Process sensor reading")
private String name; private String name;
@Schema(description = "Timestamp of the last rule node update.") @Schema(description = "Debug failures. ", example = "false")
private long lastUpdateTs; private boolean debugFailures;
@Schema(description = "Debug strategy. ", example = "ALL_EVENTS") @Schema(description = "Debug All. Used as a trigger for updating debugAllUntil.", example = "false")
private DebugStrategy debugStrategy; private boolean debugAll;
@Schema(description = "Timestamp of the end time for the processing debug events.")
private long debugAllUntil;
@Schema(description = "Enable/disable singleton mode. ", example = "false") @Schema(description = "Enable/disable singleton mode. ", example = "false")
private boolean singletonMode; private boolean singletonMode;
@Schema(description = "Queue name. ", example = "Main") @Schema(description = "Queue name. ", example = "Main")
@ -77,8 +79,9 @@ public class RuleNode extends BaseDataWithAdditionalInfo<RuleNodeId> implements
this.ruleChainId = ruleNode.getRuleChainId(); this.ruleChainId = ruleNode.getRuleChainId();
this.type = ruleNode.getType(); this.type = ruleNode.getType();
this.name = ruleNode.getName(); this.name = ruleNode.getName();
this.lastUpdateTs = ruleNode.getLastUpdateTs(); this.debugFailures = ruleNode.isDebugFailures();
this.debugStrategy = ruleNode.getDebugStrategy(); this.debugAll = ruleNode.isDebugAll();
this.debugAllUntil = ruleNode.getDebugAllUntil();
this.singletonMode = ruleNode.isSingletonMode(); this.singletonMode = ruleNode.isSingletonMode();
this.setConfiguration(ruleNode.getConfiguration()); this.setConfiguration(ruleNode.getConfiguration());
this.externalId = ruleNode.getExternalId(); this.externalId = ruleNode.getExternalId();
@ -89,10 +92,6 @@ public class RuleNode extends BaseDataWithAdditionalInfo<RuleNodeId> implements
return name; return name;
} }
public DebugStrategy getDebugStrategy() {
return debugStrategy == null ? DebugStrategy.DISABLED : debugStrategy;
}
public JsonNode getConfiguration() { public JsonNode getConfiguration() {
return BaseDataWithAdditionalInfo.getJson(() -> configuration, () -> configurationBytes); return BaseDataWithAdditionalInfo.getJson(() -> configuration, () -> configurationBytes);
} }

45
common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleNodeDebugUtil.java

@ -0,0 +1,45 @@
/**
* Copyright © 2016-2024 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.common.data.rule;
import org.thingsboard.server.common.data.msg.TbNodeConnectionType;
import java.util.Set;
public final class RuleNodeDebugUtil {
private RuleNodeDebugUtil() {}
public static boolean isDebugAllAvailable(RuleNode ruleNode) {
return ruleNode.getDebugAllUntil() > System.currentTimeMillis();
}
public static boolean isDebugAvailable(RuleNode ruleNode, String nodeConnection) {
return isDebugAllAvailable(ruleNode) || ruleNode.isDebugFailures() && TbNodeConnectionType.FAILURE.equals(nodeConnection);
}
public static boolean isDebugFailuresAvailable(RuleNode ruleNode, Set<String> nodeConnections) {
return isDebugFailuresAvailable(ruleNode) && nodeConnections.contains(TbNodeConnectionType.FAILURE);
}
public static boolean isDebugFailuresAvailable(RuleNode ruleNode, String nodeConnection) {
return isDebugFailuresAvailable(ruleNode) && TbNodeConnectionType.FAILURE.equals(nodeConnection);
}
public static boolean isDebugFailuresAvailable(RuleNode ruleNode) {
return ruleNode.isDebugFailures() || isDebugAllAvailable(ruleNode);
}
}

5
common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/DefaultTenantProfileConfiguration.java

@ -205,6 +205,9 @@ public class DefaultTenantProfileConfiguration implements TenantProfileConfigura
@Override @Override
public int getMaxRuleNodeDebugModeDurationMinutes(int systemMaxRuleNodeDebugModeDurationMinutes) { public int getMaxRuleNodeDebugModeDurationMinutes(int systemMaxRuleNodeDebugModeDurationMinutes) {
return Math.min(systemMaxRuleNodeDebugModeDurationMinutes, maxRuleNodeDebugDurationMinutes); if (maxRuleNodeDebugDurationMinutes > 0) {
return Math.min(systemMaxRuleNodeDebugModeDurationMinutes, maxRuleNodeDebugDurationMinutes);
}
return systemMaxRuleNodeDebugModeDurationMinutes;
} }
} }

11
common/edge-api/src/main/proto/edge.proto

@ -162,13 +162,6 @@ message RuleChainMetadataUpdateMsg {
string entity = 8; string entity = 8;
} }
enum DebugStrategy {
DISABLED = 0;
ALL_EVENTS = 1;
ALL_THEN_ONLY_FAILURE_EVENTS = 2;
ONLY_FAILURE_EVENTS = 3;
}
message RuleNodeProto { message RuleNodeProto {
option deprecated = true; option deprecated = true;
int64 idMSB = 1; int64 idMSB = 1;
@ -180,8 +173,8 @@ message RuleNodeProto {
string additionalInfo = 7; string additionalInfo = 7;
bool singletonMode = 8; bool singletonMode = 8;
int32 configurationVersion = 9; int32 configurationVersion = 9;
int64 lastUpdateTs = 10; bool debugFailures = 10;
DebugStrategy debugStrategy = 11; int64 debugAllUntil = 11;
} }
message NodeConnectionInfoProto { message NodeConnectionInfoProto {

3
dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java

@ -398,7 +398,8 @@ public class ModelConstants {
public static final String EVENT_MESSAGE_COLUMN_NAME = "e_message"; public static final String EVENT_MESSAGE_COLUMN_NAME = "e_message";
public static final String DEBUG_MODE = "debug_mode"; public static final String DEBUG_MODE = "debug_mode";
public static final String DEBUG_STRATEGY = "debug_strategy"; public static final String DEBUG_FAILURES = "debug_failures";
public static final String DEBUG__ALL_UNTIL = "debug_all_until";
public static final String SINGLETON_MODE = "singleton_mode"; public static final String SINGLETON_MODE = "singleton_mode";
public static final String QUEUE_NAME = "queue_name"; public static final String QUEUE_NAME = "queue_name";

20
dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleNodeEntity.java

@ -19,14 +19,11 @@ import com.fasterxml.jackson.databind.JsonNode;
import jakarta.persistence.Column; import jakarta.persistence.Column;
import jakarta.persistence.Convert; import jakarta.persistence.Convert;
import jakarta.persistence.Entity; import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.Table; import jakarta.persistence.Table;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.id.RuleNodeId; import org.thingsboard.server.common.data.id.RuleNodeId;
import org.thingsboard.server.common.data.rule.DebugStrategy;
import org.thingsboard.server.common.data.rule.RuleNode; import org.thingsboard.server.common.data.rule.RuleNode;
import org.thingsboard.server.dao.DaoUtil; import org.thingsboard.server.dao.DaoUtil;
import org.thingsboard.server.dao.model.BaseSqlEntity; import org.thingsboard.server.dao.model.BaseSqlEntity;
@ -61,12 +58,11 @@ public class RuleNodeEntity extends BaseSqlEntity<RuleNode> {
@Column(name = ModelConstants.ADDITIONAL_INFO_PROPERTY) @Column(name = ModelConstants.ADDITIONAL_INFO_PROPERTY)
private JsonNode additionalInfo; private JsonNode additionalInfo;
@Column(name = ModelConstants.LAST_UPDATE_TS_COLUMN) @Column(name = ModelConstants.DEBUG_FAILURES)
private long lastUpdateTs; private boolean debugFailures;
@Enumerated(EnumType.STRING) @Column(name = ModelConstants.DEBUG__ALL_UNTIL)
@Column(name = ModelConstants.DEBUG_STRATEGY) private long debugAllUntil;
private DebugStrategy debugStrategy;
@Column(name = ModelConstants.SINGLETON_MODE) @Column(name = ModelConstants.SINGLETON_MODE)
private boolean singletonMode; private boolean singletonMode;
@ -90,8 +86,8 @@ public class RuleNodeEntity extends BaseSqlEntity<RuleNode> {
} }
this.type = ruleNode.getType(); this.type = ruleNode.getType();
this.name = ruleNode.getName(); this.name = ruleNode.getName();
this.lastUpdateTs = ruleNode.getLastUpdateTs(); this.debugFailures = ruleNode.isDebugFailures();
this.debugStrategy = ruleNode.getDebugStrategy(); this.debugAllUntil = ruleNode.getDebugAllUntil();
this.singletonMode = ruleNode.isSingletonMode(); this.singletonMode = ruleNode.isSingletonMode();
this.queueName = ruleNode.getQueueName(); this.queueName = ruleNode.getQueueName();
this.configurationVersion = ruleNode.getConfigurationVersion(); this.configurationVersion = ruleNode.getConfigurationVersion();
@ -111,8 +107,8 @@ public class RuleNodeEntity extends BaseSqlEntity<RuleNode> {
} }
ruleNode.setType(type); ruleNode.setType(type);
ruleNode.setName(name); ruleNode.setName(name);
ruleNode.setLastUpdateTs(lastUpdateTs); ruleNode.setDebugFailures(debugFailures);
ruleNode.setDebugStrategy(debugStrategy); ruleNode.setDebugAllUntil(debugAllUntil);
ruleNode.setSingletonMode(singletonMode); ruleNode.setSingletonMode(singletonMode);
ruleNode.setQueueName(queueName); ruleNode.setQueueName(queueName);
ruleNode.setConfigurationVersion(configurationVersion); ruleNode.setConfigurationVersion(configurationVersion);

21
dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java

@ -24,6 +24,7 @@ import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.commons.lang3.exception.ExceptionUtils;
import org.hibernate.exception.ConstraintViolationException; import org.hibernate.exception.ConstraintViolationException;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.common.util.JacksonUtil;
@ -44,7 +45,6 @@ import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.plugin.ComponentClusteringMode; import org.thingsboard.server.common.data.plugin.ComponentClusteringMode;
import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.EntityRelation;
import org.thingsboard.server.common.data.relation.RelationTypeGroup; import org.thingsboard.server.common.data.relation.RelationTypeGroup;
import org.thingsboard.server.common.data.rule.DebugStrategy;
import org.thingsboard.server.common.data.rule.NodeConnectionInfo; import org.thingsboard.server.common.data.rule.NodeConnectionInfo;
import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.common.data.rule.RuleChain;
import org.thingsboard.server.common.data.rule.RuleChainConnectionInfo; import org.thingsboard.server.common.data.rule.RuleChainConnectionInfo;
@ -66,6 +66,8 @@ import org.thingsboard.server.dao.service.DataValidator;
import org.thingsboard.server.dao.service.PaginatedRemover; import org.thingsboard.server.dao.service.PaginatedRemover;
import org.thingsboard.server.dao.service.Validator; import org.thingsboard.server.dao.service.Validator;
import org.thingsboard.server.dao.service.validator.RuleChainDataValidator; import org.thingsboard.server.dao.service.validator.RuleChainDataValidator;
import org.thingsboard.server.dao.tenant.TbTenantProfileCache;
import org.thingsboard.server.dao.util.TimeUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
@ -77,6 +79,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -110,6 +113,12 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
@Autowired @Autowired
private DataValidator<RuleChain> ruleChainValidator; private DataValidator<RuleChain> ruleChainValidator;
@Autowired
private TbTenantProfileCache tbTenantProfileCache;
@Value("${actors.rule.node.max_debug_mode_duration:60}")
private int maxRuleNodeDebugModeDurationMinutes;
@Override @Override
@Transactional @Transactional
public RuleChain saveRuleChain(RuleChain ruleChain) { public RuleChain saveRuleChain(RuleChain ruleChain) {
@ -215,11 +224,16 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
} }
RuleChainId ruleChainId = ruleChain.getId(); RuleChainId ruleChainId = ruleChain.getId();
if (nodes != null) { if (nodes != null) {
long lastUpdateTs = System.currentTimeMillis(); long now = System.currentTimeMillis();
for (RuleNode node : toAddOrUpdate) { for (RuleNode node : toAddOrUpdate) {
node.setRuleChainId(ruleChainId); node.setRuleChainId(ruleChainId);
node = ruleNodeUpdater.apply(node); node = ruleNodeUpdater.apply(node);
node.setLastUpdateTs(lastUpdateTs);
if (node.isDebugAll()) {
int debugDuration = tbTenantProfileCache.get(tenantId).getDefaultProfileConfiguration().getMaxRuleNodeDebugModeDurationMinutes(maxRuleNodeDebugModeDurationMinutes);
node.setDebugAllUntil(now + TimeUnit.MINUTES.toMillis(debugDuration));
}
RuleChainDataValidator.validateRuleNode(node); RuleChainDataValidator.validateRuleNode(node);
RuleNode savedNode = ruleNodeDao.save(tenantId, node); RuleNode savedNode = ruleNodeDao.save(tenantId, node);
relations.add(new EntityRelation(ruleChainMetaData.getRuleChainId(), savedNode.getId(), relations.add(new EntityRelation(ruleChainMetaData.getRuleChainId(), savedNode.getId(),
@ -264,7 +278,6 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
layout.remove("description"); layout.remove("description");
layout.remove("ruleChainNodeId"); layout.remove("ruleChainNodeId");
targetNode.setAdditionalInfo(layout); targetNode.setAdditionalInfo(layout);
targetNode.setDebugStrategy(DebugStrategy.DISABLED);
targetNode = ruleNodeDao.save(tenantId, targetNode); targetNode = ruleNodeDao.save(tenantId, targetNode);
EntityRelation sourceRuleChainToRuleNode = new EntityRelation(); EntityRelation sourceRuleChainToRuleNode = new EntityRelation();

4
dao/src/main/resources/sql/schema-entities.sql

@ -181,8 +181,8 @@ CREATE TABLE IF NOT EXISTS rule_node (
configuration varchar(10000000), configuration varchar(10000000),
type varchar(255), type varchar(255),
name varchar(255), name varchar(255),
last_update_ts bigint NOT NULL, debug_failures boolean,
debug_strategy varchar(32) DEFAULT 'DISABLED', debug_all_until bigint NOT NULL,
singleton_mode boolean, singleton_mode boolean,
queue_name varchar(255), queue_name varchar(255),
external_id uuid external_id uuid

54
monitoring/src/main/resources/root_rule_chain.json

@ -20,7 +20,8 @@
}, },
"type": "org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode", "type": "org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode",
"name": "Save Timeseries", "name": "Save Timeseries",
"debugStrategy": "ALL_EVENTS", "debugFailures": false,
"debugAll": true,
"singletonMode": false, "singletonMode": false,
"configurationVersion": 0, "configurationVersion": 0,
"configuration": { "configuration": {
@ -35,7 +36,8 @@
}, },
"type": "org.thingsboard.rule.engine.telemetry.TbMsgAttributesNode", "type": "org.thingsboard.rule.engine.telemetry.TbMsgAttributesNode",
"name": "Save Attributes", "name": "Save Attributes",
"debugStrategy": "DISABLED", "debugFailures": false,
"debugAll": false,
"singletonMode": false, "singletonMode": false,
"configurationVersion": 1, "configurationVersion": 1,
"configuration": { "configuration": {
@ -53,7 +55,8 @@
}, },
"type": "org.thingsboard.rule.engine.filter.TbMsgTypeSwitchNode", "type": "org.thingsboard.rule.engine.filter.TbMsgTypeSwitchNode",
"name": "Message Type Switch", "name": "Message Type Switch",
"debugStrategy": "DISABLED", "debugFailures": false,
"debugAll": false,
"singletonMode": false, "singletonMode": false,
"configurationVersion": 0, "configurationVersion": 0,
"configuration": { "configuration": {
@ -68,7 +71,8 @@
}, },
"type": "org.thingsboard.rule.engine.action.TbLogNode", "type": "org.thingsboard.rule.engine.action.TbLogNode",
"name": "Log RPC from Device", "name": "Log RPC from Device",
"debugStrategy": "DISABLED", "debugFailures": false,
"debugAll": false,
"singletonMode": false, "singletonMode": false,
"configurationVersion": 0, "configurationVersion": 0,
"configuration": { "configuration": {
@ -85,7 +89,8 @@
}, },
"type": "org.thingsboard.rule.engine.action.TbLogNode", "type": "org.thingsboard.rule.engine.action.TbLogNode",
"name": "Log Other", "name": "Log Other",
"debugStrategy": "DISABLED", "debugFailures": false,
"debugAll": false,
"singletonMode": false, "singletonMode": false,
"configurationVersion": 0, "configurationVersion": 0,
"configuration": { "configuration": {
@ -102,7 +107,8 @@
}, },
"type": "org.thingsboard.rule.engine.rpc.TbSendRPCRequestNode", "type": "org.thingsboard.rule.engine.rpc.TbSendRPCRequestNode",
"name": "RPC Call Request", "name": "RPC Call Request",
"debugStrategy": "DISABLED", "debugFailures": false,
"debugAll": false,
"singletonMode": false, "singletonMode": false,
"configurationVersion": 0, "configurationVersion": 0,
"configuration": { "configuration": {
@ -117,7 +123,8 @@
}, },
"type": "org.thingsboard.rule.engine.filter.TbOriginatorTypeFilterNode", "type": "org.thingsboard.rule.engine.filter.TbOriginatorTypeFilterNode",
"name": "Is Entity Group", "name": "Is Entity Group",
"debugStrategy": "DISABLED", "debugFailures": false,
"debugAll": false,
"singletonMode": false, "singletonMode": false,
"configurationVersion": 0, "configurationVersion": 0,
"configuration": { "configuration": {
@ -134,7 +141,8 @@
}, },
"type": "org.thingsboard.rule.engine.filter.TbMsgTypeFilterNode", "type": "org.thingsboard.rule.engine.filter.TbMsgTypeFilterNode",
"name": "Post attributes or RPC request", "name": "Post attributes or RPC request",
"debugStrategy": "DISABLED", "debugFailures": false,
"debugAll": false,
"singletonMode": false, "singletonMode": false,
"configurationVersion": 0, "configurationVersion": 0,
"configuration": { "configuration": {
@ -152,7 +160,8 @@
}, },
"type": "org.thingsboard.rule.engine.transform.TbDuplicateMsgToGroupNode", "type": "org.thingsboard.rule.engine.transform.TbDuplicateMsgToGroupNode",
"name": "Duplicate To Group Entities", "name": "Duplicate To Group Entities",
"debugStrategy": "DISABLED", "debugFailures": false,
"debugAll": false,
"singletonMode": false, "singletonMode": false,
"configurationVersion": 0, "configurationVersion": 0,
"configuration": { "configuration": {
@ -169,7 +178,8 @@
}, },
"type": "org.thingsboard.rule.engine.profile.TbDeviceProfileNode", "type": "org.thingsboard.rule.engine.profile.TbDeviceProfileNode",
"name": "Device Profile Node", "name": "Device Profile Node",
"debugStrategy": "ALL_EVENTS", "debugFailures": false,
"debugAll": true,
"singletonMode": false, "singletonMode": false,
"configurationVersion": 0, "configurationVersion": 0,
"configuration": { "configuration": {
@ -186,7 +196,8 @@
}, },
"type": "org.thingsboard.rule.engine.filter.TbJsFilterNode", "type": "org.thingsboard.rule.engine.filter.TbJsFilterNode",
"name": "Test JS script", "name": "Test JS script",
"debugStrategy": "DISABLED", "debugFailures": false,
"debugAll": false,
"singletonMode": false, "singletonMode": false,
"configurationVersion": 0, "configurationVersion": 0,
"configuration": { "configuration": {
@ -204,7 +215,8 @@
}, },
"type": "org.thingsboard.rule.engine.filter.TbJsFilterNode", "type": "org.thingsboard.rule.engine.filter.TbJsFilterNode",
"name": "Test TBEL script", "name": "Test TBEL script",
"debugStrategy": "DISABLED", "debugFailures": false,
"debugAll": false,
"singletonMode": false, "singletonMode": false,
"configurationVersion": 0, "configurationVersion": 0,
"configuration": { "configuration": {
@ -222,7 +234,8 @@
}, },
"type": "org.thingsboard.rule.engine.transform.TbTransformMsgNode", "type": "org.thingsboard.rule.engine.transform.TbTransformMsgNode",
"name": "Add arrival timestamp", "name": "Add arrival timestamp",
"debugStrategy": "DISABLED", "debugFailures": false,
"debugAll": false,
"singletonMode": false, "singletonMode": false,
"configurationVersion": 0, "configurationVersion": 0,
"configuration": { "configuration": {
@ -240,7 +253,8 @@
}, },
"type": "org.thingsboard.rule.engine.transform.TbTransformMsgNode", "type": "org.thingsboard.rule.engine.transform.TbTransformMsgNode",
"name": "Calculate additional latencies", "name": "Calculate additional latencies",
"debugStrategy": "ALL_EVENTS", "debugFailures": false,
"debugAll": true,
"singletonMode": false, "singletonMode": false,
"configurationVersion": 0, "configurationVersion": 0,
"configuration": { "configuration": {
@ -258,7 +272,8 @@
}, },
"type": "org.thingsboard.rule.engine.transform.TbChangeOriginatorNode", "type": "org.thingsboard.rule.engine.transform.TbChangeOriginatorNode",
"name": "To latencies asset", "name": "To latencies asset",
"debugStrategy": "DISABLED", "debugFailures": false,
"debugAll": false,
"singletonMode": false, "singletonMode": false,
"configurationVersion": 0, "configurationVersion": 0,
"configuration": { "configuration": {
@ -287,7 +302,8 @@
}, },
"type": "org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode", "type": "org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode",
"name": "Save Timeseries", "name": "Save Timeseries",
"debugStrategy": "ALL_EVENTS", "debugFailures": false,
"debugAll": true,
"singletonMode": false, "singletonMode": false,
"configurationVersion": 0, "configurationVersion": 0,
"configuration": { "configuration": {
@ -303,7 +319,8 @@
}, },
"type": "org.thingsboard.rule.engine.filter.TbCheckMessageNode", "type": "org.thingsboard.rule.engine.filter.TbCheckMessageNode",
"name": "Has testData", "name": "Has testData",
"debugStrategy": "DISABLED", "debugFailures": false,
"debugAll": false,
"singletonMode": false, "singletonMode": false,
"configurationVersion": 0, "configurationVersion": 0,
"configuration": { "configuration": {
@ -323,7 +340,8 @@
}, },
"type": "org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode", "type": "org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode",
"name": "Save Timeseries with TTL", "name": "Save Timeseries with TTL",
"debugStrategy": "ALL_EVENTS", "debugFailures": false,
"debugAll": true,
"singletonMode": false, "singletonMode": false,
"configurationVersion": 0, "configurationVersion": 0,
"configuration": { "configuration": {

9
msa/black-box-tests/src/test/resources/MqttRuleNodeTestMetadata.json

@ -9,7 +9,8 @@
}, },
"type": "org.thingsboard.rule.engine.mqtt.TbMqttNode", "type": "org.thingsboard.rule.engine.mqtt.TbMqttNode",
"name": "test mqtt", "name": "test mqtt",
"debugStrategy": "ALL_EVENTS", "debugFailures": false,
"debugAll": true,
"singletonMode": true, "singletonMode": true,
"queueName": "HighPriority", "queueName": "HighPriority",
"configurationVersion": 0, "configurationVersion": 0,
@ -36,7 +37,8 @@
}, },
"type": "org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode", "type": "org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode",
"name": "save timeseries", "name": "save timeseries",
"debugStrategy": "ALL_EVENTS", "debugFailures": false,
"debugAll": true,
"singletonMode": false, "singletonMode": false,
"configurationVersion": 0, "configurationVersion": 0,
"configuration": { "configuration": {
@ -54,7 +56,8 @@
}, },
"type": "org.thingsboard.rule.engine.filter.TbMsgTypeSwitchNode", "type": "org.thingsboard.rule.engine.filter.TbMsgTypeSwitchNode",
"name": "switch", "name": "switch",
"debugStrategy": "DISABLED", "debugFailures": false,
"debugAll": false,
"singletonMode": false, "singletonMode": false,
"configurationVersion": 0, "configurationVersion": 0,
"configuration": { "configuration": {

9
msa/black-box-tests/src/test/resources/RpcResponseRuleChainMetadata.json

@ -8,7 +8,8 @@
}, },
"type": "org.thingsboard.rule.engine.filter.TbMsgTypeSwitchNode", "type": "org.thingsboard.rule.engine.filter.TbMsgTypeSwitchNode",
"name": "msgTypeSwitch", "name": "msgTypeSwitch",
"debugStrategy": "ALL_EVENTS", "debugFailures": false,
"debugAll": true,
"configuration": { "configuration": {
"version": 0 "version": 0
} }
@ -20,7 +21,8 @@
}, },
"type": "org.thingsboard.rule.engine.transform.TbTransformMsgNode", "type": "org.thingsboard.rule.engine.transform.TbTransformMsgNode",
"name": "formResponse", "name": "formResponse",
"debugStrategy": "ALL_EVENTS", "debugFailures": false,
"debugAll": true,
"configuration": { "configuration": {
"jsScript": "if (msg.method == \"getResponse\") {\n return {msg: {\"response\": \"requestReceived\"}, metadata: metadata, msgType: msgType};\n}\n\nreturn {msg: msg, metadata: metadata, msgType: msgType};" "jsScript": "if (msg.method == \"getResponse\") {\n return {msg: {\"response\": \"requestReceived\"}, metadata: metadata, msgType: msgType};\n}\n\nreturn {msg: msg, metadata: metadata, msgType: msgType};"
} }
@ -32,7 +34,8 @@
}, },
"type": "org.thingsboard.rule.engine.rpc.TbSendRPCReplyNode", "type": "org.thingsboard.rule.engine.rpc.TbSendRPCReplyNode",
"name": "rpcReply", "name": "rpcReply",
"debugStrategy": "ALL_EVENTS", "debugFailures": false,
"debugAll": true,
"configuration": { "configuration": {
"requestIdMetaDataAttribute": "requestId" "requestIdMetaDataAttribute": "requestId"
} }

Loading…
Cancel
Save