Commit 5752ba81a43a75f542a405467081ff449c0575e4
1 parent
fd1aaba6
Implementation of Flows in Rule Engine
Showing
18 changed files
with
361 additions
and
253 deletions
... | ... | @@ -15,6 +15,8 @@ |
15 | 15 | */ |
16 | 16 | package org.thingsboard.server.actors.ruleChain; |
17 | 17 | |
18 | +import akka.actor.OneForOneStrategy; | |
19 | +import akka.actor.SupervisorStrategy; | |
18 | 20 | import org.thingsboard.server.actors.ActorSystemContext; |
19 | 21 | import org.thingsboard.server.actors.service.ComponentActor; |
20 | 22 | import org.thingsboard.server.actors.service.ContextBasedCreator; |
... | ... | @@ -23,6 +25,7 @@ import org.thingsboard.server.common.data.id.TenantId; |
23 | 25 | import org.thingsboard.server.common.msg.TbActorMsg; |
24 | 26 | import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; |
25 | 27 | import org.thingsboard.server.common.msg.system.ServiceToRuleEngineMsg; |
28 | +import scala.concurrent.duration.Duration; | |
26 | 29 | |
27 | 30 | public class RuleChainActor extends ComponentActor<RuleChainId, RuleChainActorMessageProcessor> { |
28 | 31 | |
... | ... | @@ -73,5 +76,13 @@ public class RuleChainActor extends ComponentActor<RuleChainId, RuleChainActorMe |
73 | 76 | return systemContext.getRuleChainErrorPersistFrequency(); |
74 | 77 | } |
75 | 78 | |
76 | - //TODO: failover strategy | |
79 | + @Override | |
80 | + public SupervisorStrategy supervisorStrategy() { | |
81 | + return strategy; | |
82 | + } | |
83 | + | |
84 | + private final SupervisorStrategy strategy = new OneForOneStrategy(3, Duration.create("1 minute"), t -> { | |
85 | + logAndPersist("Unknown Failure", ActorSystemContext.toException(t)); | |
86 | + return SupervisorStrategy.resume(); | |
87 | + }); | |
77 | 88 | } | ... | ... |
... | ... | @@ -27,12 +27,14 @@ import org.thingsboard.server.common.data.id.EntityId; |
27 | 27 | import org.thingsboard.server.common.data.id.RuleChainId; |
28 | 28 | import org.thingsboard.server.common.data.id.RuleNodeId; |
29 | 29 | import org.thingsboard.server.common.data.id.TenantId; |
30 | +import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; | |
30 | 31 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleState; |
31 | 32 | import org.thingsboard.server.common.data.relation.EntityRelation; |
32 | 33 | import org.thingsboard.server.common.data.rule.RuleChain; |
33 | 34 | import org.thingsboard.server.common.data.rule.RuleNode; |
34 | 35 | import org.thingsboard.server.common.msg.TbMsg; |
35 | 36 | import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; |
37 | +import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; | |
36 | 38 | import org.thingsboard.server.common.msg.system.ServiceToRuleEngineMsg; |
37 | 39 | import org.thingsboard.server.dao.rule.RuleChainService; |
38 | 40 | |
... | ... | @@ -40,6 +42,8 @@ import java.util.ArrayList; |
40 | 42 | import java.util.HashMap; |
41 | 43 | import java.util.List; |
42 | 44 | import java.util.Map; |
45 | +import java.util.Set; | |
46 | +import java.util.stream.Collectors; | |
43 | 47 | |
44 | 48 | /** |
45 | 49 | * @author Andrew Shvayka |
... | ... | @@ -54,7 +58,6 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh |
54 | 58 | |
55 | 59 | private RuleNodeId firstId; |
56 | 60 | private RuleNodeCtx firstNode; |
57 | - private ComponentLifecycleState state; | |
58 | 61 | |
59 | 62 | RuleChainActorMessageProcessor(TenantId tenantId, RuleChainId ruleChainId, ActorSystemContext systemContext |
60 | 63 | , LoggingAdapter logger, ActorRef parent, ActorRef self) { |
... | ... | @@ -68,20 +71,64 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh |
68 | 71 | |
69 | 72 | @Override |
70 | 73 | public void start(ActorContext context) throws Exception { |
71 | - if (state == ComponentLifecycleState.ACTIVE) { | |
72 | - return; | |
73 | - } | |
74 | 74 | RuleChain ruleChain = service.findRuleChainById(entityId); |
75 | 75 | List<RuleNode> ruleNodeList = service.getRuleChainNodes(entityId); |
76 | 76 | // Creating and starting the actors; |
77 | 77 | for (RuleNode ruleNode : ruleNodeList) { |
78 | - String dispatcherName = tenantId.getId().equals(EntityId.NULL_UUID) ? | |
79 | - DefaultActorService.SYSTEM_RULE_DISPATCHER_NAME : DefaultActorService.TENANT_RULE_DISPATCHER_NAME; | |
80 | - ActorRef ruleNodeActor = context.actorOf( | |
81 | - Props.create(new RuleNodeActor.ActorCreator(systemContext, tenantId, entityId, ruleNode.getId())) | |
82 | - .withDispatcher(dispatcherName), ruleNode.getId().toString()); | |
78 | + ActorRef ruleNodeActor = createRuleNodeActor(context, ruleNode); | |
83 | 79 | nodeActors.put(ruleNode.getId(), new RuleNodeCtx(tenantId, self, ruleNodeActor, ruleNode)); |
84 | 80 | } |
81 | + initRoutes(ruleChain, ruleNodeList); | |
82 | + } | |
83 | + | |
84 | + @Override | |
85 | + public void onUpdate(ActorContext context) throws Exception { | |
86 | + RuleChain ruleChain = service.findRuleChainById(entityId); | |
87 | + List<RuleNode> ruleNodeList = service.getRuleChainNodes(entityId); | |
88 | + | |
89 | + for (RuleNode ruleNode : ruleNodeList) { | |
90 | + RuleNodeCtx existing = nodeActors.get(ruleNode.getId()); | |
91 | + if (existing == null) { | |
92 | + ActorRef ruleNodeActor = createRuleNodeActor(context, ruleNode); | |
93 | + nodeActors.put(ruleNode.getId(), new RuleNodeCtx(tenantId, self, ruleNodeActor, ruleNode)); | |
94 | + } else { | |
95 | + existing.getSelfActor().tell(new ComponentLifecycleMsg(tenantId, existing.getSelf().getId(), ComponentLifecycleEvent.UPDATED), self); | |
96 | + } | |
97 | + } | |
98 | + | |
99 | + Set<RuleNodeId> existingNodes = ruleNodeList.stream().map(RuleNode::getId).collect(Collectors.toSet()); | |
100 | + List<RuleNodeId> removedRules = nodeActors.keySet().stream().filter(node -> !existingNodes.contains(node)).collect(Collectors.toList()); | |
101 | + removedRules.forEach(ruleNodeId -> { | |
102 | + RuleNodeCtx removed = nodeActors.remove(ruleNodeId); | |
103 | + removed.getSelfActor().tell(new ComponentLifecycleMsg(tenantId, removed.getSelf().getId(), ComponentLifecycleEvent.DELETED), self); | |
104 | + }); | |
105 | + | |
106 | + initRoutes(ruleChain, ruleNodeList); | |
107 | + } | |
108 | + | |
109 | + @Override | |
110 | + public void stop(ActorContext context) throws Exception { | |
111 | + nodeActors.values().stream().map(RuleNodeCtx::getSelfActor).forEach(context::stop); | |
112 | + nodeActors.clear(); | |
113 | + nodeRoutes.clear(); | |
114 | + context.stop(self); | |
115 | + } | |
116 | + | |
117 | + @Override | |
118 | + public void onClusterEventMsg(ClusterEventMsg msg) throws Exception { | |
119 | + | |
120 | + } | |
121 | + | |
122 | + private ActorRef createRuleNodeActor(ActorContext context, RuleNode ruleNode) { | |
123 | + String dispatcherName = tenantId.getId().equals(EntityId.NULL_UUID) ? | |
124 | + DefaultActorService.SYSTEM_RULE_DISPATCHER_NAME : DefaultActorService.TENANT_RULE_DISPATCHER_NAME; | |
125 | + return context.actorOf( | |
126 | + Props.create(new RuleNodeActor.ActorCreator(systemContext, tenantId, entityId, ruleNode.getId())) | |
127 | + .withDispatcher(dispatcherName), ruleNode.getId().toString()); | |
128 | + } | |
129 | + | |
130 | + private void initRoutes(RuleChain ruleChain, List<RuleNode> ruleNodeList) { | |
131 | + nodeRoutes.clear(); | |
85 | 132 | // Populating the routes map; |
86 | 133 | for (RuleNode ruleNode : ruleNodeList) { |
87 | 134 | List<EntityRelation> relations = service.getRuleNodeRelations(ruleNode.getId()); |
... | ... | @@ -102,19 +149,6 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh |
102 | 149 | state = ComponentLifecycleState.ACTIVE; |
103 | 150 | } |
104 | 151 | |
105 | - @Override | |
106 | - public void stop(ActorContext context) throws Exception { | |
107 | - nodeActors.values().stream().map(RuleNodeCtx::getSelfActor).forEach(context::stop); | |
108 | - nodeActors.clear(); | |
109 | - nodeRoutes.clear(); | |
110 | - state = ComponentLifecycleState.SUSPENDED; | |
111 | - } | |
112 | - | |
113 | - @Override | |
114 | - public void onClusterEventMsg(ClusterEventMsg msg) throws Exception { | |
115 | - | |
116 | - } | |
117 | - | |
118 | 152 | void onServiceToRuleEngineMsg(ServiceToRuleEngineMsg envelope) { |
119 | 153 | checkActive(); |
120 | 154 | TbMsg tbMsg = envelope.getTbMsg(); |
... | ... | @@ -126,7 +160,6 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh |
126 | 160 | checkActive(); |
127 | 161 | RuleNodeId originator = envelope.getOriginator(); |
128 | 162 | String targetRelationType = envelope.getRelationType(); |
129 | - //TODO: log debug output | |
130 | 163 | List<RuleNodeRelation> relations = nodeRoutes.get(originator); |
131 | 164 | if (relations == null) { |
132 | 165 | return; |
... | ... | @@ -153,12 +186,8 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh |
153 | 186 | } |
154 | 187 | |
155 | 188 | private void pushMstToNode(RuleNodeCtx nodeCtx, TbMsg msg) { |
156 | - firstNode.getSelfActor().tell(new RuleChainToRuleNodeMsg(new DefaultTbContext(systemContext, nodeCtx), msg), self); | |
157 | - } | |
158 | - | |
159 | - private void checkActive() { | |
160 | - if (state != ComponentLifecycleState.ACTIVE) { | |
161 | - throw new IllegalStateException("Rule chain is not active!"); | |
189 | + if (nodeCtx != null) { | |
190 | + nodeCtx.getSelfActor().tell(new RuleChainToRuleNodeMsg(new DefaultTbContext(systemContext, nodeCtx), msg), self); | |
162 | 191 | } |
163 | 192 | } |
164 | 193 | ... | ... |
... | ... | @@ -17,7 +17,6 @@ package org.thingsboard.server.actors.ruleChain; |
17 | 17 | |
18 | 18 | import lombok.Data; |
19 | 19 | import org.thingsboard.rule.engine.api.TbContext; |
20 | -import org.thingsboard.server.common.data.id.RuleNodeId; | |
21 | 20 | import org.thingsboard.server.common.msg.MsgType; |
22 | 21 | import org.thingsboard.server.common.msg.TbActorMsg; |
23 | 22 | import org.thingsboard.server.common.msg.TbMsg; | ... | ... |
... | ... | @@ -22,6 +22,7 @@ import org.thingsboard.server.common.data.id.RuleChainId; |
22 | 22 | import org.thingsboard.server.common.data.id.RuleNodeId; |
23 | 23 | import org.thingsboard.server.common.data.id.TenantId; |
24 | 24 | import org.thingsboard.server.common.msg.TbActorMsg; |
25 | +import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; | |
25 | 26 | |
26 | 27 | public class RuleNodeActor extends ComponentActor<RuleNodeId, RuleNodeActorMessageProcessor> { |
27 | 28 | |
... | ... | @@ -37,6 +38,9 @@ public class RuleNodeActor extends ComponentActor<RuleNodeId, RuleNodeActorMessa |
37 | 38 | @Override |
38 | 39 | protected boolean process(TbActorMsg msg) { |
39 | 40 | switch (msg.getMsgType()) { |
41 | + case COMPONENT_LIFE_CYCLE_MSG: | |
42 | + onComponentLifecycleMsg((ComponentLifecycleMsg) msg); | |
43 | + break; | |
40 | 44 | case RULE_CHAIN_TO_RULE_MSG: |
41 | 45 | onRuleChainToRuleNodeMsg((RuleChainToRuleNodeMsg) msg); |
42 | 46 | break; |
... | ... | @@ -89,6 +93,4 @@ public class RuleNodeActor extends ComponentActor<RuleNodeId, RuleNodeActorMessa |
89 | 93 | return systemContext.getRuleNodeErrorPersistFrequency(); |
90 | 94 | } |
91 | 95 | |
92 | - //TODO: failover strategy | |
93 | - | |
94 | 96 | } | ... | ... |
application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeActorMessageProcessor.java
... | ... | @@ -18,28 +18,19 @@ package org.thingsboard.server.actors.ruleChain; |
18 | 18 | import akka.actor.ActorContext; |
19 | 19 | import akka.actor.ActorRef; |
20 | 20 | import akka.event.LoggingAdapter; |
21 | -import com.fasterxml.jackson.databind.JsonNode; | |
22 | -import com.fasterxml.jackson.databind.node.ObjectNode; | |
23 | -import org.springframework.util.Base64Utils; | |
24 | 21 | import org.thingsboard.rule.engine.api.TbNode; |
25 | 22 | import org.thingsboard.rule.engine.api.TbNodeConfiguration; |
26 | 23 | import org.thingsboard.rule.engine.api.TbNodeState; |
27 | 24 | import org.thingsboard.server.actors.ActorSystemContext; |
28 | 25 | import org.thingsboard.server.actors.shared.ComponentMsgProcessor; |
29 | -import org.thingsboard.server.common.data.DataConstants; | |
30 | -import org.thingsboard.server.common.data.Event; | |
31 | 26 | import org.thingsboard.server.common.data.id.RuleChainId; |
32 | 27 | import org.thingsboard.server.common.data.id.RuleNodeId; |
33 | 28 | import org.thingsboard.server.common.data.id.TenantId; |
29 | +import org.thingsboard.server.common.data.plugin.ComponentLifecycleState; | |
34 | 30 | import org.thingsboard.server.common.data.rule.RuleNode; |
35 | -import org.thingsboard.server.common.msg.TbMsg; | |
36 | 31 | import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; |
37 | 32 | import org.thingsboard.server.dao.rule.RuleChainService; |
38 | 33 | |
39 | -import java.io.PrintWriter; | |
40 | -import java.io.StringWriter; | |
41 | -import java.nio.charset.StandardCharsets; | |
42 | - | |
43 | 34 | /** |
44 | 35 | * @author Andrew Shvayka |
45 | 36 | */ |
... | ... | @@ -63,11 +54,25 @@ public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor<RuleNod |
63 | 54 | @Override |
64 | 55 | public void start(ActorContext context) throws Exception { |
65 | 56 | tbNode = initComponent(ruleNode); |
57 | + state = ComponentLifecycleState.ACTIVE; | |
58 | + } | |
59 | + | |
60 | + @Override | |
61 | + public void onUpdate(ActorContext context) throws Exception { | |
62 | + RuleNode newRuleNode = systemContext.getRuleChainService().findRuleNodeById(entityId); | |
63 | + boolean restartRequired = !(ruleNode.getType().equals(newRuleNode.getType()) | |
64 | + && ruleNode.getConfiguration().equals(newRuleNode.getConfiguration())); | |
65 | + this.ruleNode = newRuleNode; | |
66 | + if (restartRequired) { | |
67 | + tbNode.destroy(); | |
68 | + start(context); | |
69 | + } | |
66 | 70 | } |
67 | 71 | |
68 | 72 | @Override |
69 | 73 | public void stop(ActorContext context) throws Exception { |
70 | 74 | tbNode.destroy(); |
75 | + context.stop(self); | |
71 | 76 | } |
72 | 77 | |
73 | 78 | @Override |
... | ... | @@ -76,6 +81,7 @@ public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor<RuleNod |
76 | 81 | } |
77 | 82 | |
78 | 83 | void onRuleChainToRuleNodeMsg(RuleChainToRuleNodeMsg msg) throws Exception { |
84 | + checkActive(); | |
79 | 85 | if (ruleNode.isDebugMode()) { |
80 | 86 | systemContext.persistDebugInput(tenantId, entityId, msg.getMsg()); |
81 | 87 | } |
... | ... | @@ -89,4 +95,5 @@ public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor<RuleNod |
89 | 95 | return tbNode; |
90 | 96 | } |
91 | 97 | |
98 | + | |
92 | 99 | } | ... | ... |
... | ... | @@ -17,7 +17,6 @@ package org.thingsboard.server.actors.ruleChain; |
17 | 17 | |
18 | 18 | import akka.actor.ActorRef; |
19 | 19 | import lombok.Data; |
20 | -import org.thingsboard.server.common.data.id.RuleNodeId; | |
21 | 20 | import org.thingsboard.server.common.data.id.TenantId; |
22 | 21 | import org.thingsboard.server.common.data.rule.RuleNode; |
23 | 22 | ... | ... |
... | ... | @@ -16,7 +16,6 @@ |
16 | 16 | package org.thingsboard.server.actors.ruleChain; |
17 | 17 | |
18 | 18 | import lombok.Data; |
19 | -import org.thingsboard.server.common.data.id.RuleNodeId; | |
20 | 19 | import org.thingsboard.server.common.msg.MsgType; |
21 | 20 | import org.thingsboard.server.common.msg.TbActorMsg; |
22 | 21 | import org.thingsboard.server.common.msg.TbMsg; | ... | ... |
... | ... | @@ -20,12 +20,14 @@ import akka.event.LoggingAdapter; |
20 | 20 | import org.thingsboard.server.actors.ActorSystemContext; |
21 | 21 | import org.thingsboard.server.actors.stats.StatsPersistTick; |
22 | 22 | import org.thingsboard.server.common.data.id.TenantId; |
23 | +import org.thingsboard.server.common.data.plugin.ComponentLifecycleState; | |
23 | 24 | import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; |
24 | 25 | |
25 | 26 | public abstract class ComponentMsgProcessor<T> extends AbstractContextAwareMsgProcessor { |
26 | 27 | |
27 | 28 | protected final TenantId tenantId; |
28 | 29 | protected final T entityId; |
30 | + protected ComponentLifecycleState state; | |
29 | 31 | |
30 | 32 | protected ComponentMsgProcessor(ActorSystemContext systemContext, LoggingAdapter logger, TenantId tenantId, T id) { |
31 | 33 | super(systemContext, logger); |
... | ... | @@ -67,4 +69,10 @@ public abstract class ComponentMsgProcessor<T> extends AbstractContextAwareMsgPr |
67 | 69 | public void scheduleStatsPersistTick(ActorContext context, long statsPersistFrequency) { |
68 | 70 | schedulePeriodicMsgWithDelay(context, new StatsPersistTick(), statsPersistFrequency, statsPersistFrequency); |
69 | 71 | } |
72 | + | |
73 | + protected void checkActive() { | |
74 | + if (state != ComponentLifecycleState.ACTIVE) { | |
75 | + throw new IllegalStateException("Rule chain is not active!"); | |
76 | + } | |
77 | + } | |
70 | 78 | } | ... | ... |
... | ... | @@ -29,7 +29,7 @@ import org.thingsboard.server.common.data.rule.RuleChainMetaData; |
29 | 29 | /** |
30 | 30 | * Created by ashvayka on 20.03.18. |
31 | 31 | */ |
32 | -public class AbstractRuleEngineControllerTest extends AbstractControllerTest{ | |
32 | +public class AbstractRuleEngineControllerTest extends AbstractControllerTest { | |
33 | 33 | |
34 | 34 | protected RuleChain saveRuleChain(RuleChain ruleChain) throws Exception { |
35 | 35 | return doPost("/api/ruleChain", ruleChain, RuleChain.class); | ... | ... |
... | ... | @@ -24,7 +24,7 @@ import java.util.Arrays; |
24 | 24 | |
25 | 25 | @RunWith(ClasspathSuite.class) |
26 | 26 | @ClasspathSuite.ClassnameFilters({ |
27 | - "org.thingsboard.server.rules.flow.*Test", "org.thingsboard.server.rules.lifecycle.*Test"}) | |
27 | + "org.thingsboard.server.rules.flow.*Test"}) | |
28 | 28 | public class RuleEngineSqlTestSuite { |
29 | 29 | |
30 | 30 | @ClassRule | ... | ... |
... | ... | @@ -38,7 +38,9 @@ import org.thingsboard.server.common.msg.TbMsgMetaData; |
38 | 38 | import org.thingsboard.server.common.msg.system.ServiceToRuleEngineMsg; |
39 | 39 | import org.thingsboard.server.controller.AbstractRuleEngineControllerTest; |
40 | 40 | import org.thingsboard.server.dao.attributes.AttributesService; |
41 | +import org.thingsboard.server.dao.rule.RuleChainService; | |
41 | 42 | |
43 | +import java.util.Arrays; | |
42 | 44 | import java.util.Collections; |
43 | 45 | |
44 | 46 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; |
... | ... | @@ -49,17 +51,17 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. |
49 | 51 | @Slf4j |
50 | 52 | public abstract class AbstractRuleEngineFlowIntegrationTest extends AbstractRuleEngineControllerTest { |
51 | 53 | |
52 | - private static final String MQTT_URL = "tcp://localhost:1883"; | |
53 | - private static final Long TIME_TO_HANDLE_REQUEST = 500L; | |
54 | + protected Tenant savedTenant; | |
55 | + protected User tenantAdmin; | |
54 | 56 | |
55 | - private Tenant savedTenant; | |
56 | - private User tenantAdmin; | |
57 | + @Autowired | |
58 | + protected ActorService actorService; | |
57 | 59 | |
58 | 60 | @Autowired |
59 | - private ActorService actorService; | |
61 | + protected AttributesService attributesService; | |
60 | 62 | |
61 | 63 | @Autowired |
62 | - private AttributesService attributesService; | |
64 | + protected RuleChainService ruleChainService; | |
63 | 65 | |
64 | 66 | @Before |
65 | 67 | public void beforeTest() throws Exception { |
... | ... | @@ -89,7 +91,7 @@ public abstract class AbstractRuleEngineFlowIntegrationTest extends AbstractRule |
89 | 91 | } |
90 | 92 | |
91 | 93 | @Test |
92 | - public void testSimpleRuleChainCreation() throws Exception { | |
94 | + public void testRuleChainWithTwoRules() throws Exception { | |
93 | 95 | // Creating Rule Chain |
94 | 96 | RuleChain ruleChain = new RuleChain(); |
95 | 97 | ruleChain.setName("Simple Rule Chain"); |
... | ... | @@ -102,17 +104,26 @@ public abstract class AbstractRuleEngineFlowIntegrationTest extends AbstractRule |
102 | 104 | RuleChainMetaData metaData = new RuleChainMetaData(); |
103 | 105 | metaData.setRuleChainId(ruleChain.getId()); |
104 | 106 | |
105 | - RuleNode ruleNode = new RuleNode(); | |
106 | - ruleNode.setName("Simple Rule Node"); | |
107 | - ruleNode.setType(org.thingsboard.rule.engine.metadata.TbGetAttributesNode.class.getName()); | |
108 | - ruleNode.setDebugMode(true); | |
109 | - TbGetAttributesNodeConfiguration configuration = new TbGetAttributesNodeConfiguration(); | |
110 | - configuration.setServerAttributeNames(Collections.singletonList("serverAttributeKey")); | |
111 | - ruleNode.setConfiguration(mapper.valueToTree(configuration)); | |
107 | + RuleNode ruleNode1 = new RuleNode(); | |
108 | + ruleNode1.setName("Simple Rule Node 1"); | |
109 | + ruleNode1.setType(org.thingsboard.rule.engine.metadata.TbGetAttributesNode.class.getName()); | |
110 | + ruleNode1.setDebugMode(true); | |
111 | + TbGetAttributesNodeConfiguration configuration1 = new TbGetAttributesNodeConfiguration(); | |
112 | + configuration1.setServerAttributeNames(Collections.singletonList("serverAttributeKey1")); | |
113 | + ruleNode1.setConfiguration(mapper.valueToTree(configuration1)); | |
112 | 114 | |
113 | - metaData.setNodes(Collections.singletonList(ruleNode)); | |
114 | - metaData.setFirstNodeIndex(0); | |
115 | + RuleNode ruleNode2 = new RuleNode(); | |
116 | + ruleNode2.setName("Simple Rule Node 2"); | |
117 | + ruleNode2.setType(org.thingsboard.rule.engine.metadata.TbGetAttributesNode.class.getName()); | |
118 | + ruleNode2.setDebugMode(true); | |
119 | + TbGetAttributesNodeConfiguration configuration2 = new TbGetAttributesNodeConfiguration(); | |
120 | + configuration2.setServerAttributeNames(Collections.singletonList("serverAttributeKey2")); | |
121 | + ruleNode2.setConfiguration(mapper.valueToTree(configuration2)); | |
115 | 122 | |
123 | + | |
124 | + metaData.setNodes(Arrays.asList(ruleNode1, ruleNode2)); | |
125 | + metaData.setFirstNodeIndex(0); | |
126 | + metaData.addConnectionInfo(0, 1, "Success"); | |
116 | 127 | metaData = saveRuleChainMetaData(metaData); |
117 | 128 | Assert.assertNotNull(metaData); |
118 | 129 | |
... | ... | @@ -126,7 +137,12 @@ public abstract class AbstractRuleEngineFlowIntegrationTest extends AbstractRule |
126 | 137 | device = doPost("/api/device", device, Device.class); |
127 | 138 | |
128 | 139 | attributesService.save(device.getId(), DataConstants.SERVER_SCOPE, |
129 | - Collections.singletonList(new BaseAttributeKvEntry(new StringDataEntry("serverAttributeKey", "serverAttributeValue"), System.currentTimeMillis()))); | |
140 | + Collections.singletonList(new BaseAttributeKvEntry(new StringDataEntry("serverAttributeKey1", "serverAttributeValue1"), System.currentTimeMillis()))); | |
141 | + attributesService.save(device.getId(), DataConstants.SERVER_SCOPE, | |
142 | + Collections.singletonList(new BaseAttributeKvEntry(new StringDataEntry("serverAttributeKey2", "serverAttributeValue2"), System.currentTimeMillis()))); | |
143 | + | |
144 | + | |
145 | + Thread.sleep(1000); | |
130 | 146 | |
131 | 147 | // Pushing Message to the system |
132 | 148 | TbMsg tbMsg = new TbMsg(UUIDs.timeBased(), |
... | ... | @@ -150,7 +166,25 @@ public abstract class AbstractRuleEngineFlowIntegrationTest extends AbstractRule |
150 | 166 | Assert.assertEquals(ruleChain.getFirstRuleNodeId(), outEvent.getEntityId()); |
151 | 167 | Assert.assertEquals(device.getId().getId().toString(), outEvent.getBody().get("entityId").asText()); |
152 | 168 | |
153 | - Assert.assertEquals("serverAttributeValue", outEvent.getBody().get("metadata").get("ss.serverAttributeKey").asText()); | |
169 | + Assert.assertEquals("serverAttributeValue1", outEvent.getBody().get("metadata").get("ss.serverAttributeKey1").asText()); | |
170 | + | |
171 | + RuleChain finalRuleChain = ruleChain; | |
172 | + RuleNode lastRuleNode = metaData.getNodes().stream().filter(node -> !node.getId().equals(finalRuleChain.getFirstRuleNodeId())).findFirst().get(); | |
173 | + | |
174 | + events = getDebugEvents(savedTenant.getId(), lastRuleNode.getId(), 1000); | |
175 | + | |
176 | + Assert.assertEquals(2, events.getData().size()); | |
177 | + | |
178 | + inEvent = events.getData().stream().filter(e -> e.getBody().get("type").asText().equals(DataConstants.IN)).findFirst().get(); | |
179 | + Assert.assertEquals(lastRuleNode.getId(), inEvent.getEntityId()); | |
180 | + Assert.assertEquals(device.getId().getId().toString(), inEvent.getBody().get("entityId").asText()); | |
181 | + | |
182 | + outEvent = events.getData().stream().filter(e -> e.getBody().get("type").asText().equals(DataConstants.OUT)).findFirst().get(); | |
183 | + Assert.assertEquals(lastRuleNode.getId(), outEvent.getEntityId()); | |
184 | + Assert.assertEquals(device.getId().getId().toString(), outEvent.getBody().get("entityId").asText()); | |
185 | + | |
186 | + Assert.assertEquals("serverAttributeValue1", outEvent.getBody().get("metadata").get("ss.serverAttributeKey1").asText()); | |
187 | + Assert.assertEquals("serverAttributeValue2", outEvent.getBody().get("metadata").get("ss.serverAttributeKey2").asText()); | |
154 | 188 | } |
155 | 189 | |
156 | 190 | } | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2018 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.rules.lifecycle; | |
17 | + | |
18 | +import com.datastax.driver.core.utils.UUIDs; | |
19 | +import lombok.extern.slf4j.Slf4j; | |
20 | +import org.junit.After; | |
21 | +import org.junit.Assert; | |
22 | +import org.junit.Before; | |
23 | +import org.junit.Test; | |
24 | +import org.springframework.beans.factory.annotation.Autowired; | |
25 | +import org.thingsboard.rule.engine.metadata.TbGetAttributesNodeConfiguration; | |
26 | +import org.thingsboard.server.actors.service.ActorService; | |
27 | +import org.thingsboard.server.common.data.DataConstants; | |
28 | +import org.thingsboard.server.common.data.Device; | |
29 | +import org.thingsboard.server.common.data.Event; | |
30 | +import org.thingsboard.server.common.data.Tenant; | |
31 | +import org.thingsboard.server.common.data.User; | |
32 | +import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; | |
33 | +import org.thingsboard.server.common.data.kv.StringDataEntry; | |
34 | +import org.thingsboard.server.common.data.page.TimePageData; | |
35 | +import org.thingsboard.server.common.data.rule.RuleChain; | |
36 | +import org.thingsboard.server.common.data.rule.RuleChainMetaData; | |
37 | +import org.thingsboard.server.common.data.rule.RuleNode; | |
38 | +import org.thingsboard.server.common.data.security.Authority; | |
39 | +import org.thingsboard.server.common.msg.TbMsg; | |
40 | +import org.thingsboard.server.common.msg.TbMsgMetaData; | |
41 | +import org.thingsboard.server.common.msg.system.ServiceToRuleEngineMsg; | |
42 | +import org.thingsboard.server.controller.AbstractRuleEngineControllerTest; | |
43 | +import org.thingsboard.server.dao.attributes.AttributesService; | |
44 | + | |
45 | +import java.util.Collections; | |
46 | + | |
47 | +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; | |
48 | + | |
49 | +/** | |
50 | + * @author Valerii Sosliuk | |
51 | + */ | |
52 | +@Slf4j | |
53 | +public abstract class AbstractRuleEngineLifecycleIntegrationTest extends AbstractRuleEngineControllerTest { | |
54 | + | |
55 | + protected Tenant savedTenant; | |
56 | + protected User tenantAdmin; | |
57 | + | |
58 | + @Autowired | |
59 | + protected ActorService actorService; | |
60 | + | |
61 | + @Autowired | |
62 | + protected AttributesService attributesService; | |
63 | + | |
64 | + @Before | |
65 | + public void beforeTest() throws Exception { | |
66 | + loginSysAdmin(); | |
67 | + | |
68 | + Tenant tenant = new Tenant(); | |
69 | + tenant.setTitle("My tenant"); | |
70 | + savedTenant = doPost("/api/tenant", tenant, Tenant.class); | |
71 | + Assert.assertNotNull(savedTenant); | |
72 | + | |
73 | + tenantAdmin = new User(); | |
74 | + tenantAdmin.setAuthority(Authority.TENANT_ADMIN); | |
75 | + tenantAdmin.setTenantId(savedTenant.getId()); | |
76 | + tenantAdmin.setEmail("tenant2@thingsboard.org"); | |
77 | + tenantAdmin.setFirstName("Joe"); | |
78 | + tenantAdmin.setLastName("Downs"); | |
79 | + | |
80 | + createUserAndLogin(tenantAdmin, "testPassword1"); | |
81 | + } | |
82 | + | |
83 | + @After | |
84 | + public void afterTest() throws Exception { | |
85 | + loginSysAdmin(); | |
86 | + if (savedTenant != null) { | |
87 | + doDelete("/api/tenant/" + savedTenant.getId().getId().toString()).andExpect(status().isOk()); | |
88 | + } | |
89 | + } | |
90 | + | |
91 | + @Test | |
92 | + public void testRuleChainWithOneRule() throws Exception { | |
93 | + // Creating Rule Chain | |
94 | + RuleChain ruleChain = new RuleChain(); | |
95 | + ruleChain.setName("Simple Rule Chain"); | |
96 | + ruleChain.setTenantId(savedTenant.getId()); | |
97 | + ruleChain.setRoot(true); | |
98 | + ruleChain.setDebugMode(true); | |
99 | + ruleChain = saveRuleChain(ruleChain); | |
100 | + Assert.assertNull(ruleChain.getFirstRuleNodeId()); | |
101 | + | |
102 | + RuleChainMetaData metaData = new RuleChainMetaData(); | |
103 | + metaData.setRuleChainId(ruleChain.getId()); | |
104 | + | |
105 | + RuleNode ruleNode = new RuleNode(); | |
106 | + ruleNode.setName("Simple Rule Node"); | |
107 | + ruleNode.setType(org.thingsboard.rule.engine.metadata.TbGetAttributesNode.class.getName()); | |
108 | + ruleNode.setDebugMode(true); | |
109 | + TbGetAttributesNodeConfiguration configuration = new TbGetAttributesNodeConfiguration(); | |
110 | + configuration.setServerAttributeNames(Collections.singletonList("serverAttributeKey")); | |
111 | + ruleNode.setConfiguration(mapper.valueToTree(configuration)); | |
112 | + | |
113 | + metaData.setNodes(Collections.singletonList(ruleNode)); | |
114 | + metaData.setFirstNodeIndex(0); | |
115 | + | |
116 | + metaData = saveRuleChainMetaData(metaData); | |
117 | + Assert.assertNotNull(metaData); | |
118 | + | |
119 | + ruleChain = getRuleChain(ruleChain.getId()); | |
120 | + Assert.assertNotNull(ruleChain.getFirstRuleNodeId()); | |
121 | + | |
122 | + // Saving the device | |
123 | + Device device = new Device(); | |
124 | + device.setName("My device"); | |
125 | + device.setType("default"); | |
126 | + device = doPost("/api/device", device, Device.class); | |
127 | + | |
128 | + attributesService.save(device.getId(), DataConstants.SERVER_SCOPE, | |
129 | + Collections.singletonList(new BaseAttributeKvEntry(new StringDataEntry("serverAttributeKey", "serverAttributeValue"), System.currentTimeMillis()))); | |
130 | + | |
131 | + Thread.sleep(1000); | |
132 | + | |
133 | + // Pushing Message to the system | |
134 | + TbMsg tbMsg = new TbMsg(UUIDs.timeBased(), | |
135 | + "CUSTOM", | |
136 | + device.getId(), | |
137 | + new TbMsgMetaData(), | |
138 | + new byte[]{}); | |
139 | + actorService.onMsg(new ServiceToRuleEngineMsg(savedTenant.getId(), tbMsg)); | |
140 | + | |
141 | + Thread.sleep(3000); | |
142 | + | |
143 | + TimePageData<Event> events = getDebugEvents(savedTenant.getId(), ruleChain.getFirstRuleNodeId(), 1000); | |
144 | + | |
145 | + Assert.assertEquals(2, events.getData().size()); | |
146 | + | |
147 | + Event inEvent = events.getData().stream().filter(e -> e.getBody().get("type").asText().equals(DataConstants.IN)).findFirst().get(); | |
148 | + Assert.assertEquals(ruleChain.getFirstRuleNodeId(), inEvent.getEntityId()); | |
149 | + Assert.assertEquals(device.getId().getId().toString(), inEvent.getBody().get("entityId").asText()); | |
150 | + | |
151 | + Event outEvent = events.getData().stream().filter(e -> e.getBody().get("type").asText().equals(DataConstants.OUT)).findFirst().get(); | |
152 | + Assert.assertEquals(ruleChain.getFirstRuleNodeId(), outEvent.getEntityId()); | |
153 | + Assert.assertEquals(device.getId().getId().toString(), outEvent.getBody().get("entityId").asText()); | |
154 | + | |
155 | + Assert.assertEquals("serverAttributeValue", outEvent.getBody().get("metadata").get("ss.serverAttributeKey").asText()); | |
156 | + } | |
157 | + | |
158 | +} | ... | ... |
application/src/test/java/org/thingsboard/server/rules/lifecycle/RuleEngineLifecycleSqlIntegrationTest.java
renamed from
dao/src/test/java/org/thingsboard/server/dao/service/rule/sql/RuleServiceSqlTest.java
... | ... | @@ -13,11 +13,14 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.dao.service.rule.sql; | |
16 | +package org.thingsboard.server.rules.lifecycle; | |
17 | 17 | |
18 | 18 | import org.thingsboard.server.dao.service.DaoSqlTest; |
19 | -import org.thingsboard.server.dao.service.rule.BaseRuleServiceTest; | |
19 | +import org.thingsboard.server.rules.flow.AbstractRuleEngineFlowIntegrationTest; | |
20 | 20 | |
21 | +/** | |
22 | + * Created by Valerii Sosliuk on 8/22/2017. | |
23 | + */ | |
21 | 24 | @DaoSqlTest |
22 | -public class RuleServiceSqlTest extends BaseRuleServiceTest { | |
25 | +public class RuleEngineLifecycleSqlIntegrationTest extends AbstractRuleEngineLifecycleIntegrationTest { | |
23 | 26 | } | ... | ... |
common/data/src/main/java/org/thingsboard/server/common/data/rule/NodeConnectionInfo.java
renamed from
dao/src/test/java/org/thingsboard/server/dao/service/rule/nosql/RuleServiceNoSqlTest.java
... | ... | @@ -13,11 +13,16 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.dao.service.rule.nosql; | |
16 | +package org.thingsboard.server.common.data.rule; | |
17 | 17 | |
18 | -import org.thingsboard.server.dao.service.DaoNoSqlTest; | |
19 | -import org.thingsboard.server.dao.service.rule.BaseRuleServiceTest; | |
18 | +import lombok.Data; | |
20 | 19 | |
21 | -@DaoNoSqlTest | |
22 | -public class RuleServiceNoSqlTest extends BaseRuleServiceTest { | |
20 | +/** | |
21 | + * Created by ashvayka on 21.03.18. | |
22 | + */ | |
23 | +@Data | |
24 | +public class NodeConnectionInfo { | |
25 | + private int fromIndex; | |
26 | + private int toIndex; | |
27 | + private String type; | |
23 | 28 | } | ... | ... |
common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleChainConnectionInfo.java
0 → 100644
1 | +/** | |
2 | + * Copyright © 2016-2018 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.common.data.rule; | |
17 | + | |
18 | +import lombok.Data; | |
19 | +import org.thingsboard.server.common.data.id.RuleChainId; | |
20 | + | |
21 | +/** | |
22 | + * Created by ashvayka on 21.03.18. | |
23 | + */ | |
24 | +@Data | |
25 | +public class RuleChainConnectionInfo { | |
26 | + private int fromIndex; | |
27 | + private RuleChainId targetRuleChainId; | |
28 | + private String type; | |
29 | +} | ... | ... |
... | ... | @@ -58,18 +58,4 @@ public class RuleChainMetaData { |
58 | 58 | ruleChainConnections.add(connectionInfo); |
59 | 59 | } |
60 | 60 | |
61 | - @Data | |
62 | - public class NodeConnectionInfo { | |
63 | - private int fromIndex; | |
64 | - private int toIndex; | |
65 | - private String type; | |
66 | - } | |
67 | - | |
68 | - @Data | |
69 | - public class RuleChainConnectionInfo { | |
70 | - private int fromIndex; | |
71 | - private RuleChainId targetRuleChainId; | |
72 | - private String type; | |
73 | - } | |
74 | - | |
75 | 61 | } | ... | ... |
... | ... | @@ -31,7 +31,9 @@ import org.thingsboard.server.common.data.page.TextPageData; |
31 | 31 | import org.thingsboard.server.common.data.page.TextPageLink; |
32 | 32 | import org.thingsboard.server.common.data.relation.EntityRelation; |
33 | 33 | import org.thingsboard.server.common.data.relation.RelationTypeGroup; |
34 | +import org.thingsboard.server.common.data.rule.NodeConnectionInfo; | |
34 | 35 | import org.thingsboard.server.common.data.rule.RuleChain; |
36 | +import org.thingsboard.server.common.data.rule.RuleChainConnectionInfo; | |
35 | 37 | import org.thingsboard.server.common.data.rule.RuleChainMetaData; |
36 | 38 | import org.thingsboard.server.common.data.rule.RuleNode; |
37 | 39 | import org.thingsboard.server.dao.entity.AbstractEntityService; |
... | ... | @@ -148,7 +150,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC |
148 | 150 | ruleChainDao.save(ruleChain); |
149 | 151 | } |
150 | 152 | if (ruleChainMetaData.getConnections() != null) { |
151 | - for (RuleChainMetaData.NodeConnectionInfo nodeConnection : ruleChainMetaData.getConnections()) { | |
153 | + for (NodeConnectionInfo nodeConnection : ruleChainMetaData.getConnections()) { | |
152 | 154 | EntityId from = nodes.get(nodeConnection.getFromIndex()).getId(); |
153 | 155 | EntityId to = nodes.get(nodeConnection.getToIndex()).getId(); |
154 | 156 | String type = nodeConnection.getType(); |
... | ... | @@ -161,7 +163,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC |
161 | 163 | } |
162 | 164 | } |
163 | 165 | if (ruleChainMetaData.getRuleChainConnections() != null) { |
164 | - for (RuleChainMetaData.RuleChainConnectionInfo nodeToRuleChainConnection : ruleChainMetaData.getRuleChainConnections()) { | |
166 | + for (RuleChainConnectionInfo nodeToRuleChainConnection : ruleChainMetaData.getRuleChainConnections()) { | |
165 | 167 | EntityId from = nodes.get(nodeToRuleChainConnection.getFromIndex()).getId(); |
166 | 168 | EntityId to = nodeToRuleChainConnection.getTargetRuleChainId(); |
167 | 169 | String type = nodeToRuleChainConnection.getType(); |
... | ... | @@ -314,7 +316,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC |
314 | 316 | |
315 | 317 | private void createRelation(EntityRelation relation) throws ExecutionException, InterruptedException { |
316 | 318 | log.debug("Creating relation: {}", relation); |
317 | - relationService.saveRelationAsync(relation).get(); | |
319 | + relationService.saveRelation(relation); | |
318 | 320 | } |
319 | 321 | |
320 | 322 | private DataValidator<RuleChain> ruleChainValidator = | ... | ... |
dao/src/test/java/org/thingsboard/server/dao/service/rule/BaseRuleServiceTest.java
deleted
100644 → 0
1 | -/** | |
2 | - * Copyright © 2016-2018 The Thingsboard Authors | |
3 | - * | |
4 | - * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | - * you may not use this file except in compliance with the License. | |
6 | - * You may obtain a copy of the License at | |
7 | - * | |
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | - * | |
10 | - * Unless required by applicable law or agreed to in writing, software | |
11 | - * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | - * See the License for the specific language governing permissions and | |
14 | - * limitations under the License. | |
15 | - */ | |
16 | -package org.thingsboard.server.dao.service.rule; | |
17 | - | |
18 | -import com.datastax.driver.core.utils.UUIDs; | |
19 | -import org.junit.Assert; | |
20 | -import org.junit.Test; | |
21 | -import org.thingsboard.server.common.data.id.TenantId; | |
22 | -import org.thingsboard.server.common.data.page.TextPageData; | |
23 | -import org.thingsboard.server.common.data.page.TextPageLink; | |
24 | -import org.thingsboard.server.common.data.plugin.PluginMetaData; | |
25 | -import org.thingsboard.server.common.data.rule.RuleMetaData; | |
26 | -import org.thingsboard.server.dao.model.ModelConstants; | |
27 | -import org.thingsboard.server.dao.service.AbstractServiceTest; | |
28 | - | |
29 | -import java.util.List; | |
30 | -import java.util.concurrent.ThreadLocalRandom; | |
31 | - | |
32 | -public abstract class BaseRuleServiceTest extends AbstractServiceTest { | |
33 | - | |
34 | - @Test | |
35 | - public void saveRule() throws Exception { | |
36 | - PluginMetaData plugin = generatePlugin(null, "testPluginToken" + ThreadLocalRandom.current().nextInt()); | |
37 | - pluginService.savePlugin(plugin); | |
38 | - RuleMetaData ruleMetaData = ruleService.saveRule(generateRule(plugin.getTenantId(), null, plugin.getApiToken())); | |
39 | - Assert.assertNotNull(ruleMetaData.getId()); | |
40 | - Assert.assertNotNull(ruleMetaData.getAdditionalInfo()); | |
41 | - ruleMetaData.setAdditionalInfo(mapper.readTree("{\"description\":\"test\"}")); | |
42 | - RuleMetaData newRuleMetaData = ruleService.saveRule(ruleMetaData); | |
43 | - Assert.assertEquals(ruleMetaData.getAdditionalInfo(), newRuleMetaData.getAdditionalInfo()); | |
44 | - } | |
45 | - | |
46 | - @Test | |
47 | - public void findRuleById() throws Exception { | |
48 | - PluginMetaData plugin = generatePlugin(null, "testPluginToken" + ThreadLocalRandom.current().nextInt()); | |
49 | - pluginService.savePlugin(plugin); | |
50 | - | |
51 | - RuleMetaData expected = ruleService.saveRule(generateRule(plugin.getTenantId(), null, plugin.getApiToken())); | |
52 | - Assert.assertNotNull(expected.getId()); | |
53 | - RuleMetaData found = ruleService.findRuleById(expected.getId()); | |
54 | - Assert.assertEquals(expected, found); | |
55 | - } | |
56 | - | |
57 | - @Test | |
58 | - public void findPluginRules() throws Exception { | |
59 | - TenantId tenantIdA = new TenantId(UUIDs.timeBased()); | |
60 | - TenantId tenantIdB = new TenantId(UUIDs.timeBased()); | |
61 | - | |
62 | - PluginMetaData pluginA = generatePlugin(tenantIdA, "testPluginToken" + ThreadLocalRandom.current().nextInt()); | |
63 | - PluginMetaData pluginB = generatePlugin(tenantIdB, "testPluginToken" + ThreadLocalRandom.current().nextInt()); | |
64 | - pluginService.savePlugin(pluginA); | |
65 | - pluginService.savePlugin(pluginB); | |
66 | - | |
67 | - ruleService.saveRule(generateRule(tenantIdA, null, pluginA.getApiToken())); | |
68 | - ruleService.saveRule(generateRule(tenantIdA, null, pluginA.getApiToken())); | |
69 | - ruleService.saveRule(generateRule(tenantIdA, null, pluginA.getApiToken())); | |
70 | - | |
71 | - ruleService.saveRule(generateRule(tenantIdB, null, pluginB.getApiToken())); | |
72 | - ruleService.saveRule(generateRule(tenantIdB, null, pluginB.getApiToken())); | |
73 | - | |
74 | - List<RuleMetaData> foundA = ruleService.findPluginRules(pluginA.getApiToken()); | |
75 | - Assert.assertEquals(3, foundA.size()); | |
76 | - | |
77 | - List<RuleMetaData> foundB = ruleService.findPluginRules(pluginB.getApiToken()); | |
78 | - Assert.assertEquals(2, foundB.size()); | |
79 | - } | |
80 | - | |
81 | - @Test | |
82 | - public void findSystemRules() throws Exception { | |
83 | - TenantId systemTenant = new TenantId(ModelConstants.NULL_UUID); // system tenant id | |
84 | - | |
85 | - PluginMetaData plugin = generatePlugin(systemTenant, "testPluginToken" + ThreadLocalRandom.current().nextInt()); | |
86 | - pluginService.savePlugin(plugin); | |
87 | - ruleService.saveRule(generateRule(systemTenant, null, plugin.getApiToken())); | |
88 | - ruleService.saveRule(generateRule(systemTenant, null, plugin.getApiToken())); | |
89 | - ruleService.saveRule(generateRule(systemTenant, null, plugin.getApiToken())); | |
90 | - TextPageData<RuleMetaData> found = ruleService.findSystemRules(new TextPageLink(100)); | |
91 | - Assert.assertEquals(3, found.getData().size()); | |
92 | - } | |
93 | - | |
94 | - @Test | |
95 | - public void findTenantRules() throws Exception { | |
96 | - TenantId tenantIdA = new TenantId(UUIDs.timeBased()); | |
97 | - TenantId tenantIdB = new TenantId(UUIDs.timeBased()); | |
98 | - | |
99 | - PluginMetaData pluginA = generatePlugin(tenantIdA, "testPluginToken" + ThreadLocalRandom.current().nextInt()); | |
100 | - PluginMetaData pluginB = generatePlugin(tenantIdB, "testPluginToken" + ThreadLocalRandom.current().nextInt()); | |
101 | - pluginService.savePlugin(pluginA); | |
102 | - pluginService.savePlugin(pluginB); | |
103 | - | |
104 | - ruleService.saveRule(generateRule(tenantIdA, null, pluginA.getApiToken())); | |
105 | - ruleService.saveRule(generateRule(tenantIdA, null, pluginA.getApiToken())); | |
106 | - ruleService.saveRule(generateRule(tenantIdA, null, pluginA.getApiToken())); | |
107 | - | |
108 | - ruleService.saveRule(generateRule(tenantIdB, null, pluginB.getApiToken())); | |
109 | - ruleService.saveRule(generateRule(tenantIdB, null, pluginB.getApiToken())); | |
110 | - | |
111 | - TextPageData<RuleMetaData> foundA = ruleService.findTenantRules(tenantIdA, new TextPageLink(100)); | |
112 | - Assert.assertEquals(3, foundA.getData().size()); | |
113 | - | |
114 | - TextPageData<RuleMetaData> foundB = ruleService.findTenantRules(tenantIdB, new TextPageLink(100)); | |
115 | - Assert.assertEquals(2, foundB.getData().size()); | |
116 | - } | |
117 | - | |
118 | - @Test | |
119 | - public void deleteRuleById() throws Exception { | |
120 | - PluginMetaData plugin = generatePlugin(null, "testPluginToken" + ThreadLocalRandom.current().nextInt()); | |
121 | - pluginService.savePlugin(plugin); | |
122 | - | |
123 | - RuleMetaData expected = ruleService.saveRule(generateRule(plugin.getTenantId(), null, plugin.getApiToken())); | |
124 | - Assert.assertNotNull(expected.getId()); | |
125 | - RuleMetaData found = ruleService.findRuleById(expected.getId()); | |
126 | - Assert.assertEquals(expected, found); | |
127 | - ruleService.deleteRuleById(expected.getId()); | |
128 | - found = ruleService.findRuleById(expected.getId()); | |
129 | - Assert.assertNull(found); | |
130 | - } | |
131 | - | |
132 | - @Test | |
133 | - public void deleteRulesByTenantId() throws Exception { | |
134 | - TenantId tenantIdA = new TenantId(UUIDs.timeBased()); | |
135 | - TenantId tenantIdB = new TenantId(UUIDs.timeBased()); | |
136 | - | |
137 | - PluginMetaData pluginA = generatePlugin(tenantIdA, "testPluginToken" + ThreadLocalRandom.current().nextInt()); | |
138 | - PluginMetaData pluginB = generatePlugin(tenantIdB, "testPluginToken" + ThreadLocalRandom.current().nextInt()); | |
139 | - pluginService.savePlugin(pluginA); | |
140 | - pluginService.savePlugin(pluginB); | |
141 | - | |
142 | - ruleService.saveRule(generateRule(tenantIdA, null, pluginA.getApiToken())); | |
143 | - ruleService.saveRule(generateRule(tenantIdA, null, pluginA.getApiToken())); | |
144 | - ruleService.saveRule(generateRule(tenantIdA, null, pluginA.getApiToken())); | |
145 | - | |
146 | - ruleService.saveRule(generateRule(tenantIdB, null, pluginB.getApiToken())); | |
147 | - ruleService.saveRule(generateRule(tenantIdB, null, pluginB.getApiToken())); | |
148 | - | |
149 | - TextPageData<RuleMetaData> foundA = ruleService.findTenantRules(tenantIdA, new TextPageLink(100)); | |
150 | - Assert.assertEquals(3, foundA.getData().size()); | |
151 | - | |
152 | - TextPageData<RuleMetaData> foundB = ruleService.findTenantRules(tenantIdB, new TextPageLink(100)); | |
153 | - Assert.assertEquals(2, foundB.getData().size()); | |
154 | - | |
155 | - ruleService.deleteRulesByTenantId(tenantIdA); | |
156 | - | |
157 | - foundA = ruleService.findTenantRules(tenantIdA, new TextPageLink(100)); | |
158 | - Assert.assertEquals(0, foundA.getData().size()); | |
159 | - | |
160 | - foundB = ruleService.findTenantRules(tenantIdB, new TextPageLink(100)); | |
161 | - Assert.assertEquals(2, foundB.getData().size()); | |
162 | - } | |
163 | -} | |
\ No newline at end of file |