Commit 64a8e5c152c6f0629d883608b87686edb9eace6a
1 parent
fc79356a
First integration test for the new rule engine. Fixed a lot of bugs
Showing
92 changed files
with
1153 additions
and
1473 deletions
... | ... | @@ -58,6 +58,10 @@ |
58 | 58 | <artifactId>rule-engine-api</artifactId> |
59 | 59 | </dependency> |
60 | 60 | <dependency> |
61 | + <groupId>org.thingsboard.rule-engine</groupId> | |
62 | + <artifactId>rule-engine-components</artifactId> | |
63 | + </dependency> | |
64 | + <dependency> | |
61 | 65 | <groupId>org.thingsboard</groupId> |
62 | 66 | <artifactId>extensions-core</artifactId> |
63 | 67 | </dependency> | ... | ... |
... | ... | @@ -69,6 +69,7 @@ CREATE TABLE IF NOT EXISTS thingsboard.rule_chain ( |
69 | 69 | search_text text, |
70 | 70 | first_rule_node_id uuid, |
71 | 71 | root boolean, |
72 | + debug_mode boolean, | |
72 | 73 | configuration text, |
73 | 74 | additional_info text, |
74 | 75 | PRIMARY KEY (id, tenant_id) |
... | ... | @@ -85,6 +86,7 @@ CREATE TABLE IF NOT EXISTS thingsboard.rule_node ( |
85 | 86 | id uuid, |
86 | 87 | type text, |
87 | 88 | name text, |
89 | + debug_mode boolean, | |
88 | 90 | search_text text, |
89 | 91 | configuration text, |
90 | 92 | additional_info text, | ... | ... |
... | ... | @@ -21,6 +21,7 @@ CREATE TABLE IF NOT EXISTS rule_chain ( |
21 | 21 | name varchar(255), |
22 | 22 | first_rule_node_id varchar(31), |
23 | 23 | root boolean, |
24 | + debug_mode boolean, | |
24 | 25 | search_text varchar(255), |
25 | 26 | tenant_id varchar(31) |
26 | 27 | ); |
... | ... | @@ -31,5 +32,6 @@ CREATE TABLE IF NOT EXISTS rule_node ( |
31 | 32 | configuration varchar(10000000), |
32 | 33 | type varchar(255), |
33 | 34 | name varchar(255), |
35 | + debug_mode boolean, | |
34 | 36 | search_text varchar(255) |
35 | 37 | ); |
\ No newline at end of file | ... | ... |
1 | 1 | /** |
2 | 2 | * Copyright © 2016-2018 The Thingsboard Authors |
3 | - * | |
3 | + * <p> | |
4 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | 5 | * you may not use this file except in compliance with the License. |
6 | 6 | * You may obtain a copy of the License at |
7 | - * | |
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | - * | |
7 | + * <p> | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * <p> | |
10 | 10 | * Unless required by applicable law or agreed to in writing, software |
11 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
... | ... | @@ -28,12 +28,14 @@ import lombok.Setter; |
28 | 28 | import org.springframework.beans.factory.annotation.Autowired; |
29 | 29 | import org.springframework.beans.factory.annotation.Value; |
30 | 30 | import org.springframework.stereotype.Component; |
31 | +import org.springframework.util.Base64Utils; | |
31 | 32 | import org.thingsboard.server.actors.service.ActorService; |
32 | 33 | import org.thingsboard.server.common.data.DataConstants; |
33 | 34 | import org.thingsboard.server.common.data.Event; |
34 | 35 | import org.thingsboard.server.common.data.id.EntityId; |
35 | 36 | import org.thingsboard.server.common.data.id.TenantId; |
36 | 37 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; |
38 | +import org.thingsboard.server.common.msg.TbMsg; | |
37 | 39 | import org.thingsboard.server.common.msg.cluster.ServerAddress; |
38 | 40 | import org.thingsboard.server.common.transport.auth.DeviceAuthService; |
39 | 41 | import org.thingsboard.server.controller.plugin.PluginWebSocketMsgEndpoint; |
... | ... | @@ -50,6 +52,7 @@ import org.thingsboard.server.dao.rule.RuleChainService; |
50 | 52 | import org.thingsboard.server.dao.rule.RuleService; |
51 | 53 | import org.thingsboard.server.dao.tenant.TenantService; |
52 | 54 | import org.thingsboard.server.dao.timeseries.TimeseriesService; |
55 | +import org.thingsboard.server.dao.user.UserService; | |
53 | 56 | import org.thingsboard.server.service.cluster.discovery.DiscoveryService; |
54 | 57 | import org.thingsboard.server.service.cluster.routing.ClusterRoutingService; |
55 | 58 | import org.thingsboard.server.service.cluster.rpc.ClusterRpcService; |
... | ... | @@ -57,6 +60,7 @@ import org.thingsboard.server.service.component.ComponentDiscoveryService; |
57 | 60 | |
58 | 61 | import java.io.PrintWriter; |
59 | 62 | import java.io.StringWriter; |
63 | +import java.nio.charset.StandardCharsets; | |
60 | 64 | import java.util.Optional; |
61 | 65 | |
62 | 66 | @Component |
... | ... | @@ -65,107 +69,154 @@ public class ActorSystemContext { |
65 | 69 | |
66 | 70 | protected final ObjectMapper mapper = new ObjectMapper(); |
67 | 71 | |
68 | - @Getter @Setter private ActorService actorService; | |
72 | + @Getter | |
73 | + @Setter | |
74 | + private ActorService actorService; | |
69 | 75 | |
70 | 76 | @Autowired |
71 | - @Getter private DiscoveryService discoveryService; | |
77 | + @Getter | |
78 | + private DiscoveryService discoveryService; | |
72 | 79 | |
73 | 80 | @Autowired |
74 | - @Getter @Setter private ComponentDiscoveryService componentService; | |
81 | + @Getter | |
82 | + @Setter | |
83 | + private ComponentDiscoveryService componentService; | |
75 | 84 | |
76 | 85 | @Autowired |
77 | - @Getter private ClusterRoutingService routingService; | |
86 | + @Getter | |
87 | + private ClusterRoutingService routingService; | |
78 | 88 | |
79 | 89 | @Autowired |
80 | - @Getter private ClusterRpcService rpcService; | |
90 | + @Getter | |
91 | + private ClusterRpcService rpcService; | |
81 | 92 | |
82 | 93 | @Autowired |
83 | - @Getter private DeviceAuthService deviceAuthService; | |
94 | + @Getter | |
95 | + private DeviceAuthService deviceAuthService; | |
84 | 96 | |
85 | 97 | @Autowired |
86 | - @Getter private DeviceService deviceService; | |
98 | + @Getter | |
99 | + private DeviceService deviceService; | |
87 | 100 | |
88 | 101 | @Autowired |
89 | - @Getter private AssetService assetService; | |
102 | + @Getter | |
103 | + private AssetService assetService; | |
90 | 104 | |
91 | 105 | @Autowired |
92 | - @Getter private TenantService tenantService; | |
106 | + @Getter | |
107 | + private TenantService tenantService; | |
93 | 108 | |
94 | 109 | @Autowired |
95 | - @Getter private CustomerService customerService; | |
110 | + @Getter | |
111 | + private CustomerService customerService; | |
96 | 112 | |
97 | 113 | @Autowired |
98 | - @Getter private RuleService ruleService; | |
114 | + @Getter | |
115 | + private UserService userService; | |
99 | 116 | |
100 | 117 | @Autowired |
101 | - @Getter private RuleChainService ruleChainService; | |
118 | + @Getter | |
119 | + private RuleService ruleService; | |
102 | 120 | |
103 | 121 | @Autowired |
104 | - @Getter private PluginService pluginService; | |
122 | + @Getter | |
123 | + private RuleChainService ruleChainService; | |
105 | 124 | |
106 | 125 | @Autowired |
107 | - @Getter private TimeseriesService tsService; | |
126 | + @Getter | |
127 | + private PluginService pluginService; | |
108 | 128 | |
109 | 129 | @Autowired |
110 | - @Getter private AttributesService attributesService; | |
130 | + @Getter | |
131 | + private TimeseriesService tsService; | |
111 | 132 | |
112 | 133 | @Autowired |
113 | - @Getter private EventService eventService; | |
134 | + @Getter | |
135 | + private AttributesService attributesService; | |
114 | 136 | |
115 | 137 | @Autowired |
116 | - @Getter private AlarmService alarmService; | |
138 | + @Getter | |
139 | + private EventService eventService; | |
117 | 140 | |
118 | 141 | @Autowired |
119 | - @Getter private RelationService relationService; | |
142 | + @Getter | |
143 | + private AlarmService alarmService; | |
120 | 144 | |
121 | 145 | @Autowired |
122 | - @Getter private AuditLogService auditLogService; | |
146 | + @Getter | |
147 | + private RelationService relationService; | |
123 | 148 | |
124 | 149 | @Autowired |
125 | - @Getter @Setter private PluginWebSocketMsgEndpoint wsMsgEndpoint; | |
150 | + @Getter | |
151 | + private AuditLogService auditLogService; | |
152 | + | |
153 | + @Autowired | |
154 | + @Getter | |
155 | + @Setter | |
156 | + private PluginWebSocketMsgEndpoint wsMsgEndpoint; | |
126 | 157 | |
127 | 158 | @Value("${actors.session.sync.timeout}") |
128 | - @Getter private long syncSessionTimeout; | |
159 | + @Getter | |
160 | + private long syncSessionTimeout; | |
129 | 161 | |
130 | 162 | @Value("${actors.plugin.termination.delay}") |
131 | - @Getter private long pluginActorTerminationDelay; | |
163 | + @Getter | |
164 | + private long pluginActorTerminationDelay; | |
132 | 165 | |
133 | 166 | @Value("${actors.plugin.processing.timeout}") |
134 | - @Getter private long pluginProcessingTimeout; | |
167 | + @Getter | |
168 | + private long pluginProcessingTimeout; | |
135 | 169 | |
136 | 170 | @Value("${actors.plugin.error_persist_frequency}") |
137 | - @Getter private long pluginErrorPersistFrequency; | |
171 | + @Getter | |
172 | + private long pluginErrorPersistFrequency; | |
138 | 173 | |
139 | 174 | @Value("${actors.rule.chain.error_persist_frequency}") |
140 | - @Getter private long ruleChainErrorPersistFrequency; | |
175 | + @Getter | |
176 | + private long ruleChainErrorPersistFrequency; | |
141 | 177 | |
142 | 178 | @Value("${actors.rule.node.error_persist_frequency}") |
143 | - @Getter private long ruleNodeErrorPersistFrequency; | |
179 | + @Getter | |
180 | + private long ruleNodeErrorPersistFrequency; | |
144 | 181 | |
145 | 182 | @Value("${actors.rule.termination.delay}") |
146 | - @Getter private long ruleActorTerminationDelay; | |
183 | + @Getter | |
184 | + private long ruleActorTerminationDelay; | |
147 | 185 | |
148 | 186 | @Value("${actors.rule.error_persist_frequency}") |
149 | - @Getter private long ruleErrorPersistFrequency; | |
187 | + @Getter | |
188 | + private long ruleErrorPersistFrequency; | |
150 | 189 | |
151 | 190 | @Value("${actors.statistics.enabled}") |
152 | - @Getter private boolean statisticsEnabled; | |
191 | + @Getter | |
192 | + private boolean statisticsEnabled; | |
153 | 193 | |
154 | 194 | @Value("${actors.statistics.persist_frequency}") |
155 | - @Getter private long statisticsPersistFrequency; | |
195 | + @Getter | |
196 | + private long statisticsPersistFrequency; | |
156 | 197 | |
157 | 198 | @Value("${actors.tenant.create_components_on_init}") |
158 | - @Getter private boolean tenantComponentsInitEnabled; | |
199 | + @Getter | |
200 | + private boolean tenantComponentsInitEnabled; | |
159 | 201 | |
160 | - @Getter @Setter private ActorSystem actorSystem; | |
202 | + @Getter | |
203 | + @Setter | |
204 | + private ActorSystem actorSystem; | |
161 | 205 | |
162 | - @Getter @Setter private ActorRef appActor; | |
206 | + @Getter | |
207 | + @Setter | |
208 | + private ActorRef appActor; | |
163 | 209 | |
164 | - @Getter @Setter private ActorRef sessionManagerActor; | |
210 | + @Getter | |
211 | + @Setter | |
212 | + private ActorRef sessionManagerActor; | |
165 | 213 | |
166 | - @Getter @Setter private ActorRef statsActor; | |
214 | + @Getter | |
215 | + @Setter | |
216 | + private ActorRef statsActor; | |
167 | 217 | |
168 | - @Getter private final Config config; | |
218 | + @Getter | |
219 | + private final Config config; | |
169 | 220 | |
170 | 221 | public ActorSystemContext() { |
171 | 222 | config = ConfigFactory.parseResources(AKKA_CONF_FILE_NAME).withFallback(ConfigFactory.load()); |
... | ... | @@ -197,7 +248,7 @@ public class ActorSystemContext { |
197 | 248 | eventService.save(event); |
198 | 249 | } |
199 | 250 | |
200 | - private String toString(Exception e) { | |
251 | + private String toString(Throwable e) { | |
201 | 252 | StringWriter sw = new StringWriter(); |
202 | 253 | e.printStackTrace(new PrintWriter(sw)); |
203 | 254 | return sw.toString(); |
... | ... | @@ -217,4 +268,64 @@ public class ActorSystemContext { |
217 | 268 | private JsonNode toBodyJson(ServerAddress server, String method, String body) { |
218 | 269 | return mapper.createObjectNode().put("server", server.toString()).put("method", method).put("error", body); |
219 | 270 | } |
271 | + | |
272 | + public String getServerAddress() { | |
273 | + return discoveryService.getCurrentServer().getServerAddress().toString(); | |
274 | + } | |
275 | + | |
276 | + public void persistDebugInput(TenantId tenantId, EntityId entityId, TbMsg tbMsg) { | |
277 | + persistDebug(tenantId, entityId, "IN", tbMsg, null); | |
278 | + } | |
279 | + | |
280 | + public void persistDebugInput(TenantId tenantId, EntityId entityId, TbMsg tbMsg, Throwable error) { | |
281 | + persistDebug(tenantId, entityId, "IN", tbMsg, error); | |
282 | + } | |
283 | + | |
284 | + public void persistDebugOutput(TenantId tenantId, EntityId entityId, TbMsg tbMsg, Throwable error) { | |
285 | + persistDebug(tenantId, entityId, "OUT", tbMsg, error); | |
286 | + } | |
287 | + | |
288 | + public void persistDebugOutput(TenantId tenantId, EntityId entityId, TbMsg tbMsg) { | |
289 | + persistDebug(tenantId, entityId, "OUT", tbMsg, null); | |
290 | + } | |
291 | + | |
292 | + private void persistDebug(TenantId tenantId, EntityId entityId, String type, TbMsg tbMsg, Throwable error) { | |
293 | + Event event = new Event(); | |
294 | + event.setTenantId(tenantId); | |
295 | + event.setEntityId(entityId); | |
296 | + event.setType(DataConstants.DEBUG); | |
297 | + | |
298 | + ObjectNode node = mapper.createObjectNode() | |
299 | + .put("type", type) | |
300 | + .put("server", getServerAddress()) | |
301 | + .put("entityId", tbMsg.getOriginator().getId().toString()) | |
302 | + .put("entityName", tbMsg.getOriginator().getEntityType().name()) | |
303 | + .put("msgId", tbMsg.getId().toString()) | |
304 | + .put("msgType", tbMsg.getType()) | |
305 | + .put("dataType", tbMsg.getDataType().name()); | |
306 | + | |
307 | + ObjectNode mdNode = node.putObject("metadata"); | |
308 | + tbMsg.getMetaData().getData().forEach(mdNode::put); | |
309 | + | |
310 | + switch (tbMsg.getDataType()) { | |
311 | + case BINARY: | |
312 | + node.put("data", Base64Utils.encodeUrlSafe(tbMsg.getData())); | |
313 | + break; | |
314 | + default: | |
315 | + node.put("data", new String(tbMsg.getData(), StandardCharsets.UTF_8)); | |
316 | + break; | |
317 | + } | |
318 | + | |
319 | + if (error != null) { | |
320 | + node = node.put("error", toString(error)); | |
321 | + } | |
322 | + | |
323 | + event.setBody(node); | |
324 | + eventService.save(event); | |
325 | + } | |
326 | + | |
327 | + public static Exception toException(Throwable error) { | |
328 | + return Exception.class.isInstance(error) ? (Exception) error : new Exception(error); | |
329 | + } | |
330 | + | |
220 | 331 | } | ... | ... |
1 | 1 | /** |
2 | 2 | * Copyright © 2016-2018 The Thingsboard Authors |
3 | - * <p> | |
3 | + * | |
4 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | 5 | * you may not use this file except in compliance with the License. |
6 | 6 | * You may obtain a copy of the License at |
7 | - * <p> | |
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | - * <p> | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | 10 | * Unless required by applicable law or agreed to in writing, software |
11 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
... | ... | @@ -88,7 +88,7 @@ public class AppActor extends RuleChainManagerActor { |
88 | 88 | } |
89 | 89 | |
90 | 90 | @Override |
91 | - protected void process(TbActorMsg msg) { | |
91 | + protected boolean process(TbActorMsg msg) { | |
92 | 92 | switch (msg.getMsgType()) { |
93 | 93 | case COMPONENT_LIFE_CYCLE_MSG: |
94 | 94 | onComponentLifecycleMsg((ComponentLifecycleMsg) msg); |
... | ... | @@ -96,7 +96,10 @@ public class AppActor extends RuleChainManagerActor { |
96 | 96 | case SERVICE_TO_RULE_ENGINE_MSG: |
97 | 97 | onServiceToRuleEngineMsg((ServiceToRuleEngineMsg) msg); |
98 | 98 | break; |
99 | + default: | |
100 | + return false; | |
99 | 101 | } |
102 | + return true; | |
100 | 103 | } |
101 | 104 | |
102 | 105 | private void onServiceToRuleEngineMsg(ServiceToRuleEngineMsg msg) { | ... | ... |
... | ... | @@ -18,19 +18,19 @@ package org.thingsboard.server.actors.device; |
18 | 18 | import akka.event.Logging; |
19 | 19 | import akka.event.LoggingAdapter; |
20 | 20 | import org.thingsboard.server.actors.ActorSystemContext; |
21 | -import org.thingsboard.server.actors.rule.RulesProcessedMsg; | |
22 | 21 | import org.thingsboard.server.actors.service.ContextAwareActor; |
23 | 22 | import org.thingsboard.server.actors.service.ContextBasedCreator; |
24 | -import org.thingsboard.server.actors.tenant.RuleChainDeviceMsg; | |
25 | 23 | import org.thingsboard.server.common.data.id.DeviceId; |
26 | 24 | import org.thingsboard.server.common.data.id.TenantId; |
25 | +import org.thingsboard.server.common.msg.TbActorMsg; | |
27 | 26 | import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; |
28 | 27 | import org.thingsboard.server.common.msg.device.ToDeviceActorMsg; |
29 | 28 | import org.thingsboard.server.extensions.api.device.DeviceAttributesEventNotificationMsg; |
30 | 29 | import org.thingsboard.server.extensions.api.device.DeviceCredentialsUpdateNotificationMsg; |
31 | 30 | import org.thingsboard.server.extensions.api.device.DeviceNameOrTypeUpdateMsg; |
32 | 31 | import org.thingsboard.server.extensions.api.device.ToDeviceActorNotificationMsg; |
33 | -import org.thingsboard.server.extensions.api.plugins.msg.*; | |
32 | +import org.thingsboard.server.extensions.api.plugins.msg.TimeoutMsg; | |
33 | +import org.thingsboard.server.extensions.api.plugins.msg.ToDeviceRpcRequestPluginMsg; | |
34 | 34 | |
35 | 35 | public class DeviceActor extends ContextAwareActor { |
36 | 36 | |
... | ... | @@ -48,12 +48,17 @@ public class DeviceActor extends ContextAwareActor { |
48 | 48 | } |
49 | 49 | |
50 | 50 | @Override |
51 | + protected boolean process(TbActorMsg msg) { | |
52 | + return false; | |
53 | + } | |
54 | + | |
55 | + @Override | |
51 | 56 | public void onReceive(Object msg) throws Exception { |
52 | - if (msg instanceof RuleChainDeviceMsg) { | |
53 | - processor.process(context(), (RuleChainDeviceMsg) msg); | |
54 | - } else if (msg instanceof RulesProcessedMsg) { | |
55 | - processor.onRulesProcessedMsg(context(), (RulesProcessedMsg) msg); | |
56 | - } else if (msg instanceof ToDeviceActorMsg) { | |
57 | +// if (msg instanceof RuleChainDeviceMsg) { | |
58 | +// processor.process(context(), (RuleChainDeviceMsg) msg); | |
59 | +// } else if (msg instanceof RulesProcessedMsg) { | |
60 | +// processor.onRulesProcessedMsg(context(), (RulesProcessedMsg) msg); | |
61 | + if (msg instanceof ToDeviceActorMsg) { | |
57 | 62 | processor.process(context(), (ToDeviceActorMsg) msg); |
58 | 63 | } else if (msg instanceof ToDeviceActorNotificationMsg) { |
59 | 64 | if (msg instanceof DeviceAttributesEventNotificationMsg) { | ... | ... |
... | ... | @@ -19,9 +19,7 @@ import akka.actor.ActorContext; |
19 | 19 | import akka.actor.ActorRef; |
20 | 20 | import akka.event.LoggingAdapter; |
21 | 21 | import org.thingsboard.server.actors.ActorSystemContext; |
22 | -import org.thingsboard.server.actors.rule.*; | |
23 | 22 | import org.thingsboard.server.actors.shared.AbstractContextAwareMsgProcessor; |
24 | -import org.thingsboard.server.actors.tenant.RuleChainDeviceMsg; | |
25 | 23 | import org.thingsboard.server.common.data.DataConstants; |
26 | 24 | import org.thingsboard.server.common.data.Device; |
27 | 25 | import org.thingsboard.server.common.data.id.DeviceId; |
... | ... | @@ -37,15 +35,10 @@ import org.thingsboard.server.common.msg.session.FromDeviceMsg; |
37 | 35 | import org.thingsboard.server.common.msg.session.MsgType; |
38 | 36 | import org.thingsboard.server.common.msg.session.SessionType; |
39 | 37 | import org.thingsboard.server.common.msg.session.ToDeviceMsg; |
40 | -import org.thingsboard.server.extensions.api.device.*; | |
41 | -import org.thingsboard.server.extensions.api.plugins.msg.FromDeviceRpcResponse; | |
42 | -import org.thingsboard.server.extensions.api.plugins.msg.RpcError; | |
43 | -import org.thingsboard.server.extensions.api.plugins.msg.TimeoutIntMsg; | |
44 | -import org.thingsboard.server.extensions.api.plugins.msg.TimeoutMsg; | |
45 | -import org.thingsboard.server.extensions.api.plugins.msg.ToDeviceRpcRequest; | |
46 | -import org.thingsboard.server.extensions.api.plugins.msg.ToDeviceRpcRequestBody; | |
47 | -import org.thingsboard.server.extensions.api.plugins.msg.ToDeviceRpcRequestPluginMsg; | |
48 | -import org.thingsboard.server.extensions.api.plugins.msg.ToPluginRpcResponseDeviceMsg; | |
38 | +import org.thingsboard.server.extensions.api.device.DeviceAttributes; | |
39 | +import org.thingsboard.server.extensions.api.device.DeviceAttributesEventNotificationMsg; | |
40 | +import org.thingsboard.server.extensions.api.device.DeviceNameOrTypeUpdateMsg; | |
41 | +import org.thingsboard.server.extensions.api.plugins.msg.*; | |
49 | 42 | |
50 | 43 | import java.util.*; |
51 | 44 | import java.util.concurrent.ExecutionException; |
... | ... | @@ -230,18 +223,18 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso |
230 | 223 | } |
231 | 224 | } |
232 | 225 | |
233 | - void process(ActorContext context, RuleChainDeviceMsg srcMsg) { | |
234 | - ChainProcessingMetaData md = new ChainProcessingMetaData(srcMsg.getRuleChain(), | |
235 | - srcMsg.getToDeviceActorMsg(), new DeviceMetaData(deviceId, deviceName, deviceType, deviceAttributes), context.self()); | |
236 | - ChainProcessingContext ctx = new ChainProcessingContext(md); | |
237 | - if (ctx.getChainLength() > 0) { | |
238 | - RuleProcessingMsg msg = new RuleProcessingMsg(ctx); | |
239 | - ActorRef ruleActorRef = ctx.getCurrentActor(); | |
240 | - ruleActorRef.tell(msg, ActorRef.noSender()); | |
241 | - } else { | |
242 | - context.self().tell(new RulesProcessedMsg(ctx), context.self()); | |
243 | - } | |
244 | - } | |
226 | +// void process(ActorContext context, RuleChainDeviceMsg srcMsg) { | |
227 | +// ChainProcessingMetaData md = new ChainProcessingMetaData(srcMsg.getRuleChain(), | |
228 | +// srcMsg.getToDeviceActorMsg(), new DeviceMetaData(deviceId, deviceName, deviceType, deviceAttributes), context.self()); | |
229 | +// ChainProcessingContext ctx = new ChainProcessingContext(md); | |
230 | +// if (ctx.getChainLength() > 0) { | |
231 | +// RuleProcessingMsg msg = new RuleProcessingMsg(ctx); | |
232 | +// ActorRef ruleActorRef = ctx.getCurrentActor(); | |
233 | +// ruleActorRef.tell(msg, ActorRef.noSender()); | |
234 | +// } else { | |
235 | +// context.self().tell(new RulesProcessedMsg(ctx), context.self()); | |
236 | +// } | |
237 | +// } | |
245 | 238 | |
246 | 239 | void processRpcResponses(ActorContext context, ToDeviceActorMsg msg) { |
247 | 240 | SessionId sessionId = msg.getSessionId(); |
... | ... | @@ -302,18 +295,18 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso |
302 | 295 | ); |
303 | 296 | } |
304 | 297 | |
305 | - void onRulesProcessedMsg(ActorContext context, RulesProcessedMsg msg) { | |
306 | - ChainProcessingContext ctx = msg.getCtx(); | |
307 | - ToDeviceActorMsg inMsg = ctx.getInMsg(); | |
308 | - SessionId sid = inMsg.getSessionId(); | |
309 | - ToDeviceSessionActorMsg response; | |
310 | - if (ctx.getResponse() != null) { | |
311 | - response = new BasicToDeviceSessionActorMsg(ctx.getResponse(), sid); | |
312 | - } else { | |
313 | - response = new BasicToDeviceSessionActorMsg(ctx.getError(), sid); | |
314 | - } | |
315 | - sendMsgToSessionActor(response, inMsg.getServerAddress()); | |
316 | - } | |
298 | +// void onRulesProcessedMsg(ActorContext context, RulesProcessedMsg msg) { | |
299 | +// ChainProcessingContext ctx = msg.getCtx(); | |
300 | +// ToDeviceActorMsg inMsg = ctx.getInMsg(); | |
301 | +// SessionId sid = inMsg.getSessionId(); | |
302 | +// ToDeviceSessionActorMsg response; | |
303 | +// if (ctx.getResponse() != null) { | |
304 | +// response = new BasicToDeviceSessionActorMsg(ctx.getResponse(), sid); | |
305 | +// } else { | |
306 | +// response = new BasicToDeviceSessionActorMsg(ctx.getError(), sid); | |
307 | +// } | |
308 | +// sendMsgToSessionActor(response, inMsg.getServerAddress()); | |
309 | +// } | |
317 | 310 | |
318 | 311 | private void processSubscriptionCommands(ActorContext context, ToDeviceActorMsg msg) { |
319 | 312 | SessionId sessionId = msg.getSessionId(); | ... | ... |
... | ... | @@ -23,6 +23,7 @@ import org.thingsboard.server.actors.service.ContextBasedCreator; |
23 | 23 | import org.thingsboard.server.actors.stats.StatsPersistTick; |
24 | 24 | import org.thingsboard.server.common.data.id.PluginId; |
25 | 25 | import org.thingsboard.server.common.data.id.TenantId; |
26 | +import org.thingsboard.server.common.msg.TbActorMsg; | |
26 | 27 | import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; |
27 | 28 | import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; |
28 | 29 | import org.thingsboard.server.extensions.api.plugins.msg.TimeoutMsg; |
... | ... | @@ -41,6 +42,12 @@ public class PluginActor extends ComponentActor<PluginId, PluginActorMessageProc |
41 | 42 | } |
42 | 43 | |
43 | 44 | @Override |
45 | + protected boolean process(TbActorMsg msg) { | |
46 | + //TODO Move everything here, to work with TbActorMsg | |
47 | + return false; | |
48 | + } | |
49 | + | |
50 | + @Override | |
44 | 51 | public void onReceive(Object msg) throws Exception { |
45 | 52 | if (msg instanceof PluginWebsocketMsg) { |
46 | 53 | onWebsocketMsg((PluginWebsocketMsg<?>) msg); | ... | ... |
... | ... | @@ -23,6 +23,7 @@ import org.thingsboard.server.actors.ActorSystemContext; |
23 | 23 | import org.thingsboard.server.actors.service.ContextAwareActor; |
24 | 24 | import org.thingsboard.server.actors.service.ContextBasedCreator; |
25 | 25 | import org.thingsboard.server.actors.service.DefaultActorService; |
26 | +import org.thingsboard.server.common.msg.TbActorMsg; | |
26 | 27 | import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; |
27 | 28 | import org.thingsboard.server.common.msg.cluster.ServerAddress; |
28 | 29 | import org.thingsboard.server.gen.cluster.ClusterAPIProtos; |
... | ... | @@ -57,6 +58,12 @@ public class RpcManagerActor extends ContextAwareActor { |
57 | 58 | } |
58 | 59 | |
59 | 60 | @Override |
61 | + protected boolean process(TbActorMsg msg) { | |
62 | + //TODO Move everything here, to work with TbActorMsg | |
63 | + return false; | |
64 | + } | |
65 | + | |
66 | + @Override | |
60 | 67 | public void onReceive(Object msg) throws Exception { |
61 | 68 | if (msg instanceof RpcSessionTellMsg) { |
62 | 69 | onMsg((RpcSessionTellMsg) msg); | ... | ... |
... | ... | @@ -23,6 +23,7 @@ import io.grpc.stub.StreamObserver; |
23 | 23 | import org.thingsboard.server.actors.ActorSystemContext; |
24 | 24 | import org.thingsboard.server.actors.service.ContextAwareActor; |
25 | 25 | import org.thingsboard.server.actors.service.ContextBasedCreator; |
26 | +import org.thingsboard.server.common.msg.TbActorMsg; | |
26 | 27 | import org.thingsboard.server.common.msg.cluster.ServerAddress; |
27 | 28 | import org.thingsboard.server.gen.cluster.ClusterAPIProtos; |
28 | 29 | import org.thingsboard.server.gen.cluster.ClusterRpcServiceGrpc; |
... | ... | @@ -48,6 +49,12 @@ public class RpcSessionActor extends ContextAwareActor { |
48 | 49 | } |
49 | 50 | |
50 | 51 | @Override |
52 | + protected boolean process(TbActorMsg msg) { | |
53 | + //TODO Move everything here, to work with TbActorMsg | |
54 | + return false; | |
55 | + } | |
56 | + | |
57 | + @Override | |
51 | 58 | public void onReceive(Object msg) throws Exception { |
52 | 59 | if (msg instanceof RpcSessionTellMsg) { |
53 | 60 | tell((RpcSessionTellMsg) msg); | ... | ... |
application/src/main/java/org/thingsboard/server/actors/rule/ChainProcessingContext.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.actors.rule; | |
17 | - | |
18 | -import akka.actor.ActorRef; | |
19 | -import org.thingsboard.server.common.msg.core.RuleEngineError; | |
20 | -import org.thingsboard.server.common.msg.core.RuleEngineErrorMsg; | |
21 | -import org.thingsboard.server.common.msg.device.ToDeviceActorMsg; | |
22 | -import org.thingsboard.server.common.msg.session.ToDeviceMsg; | |
23 | -import org.thingsboard.server.extensions.api.device.DeviceAttributes; | |
24 | -import org.thingsboard.server.extensions.api.device.DeviceMetaData; | |
25 | - | |
26 | -public class ChainProcessingContext { | |
27 | - | |
28 | - private final ChainProcessingMetaData md; | |
29 | - private final int index; | |
30 | - private final RuleEngineError error; | |
31 | - private ToDeviceMsg response; | |
32 | - | |
33 | - | |
34 | - public ChainProcessingContext(ChainProcessingMetaData md) { | |
35 | - super(); | |
36 | - this.md = md; | |
37 | - this.index = 0; | |
38 | - this.error = RuleEngineError.NO_RULES; | |
39 | - } | |
40 | - | |
41 | - private ChainProcessingContext(ChainProcessingContext other, int indexOffset, RuleEngineError error) { | |
42 | - super(); | |
43 | - this.md = other.md; | |
44 | - this.index = other.index + indexOffset; | |
45 | - this.error = error; | |
46 | - this.response = other.response; | |
47 | - | |
48 | - if (this.index < 0 || this.index >= this.md.chain.size()) { | |
49 | - throw new IllegalArgumentException("Can't apply offset " + indexOffset + " to the chain!"); | |
50 | - } | |
51 | - } | |
52 | - | |
53 | - public ActorRef getDeviceActor() { | |
54 | - return md.originator; | |
55 | - } | |
56 | - | |
57 | - public ActorRef getCurrentActor() { | |
58 | - return md.chain.getRuleActorMd(index).getActorRef(); | |
59 | - } | |
60 | - | |
61 | - public boolean hasNext() { | |
62 | - return (getChainLength() - 1) > index; | |
63 | - } | |
64 | - | |
65 | - public boolean isFailure() { | |
66 | - return (error != null && error.isCritical()) || (response != null && !response.isSuccess()); | |
67 | - } | |
68 | - | |
69 | - public ChainProcessingContext getNext() { | |
70 | - return new ChainProcessingContext(this, 1, this.error); | |
71 | - } | |
72 | - | |
73 | - public ChainProcessingContext withError(RuleEngineError error) { | |
74 | - if (error != null && (this.error == null || this.error.getPriority() < error.getPriority())) { | |
75 | - return new ChainProcessingContext(this, 0, error); | |
76 | - } else { | |
77 | - return this; | |
78 | - } | |
79 | - } | |
80 | - | |
81 | - public int getChainLength() { | |
82 | - return md.chain.size(); | |
83 | - } | |
84 | - | |
85 | - public ToDeviceActorMsg getInMsg() { | |
86 | - return md.inMsg; | |
87 | - } | |
88 | - | |
89 | - public DeviceMetaData getDeviceMetaData() { | |
90 | - return md.deviceMetaData; | |
91 | - } | |
92 | - | |
93 | - public String getDeviceName() { | |
94 | - return md.deviceMetaData.getDeviceName(); | |
95 | - } | |
96 | - | |
97 | - public String getDeviceType() { | |
98 | - return md.deviceMetaData.getDeviceType(); | |
99 | - } | |
100 | - | |
101 | - public DeviceAttributes getAttributes() { | |
102 | - return md.deviceMetaData.getDeviceAttributes(); | |
103 | - } | |
104 | - | |
105 | - public ToDeviceMsg getResponse() { | |
106 | - return response; | |
107 | - } | |
108 | - | |
109 | - public void mergeResponse(ToDeviceMsg response) { | |
110 | - // TODO add merge logic | |
111 | - this.response = response; | |
112 | - } | |
113 | - | |
114 | - public RuleEngineErrorMsg getError() { | |
115 | - return new RuleEngineErrorMsg(md.inMsg.getPayload().getMsgType(), error); | |
116 | - } | |
117 | -} |
application/src/main/java/org/thingsboard/server/actors/rule/ChainProcessingMetaData.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.actors.rule; | |
17 | - | |
18 | -import akka.actor.ActorRef; | |
19 | -import org.thingsboard.server.common.msg.device.ToDeviceActorMsg; | |
20 | -import org.thingsboard.server.extensions.api.device.DeviceMetaData; | |
21 | - | |
22 | -/** | |
23 | - * Immutable part of chain processing data; | |
24 | - * | |
25 | - * @author ashvayka | |
26 | - */ | |
27 | -public final class ChainProcessingMetaData { | |
28 | - | |
29 | - final RuleActorChain chain; | |
30 | - final ToDeviceActorMsg inMsg; | |
31 | - final ActorRef originator; | |
32 | - final DeviceMetaData deviceMetaData; | |
33 | - | |
34 | - public ChainProcessingMetaData(RuleActorChain chain, ToDeviceActorMsg inMsg, DeviceMetaData deviceMetaData, ActorRef originator) { | |
35 | - super(); | |
36 | - this.chain = chain; | |
37 | - this.inMsg = inMsg; | |
38 | - this.originator = originator; | |
39 | - this.deviceMetaData = deviceMetaData; | |
40 | - } | |
41 | -} |
application/src/main/java/org/thingsboard/server/actors/rule/ComplexRuleActorChain.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.actors.rule; | |
17 | - | |
18 | -public class ComplexRuleActorChain implements RuleActorChain { | |
19 | - | |
20 | - private final RuleActorChain systemChain; | |
21 | - private final RuleActorChain tenantChain; | |
22 | - | |
23 | - public ComplexRuleActorChain(RuleActorChain systemChain, RuleActorChain tenantChain) { | |
24 | - super(); | |
25 | - this.systemChain = systemChain; | |
26 | - this.tenantChain = tenantChain; | |
27 | - } | |
28 | - | |
29 | - @Override | |
30 | - public int size() { | |
31 | - return systemChain.size() + tenantChain.size(); | |
32 | - } | |
33 | - | |
34 | - @Override | |
35 | - public RuleActorMetaData getRuleActorMd(int index) { | |
36 | - if (index < systemChain.size()) { | |
37 | - return systemChain.getRuleActorMd(index); | |
38 | - } else { | |
39 | - return tenantChain.getRuleActorMd(index - systemChain.size()); | |
40 | - } | |
41 | - } | |
42 | - | |
43 | -} |
application/src/main/java/org/thingsboard/server/actors/rule/RuleActor.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.actors.rule; | |
17 | - | |
18 | -import org.thingsboard.server.actors.ActorSystemContext; | |
19 | -import org.thingsboard.server.actors.service.ComponentActor; | |
20 | -import org.thingsboard.server.actors.service.ContextBasedCreator; | |
21 | -import org.thingsboard.server.actors.stats.StatsPersistTick; | |
22 | -import org.thingsboard.server.common.data.id.RuleId; | |
23 | -import org.thingsboard.server.common.data.id.TenantId; | |
24 | -import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; | |
25 | -import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; | |
26 | -import org.thingsboard.server.extensions.api.plugins.msg.PluginToRuleMsg; | |
27 | - | |
28 | -public class RuleActor extends ComponentActor<RuleId, RuleActorMessageProcessor> { | |
29 | - | |
30 | - private RuleActor(ActorSystemContext systemContext, TenantId tenantId, RuleId ruleId) { | |
31 | - super(systemContext, tenantId, ruleId); | |
32 | - setProcessor(new RuleActorMessageProcessor(tenantId, ruleId, systemContext, logger)); | |
33 | - } | |
34 | - | |
35 | - @Override | |
36 | - public void onReceive(Object msg) throws Exception { | |
37 | - logger.debug("[{}] Received message: {}", id, msg); | |
38 | - if (msg instanceof RuleProcessingMsg) { | |
39 | - try { | |
40 | - processor.onRuleProcessingMsg(context(), (RuleProcessingMsg) msg); | |
41 | - increaseMessagesProcessedCount(); | |
42 | - } catch (Exception e) { | |
43 | - logAndPersist("onDeviceMsg", e); | |
44 | - } | |
45 | - } else if (msg instanceof PluginToRuleMsg<?>) { | |
46 | - try { | |
47 | - processor.onPluginMsg(context(), (PluginToRuleMsg<?>) msg); | |
48 | - } catch (Exception e) { | |
49 | - logAndPersist("onPluginMsg", e); | |
50 | - } | |
51 | - } else if (msg instanceof ComponentLifecycleMsg) { | |
52 | - onComponentLifecycleMsg((ComponentLifecycleMsg) msg); | |
53 | - } else if (msg instanceof ClusterEventMsg) { | |
54 | - onClusterEventMsg((ClusterEventMsg) msg); | |
55 | - } else if (msg instanceof RuleToPluginTimeoutMsg) { | |
56 | - try { | |
57 | - processor.onTimeoutMsg(context(), (RuleToPluginTimeoutMsg) msg); | |
58 | - } catch (Exception e) { | |
59 | - logAndPersist("onTimeoutMsg", e); | |
60 | - } | |
61 | - } else if (msg instanceof StatsPersistTick) { | |
62 | - onStatsPersistTick(id); | |
63 | - } else { | |
64 | - logger.debug("[{}][{}] Unknown msg type.", tenantId, id, msg.getClass().getName()); | |
65 | - } | |
66 | - } | |
67 | - | |
68 | - public static class ActorCreator extends ContextBasedCreator<RuleActor> { | |
69 | - private static final long serialVersionUID = 1L; | |
70 | - | |
71 | - private final TenantId tenantId; | |
72 | - private final RuleId ruleId; | |
73 | - | |
74 | - public ActorCreator(ActorSystemContext context, TenantId tenantId, RuleId ruleId) { | |
75 | - super(context); | |
76 | - this.tenantId = tenantId; | |
77 | - this.ruleId = ruleId; | |
78 | - } | |
79 | - | |
80 | - @Override | |
81 | - public RuleActor create() throws Exception { | |
82 | - return new RuleActor(context, tenantId, ruleId); | |
83 | - } | |
84 | - } | |
85 | - | |
86 | - @Override | |
87 | - protected long getErrorPersistFrequency() { | |
88 | - return systemContext.getRuleErrorPersistFrequency(); | |
89 | - } | |
90 | -} |
application/src/main/java/org/thingsboard/server/actors/rule/RuleActorMessageProcessor.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.actors.rule; | |
17 | - | |
18 | -import java.util.*; | |
19 | - | |
20 | -import com.fasterxml.jackson.core.JsonProcessingException; | |
21 | -import org.springframework.util.StringUtils; | |
22 | -import org.thingsboard.server.actors.ActorSystemContext; | |
23 | -import org.thingsboard.server.actors.plugin.RuleToPluginMsgWrapper; | |
24 | -import org.thingsboard.server.actors.shared.ComponentMsgProcessor; | |
25 | -import org.thingsboard.server.common.data.id.PluginId; | |
26 | -import org.thingsboard.server.common.data.id.RuleId; | |
27 | -import org.thingsboard.server.common.data.id.TenantId; | |
28 | -import org.thingsboard.server.common.data.plugin.ComponentLifecycleState; | |
29 | -import org.thingsboard.server.common.data.plugin.PluginMetaData; | |
30 | -import org.thingsboard.server.common.data.rule.RuleMetaData; | |
31 | -import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; | |
32 | -import org.thingsboard.server.common.msg.core.BasicRequest; | |
33 | -import org.thingsboard.server.common.msg.core.BasicStatusCodeResponse; | |
34 | -import org.thingsboard.server.common.msg.core.RuleEngineError; | |
35 | -import org.thingsboard.server.common.msg.device.ToDeviceActorMsg; | |
36 | -import org.thingsboard.server.common.msg.session.MsgType; | |
37 | -import org.thingsboard.server.common.msg.session.ToDeviceMsg; | |
38 | -import org.thingsboard.server.common.msg.session.ex.ProcessingTimeoutException; | |
39 | -import org.thingsboard.server.extensions.api.rules.*; | |
40 | -import org.thingsboard.server.extensions.api.plugins.PluginAction; | |
41 | -import org.thingsboard.server.extensions.api.plugins.msg.PluginToRuleMsg; | |
42 | -import org.thingsboard.server.extensions.api.plugins.msg.RuleToPluginMsg; | |
43 | - | |
44 | -import com.fasterxml.jackson.databind.JsonNode; | |
45 | - | |
46 | -import akka.actor.ActorContext; | |
47 | -import akka.actor.ActorRef; | |
48 | -import akka.event.LoggingAdapter; | |
49 | - | |
50 | -class RuleActorMessageProcessor extends ComponentMsgProcessor<RuleId> { | |
51 | - | |
52 | - private final RuleProcessingContext ruleCtx; | |
53 | - private final Map<UUID, RuleProcessingMsg> pendingMsgMap; | |
54 | - | |
55 | - private RuleMetaData ruleMd; | |
56 | - private ComponentLifecycleState state; | |
57 | - private List<RuleFilter> filters; | |
58 | - private RuleProcessor processor; | |
59 | - private PluginAction action; | |
60 | - | |
61 | - private TenantId pluginTenantId; | |
62 | - private PluginId pluginId; | |
63 | - | |
64 | - protected RuleActorMessageProcessor(TenantId tenantId, RuleId ruleId, ActorSystemContext systemContext, LoggingAdapter logger) { | |
65 | - super(systemContext, logger, tenantId, ruleId); | |
66 | - this.pendingMsgMap = new HashMap<>(); | |
67 | - this.ruleCtx = new RuleProcessingContext(systemContext, ruleId); | |
68 | - } | |
69 | - | |
70 | - @Override | |
71 | - public void start(ActorContext context) throws Exception { | |
72 | - logger.info("[{}][{}] Starting rule actor.", entityId, tenantId); | |
73 | - ruleMd = systemContext.getRuleService().findRuleById(entityId); | |
74 | - if (ruleMd == null) { | |
75 | - throw new RuleInitializationException("Rule not found!"); | |
76 | - } | |
77 | - state = ruleMd.getState(); | |
78 | - if (state == ComponentLifecycleState.ACTIVE) { | |
79 | - logger.info("[{}] Rule is active. Going to initialize rule components.", entityId); | |
80 | - initComponent(); | |
81 | - } else { | |
82 | - logger.info("[{}] Rule is suspended. Skipping rule components initialization.", entityId); | |
83 | - } | |
84 | - | |
85 | - logger.info("[{}][{}] Started rule actor.", entityId, tenantId); | |
86 | - } | |
87 | - | |
88 | - @Override | |
89 | - public void stop(ActorContext context) throws Exception { | |
90 | - onStop(); | |
91 | - } | |
92 | - | |
93 | - | |
94 | - private void initComponent() throws RuleException { | |
95 | - try { | |
96 | - if (!ruleMd.getFilters().isArray()) { | |
97 | - throw new RuntimeException("Filters are not array!"); | |
98 | - } | |
99 | - fetchPluginInfo(); | |
100 | - initFilters(); | |
101 | - initProcessor(); | |
102 | - initAction(); | |
103 | - } catch (RuntimeException e) { | |
104 | - throw new RuleInitializationException("Unknown runtime exception!", e); | |
105 | - } catch (InstantiationException e) { | |
106 | - throw new RuleInitializationException("No default constructor for rule implementation!", e); | |
107 | - } catch (IllegalAccessException e) { | |
108 | - throw new RuleInitializationException("Illegal Access Exception during rule initialization!", e); | |
109 | - } catch (ClassNotFoundException e) { | |
110 | - throw new RuleInitializationException("Rule Class not found!", e); | |
111 | - } catch (Exception e) { | |
112 | - throw new RuleException(e.getMessage(), e); | |
113 | - } | |
114 | - } | |
115 | - | |
116 | - private void initAction() throws Exception { | |
117 | - if (ruleMd.getAction() != null && !ruleMd.getAction().isNull()) { | |
118 | - action = initComponent(ruleMd.getAction()); | |
119 | - } | |
120 | - } | |
121 | - | |
122 | - private void initProcessor() throws Exception { | |
123 | - if (ruleMd.getProcessor() != null && !ruleMd.getProcessor().isNull()) { | |
124 | - processor = initComponent(ruleMd.getProcessor()); | |
125 | - } | |
126 | - } | |
127 | - | |
128 | - private void initFilters() throws Exception { | |
129 | - filters = new ArrayList<>(ruleMd.getFilters().size()); | |
130 | - for (int i = 0; i < ruleMd.getFilters().size(); i++) { | |
131 | - filters.add(initComponent(ruleMd.getFilters().get(i))); | |
132 | - } | |
133 | - } | |
134 | - | |
135 | - private void fetchPluginInfo() { | |
136 | - if (!StringUtils.isEmpty(ruleMd.getPluginToken())) { | |
137 | - PluginMetaData pluginMd = systemContext.getPluginService().findPluginByApiToken(ruleMd.getPluginToken()); | |
138 | - pluginTenantId = pluginMd.getTenantId(); | |
139 | - pluginId = pluginMd.getId(); | |
140 | - } | |
141 | - } | |
142 | - | |
143 | - protected void onRuleProcessingMsg(ActorContext context, RuleProcessingMsg msg) throws RuleException { | |
144 | - if (state != ComponentLifecycleState.ACTIVE) { | |
145 | - pushToNextRule(context, msg.getCtx(), RuleEngineError.NO_ACTIVE_RULES); | |
146 | - return; | |
147 | - } | |
148 | - ChainProcessingContext chainCtx = msg.getCtx(); | |
149 | - ToDeviceActorMsg inMsg = chainCtx.getInMsg(); | |
150 | - | |
151 | - ruleCtx.update(inMsg, chainCtx.getDeviceMetaData()); | |
152 | - | |
153 | - logger.debug("[{}] Going to filter in msg: {}", entityId, inMsg); | |
154 | - for (RuleFilter filter : filters) { | |
155 | - if (!filter.filter(ruleCtx, inMsg)) { | |
156 | - logger.debug("[{}] In msg is NOT valid for processing by current rule: {}", entityId, inMsg); | |
157 | - pushToNextRule(context, msg.getCtx(), RuleEngineError.NO_FILTERS_MATCHED); | |
158 | - return; | |
159 | - } | |
160 | - } | |
161 | - RuleProcessingMetaData inMsgMd; | |
162 | - if (processor != null) { | |
163 | - logger.debug("[{}] Going to process in msg: {}", entityId, inMsg); | |
164 | - inMsgMd = processor.process(ruleCtx, inMsg); | |
165 | - } else { | |
166 | - inMsgMd = new RuleProcessingMetaData(); | |
167 | - } | |
168 | - logger.debug("[{}] Going to convert in msg: {}", entityId, inMsg); | |
169 | - if (action != null) { | |
170 | - Optional<RuleToPluginMsg<?>> ruleToPluginMsgOptional = action.convert(ruleCtx, inMsg, inMsgMd); | |
171 | - if (ruleToPluginMsgOptional.isPresent()) { | |
172 | - RuleToPluginMsg<?> ruleToPluginMsg = ruleToPluginMsgOptional.get(); | |
173 | - logger.debug("[{}] Device msg is converted to: {}", entityId, ruleToPluginMsg); | |
174 | - context.parent().tell(new RuleToPluginMsgWrapper(pluginTenantId, pluginId, tenantId, entityId, ruleToPluginMsg), context.self()); | |
175 | - if (action.isOneWayAction()) { | |
176 | - pushToNextRule(context, msg.getCtx(), RuleEngineError.NO_TWO_WAY_ACTIONS); | |
177 | - return; | |
178 | - } else { | |
179 | - pendingMsgMap.put(ruleToPluginMsg.getUid(), msg); | |
180 | - scheduleMsgWithDelay(context, new RuleToPluginTimeoutMsg(ruleToPluginMsg.getUid()), systemContext.getPluginProcessingTimeout()); | |
181 | - return; | |
182 | - } | |
183 | - } | |
184 | - } | |
185 | - logger.debug("[{}] Nothing to send to plugin: {}", entityId, pluginId); | |
186 | - pushToNextRule(context, msg.getCtx(), RuleEngineError.NO_TWO_WAY_ACTIONS); | |
187 | - } | |
188 | - | |
189 | - void onPluginMsg(ActorContext context, PluginToRuleMsg<?> msg) { | |
190 | - RuleProcessingMsg pendingMsg = pendingMsgMap.remove(msg.getUid()); | |
191 | - if (pendingMsg != null) { | |
192 | - ChainProcessingContext ctx = pendingMsg.getCtx(); | |
193 | - Optional<ToDeviceMsg> ruleResponseOptional = action.convert(msg); | |
194 | - if (ruleResponseOptional.isPresent()) { | |
195 | - ctx.mergeResponse(ruleResponseOptional.get()); | |
196 | - pushToNextRule(context, ctx, null); | |
197 | - } else { | |
198 | - pushToNextRule(context, ctx, RuleEngineError.NO_RESPONSE_FROM_ACTIONS); | |
199 | - } | |
200 | - } else { | |
201 | - logger.warning("[{}] Processing timeout detected: [{}]", entityId, msg.getUid()); | |
202 | - } | |
203 | - } | |
204 | - | |
205 | - void onTimeoutMsg(ActorContext context, RuleToPluginTimeoutMsg msg) { | |
206 | - RuleProcessingMsg pendingMsg = pendingMsgMap.remove(msg.getMsgId()); | |
207 | - if (pendingMsg != null) { | |
208 | - logger.debug("[{}] Processing timeout detected [{}]: {}", entityId, msg.getMsgId(), pendingMsg); | |
209 | - ChainProcessingContext ctx = pendingMsg.getCtx(); | |
210 | - pushToNextRule(context, ctx, RuleEngineError.PLUGIN_TIMEOUT); | |
211 | - } | |
212 | - } | |
213 | - | |
214 | - private void pushToNextRule(ActorContext context, ChainProcessingContext ctx, RuleEngineError error) { | |
215 | - if (error != null) { | |
216 | - ctx = ctx.withError(error); | |
217 | - } | |
218 | - if (ctx.isFailure()) { | |
219 | - logger.debug("[{}][{}] Forwarding processing chain to device actor due to failure.", ruleMd.getId(), ctx.getInMsg().getDeviceId()); | |
220 | - ctx.getDeviceActor().tell(new RulesProcessedMsg(ctx), ActorRef.noSender()); | |
221 | - } else if (!ctx.hasNext()) { | |
222 | - logger.debug("[{}][{}] Forwarding processing chain to device actor due to end of chain.", ruleMd.getId(), ctx.getInMsg().getDeviceId()); | |
223 | - ctx.getDeviceActor().tell(new RulesProcessedMsg(ctx), ActorRef.noSender()); | |
224 | - } else { | |
225 | - logger.debug("[{}][{}] Forwarding processing chain to next rule actor.", ruleMd.getId(), ctx.getInMsg().getDeviceId()); | |
226 | - ChainProcessingContext nextTask = ctx.getNext(); | |
227 | - nextTask.getCurrentActor().tell(new RuleProcessingMsg(nextTask), context.self()); | |
228 | - } | |
229 | - } | |
230 | - | |
231 | - @Override | |
232 | - public void onCreated(ActorContext context) { | |
233 | - logger.info("[{}] Going to process onCreated rule.", entityId); | |
234 | - } | |
235 | - | |
236 | - @Override | |
237 | - public void onUpdate(ActorContext context) throws RuleException { | |
238 | - RuleMetaData oldRuleMd = ruleMd; | |
239 | - ruleMd = systemContext.getRuleService().findRuleById(entityId); | |
240 | - logger.info("[{}] Rule configuration was updated from {} to {}.", entityId, oldRuleMd, ruleMd); | |
241 | - try { | |
242 | - fetchPluginInfo(); | |
243 | - if (filters == null || !Objects.equals(oldRuleMd.getFilters(), ruleMd.getFilters())) { | |
244 | - logger.info("[{}] Rule filters require restart due to json change from {} to {}.", | |
245 | - entityId, mapper.writeValueAsString(oldRuleMd.getFilters()), mapper.writeValueAsString(ruleMd.getFilters())); | |
246 | - stopFilters(); | |
247 | - initFilters(); | |
248 | - } | |
249 | - if (processor == null || !Objects.equals(oldRuleMd.getProcessor(), ruleMd.getProcessor())) { | |
250 | - logger.info("[{}] Rule processor require restart due to configuration change.", entityId); | |
251 | - stopProcessor(); | |
252 | - initProcessor(); | |
253 | - } | |
254 | - if (action == null || !Objects.equals(oldRuleMd.getAction(), ruleMd.getAction())) { | |
255 | - logger.info("[{}] Rule action require restart due to configuration change.", entityId); | |
256 | - stopAction(); | |
257 | - initAction(); | |
258 | - } | |
259 | - } catch (RuntimeException e) { | |
260 | - throw new RuleInitializationException("Unknown runtime exception!", e); | |
261 | - } catch (InstantiationException e) { | |
262 | - throw new RuleInitializationException("No default constructor for rule implementation!", e); | |
263 | - } catch (IllegalAccessException e) { | |
264 | - throw new RuleInitializationException("Illegal Access Exception during rule initialization!", e); | |
265 | - } catch (ClassNotFoundException e) { | |
266 | - throw new RuleInitializationException("Rule Class not found!", e); | |
267 | - } catch (JsonProcessingException e) { | |
268 | - throw new RuleInitializationException("Rule configuration is invalid!", e); | |
269 | - } catch (Exception e) { | |
270 | - throw new RuleInitializationException(e.getMessage(), e); | |
271 | - } | |
272 | - } | |
273 | - | |
274 | - @Override | |
275 | - public void onActivate(ActorContext context) throws Exception { | |
276 | - logger.info("[{}] Going to process onActivate rule.", entityId); | |
277 | - this.state = ComponentLifecycleState.ACTIVE; | |
278 | - if (filters != null) { | |
279 | - filters.forEach(RuleLifecycleComponent::resume); | |
280 | - if (processor != null) { | |
281 | - processor.resume(); | |
282 | - } else { | |
283 | - initProcessor(); | |
284 | - } | |
285 | - if (action != null) { | |
286 | - action.resume(); | |
287 | - } | |
288 | - logger.info("[{}] Rule resumed.", entityId); | |
289 | - } else { | |
290 | - start(); | |
291 | - } | |
292 | - } | |
293 | - | |
294 | - @Override | |
295 | - public void onSuspend(ActorContext context) { | |
296 | - logger.info("[{}] Going to process onSuspend rule.", entityId); | |
297 | - this.state = ComponentLifecycleState.SUSPENDED; | |
298 | - if (filters != null) { | |
299 | - filters.forEach(f -> f.suspend()); | |
300 | - } | |
301 | - if (processor != null) { | |
302 | - processor.suspend(); | |
303 | - } | |
304 | - if (action != null) { | |
305 | - action.suspend(); | |
306 | - } | |
307 | - } | |
308 | - | |
309 | - @Override | |
310 | - public void onStop(ActorContext context) { | |
311 | - logger.info("[{}] Going to process onStop rule.", entityId); | |
312 | - onStop(); | |
313 | - scheduleMsgWithDelay(context, new RuleTerminationMsg(entityId), systemContext.getRuleActorTerminationDelay()); | |
314 | - } | |
315 | - | |
316 | - private void onStop() { | |
317 | - this.state = ComponentLifecycleState.SUSPENDED; | |
318 | - stopFilters(); | |
319 | - stopProcessor(); | |
320 | - stopAction(); | |
321 | - } | |
322 | - | |
323 | - @Override | |
324 | - public void onClusterEventMsg(ClusterEventMsg msg) throws Exception { | |
325 | - //Do nothing | |
326 | - } | |
327 | - | |
328 | - private void stopAction() { | |
329 | - if (action != null) { | |
330 | - action.stop(); | |
331 | - } | |
332 | - } | |
333 | - | |
334 | - private void stopProcessor() { | |
335 | - if (processor != null) { | |
336 | - processor.stop(); | |
337 | - } | |
338 | - } | |
339 | - | |
340 | - private void stopFilters() { | |
341 | - if (filters != null) { | |
342 | - filters.forEach(f -> f.stop()); | |
343 | - } | |
344 | - } | |
345 | -} |
application/src/main/java/org/thingsboard/server/actors/rule/RuleActorMetaData.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.actors.rule; | |
17 | - | |
18 | -import java.util.Comparator; | |
19 | - | |
20 | -import org.thingsboard.server.common.data.id.RuleId; | |
21 | - | |
22 | -import akka.actor.ActorRef; | |
23 | - | |
24 | -public class RuleActorMetaData { | |
25 | - | |
26 | - private final RuleId ruleId; | |
27 | - private final boolean systemRule; | |
28 | - private final int weight; | |
29 | - private final ActorRef actorRef; | |
30 | - | |
31 | - public static final Comparator<RuleActorMetaData> RULE_ACTOR_MD_COMPARATOR = new Comparator<RuleActorMetaData>() { | |
32 | - | |
33 | - @Override | |
34 | - public int compare(RuleActorMetaData r1, RuleActorMetaData r2) { | |
35 | - if (r1.isSystemRule() && !r2.isSystemRule()) { | |
36 | - return 1; | |
37 | - } else if (!r1.isSystemRule() && r2.isSystemRule()) { | |
38 | - return -1; | |
39 | - } else { | |
40 | - return Integer.compare(r2.getWeight(), r1.getWeight()); | |
41 | - } | |
42 | - } | |
43 | - }; | |
44 | - | |
45 | - public static RuleActorMetaData systemRule(RuleId ruleId, int weight, ActorRef actorRef) { | |
46 | - return new RuleActorMetaData(ruleId, true, weight, actorRef); | |
47 | - } | |
48 | - | |
49 | - public static RuleActorMetaData tenantRule(RuleId ruleId, int weight, ActorRef actorRef) { | |
50 | - return new RuleActorMetaData(ruleId, false, weight, actorRef); | |
51 | - } | |
52 | - | |
53 | - private RuleActorMetaData(RuleId ruleId, boolean systemRule, int weight, ActorRef actorRef) { | |
54 | - super(); | |
55 | - this.ruleId = ruleId; | |
56 | - this.systemRule = systemRule; | |
57 | - this.weight = weight; | |
58 | - this.actorRef = actorRef; | |
59 | - } | |
60 | - | |
61 | - public RuleId getRuleId() { | |
62 | - return ruleId; | |
63 | - } | |
64 | - | |
65 | - public boolean isSystemRule() { | |
66 | - return systemRule; | |
67 | - } | |
68 | - | |
69 | - public int getWeight() { | |
70 | - return weight; | |
71 | - } | |
72 | - | |
73 | - public ActorRef getActorRef() { | |
74 | - return actorRef; | |
75 | - } | |
76 | - | |
77 | - @Override | |
78 | - public int hashCode() { | |
79 | - final int prime = 31; | |
80 | - int result = 1; | |
81 | - result = prime * result + ((ruleId == null) ? 0 : ruleId.hashCode()); | |
82 | - return result; | |
83 | - } | |
84 | - | |
85 | - @Override | |
86 | - public boolean equals(Object obj) { | |
87 | - if (this == obj) | |
88 | - return true; | |
89 | - if (obj == null) | |
90 | - return false; | |
91 | - if (getClass() != obj.getClass()) | |
92 | - return false; | |
93 | - RuleActorMetaData other = (RuleActorMetaData) obj; | |
94 | - if (ruleId == null) { | |
95 | - if (other.ruleId != null) | |
96 | - return false; | |
97 | - } else if (!ruleId.equals(other.ruleId)) | |
98 | - return false; | |
99 | - return true; | |
100 | - } | |
101 | - | |
102 | - @Override | |
103 | - public String toString() { | |
104 | - return "RuleActorMetaData [ruleId=" + ruleId + ", systemRule=" + systemRule + ", weight=" + weight + ", actorRef=" + actorRef + "]"; | |
105 | - } | |
106 | - | |
107 | -} |
application/src/main/java/org/thingsboard/server/actors/rule/RuleProcessingContext.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.actors.rule; | |
17 | - | |
18 | -import com.google.common.util.concurrent.ListenableFuture; | |
19 | -import org.thingsboard.server.actors.ActorSystemContext; | |
20 | -import org.thingsboard.server.common.data.Event; | |
21 | -import org.thingsboard.server.common.data.alarm.Alarm; | |
22 | -import org.thingsboard.server.common.data.alarm.AlarmId; | |
23 | -import org.thingsboard.server.common.data.id.*; | |
24 | -import org.thingsboard.server.dao.alarm.AlarmService; | |
25 | -import org.thingsboard.server.dao.event.EventService; | |
26 | -import org.thingsboard.server.dao.timeseries.TimeseriesService; | |
27 | -import org.thingsboard.server.common.msg.device.ToDeviceActorMsg; | |
28 | -import org.thingsboard.server.extensions.api.device.DeviceMetaData; | |
29 | -import org.thingsboard.server.extensions.api.rules.RuleContext; | |
30 | - | |
31 | -import java.util.Optional; | |
32 | -import java.util.concurrent.ExecutionException; | |
33 | - | |
34 | -public class RuleProcessingContext implements RuleContext { | |
35 | - | |
36 | - private final TimeseriesService tsService; | |
37 | - private final EventService eventService; | |
38 | - private final AlarmService alarmService; | |
39 | - private final RuleId ruleId; | |
40 | - private TenantId tenantId; | |
41 | - private CustomerId customerId; | |
42 | - private DeviceId deviceId; | |
43 | - private DeviceMetaData deviceMetaData; | |
44 | - | |
45 | - RuleProcessingContext(ActorSystemContext systemContext, RuleId ruleId) { | |
46 | - this.tsService = systemContext.getTsService(); | |
47 | - this.eventService = systemContext.getEventService(); | |
48 | - this.alarmService = systemContext.getAlarmService(); | |
49 | - this.ruleId = ruleId; | |
50 | - } | |
51 | - | |
52 | - void update(ToDeviceActorMsg toDeviceActorMsg, DeviceMetaData deviceMetaData) { | |
53 | - this.tenantId = toDeviceActorMsg.getTenantId(); | |
54 | - this.customerId = toDeviceActorMsg.getCustomerId(); | |
55 | - this.deviceId = toDeviceActorMsg.getDeviceId(); | |
56 | - this.deviceMetaData = deviceMetaData; | |
57 | - } | |
58 | - | |
59 | - @Override | |
60 | - public RuleId getRuleId() { | |
61 | - return ruleId; | |
62 | - } | |
63 | - | |
64 | - @Override | |
65 | - public DeviceMetaData getDeviceMetaData() { | |
66 | - return deviceMetaData; | |
67 | - } | |
68 | - | |
69 | - @Override | |
70 | - public Event save(Event event) { | |
71 | - checkEvent(event); | |
72 | - return eventService.save(event); | |
73 | - } | |
74 | - | |
75 | - @Override | |
76 | - public Optional<Event> saveIfNotExists(Event event) { | |
77 | - checkEvent(event); | |
78 | - return eventService.saveIfNotExists(event); | |
79 | - } | |
80 | - | |
81 | - @Override | |
82 | - public Optional<Event> findEvent(String eventType, String eventUid) { | |
83 | - return eventService.findEvent(tenantId, deviceId, eventType, eventUid); | |
84 | - } | |
85 | - | |
86 | - @Override | |
87 | - public Alarm createOrUpdateAlarm(Alarm alarm) { | |
88 | - alarm.setTenantId(tenantId); | |
89 | - return alarmService.createOrUpdateAlarm(alarm); | |
90 | - } | |
91 | - | |
92 | - public Optional<Alarm> findLatestAlarm(EntityId originator, String alarmType) { | |
93 | - try { | |
94 | - return Optional.ofNullable(alarmService.findLatestByOriginatorAndType(tenantId, originator, alarmType).get()); | |
95 | - } catch (InterruptedException | ExecutionException e) { | |
96 | - throw new RuntimeException("Failed to lookup alarm!", e); | |
97 | - } | |
98 | - } | |
99 | - | |
100 | - @Override | |
101 | - public ListenableFuture<Boolean> clearAlarm(AlarmId alarmId, long clearTs) { | |
102 | - return alarmService.clearAlarm(alarmId, clearTs); | |
103 | - } | |
104 | - | |
105 | - private void checkEvent(Event event) { | |
106 | - if (event.getTenantId() == null) { | |
107 | - event.setTenantId(tenantId); | |
108 | - } else if (!tenantId.equals(event.getTenantId())) { | |
109 | - throw new IllegalArgumentException("Invalid Tenant id!"); | |
110 | - } | |
111 | - if (event.getEntityId() == null) { | |
112 | - event.setEntityId(deviceId); | |
113 | - } | |
114 | - } | |
115 | -} |
application/src/main/java/org/thingsboard/server/actors/rule/RulesProcessedMsg.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.actors.rule; | |
17 | - | |
18 | -public class RulesProcessedMsg { | |
19 | - private final ChainProcessingContext ctx; | |
20 | - | |
21 | - public RulesProcessedMsg(ChainProcessingContext ctx) { | |
22 | - super(); | |
23 | - this.ctx = ctx; | |
24 | - } | |
25 | - | |
26 | - public ChainProcessingContext getCtx() { | |
27 | - return ctx; | |
28 | - } | |
29 | - | |
30 | - @Override | |
31 | - public String toString() { | |
32 | - return "RulesProcessedMsg [ctx=" + ctx + "]"; | |
33 | - } | |
34 | -} |
application/src/main/java/org/thingsboard/server/actors/rule/SimpleRuleActorChain.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.actors.rule; | |
17 | - | |
18 | -import java.util.ArrayList; | |
19 | -import java.util.List; | |
20 | -import java.util.Set; | |
21 | - | |
22 | -public class SimpleRuleActorChain implements RuleActorChain { | |
23 | - | |
24 | - private final List<RuleActorMetaData> rules; | |
25 | - | |
26 | - public SimpleRuleActorChain(Set<RuleActorMetaData> ruleSet) { | |
27 | - rules = new ArrayList<>(ruleSet); | |
28 | - rules.sort(RuleActorMetaData.RULE_ACTOR_MD_COMPARATOR); | |
29 | - } | |
30 | - | |
31 | - public int size() { | |
32 | - return rules.size(); | |
33 | - } | |
34 | - | |
35 | - public RuleActorMetaData getRuleActorMd(int index) { | |
36 | - return rules.get(index); | |
37 | - } | |
38 | - | |
39 | -} |
1 | +/** | |
2 | + * Copyright © 2016-2018 The Thingsboard Authors | |
3 | + * <p> | |
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 | + * <p> | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * <p> | |
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 | + */ | |
1 | 16 | package org.thingsboard.server.actors.ruleChain; |
2 | 17 | |
3 | 18 | import org.thingsboard.rule.engine.api.TbContext; |
4 | 19 | import org.thingsboard.server.actors.ActorSystemContext; |
5 | 20 | import org.thingsboard.server.common.msg.TbMsg; |
6 | 21 | import org.thingsboard.server.common.msg.cluster.ServerAddress; |
22 | +import org.thingsboard.server.dao.alarm.AlarmService; | |
23 | +import org.thingsboard.server.dao.asset.AssetService; | |
7 | 24 | import org.thingsboard.server.dao.attributes.AttributesService; |
25 | +import org.thingsboard.server.dao.customer.CustomerService; | |
26 | +import org.thingsboard.server.dao.device.DeviceService; | |
27 | +import org.thingsboard.server.dao.plugin.PluginService; | |
28 | +import org.thingsboard.server.dao.relation.RelationService; | |
29 | +import org.thingsboard.server.dao.rule.RuleChainService; | |
30 | +import org.thingsboard.server.dao.timeseries.TimeseriesService; | |
31 | +import org.thingsboard.server.dao.user.UserService; | |
8 | 32 | |
9 | 33 | /** |
10 | 34 | * Created by ashvayka on 19.03.18. |
... | ... | @@ -26,27 +50,30 @@ class DefaultTbContext implements TbContext { |
26 | 50 | |
27 | 51 | @Override |
28 | 52 | public void tellNext(TbMsg msg, String relationType) { |
29 | - nodeCtx.getChainActor().tell(new RuleNodeToRuleChainTellNextMsg(nodeCtx.getSelfId(), relationType, msg), nodeCtx.getSelf()); | |
53 | + if (nodeCtx.getSelf().isDebugMode()) { | |
54 | + mainCtx.persistDebugOutput(nodeCtx.getTenantId(), nodeCtx.getSelf().getId(), msg); | |
55 | + } | |
56 | + nodeCtx.getChainActor().tell(new RuleNodeToRuleChainTellNextMsg(nodeCtx.getSelf().getId(), relationType, msg), nodeCtx.getSelfActor()); | |
30 | 57 | } |
31 | 58 | |
32 | 59 | @Override |
33 | 60 | public void tellSelf(TbMsg msg, long delayMs) { |
34 | - | |
61 | + throw new RuntimeException("Not Implemented!"); | |
35 | 62 | } |
36 | 63 | |
37 | 64 | @Override |
38 | 65 | public void tellOthers(TbMsg msg) { |
39 | - | |
66 | + throw new RuntimeException("Not Implemented!"); | |
40 | 67 | } |
41 | 68 | |
42 | 69 | @Override |
43 | 70 | public void tellSibling(TbMsg msg, ServerAddress address) { |
44 | - | |
71 | + throw new RuntimeException("Not Implemented!"); | |
45 | 72 | } |
46 | 73 | |
47 | 74 | @Override |
48 | 75 | public void spawn(TbMsg msg) { |
49 | - | |
76 | + throw new RuntimeException("Not Implemented!"); | |
50 | 77 | } |
51 | 78 | |
52 | 79 | @Override |
... | ... | @@ -55,7 +82,60 @@ class DefaultTbContext implements TbContext { |
55 | 82 | } |
56 | 83 | |
57 | 84 | @Override |
85 | + public void tellError(TbMsg msg, Throwable th) { | |
86 | + if (nodeCtx.getSelf().isDebugMode()) { | |
87 | + mainCtx.persistDebugOutput(nodeCtx.getTenantId(), nodeCtx.getSelf().getId(), msg, th); | |
88 | + } | |
89 | + nodeCtx.getSelfActor().tell(new RuleNodeToSelfErrorMsg(msg, th), nodeCtx.getSelfActor()); | |
90 | + } | |
91 | + | |
92 | + @Override | |
58 | 93 | public AttributesService getAttributesService() { |
59 | 94 | return mainCtx.getAttributesService(); |
60 | 95 | } |
96 | + | |
97 | + @Override | |
98 | + public CustomerService getCustomerService() { | |
99 | + return mainCtx.getCustomerService(); | |
100 | + } | |
101 | + | |
102 | + @Override | |
103 | + public UserService getUserService() { | |
104 | + return mainCtx.getUserService(); | |
105 | + } | |
106 | + | |
107 | + @Override | |
108 | + public PluginService getPluginService() { | |
109 | + return mainCtx.getPluginService(); | |
110 | + } | |
111 | + | |
112 | + @Override | |
113 | + public AssetService getAssetService() { | |
114 | + return mainCtx.getAssetService(); | |
115 | + } | |
116 | + | |
117 | + @Override | |
118 | + public DeviceService getDeviceService() { | |
119 | + return mainCtx.getDeviceService(); | |
120 | + } | |
121 | + | |
122 | + @Override | |
123 | + public AlarmService getAlarmService() { | |
124 | + return mainCtx.getAlarmService(); | |
125 | + } | |
126 | + | |
127 | + @Override | |
128 | + public RuleChainService getRuleChainService() { | |
129 | + return mainCtx.getRuleChainService(); | |
130 | + } | |
131 | + | |
132 | + @Override | |
133 | + public TimeseriesService getTimeseriesService() { | |
134 | + return mainCtx.getTsService(); | |
135 | + } | |
136 | + | |
137 | + @Override | |
138 | + public RelationService getRelationService() { | |
139 | + return mainCtx.getRelationService(); | |
140 | + } | |
61 | 141 | } | ... | ... |
1 | 1 | /** |
2 | 2 | * Copyright © 2016-2018 The Thingsboard Authors |
3 | - * <p> | |
3 | + * | |
4 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | 5 | * you may not use this file except in compliance with the License. |
6 | 6 | * You may obtain a copy of the License at |
7 | - * <p> | |
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | - * <p> | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | 10 | * Unless required by applicable law or agreed to in writing, software |
11 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
... | ... | @@ -33,7 +33,7 @@ public class RuleChainActor extends ComponentActor<RuleChainId, RuleChainActorMe |
33 | 33 | } |
34 | 34 | |
35 | 35 | @Override |
36 | - protected void process(TbActorMsg msg) { | |
36 | + protected boolean process(TbActorMsg msg) { | |
37 | 37 | switch (msg.getMsgType()) { |
38 | 38 | case COMPONENT_LIFE_CYCLE_MSG: |
39 | 39 | onComponentLifecycleMsg((ComponentLifecycleMsg) msg); |
... | ... | @@ -44,7 +44,10 @@ public class RuleChainActor extends ComponentActor<RuleChainId, RuleChainActorMe |
44 | 44 | case RULE_TO_RULE_CHAIN_TELL_NEXT_MSG: |
45 | 45 | processor.onTellNext((RuleNodeToRuleChainTellNextMsg) msg); |
46 | 46 | break; |
47 | + default: | |
48 | + return false; | |
47 | 49 | } |
50 | + return true; | |
48 | 51 | } |
49 | 52 | |
50 | 53 | public static class ActorCreator extends ContextBasedCreator<RuleChainActor> { |
... | ... | @@ -69,4 +72,6 @@ public class RuleChainActor extends ComponentActor<RuleChainId, RuleChainActorMe |
69 | 72 | protected long getErrorPersistFrequency() { |
70 | 73 | return systemContext.getRuleChainErrorPersistFrequency(); |
71 | 74 | } |
75 | + | |
76 | + //TODO: failover strategy | |
72 | 77 | } | ... | ... |
... | ... | @@ -27,6 +27,7 @@ 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.ComponentLifecycleState; | |
30 | 31 | import org.thingsboard.server.common.data.relation.EntityRelation; |
31 | 32 | import org.thingsboard.server.common.data.rule.RuleChain; |
32 | 33 | import org.thingsboard.server.common.data.rule.RuleNode; |
... | ... | @@ -53,6 +54,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh |
53 | 54 | |
54 | 55 | private RuleNodeId firstId; |
55 | 56 | private RuleNodeCtx firstNode; |
57 | + private ComponentLifecycleState state; | |
56 | 58 | |
57 | 59 | RuleChainActorMessageProcessor(TenantId tenantId, RuleChainId ruleChainId, ActorSystemContext systemContext |
58 | 60 | , LoggingAdapter logger, ActorRef parent, ActorRef self) { |
... | ... | @@ -66,6 +68,9 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh |
66 | 68 | |
67 | 69 | @Override |
68 | 70 | public void start(ActorContext context) throws Exception { |
71 | + if (state == ComponentLifecycleState.ACTIVE) { | |
72 | + return; | |
73 | + } | |
69 | 74 | RuleChain ruleChain = service.findRuleChainById(entityId); |
70 | 75 | List<RuleNode> ruleNodeList = service.getRuleChainNodes(entityId); |
71 | 76 | // Creating and starting the actors; |
... | ... | @@ -74,8 +79,8 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh |
74 | 79 | DefaultActorService.SYSTEM_RULE_DISPATCHER_NAME : DefaultActorService.TENANT_RULE_DISPATCHER_NAME; |
75 | 80 | ActorRef ruleNodeActor = context.actorOf( |
76 | 81 | Props.create(new RuleNodeActor.ActorCreator(systemContext, tenantId, entityId, ruleNode.getId())) |
77 | - .withDispatcher(dispatcherName), ruleNode.toString()); | |
78 | - nodeActors.put(ruleNode.getId(), new RuleNodeCtx(self, ruleNodeActor, ruleNode.getId())); | |
82 | + .withDispatcher(dispatcherName), ruleNode.getId().toString()); | |
83 | + nodeActors.put(ruleNode.getId(), new RuleNodeCtx(tenantId, self, ruleNodeActor, ruleNode)); | |
79 | 84 | } |
80 | 85 | // Populating the routes map; |
81 | 86 | for (RuleNode ruleNode : ruleNodeList) { |
... | ... | @@ -94,13 +99,15 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh |
94 | 99 | |
95 | 100 | firstId = ruleChain.getFirstRuleNodeId(); |
96 | 101 | firstNode = nodeActors.get(ruleChain.getFirstRuleNodeId()); |
102 | + state = ComponentLifecycleState.ACTIVE; | |
97 | 103 | } |
98 | 104 | |
99 | 105 | @Override |
100 | 106 | public void stop(ActorContext context) throws Exception { |
101 | - nodeActors.values().stream().map(RuleNodeCtx::getSelf).forEach(context::stop); | |
107 | + nodeActors.values().stream().map(RuleNodeCtx::getSelfActor).forEach(context::stop); | |
102 | 108 | nodeActors.clear(); |
103 | 109 | nodeRoutes.clear(); |
110 | + state = ComponentLifecycleState.SUSPENDED; | |
104 | 111 | } |
105 | 112 | |
106 | 113 | @Override |
... | ... | @@ -109,23 +116,33 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh |
109 | 116 | } |
110 | 117 | |
111 | 118 | void onServiceToRuleEngineMsg(ServiceToRuleEngineMsg envelope) { |
119 | + checkActive(); | |
112 | 120 | TbMsg tbMsg = envelope.getTbMsg(); |
113 | 121 | //TODO: push to queue and act on ack in async way |
114 | 122 | pushMstToNode(firstNode, tbMsg); |
115 | 123 | } |
116 | 124 | |
117 | 125 | void onTellNext(RuleNodeToRuleChainTellNextMsg envelope) { |
126 | + checkActive(); | |
118 | 127 | RuleNodeId originator = envelope.getOriginator(); |
119 | 128 | String targetRelationType = envelope.getRelationType(); |
120 | 129 | //TODO: log debug output |
121 | 130 | List<RuleNodeRelation> relations = nodeRoutes.get(originator); |
131 | + if (relations == null) { | |
132 | + return; | |
133 | + } | |
134 | + boolean copy = relations.size() > 1; | |
122 | 135 | for (RuleNodeRelation relation : relations) { |
136 | + TbMsg msg = envelope.getMsg(); | |
137 | + if (copy) { | |
138 | + msg = msg.copy(); | |
139 | + } | |
123 | 140 | if (targetRelationType == null || targetRelationType.equalsIgnoreCase(relation.getType())) { |
124 | 141 | switch (relation.getOut().getEntityType()) { |
125 | 142 | case RULE_NODE: |
126 | 143 | RuleNodeId targetRuleNodeId = new RuleNodeId(relation.getOut().getId()); |
127 | 144 | RuleNodeCtx targetRuleNode = nodeActors.get(targetRuleNodeId); |
128 | - pushMstToNode(targetRuleNode, envelope.getMsg()); | |
145 | + pushMstToNode(targetRuleNode, msg); | |
129 | 146 | break; |
130 | 147 | case RULE_CHAIN: |
131 | 148 | // TODO: implement |
... | ... | @@ -137,7 +154,13 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh |
137 | 154 | |
138 | 155 | private void pushMstToNode(RuleNodeCtx nodeCtx, TbMsg msg) { |
139 | 156 | //TODO: log debug input |
140 | - firstNode.getSelf().tell(new RuleChainToRuleNodeMsg(new DefaultTbContext(systemContext, nodeCtx), msg), self); | |
157 | + firstNode.getSelfActor().tell(new RuleChainToRuleNodeMsg(new DefaultTbContext(systemContext, nodeCtx), msg), self); | |
158 | + } | |
159 | + | |
160 | + private void checkActive() { | |
161 | + if (state != ComponentLifecycleState.ACTIVE) { | |
162 | + throw new IllegalStateException("Rule chain is not active!"); | |
163 | + } | |
141 | 164 | } |
142 | 165 | |
143 | 166 | } | ... | ... |
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 | + */ | |
1 | 16 | package org.thingsboard.server.actors.ruleChain; |
2 | 17 | |
3 | 18 | import akka.actor.ActorRef; | ... | ... |
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 | + */ | |
1 | 16 | package org.thingsboard.server.actors.ruleChain; |
2 | 17 | |
3 | 18 | import lombok.Data; | ... | ... |
... | ... | @@ -35,14 +35,34 @@ public class RuleNodeActor extends ComponentActor<RuleNodeId, RuleNodeActorMessa |
35 | 35 | } |
36 | 36 | |
37 | 37 | @Override |
38 | - protected void process(TbActorMsg msg) { | |
38 | + protected boolean process(TbActorMsg msg) { | |
39 | 39 | switch (msg.getMsgType()) { |
40 | 40 | case RULE_CHAIN_TO_RULE_MSG: |
41 | - processor.onRuleChainToRuleNodeMsg((RuleChainToRuleNodeMsg) msg); | |
41 | + onRuleChainToRuleNodeMsg((RuleChainToRuleNodeMsg) msg); | |
42 | 42 | break; |
43 | + case RULE_TO_SELF_ERROR_MSG: | |
44 | + onRuleNodeToSelfErrorMsg((RuleNodeToSelfErrorMsg) msg); | |
45 | + break; | |
46 | + default: | |
47 | + return false; | |
48 | + } | |
49 | + return true; | |
50 | + } | |
51 | + | |
52 | + private void onRuleChainToRuleNodeMsg(RuleChainToRuleNodeMsg msg) { | |
53 | + logger.debug("[{}] Going to process rule msg: {}", id, msg.getMsg()); | |
54 | + try { | |
55 | + processor.onRuleChainToRuleNodeMsg(msg); | |
56 | + increaseMessagesProcessedCount(); | |
57 | + } catch (Exception e) { | |
58 | + logAndPersist("onRuleMsg", e); | |
43 | 59 | } |
44 | 60 | } |
45 | 61 | |
62 | + private void onRuleNodeToSelfErrorMsg(RuleNodeToSelfErrorMsg msg) { | |
63 | + logAndPersist("onRuleMsg", ActorSystemContext.toException(msg.getError())); | |
64 | + } | |
65 | + | |
46 | 66 | public static class ActorCreator extends ContextBasedCreator<RuleNodeActor> { |
47 | 67 | private static final long serialVersionUID = 1L; |
48 | 68 | |
... | ... | @@ -69,4 +89,6 @@ public class RuleNodeActor extends ComponentActor<RuleNodeId, RuleNodeActorMessa |
69 | 89 | return systemContext.getRuleNodeErrorPersistFrequency(); |
70 | 90 | } |
71 | 91 | |
92 | + //TODO: failover strategy | |
93 | + | |
72 | 94 | } | ... | ... |
application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeActorMessageProcessor.java
... | ... | @@ -17,28 +17,28 @@ package org.thingsboard.server.actors.ruleChain; |
17 | 17 | |
18 | 18 | import akka.actor.ActorContext; |
19 | 19 | import akka.actor.ActorRef; |
20 | -import akka.actor.Props; | |
21 | 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 | +import org.thingsboard.rule.engine.api.TbNode; | |
25 | +import org.thingsboard.rule.engine.api.TbNodeConfiguration; | |
26 | +import org.thingsboard.rule.engine.api.TbNodeState; | |
22 | 27 | import org.thingsboard.server.actors.ActorSystemContext; |
23 | -import org.thingsboard.server.actors.service.DefaultActorService; | |
24 | 28 | import org.thingsboard.server.actors.shared.ComponentMsgProcessor; |
25 | -import org.thingsboard.server.common.data.EntityType; | |
26 | -import org.thingsboard.server.common.data.id.EntityId; | |
29 | +import org.thingsboard.server.common.data.DataConstants; | |
30 | +import org.thingsboard.server.common.data.Event; | |
27 | 31 | import org.thingsboard.server.common.data.id.RuleChainId; |
28 | 32 | import org.thingsboard.server.common.data.id.RuleNodeId; |
29 | 33 | import org.thingsboard.server.common.data.id.TenantId; |
30 | -import org.thingsboard.server.common.data.relation.EntityRelation; | |
31 | -import org.thingsboard.server.common.data.rule.RuleChain; | |
32 | 34 | import org.thingsboard.server.common.data.rule.RuleNode; |
33 | 35 | import org.thingsboard.server.common.msg.TbMsg; |
34 | 36 | import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; |
35 | -import org.thingsboard.server.common.msg.system.ServiceToRuleEngineMsg; | |
36 | 37 | import org.thingsboard.server.dao.rule.RuleChainService; |
37 | 38 | |
38 | -import java.util.ArrayList; | |
39 | -import java.util.HashMap; | |
40 | -import java.util.List; | |
41 | -import java.util.Map; | |
39 | +import java.io.PrintWriter; | |
40 | +import java.io.StringWriter; | |
41 | +import java.nio.charset.StandardCharsets; | |
42 | 42 | |
43 | 43 | /** |
44 | 44 | * @author Andrew Shvayka |
... | ... | @@ -48,6 +48,8 @@ public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor<RuleNod |
48 | 48 | private final ActorRef parent; |
49 | 49 | private final ActorRef self; |
50 | 50 | private final RuleChainService service; |
51 | + private RuleNode ruleNode; | |
52 | + private TbNode tbNode; | |
51 | 53 | |
52 | 54 | RuleNodeActorMessageProcessor(TenantId tenantId, RuleChainId ruleChainId, RuleNodeId ruleNodeId, ActorSystemContext systemContext |
53 | 55 | , LoggingAdapter logger, ActorRef parent, ActorRef self) { |
... | ... | @@ -55,15 +57,17 @@ public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor<RuleNod |
55 | 57 | this.parent = parent; |
56 | 58 | this.self = self; |
57 | 59 | this.service = systemContext.getRuleChainService(); |
60 | + this.ruleNode = systemContext.getRuleChainService().findRuleNodeById(entityId); | |
58 | 61 | } |
59 | 62 | |
60 | 63 | @Override |
61 | 64 | public void start(ActorContext context) throws Exception { |
62 | - | |
65 | + tbNode = initComponent(ruleNode); | |
63 | 66 | } |
64 | 67 | |
65 | 68 | @Override |
66 | 69 | public void stop(ActorContext context) throws Exception { |
70 | + tbNode.destroy(); | |
67 | 71 | } |
68 | 72 | |
69 | 73 | @Override |
... | ... | @@ -71,8 +75,18 @@ public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor<RuleNod |
71 | 75 | |
72 | 76 | } |
73 | 77 | |
74 | - void onRuleChainToRuleNodeMsg(RuleChainToRuleNodeMsg msg) { | |
78 | + void onRuleChainToRuleNodeMsg(RuleChainToRuleNodeMsg msg) throws Exception { | |
79 | + if (ruleNode.isDebugMode()) { | |
80 | + systemContext.persistDebugInput(tenantId, entityId, msg.getMsg()); | |
81 | + } | |
82 | + tbNode.onMsg(msg.getCtx(), msg.getMsg()); | |
83 | + } | |
75 | 84 | |
85 | + private TbNode initComponent(RuleNode ruleNode) throws Exception { | |
86 | + Class<?> componentClazz = Class.forName(ruleNode.getType()); | |
87 | + TbNode tbNode = (TbNode) (componentClazz.newInstance()); | |
88 | + tbNode.init(new TbNodeConfiguration(ruleNode.getConfiguration()), new TbNodeState()); | |
89 | + return tbNode; | |
76 | 90 | } |
77 | 91 | |
78 | 92 | } | ... | ... |
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 | + */ | |
1 | 16 | package org.thingsboard.server.actors.ruleChain; |
2 | 17 | |
3 | 18 | import akka.actor.ActorRef; |
4 | 19 | import lombok.Data; |
5 | 20 | import org.thingsboard.server.common.data.id.RuleNodeId; |
21 | +import org.thingsboard.server.common.data.id.TenantId; | |
22 | +import org.thingsboard.server.common.data.rule.RuleNode; | |
6 | 23 | |
7 | 24 | /** |
8 | 25 | * Created by ashvayka on 19.03.18. |
9 | 26 | */ |
10 | 27 | @Data |
11 | 28 | final class RuleNodeCtx { |
29 | + private final TenantId tenantId; | |
12 | 30 | private final ActorRef chainActor; |
13 | - private final ActorRef self; | |
14 | - private final RuleNodeId selfId; | |
31 | + private final ActorRef selfActor; | |
32 | + private final RuleNode self; | |
15 | 33 | } | ... | ... |
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 | + */ | |
1 | 16 | package org.thingsboard.server.actors.ruleChain; |
2 | 17 | |
3 | 18 | import lombok.Data; | ... | ... |
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 | + */ | |
1 | 16 | package org.thingsboard.server.actors.ruleChain; |
2 | 17 | |
3 | 18 | import lombok.Data; | ... | ... |
application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeToSelfErrorMsg.java
renamed from
application/src/main/java/org/thingsboard/server/actors/rule/RuleTerminationMsg.java
... | ... | @@ -13,18 +13,26 @@ |
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.actors.rule; | |
16 | +package org.thingsboard.server.actors.ruleChain; | |
17 | 17 | |
18 | -import org.thingsboard.server.actors.shared.ActorTerminationMsg; | |
19 | -import org.thingsboard.server.common.data.id.PluginId; | |
20 | -import org.thingsboard.server.common.data.id.RuleId; | |
18 | +import lombok.Data; | |
19 | +import org.thingsboard.server.common.data.id.RuleNodeId; | |
20 | +import org.thingsboard.server.common.msg.MsgType; | |
21 | +import org.thingsboard.server.common.msg.TbActorMsg; | |
22 | +import org.thingsboard.server.common.msg.TbMsg; | |
21 | 23 | |
22 | 24 | /** |
23 | - * @author Andrew Shvayka | |
25 | + * Created by ashvayka on 19.03.18. | |
24 | 26 | */ |
25 | -public class RuleTerminationMsg extends ActorTerminationMsg<RuleId> { | |
27 | +@Data | |
28 | +final class RuleNodeToSelfErrorMsg implements TbActorMsg { | |
26 | 29 | |
27 | - public RuleTerminationMsg(RuleId id) { | |
28 | - super(id); | |
30 | + private final TbMsg msg; | |
31 | + private final Throwable error; | |
32 | + | |
33 | + @Override | |
34 | + public MsgType getMsgType() { | |
35 | + return MsgType.RULE_TO_SELF_ERROR_MSG; | |
29 | 36 | } |
37 | + | |
30 | 38 | } | ... | ... |
... | ... | @@ -39,12 +39,13 @@ public abstract class ContextAwareActor extends UntypedActor { |
39 | 39 | logger.debug("Processing msg: {}", msg); |
40 | 40 | } |
41 | 41 | if (msg instanceof TbActorMsg) { |
42 | - process((TbActorMsg) msg); | |
43 | - } | |
44 | - else { | |
42 | + if(!process((TbActorMsg) msg)){ | |
43 | + logger.warning("Unknown message: {}!", msg); | |
44 | + } | |
45 | + } else { | |
45 | 46 | logger.warning("Unknown message: {}!", msg); |
46 | 47 | } |
47 | 48 | } |
48 | 49 | |
49 | - protected abstract void process(TbActorMsg msg); | |
50 | + protected abstract boolean process(TbActorMsg msg); | |
50 | 51 | } | ... | ... |
1 | 1 | /** |
2 | 2 | * Copyright © 2016-2018 The Thingsboard Authors |
3 | - * <p> | |
3 | + * | |
4 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | 5 | * you may not use this file except in compliance with the License. |
6 | 6 | * You may obtain a copy of the License at |
7 | - * <p> | |
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | - * <p> | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | 10 | * Unless required by applicable law or agreed to in writing, software |
11 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ... | ... |
... | ... | @@ -23,6 +23,7 @@ import org.thingsboard.server.actors.service.ContextAwareActor; |
23 | 23 | import org.thingsboard.server.actors.service.ContextBasedCreator; |
24 | 24 | import org.thingsboard.server.actors.shared.SessionTimeoutMsg; |
25 | 25 | import org.thingsboard.server.common.data.id.SessionId; |
26 | +import org.thingsboard.server.common.msg.TbActorMsg; | |
26 | 27 | import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; |
27 | 28 | import org.thingsboard.server.common.msg.core.ToDeviceSessionActorMsg; |
28 | 29 | import org.thingsboard.server.common.msg.session.ToDeviceActorSessionMsg; |
... | ... | @@ -61,6 +62,12 @@ public class SessionActor extends ContextAwareActor { |
61 | 62 | } |
62 | 63 | |
63 | 64 | @Override |
65 | + protected boolean process(TbActorMsg msg) { | |
66 | + //TODO Move everything here, to work with TbActorMsg | |
67 | + return false; | |
68 | + } | |
69 | + | |
70 | + @Override | |
64 | 71 | public void onReceive(Object msg) throws Exception { |
65 | 72 | logger.debug("[{}] Processing: {}.", sessionId, msg); |
66 | 73 | if (msg instanceof ToDeviceActorSessionMsg) { | ... | ... |
... | ... | @@ -26,6 +26,7 @@ import org.thingsboard.server.actors.service.ContextBasedCreator; |
26 | 26 | import org.thingsboard.server.actors.service.DefaultActorService; |
27 | 27 | import org.thingsboard.server.actors.shared.SessionTimeoutMsg; |
28 | 28 | import org.thingsboard.server.common.data.id.SessionId; |
29 | +import org.thingsboard.server.common.msg.TbActorMsg; | |
29 | 30 | import org.thingsboard.server.common.msg.aware.SessionAwareMsg; |
30 | 31 | |
31 | 32 | import akka.event.Logging; |
... | ... | @@ -49,6 +50,12 @@ public class SessionManagerActor extends ContextAwareActor { |
49 | 50 | } |
50 | 51 | |
51 | 52 | @Override |
53 | + protected boolean process(TbActorMsg msg) { | |
54 | + //TODO Move everything here, to work with TbActorMsg | |
55 | + return false; | |
56 | + } | |
57 | + | |
58 | + @Override | |
52 | 59 | public void onReceive(Object msg) throws Exception { |
53 | 60 | if (msg instanceof SessionCtrlMsg) { |
54 | 61 | onSessionCtrlMsg((SessionCtrlMsg) msg); | ... | ... |
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 | + */ | |
1 | 16 | package org.thingsboard.server.actors.shared; |
2 | 17 | |
3 | 18 | import akka.actor.ActorContext; | ... | ... |
1 | 1 | /** |
2 | 2 | * Copyright © 2016-2018 The Thingsboard Authors |
3 | - * <p> | |
3 | + * | |
4 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | 5 | * you may not use this file except in compliance with the License. |
6 | 6 | * You may obtain a copy of the License at |
7 | - * <p> | |
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | - * <p> | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | 10 | * Unless required by applicable law or agreed to in writing, software |
11 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ... | ... |
application/src/main/java/org/thingsboard/server/actors/shared/rule/RuleManager.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.actors.shared.rule; | |
17 | - | |
18 | -import akka.actor.ActorContext; | |
19 | -import akka.actor.ActorRef; | |
20 | -import akka.actor.Props; | |
21 | -import lombok.extern.slf4j.Slf4j; | |
22 | -import org.thingsboard.server.actors.ActorSystemContext; | |
23 | -import org.thingsboard.server.actors.rule.RuleActor; | |
24 | -import org.thingsboard.server.actors.rule.RuleActorChain; | |
25 | -import org.thingsboard.server.actors.rule.RuleActorMetaData; | |
26 | -import org.thingsboard.server.actors.rule.SimpleRuleActorChain; | |
27 | -import org.thingsboard.server.actors.service.ContextAwareActor; | |
28 | -import org.thingsboard.server.common.data.id.RuleId; | |
29 | -import org.thingsboard.server.common.data.id.TenantId; | |
30 | -import org.thingsboard.server.common.data.page.PageDataIterable; | |
31 | -import org.thingsboard.server.common.data.page.PageDataIterable.FetchFunction; | |
32 | -import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; | |
33 | -import org.thingsboard.server.common.data.plugin.ComponentLifecycleState; | |
34 | -import org.thingsboard.server.common.data.rule.RuleMetaData; | |
35 | -import org.thingsboard.server.dao.rule.RuleService; | |
36 | - | |
37 | -import java.util.*; | |
38 | - | |
39 | -@Slf4j | |
40 | -public abstract class RuleManager { | |
41 | - | |
42 | - protected final ActorSystemContext systemContext; | |
43 | - protected final RuleService ruleService; | |
44 | - protected final Map<RuleId, ActorRef> ruleActors; | |
45 | - protected final TenantId tenantId; | |
46 | - | |
47 | - private Map<RuleMetaData, RuleActorMetaData> ruleMap; | |
48 | - private RuleActorChain ruleChain; | |
49 | - | |
50 | - public RuleManager(ActorSystemContext systemContext, TenantId tenantId) { | |
51 | - this.systemContext = systemContext; | |
52 | - this.ruleService = systemContext.getRuleService(); | |
53 | - this.ruleActors = new HashMap<>(); | |
54 | - this.tenantId = tenantId; | |
55 | - } | |
56 | - | |
57 | - public void init(ActorContext context) { | |
58 | - doInit(context); | |
59 | - } | |
60 | - | |
61 | - private void doInit(ActorContext context) { | |
62 | - PageDataIterable<RuleMetaData> ruleIterator = new PageDataIterable<>(getFetchRulesFunction(), | |
63 | - ContextAwareActor.ENTITY_PACK_LIMIT); | |
64 | - ruleMap = new HashMap<>(); | |
65 | - | |
66 | - for (RuleMetaData rule : ruleIterator) { | |
67 | - log.debug("[{}] Creating rule actor {}", rule.getId(), rule); | |
68 | - ActorRef ref = getOrCreateRuleActor(context, rule.getId()); | |
69 | - ruleMap.put(rule, RuleActorMetaData.systemRule(rule.getId(), rule.getWeight(), ref)); | |
70 | - log.debug("[{}] Rule actor created.", rule.getId()); | |
71 | - } | |
72 | - | |
73 | - refreshRuleChain(); | |
74 | - } | |
75 | - | |
76 | - public Optional<ActorRef> update(ActorContext context, RuleId ruleId, ComponentLifecycleEvent event) { | |
77 | - if (ruleMap == null) { | |
78 | - doInit(context); | |
79 | - } | |
80 | - RuleMetaData rule; | |
81 | - if (event != ComponentLifecycleEvent.DELETED) { | |
82 | - rule = systemContext.getRuleService().findRuleById(ruleId); | |
83 | - } else { | |
84 | - rule = ruleMap.keySet().stream() | |
85 | - .filter(r -> r.getId().equals(ruleId)) | |
86 | - .peek(r -> r.setState(ComponentLifecycleState.SUSPENDED)) | |
87 | - .findFirst() | |
88 | - .orElse(null); | |
89 | - if (rule != null) { | |
90 | - ruleMap.remove(rule); | |
91 | - ruleActors.remove(ruleId); | |
92 | - } | |
93 | - } | |
94 | - if (rule != null) { | |
95 | - RuleActorMetaData actorMd = ruleMap.get(rule); | |
96 | - if (actorMd == null) { | |
97 | - ActorRef ref = getOrCreateRuleActor(context, rule.getId()); | |
98 | - actorMd = RuleActorMetaData.systemRule(rule.getId(), rule.getWeight(), ref); | |
99 | - ruleMap.put(rule, actorMd); | |
100 | - } | |
101 | - refreshRuleChain(); | |
102 | - return Optional.of(actorMd.getActorRef()); | |
103 | - } else { | |
104 | - log.warn("[{}] Can't process unknown rule!", ruleId); | |
105 | - return Optional.empty(); | |
106 | - } | |
107 | - } | |
108 | - | |
109 | - abstract FetchFunction<RuleMetaData> getFetchRulesFunction(); | |
110 | - | |
111 | - abstract String getDispatcherName(); | |
112 | - | |
113 | - public ActorRef getOrCreateRuleActor(ActorContext context, RuleId ruleId) { | |
114 | - return ruleActors.computeIfAbsent(ruleId, rId -> | |
115 | - context.actorOf(Props.create(new RuleActor.ActorCreator(systemContext, tenantId, rId)) | |
116 | - .withDispatcher(getDispatcherName()), rId.toString())); | |
117 | - } | |
118 | - | |
119 | - public RuleActorChain getRuleChain(ActorContext context) { | |
120 | - if (ruleChain == null) { | |
121 | - doInit(context); | |
122 | - } | |
123 | - return ruleChain; | |
124 | - } | |
125 | - | |
126 | - private void refreshRuleChain() { | |
127 | - Set<RuleActorMetaData> activeRuleSet = new HashSet<>(); | |
128 | - for (Map.Entry<RuleMetaData, RuleActorMetaData> rule : ruleMap.entrySet()) { | |
129 | - if (rule.getKey().getState() == ComponentLifecycleState.ACTIVE) { | |
130 | - activeRuleSet.add(rule.getValue()); | |
131 | - } | |
132 | - } | |
133 | - ruleChain = new SimpleRuleActorChain(activeRuleSet); | |
134 | - } | |
135 | -} |
application/src/main/java/org/thingsboard/server/actors/shared/rule/SystemRuleManager.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.actors.shared.rule; | |
17 | - | |
18 | -import org.thingsboard.server.actors.ActorSystemContext; | |
19 | -import org.thingsboard.server.actors.service.DefaultActorService; | |
20 | -import org.thingsboard.server.common.data.id.TenantId; | |
21 | -import org.thingsboard.server.common.data.page.PageDataIterable.FetchFunction; | |
22 | -import org.thingsboard.server.common.data.rule.RuleMetaData; | |
23 | -import org.thingsboard.server.dao.model.ModelConstants; | |
24 | - | |
25 | -public class SystemRuleManager extends RuleManager { | |
26 | - | |
27 | - public SystemRuleManager(ActorSystemContext systemContext) { | |
28 | - super(systemContext, new TenantId(ModelConstants.NULL_UUID)); | |
29 | - } | |
30 | - | |
31 | - @Override | |
32 | - FetchFunction<RuleMetaData> getFetchRulesFunction() { | |
33 | - return ruleService::findSystemRules; | |
34 | - } | |
35 | - | |
36 | - @Override | |
37 | - String getDispatcherName() { | |
38 | - return DefaultActorService.SYSTEM_RULE_DISPATCHER_NAME; | |
39 | - } | |
40 | -} |
application/src/main/java/org/thingsboard/server/actors/shared/rule/TenantRuleManager.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.actors.shared.rule; | |
17 | - | |
18 | -import akka.actor.ActorContext; | |
19 | -import org.thingsboard.server.actors.ActorSystemContext; | |
20 | -import org.thingsboard.server.actors.service.DefaultActorService; | |
21 | -import org.thingsboard.server.common.data.id.TenantId; | |
22 | -import org.thingsboard.server.common.data.page.PageDataIterable.FetchFunction; | |
23 | -import org.thingsboard.server.common.data.rule.RuleMetaData; | |
24 | - | |
25 | -public class TenantRuleManager extends RuleManager { | |
26 | - | |
27 | - public TenantRuleManager(ActorSystemContext systemContext, TenantId tenantId) { | |
28 | - super(systemContext, tenantId); | |
29 | - } | |
30 | - | |
31 | - @Override | |
32 | - public void init(ActorContext context) { | |
33 | - if (systemContext.isTenantComponentsInitEnabled()) { | |
34 | - super.init(context); | |
35 | - } | |
36 | - } | |
37 | - | |
38 | - @Override | |
39 | - FetchFunction<RuleMetaData> getFetchRulesFunction() { | |
40 | - return link -> ruleService.findTenantRules(tenantId, link); | |
41 | - } | |
42 | - | |
43 | - @Override | |
44 | - String getDispatcherName() { | |
45 | - return DefaultActorService.TENANT_RULE_DISPATCHER_NAME; | |
46 | - } | |
47 | - | |
48 | -} |
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 | + */ | |
1 | 16 | package org.thingsboard.server.actors.shared.rulechain; |
2 | 17 | |
3 | 18 | import akka.actor.ActorRef; | ... | ... |
application/src/main/java/org/thingsboard/server/actors/shared/rulechain/TenantRuleChainManager.java
1 | 1 | /** |
2 | 2 | * Copyright © 2016-2018 The Thingsboard Authors |
3 | - * <p> | |
3 | + * | |
4 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | 5 | * you may not use this file except in compliance with the License. |
6 | 6 | * You may obtain a copy of the License at |
7 | - * <p> | |
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | - * <p> | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | 10 | * Unless required by applicable law or agreed to in writing, software |
11 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
... | ... | @@ -18,12 +18,9 @@ package org.thingsboard.server.actors.shared.rulechain; |
18 | 18 | import akka.actor.ActorContext; |
19 | 19 | import org.thingsboard.server.actors.ActorSystemContext; |
20 | 20 | import org.thingsboard.server.actors.service.DefaultActorService; |
21 | -import org.thingsboard.server.actors.shared.rule.RuleManager; | |
22 | 21 | import org.thingsboard.server.common.data.id.TenantId; |
23 | -import org.thingsboard.server.common.data.page.PageDataIterable; | |
24 | 22 | import org.thingsboard.server.common.data.page.PageDataIterable.FetchFunction; |
25 | 23 | import org.thingsboard.server.common.data.rule.RuleChain; |
26 | -import org.thingsboard.server.common.data.rule.RuleMetaData; | |
27 | 24 | |
28 | 25 | public class TenantRuleChainManager extends RuleChainManager { |
29 | 26 | ... | ... |
... | ... | @@ -24,6 +24,7 @@ import org.thingsboard.server.actors.service.ContextAwareActor; |
24 | 24 | import org.thingsboard.server.actors.service.ContextBasedCreator; |
25 | 25 | import org.thingsboard.server.common.data.DataConstants; |
26 | 26 | import org.thingsboard.server.common.data.Event; |
27 | +import org.thingsboard.server.common.msg.TbActorMsg; | |
27 | 28 | import org.thingsboard.server.common.msg.cluster.ServerAddress; |
28 | 29 | |
29 | 30 | public class StatsActor extends ContextAwareActor { |
... | ... | @@ -36,6 +37,12 @@ public class StatsActor extends ContextAwareActor { |
36 | 37 | } |
37 | 38 | |
38 | 39 | @Override |
40 | + protected boolean process(TbActorMsg msg) { | |
41 | + //TODO Move everything here, to work with TbActorMsg\ | |
42 | + return false; | |
43 | + } | |
44 | + | |
45 | + @Override | |
39 | 46 | public void onReceive(Object msg) throws Exception { |
40 | 47 | logger.debug("Received message: {}", msg); |
41 | 48 | if (msg instanceof StatsPersistMsg) { | ... | ... |
application/src/main/java/org/thingsboard/server/actors/tenant/RuleChainDeviceMsg.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.actors.tenant; | |
17 | - | |
18 | -import org.thingsboard.server.actors.rule.RuleActorChain; | |
19 | -import org.thingsboard.server.common.msg.device.ToDeviceActorMsg; | |
20 | - | |
21 | -public class RuleChainDeviceMsg { | |
22 | - | |
23 | - private final ToDeviceActorMsg toDeviceActorMsg; | |
24 | - private final RuleActorChain ruleChain; | |
25 | - | |
26 | - public RuleChainDeviceMsg(ToDeviceActorMsg toDeviceActorMsg, RuleActorChain ruleChain) { | |
27 | - super(); | |
28 | - this.toDeviceActorMsg = toDeviceActorMsg; | |
29 | - this.ruleChain = ruleChain; | |
30 | - } | |
31 | - | |
32 | - public ToDeviceActorMsg getToDeviceActorMsg() { | |
33 | - return toDeviceActorMsg; | |
34 | - } | |
35 | - | |
36 | - public RuleActorChain getRuleChain() { | |
37 | - return ruleChain; | |
38 | - } | |
39 | - | |
40 | -} |
1 | 1 | /** |
2 | 2 | * Copyright © 2016-2018 The Thingsboard Authors |
3 | - * <p> | |
3 | + * | |
4 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | 5 | * you may not use this file except in compliance with the License. |
6 | 6 | * You may obtain a copy of the License at |
7 | - * <p> | |
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | - * <p> | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | 10 | * Unless required by applicable law or agreed to in writing, software |
11 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
... | ... | @@ -62,7 +62,7 @@ public class TenantActor extends RuleChainManagerActor { |
62 | 62 | } |
63 | 63 | |
64 | 64 | @Override |
65 | - protected void process(TbActorMsg msg) { | |
65 | + protected boolean process(TbActorMsg msg) { | |
66 | 66 | switch (msg.getMsgType()) { |
67 | 67 | case COMPONENT_LIFE_CYCLE_MSG: |
68 | 68 | onComponentLifecycleMsg((ComponentLifecycleMsg) msg); |
... | ... | @@ -70,7 +70,10 @@ public class TenantActor extends RuleChainManagerActor { |
70 | 70 | case SERVICE_TO_RULE_ENGINE_MSG: |
71 | 71 | onServiceToRuleEngineMsg((ServiceToRuleEngineMsg) msg); |
72 | 72 | break; |
73 | + default: | |
74 | + return false; | |
73 | 75 | } |
76 | + return true; | |
74 | 77 | } |
75 | 78 | |
76 | 79 | private void onServiceToRuleEngineMsg(ServiceToRuleEngineMsg msg) { | ... | ... |
... | ... | @@ -78,7 +78,7 @@ public class RuleChainController extends BaseController { |
78 | 78 | ruleChain.setTenantId(getCurrentUser().getTenantId()); |
79 | 79 | RuleChain savedRuleChain = checkNotNull(ruleChainService.saveRuleChain(ruleChain)); |
80 | 80 | |
81 | - actorService.onEntityStateChange(ruleChain.getTenantId(), ruleChain.getId(), | |
81 | + actorService.onEntityStateChange(ruleChain.getTenantId(), savedRuleChain.getId(), | |
82 | 82 | created ? ComponentLifecycleEvent.CREATED : ComponentLifecycleEvent.UPDATED); |
83 | 83 | |
84 | 84 | logEntityAction(savedRuleChain.getId(), savedRuleChain, | ... | ... |
... | ... | @@ -26,6 +26,10 @@ import org.springframework.context.annotation.ClassPathScanningCandidateComponen |
26 | 26 | import org.springframework.core.env.Environment; |
27 | 27 | import org.springframework.core.type.filter.AnnotationTypeFilter; |
28 | 28 | import org.springframework.stereotype.Service; |
29 | +import org.thingsboard.rule.engine.api.ActionNode; | |
30 | +import org.thingsboard.rule.engine.api.EnrichmentNode; | |
31 | +import org.thingsboard.rule.engine.api.FilterNode; | |
32 | +import org.thingsboard.rule.engine.api.TransformationNode; | |
29 | 33 | import org.thingsboard.server.common.data.plugin.ComponentDescriptor; |
30 | 34 | import org.thingsboard.server.common.data.plugin.ComponentType; |
31 | 35 | import org.thingsboard.server.dao.component.ComponentDescriptorService; |
... | ... | @@ -79,8 +83,7 @@ public class AnnotationComponentDiscoveryService implements ComponentDiscoverySe |
79 | 83 | private List<ComponentDescriptor> persist(Set<BeanDefinition> filterDefs, ComponentType type) { |
80 | 84 | List<ComponentDescriptor> result = new ArrayList<>(); |
81 | 85 | for (BeanDefinition def : filterDefs) { |
82 | - ComponentDescriptor scannedComponent = scanAndPersistComponent(def, type); | |
83 | - result.add(scannedComponent); | |
86 | + result.add(scanAndPersistComponent(def, type)); | |
84 | 87 | } |
85 | 88 | return result; |
86 | 89 | } |
... | ... | @@ -93,24 +96,36 @@ public class AnnotationComponentDiscoveryService implements ComponentDiscoverySe |
93 | 96 | Class<?> clazz = Class.forName(clazzName); |
94 | 97 | String descriptorResourceName; |
95 | 98 | switch (type) { |
99 | + case ENRICHMENT: | |
100 | + EnrichmentNode enrichmentAnnotation = clazz.getAnnotation(EnrichmentNode.class); | |
101 | + scannedComponent.setName(enrichmentAnnotation.name()); | |
102 | + scannedComponent.setScope(enrichmentAnnotation.scope()); | |
103 | + descriptorResourceName = enrichmentAnnotation.descriptor(); | |
104 | + break; | |
96 | 105 | case FILTER: |
97 | - Filter filterAnnotation = clazz.getAnnotation(Filter.class); | |
106 | + FilterNode filterAnnotation = clazz.getAnnotation(FilterNode.class); | |
98 | 107 | scannedComponent.setName(filterAnnotation.name()); |
99 | 108 | scannedComponent.setScope(filterAnnotation.scope()); |
100 | 109 | descriptorResourceName = filterAnnotation.descriptor(); |
101 | 110 | break; |
102 | - case PROCESSOR: | |
103 | - Processor processorAnnotation = clazz.getAnnotation(Processor.class); | |
104 | - scannedComponent.setName(processorAnnotation.name()); | |
105 | - scannedComponent.setScope(processorAnnotation.scope()); | |
106 | - descriptorResourceName = processorAnnotation.descriptor(); | |
111 | + case TRANSFORMATION: | |
112 | + TransformationNode trAnnotation = clazz.getAnnotation(TransformationNode.class); | |
113 | + scannedComponent.setName(trAnnotation.name()); | |
114 | + scannedComponent.setScope(trAnnotation.scope()); | |
115 | + descriptorResourceName = trAnnotation.descriptor(); | |
107 | 116 | break; |
108 | 117 | case ACTION: |
109 | - Action actionAnnotation = clazz.getAnnotation(Action.class); | |
118 | + ActionNode actionAnnotation = clazz.getAnnotation(ActionNode.class); | |
110 | 119 | scannedComponent.setName(actionAnnotation.name()); |
111 | 120 | scannedComponent.setScope(actionAnnotation.scope()); |
112 | 121 | descriptorResourceName = actionAnnotation.descriptor(); |
113 | 122 | break; |
123 | + case OLD_ACTION: | |
124 | + Action oldActionAnnotation = clazz.getAnnotation(Action.class); | |
125 | + scannedComponent.setName(oldActionAnnotation.name()); | |
126 | + scannedComponent.setScope(oldActionAnnotation.scope()); | |
127 | + descriptorResourceName = oldActionAnnotation.descriptor(); | |
128 | + break; | |
114 | 129 | case PLUGIN: |
115 | 130 | Plugin pluginAnnotation = clazz.getAnnotation(Plugin.class); |
116 | 131 | scannedComponent.setName(pluginAnnotation.name()); |
... | ... | @@ -122,12 +137,12 @@ public class AnnotationComponentDiscoveryService implements ComponentDiscoverySe |
122 | 137 | log.error("Can't initialize plugin {}, due to missing action {}!", def.getBeanClassName(), actionClazz.getName()); |
123 | 138 | return new ClassNotFoundException("Action: " + actionClazz.getName() + "is missing!"); |
124 | 139 | }); |
125 | - if (actionComponent.getType() != ComponentType.ACTION) { | |
140 | + if (actionComponent.getType() != ComponentType.OLD_ACTION) { | |
126 | 141 | log.error("Plugin {} action {} has wrong component type!", def.getBeanClassName(), actionClazz.getName(), actionComponent.getType()); |
127 | 142 | throw new RuntimeException("Plugin " + def.getBeanClassName() + "action " + actionClazz.getName() + " has wrong component type!"); |
128 | 143 | } |
129 | 144 | } |
130 | - scannedComponent.setActions(Arrays.stream(pluginAnnotation.actions()).map(action -> action.getName()).collect(Collectors.joining(","))); | |
145 | + scannedComponent.setActions(Arrays.stream(pluginAnnotation.actions()).map(Class::getName).collect(Collectors.joining(","))); | |
131 | 146 | break; |
132 | 147 | default: |
133 | 148 | throw new RuntimeException(type + " is not supported yet!"); |
... | ... | @@ -168,11 +183,15 @@ public class AnnotationComponentDiscoveryService implements ComponentDiscoverySe |
168 | 183 | |
169 | 184 | @Override |
170 | 185 | public void discoverComponents() { |
171 | - registerComponents(ComponentType.FILTER, Filter.class); | |
186 | + registerComponents(ComponentType.ENRICHMENT, EnrichmentNode.class); | |
187 | + | |
188 | + registerComponents(ComponentType.FILTER, FilterNode.class); | |
189 | + | |
190 | + registerComponents(ComponentType.TRANSFORMATION, TransformationNode.class); | |
172 | 191 | |
173 | - registerComponents(ComponentType.PROCESSOR, Processor.class); | |
192 | + registerComponents(ComponentType.ACTION, ActionNode.class); | |
174 | 193 | |
175 | - registerComponents(ComponentType.ACTION, Action.class); | |
194 | + registerComponents(ComponentType.OLD_ACTION, Action.class); | |
176 | 195 | |
177 | 196 | registerComponents(ComponentType.PLUGIN, Plugin.class); |
178 | 197 | |
... | ... | @@ -199,7 +218,7 @@ public class AnnotationComponentDiscoveryService implements ComponentDiscoverySe |
199 | 218 | } |
200 | 219 | List<ComponentDescriptor> result = new ArrayList<>(); |
201 | 220 | for (String action : plugin.getActions().split(",")) { |
202 | - getComponent(action).ifPresent(v -> result.add(v)); | |
221 | + getComponent(action).ifPresent(result::add); | |
203 | 222 | } |
204 | 223 | return result; |
205 | 224 | } else { | ... | ... |
... | ... | @@ -62,7 +62,7 @@ cluster: |
62 | 62 | # Plugins configuration parameters |
63 | 63 | plugins: |
64 | 64 | # Comma seperated package list used during classpath scanning for plugins |
65 | - scan_packages: "${PLUGINS_SCAN_PACKAGES:org.thingsboard.server.extensions}" | |
65 | + scan_packages: "${PLUGINS_SCAN_PACKAGES:org.thingsboard.server.extensions,org.thingsboard.rule.engine}" | |
66 | 66 | |
67 | 67 | # JWT Token parameters |
68 | 68 | security.jwt: |
... | ... | @@ -215,12 +215,12 @@ actors: |
215 | 215 | termination.delay: "${ACTORS_RULE_TERMINATION_DELAY:30000}" |
216 | 216 | # Errors for particular actor are persisted once per specified amount of milliseconds |
217 | 217 | error_persist_frequency: "${ACTORS_RULE_ERROR_FREQUENCY:3000}" |
218 | - chain: | |
219 | - # Errors for particular actor are persisted once per specified amount of milliseconds | |
220 | - error_persist_frequency: "${ACTORS_RULE_CHAIN_ERROR_FREQUENCY:3000}" | |
221 | - node: | |
222 | - # Errors for particular actor are persisted once per specified amount of milliseconds | |
223 | - error_persist_frequency: "${ACTORS_RULE_NODE_ERROR_FREQUENCY:3000}" | |
218 | + chain: | |
219 | + # Errors for particular actor are persisted once per specified amount of milliseconds | |
220 | + error_persist_frequency: "${ACTORS_RULE_CHAIN_ERROR_FREQUENCY:3000}" | |
221 | + node: | |
222 | + # Errors for particular actor are persisted once per specified amount of milliseconds | |
223 | + error_persist_frequency: "${ACTORS_RULE_NODE_ERROR_FREQUENCY:3000}" | |
224 | 224 | statistics: |
225 | 225 | # Enable/disable actor statistics |
226 | 226 | enabled: "${ACTORS_STATISTICS_ENABLED:true}" | ... | ... |
... | ... | @@ -96,6 +96,8 @@ import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppC |
96 | 96 | @Slf4j |
97 | 97 | public abstract class AbstractControllerTest { |
98 | 98 | |
99 | + protected ObjectMapper mapper = new ObjectMapper(); | |
100 | + | |
99 | 101 | protected static final String TEST_TENANT_NAME = "TEST TENANT"; |
100 | 102 | |
101 | 103 | protected static final String SYS_ADMIN_EMAIL = "sysadmin@thingsboard.org"; | ... | ... |
application/src/test/java/org/thingsboard/server/controller/AbstractRuleEngineControllerTest.java
0 → 100644
1 | +package org.thingsboard.server.controller; | |
2 | + | |
3 | +import com.fasterxml.jackson.core.type.TypeReference; | |
4 | +import org.thingsboard.server.common.data.DataConstants; | |
5 | +import org.thingsboard.server.common.data.Event; | |
6 | +import org.thingsboard.server.common.data.id.EntityId; | |
7 | +import org.thingsboard.server.common.data.id.RuleChainId; | |
8 | +import org.thingsboard.server.common.data.id.TenantId; | |
9 | +import org.thingsboard.server.common.data.page.TimePageData; | |
10 | +import org.thingsboard.server.common.data.page.TimePageLink; | |
11 | +import org.thingsboard.server.common.data.rule.RuleChain; | |
12 | +import org.thingsboard.server.common.data.rule.RuleChainMetaData; | |
13 | + | |
14 | +/** | |
15 | + * Created by ashvayka on 20.03.18. | |
16 | + */ | |
17 | +public class AbstractRuleEngineControllerTest extends AbstractControllerTest{ | |
18 | + | |
19 | + protected RuleChain saveRuleChain(RuleChain ruleChain) throws Exception { | |
20 | + return doPost("/api/ruleChain", ruleChain, RuleChain.class); | |
21 | + } | |
22 | + | |
23 | + protected RuleChain getRuleChain(RuleChainId ruleChainId) throws Exception { | |
24 | + return doGet("/api/ruleChain/" + ruleChainId.getId().toString(), RuleChain.class); | |
25 | + } | |
26 | + | |
27 | + protected RuleChainMetaData saveRuleChainMetaData(RuleChainMetaData ruleChainMD) throws Exception { | |
28 | + return doPost("/api/ruleChain/metadata", ruleChainMD, RuleChainMetaData.class); | |
29 | + } | |
30 | + | |
31 | + protected RuleChainMetaData getRuleChainMetaData(RuleChainId ruleChainId) throws Exception { | |
32 | + return doGet("/api/ruleChain/metadata/" + ruleChainId.getId().toString(), RuleChainMetaData.class); | |
33 | + } | |
34 | + | |
35 | + protected TimePageData<Event> getDebugEvents(TenantId tenantId, EntityId entityId, int limit) throws Exception { | |
36 | + TimePageLink pageLink = new TimePageLink(limit); | |
37 | + return doGetTypedWithTimePageLink("/api/events/{entityType}/{entityId}/{eventType}?tenantId={tenantId}&", | |
38 | + new TypeReference<TimePageData<Event>>() { | |
39 | + }, pageLink, entityId.getEntityType(), entityId.getId(), DataConstants.DEBUG, tenantId.getId()); | |
40 | + } | |
41 | +} | ... | ... |
application/src/test/java/org/thingsboard/server/rules/RuleEngineSqlTestSuite.java
renamed from
application/src/main/java/org/thingsboard/server/actors/rule/RuleActorChain.java
... | ... | @@ -13,12 +13,23 @@ |
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.actors.rule; | |
16 | +package org.thingsboard.server.rules; | |
17 | 17 | |
18 | -public interface RuleActorChain { | |
18 | +import org.junit.ClassRule; | |
19 | +import org.junit.extensions.cpsuite.ClasspathSuite; | |
20 | +import org.junit.runner.RunWith; | |
21 | +import org.thingsboard.server.dao.CustomSqlUnit; | |
19 | 22 | |
20 | - int size(); | |
23 | +import java.util.Arrays; | |
21 | 24 | |
22 | - RuleActorMetaData getRuleActorMd(int index); | |
25 | +@RunWith(ClasspathSuite.class) | |
26 | +@ClasspathSuite.ClassnameFilters({ | |
27 | + "org.thingsboard.server.rules.flow.*Test", "org.thingsboard.server.rules.lifecycle.*Test"}) | |
28 | +public class RuleEngineSqlTestSuite { | |
23 | 29 | |
30 | + @ClassRule | |
31 | + public static CustomSqlUnit sqlUnit = new CustomSqlUnit( | |
32 | + Arrays.asList("sql/schema.sql", "sql/system-data.sql"), | |
33 | + "sql/drop-all-tables.sql", | |
34 | + "sql-test.properties"); | |
24 | 35 | } | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2018 The Thingsboard Authors | |
3 | + * <p> | |
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 | + * <p> | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * <p> | |
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.flow; | |
17 | + | |
18 | +import com.datastax.driver.core.utils.UUIDs; | |
19 | +import lombok.Data; | |
20 | +import lombok.extern.slf4j.Slf4j; | |
21 | +import org.junit.After; | |
22 | +import org.junit.Assert; | |
23 | +import org.junit.Before; | |
24 | +import org.junit.Test; | |
25 | +import org.springframework.beans.factory.annotation.Autowired; | |
26 | +import org.thingsboard.rule.engine.metadata.TbGetAttributesNodeConfiguration; | |
27 | +import org.thingsboard.server.actors.service.ActorService; | |
28 | +import org.thingsboard.server.common.data.*; | |
29 | +import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; | |
30 | +import org.thingsboard.server.common.data.kv.StringDataEntry; | |
31 | +import org.thingsboard.server.common.data.page.TimePageData; | |
32 | +import org.thingsboard.server.common.data.rule.RuleChain; | |
33 | +import org.thingsboard.server.common.data.rule.RuleChainMetaData; | |
34 | +import org.thingsboard.server.common.data.rule.RuleNode; | |
35 | +import org.thingsboard.server.common.data.security.Authority; | |
36 | +import org.thingsboard.server.common.msg.TbMsg; | |
37 | +import org.thingsboard.server.common.msg.TbMsgMetaData; | |
38 | +import org.thingsboard.server.common.msg.system.ServiceToRuleEngineMsg; | |
39 | +import org.thingsboard.server.controller.AbstractRuleEngineControllerTest; | |
40 | +import org.thingsboard.server.dao.attributes.AttributesService; | |
41 | + | |
42 | +import java.util.Collections; | |
43 | + | |
44 | +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; | |
45 | + | |
46 | +/** | |
47 | + * @author Valerii Sosliuk | |
48 | + */ | |
49 | +@Slf4j | |
50 | +public abstract class AbstractRuleEngineFlowIntegrationTest extends AbstractRuleEngineControllerTest { | |
51 | + | |
52 | + private static final String MQTT_URL = "tcp://localhost:1883"; | |
53 | + private static final Long TIME_TO_HANDLE_REQUEST = 500L; | |
54 | + | |
55 | + private Tenant savedTenant; | |
56 | + private User tenantAdmin; | |
57 | + | |
58 | + @Autowired | |
59 | + private ActorService actorService; | |
60 | + | |
61 | + @Autowired | |
62 | + private 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 testSimpleRuleChainCreation() 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 | + // Pushing Message to the system | |
132 | + TbMsg tbMsg = new TbMsg(UUIDs.timeBased(), | |
133 | + "CUSTOM", | |
134 | + device.getId(), | |
135 | + new TbMsgMetaData(), | |
136 | + new byte[]{}); | |
137 | + actorService.onMsg(new ServiceToRuleEngineMsg(savedTenant.getId(), tbMsg)); | |
138 | + | |
139 | + Thread.sleep(3000); | |
140 | + | |
141 | + TimePageData<Event> events = getDebugEvents(savedTenant.getId(), ruleChain.getFirstRuleNodeId(), 1000); | |
142 | + | |
143 | + Assert.assertEquals(2, events.getData().size()); | |
144 | + | |
145 | + Event inEvent = events.getData().stream().filter(e -> e.getBody().get("type").asText().equals(DataConstants.IN)).findFirst().get(); | |
146 | + Assert.assertEquals(ruleChain.getFirstRuleNodeId(), inEvent.getEntityId()); | |
147 | + Assert.assertEquals(device.getId().getId().toString(), inEvent.getBody().get("entityId").asText()); | |
148 | + | |
149 | + Event outEvent = events.getData().stream().filter(e -> e.getBody().get("type").asText().equals(DataConstants.OUT)).findFirst().get(); | |
150 | + Assert.assertEquals(ruleChain.getFirstRuleNodeId(), outEvent.getEntityId()); | |
151 | + Assert.assertEquals(device.getId().getId().toString(), outEvent.getBody().get("entityId").asText()); | |
152 | + | |
153 | + Assert.assertEquals("serverAttributeValue", outEvent.getBody().get("metadata").get("ss.serverAttributeKey").asText()); | |
154 | + } | |
155 | + | |
156 | +} | ... | ... |
application/src/test/java/org/thingsboard/server/rules/flow/RuleEngineFlowSqlIntegrationTest.java
renamed from
application/src/main/java/org/thingsboard/server/actors/rule/CompoundRuleActorChain.java
... | ... | @@ -13,8 +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.actors.rule; | |
16 | +package org.thingsboard.server.rules.flow; | |
17 | 17 | |
18 | -public class CompoundRuleActorChain { | |
18 | +import org.thingsboard.server.dao.service.DaoSqlTest; | |
19 | +import org.thingsboard.server.mqtt.rpc.AbstractMqttServerSideRpcIntegrationTest; | |
19 | 20 | |
21 | +/** | |
22 | + * Created by Valerii Sosliuk on 8/22/2017. | |
23 | + */ | |
24 | +@DaoSqlTest | |
25 | +public class RuleEngineFlowSqlIntegrationTest extends AbstractRuleEngineFlowIntegrationTest { | |
20 | 26 | } | ... | ... |
... | ... | @@ -37,9 +37,12 @@ public class DataConstants { |
37 | 37 | public static final String ERROR = "ERROR"; |
38 | 38 | public static final String LC_EVENT = "LC_EVENT"; |
39 | 39 | public static final String STATS = "STATS"; |
40 | - public static final String RULE_CHAIN_DEBUG = "DEBUG_RULE_CHAIN"; | |
41 | - public static final String RULE_NODE_DEBUG = "DEBUG_RULE_NODE"; | |
40 | + public static final String DEBUG = "DEBUG"; | |
42 | 41 | |
43 | 42 | public static final String ONEWAY = "ONEWAY"; |
44 | 43 | public static final String TWOWAY = "TWOWAY"; |
44 | + | |
45 | + public static final String IN = "IN"; | |
46 | + public static final String OUT = "OUT"; | |
47 | + | |
45 | 48 | } | ... | ... |
... | ... | @@ -38,6 +38,7 @@ public class RuleChain extends SearchTextBasedWithAdditionalInfo<RuleChainId> im |
38 | 38 | private String name; |
39 | 39 | private RuleNodeId firstRuleNodeId; |
40 | 40 | private boolean root; |
41 | + private boolean debugMode; | |
41 | 42 | private transient JsonNode configuration; |
42 | 43 | @JsonIgnore |
43 | 44 | private byte[] configurationBytes; | ... | ... |
... | ... | @@ -34,6 +34,7 @@ public class RuleNode extends SearchTextBasedWithAdditionalInfo<RuleNodeId> impl |
34 | 34 | |
35 | 35 | private String type; |
36 | 36 | private String name; |
37 | + private boolean debugMode; | |
37 | 38 | private transient JsonNode configuration; |
38 | 39 | @JsonIgnore |
39 | 40 | private byte[] configurationBytes; | ... | ... |
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 | + */ | |
1 | 16 | package org.thingsboard.server.common.msg; |
2 | 17 | |
3 | 18 | /** |
... | ... | @@ -34,4 +49,9 @@ public enum MsgType { |
34 | 49 | */ |
35 | 50 | RULE_TO_RULE_CHAIN_TELL_NEXT_MSG, |
36 | 51 | |
52 | + /** | |
53 | + * Message that is sent by RuleActor implementation to RuleActor itself to log the error. | |
54 | + */ | |
55 | + RULE_TO_SELF_ERROR_MSG, | |
56 | + | |
37 | 57 | } | ... | ... |
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 | + */ | |
1 | 16 | package org.thingsboard.server.common.msg; |
2 | 17 | |
3 | 18 | /** | ... | ... |
1 | 1 | /** |
2 | 2 | * Copyright © 2016-2018 The Thingsboard Authors |
3 | - * <p> | |
3 | + * | |
4 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | 5 | * you may not use this file except in compliance with the License. |
6 | 6 | * You may obtain a copy of the License at |
7 | - * <p> | |
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | - * <p> | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | 10 | * Unless required by applicable law or agreed to in writing, software |
11 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
... | ... | @@ -17,6 +17,7 @@ package org.thingsboard.server.common.msg; |
17 | 17 | |
18 | 18 | import com.google.protobuf.ByteString; |
19 | 19 | import com.google.protobuf.InvalidProtocolBufferException; |
20 | +import lombok.AllArgsConstructor; | |
20 | 21 | import lombok.Data; |
21 | 22 | import org.thingsboard.server.common.data.id.EntityId; |
22 | 23 | import org.thingsboard.server.common.data.id.EntityIdFactory; |
... | ... | @@ -30,6 +31,7 @@ import java.util.UUID; |
30 | 31 | * Created by ashvayka on 13.01.18. |
31 | 32 | */ |
32 | 33 | @Data |
34 | +@AllArgsConstructor | |
33 | 35 | public final class TbMsg implements Serializable { |
34 | 36 | |
35 | 37 | private final UUID id; |
... | ... | @@ -39,6 +41,15 @@ public final class TbMsg implements Serializable { |
39 | 41 | private final TbMsgDataType dataType; |
40 | 42 | private final byte[] data; |
41 | 43 | |
44 | + public TbMsg(UUID id, String type, EntityId originator, TbMsgMetaData metaData, byte[] data) { | |
45 | + this.id = id; | |
46 | + this.type = type; | |
47 | + this.originator = originator; | |
48 | + this.metaData = metaData; | |
49 | + this.dataType = TbMsgDataType.JSON; | |
50 | + this.data = data; | |
51 | + } | |
52 | + | |
42 | 53 | public static ByteBuffer toBytes(TbMsg msg) { |
43 | 54 | MsgProtos.TbMsgProto.Builder builder = MsgProtos.TbMsgProto.newBuilder(); |
44 | 55 | builder.setId(msg.getId().toString()); |
... | ... | @@ -61,9 +72,7 @@ public final class TbMsg implements Serializable { |
61 | 72 | public static TbMsg fromBytes(ByteBuffer buffer) { |
62 | 73 | try { |
63 | 74 | MsgProtos.TbMsgProto proto = MsgProtos.TbMsgProto.parseFrom(buffer.array()); |
64 | - TbMsgMetaData metaData = new TbMsgMetaData(); | |
65 | - metaData.setData(proto.getMetaData().getDataMap()); | |
66 | - | |
75 | + TbMsgMetaData metaData = new TbMsgMetaData(proto.getMetaData().getDataMap()); | |
67 | 76 | EntityId entityId = EntityIdFactory.getByTypeAndId(proto.getEntityType(), proto.getEntityId()); |
68 | 77 | TbMsgDataType dataType = TbMsgDataType.values()[proto.getDataType()]; |
69 | 78 | return new TbMsg(UUID.fromString(proto.getId()), proto.getType(), entityId, metaData, dataType, proto.getData().toByteArray()); |
... | ... | @@ -71,4 +80,11 @@ public final class TbMsg implements Serializable { |
71 | 80 | throw new IllegalStateException("Could not parse protobuf for TbMsg", e); |
72 | 81 | } |
73 | 82 | } |
83 | + | |
84 | + public TbMsg copy() { | |
85 | + int dataSize = data.length; | |
86 | + byte[] dataCopy = new byte[dataSize]; | |
87 | + System.arraycopy( data, 0, dataCopy, 0, data.length ); | |
88 | + return new TbMsg(id, type, originator, metaData.copy(), dataType, dataCopy); | |
89 | + } | |
74 | 90 | } | ... | ... |
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 | + */ | |
1 | 16 | package org.thingsboard.server.common.msg; |
2 | 17 | |
3 | 18 | /** | ... | ... |
1 | 1 | /** |
2 | 2 | * Copyright © 2016-2018 The Thingsboard Authors |
3 | - * | |
3 | + * <p> | |
4 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | 5 | * you may not use this file except in compliance with the License. |
6 | 6 | * You may obtain a copy of the License at |
7 | - * | |
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | - * | |
7 | + * <p> | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * <p> | |
10 | 10 | * Unless required by applicable law or agreed to in writing, software |
11 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
... | ... | @@ -15,9 +15,12 @@ |
15 | 15 | */ |
16 | 16 | package org.thingsboard.server.common.msg; |
17 | 17 | |
18 | +import lombok.AllArgsConstructor; | |
18 | 19 | import lombok.Data; |
20 | +import lombok.NoArgsConstructor; | |
19 | 21 | |
20 | 22 | import java.io.Serializable; |
23 | +import java.util.HashMap; | |
21 | 24 | import java.util.Map; |
22 | 25 | import java.util.concurrent.ConcurrentHashMap; |
23 | 26 | |
... | ... | @@ -25,10 +28,15 @@ import java.util.concurrent.ConcurrentHashMap; |
25 | 28 | * Created by ashvayka on 13.01.18. |
26 | 29 | */ |
27 | 30 | @Data |
31 | +@NoArgsConstructor | |
28 | 32 | public final class TbMsgMetaData implements Serializable { |
29 | 33 | |
30 | 34 | private Map<String, String> data = new ConcurrentHashMap<>(); |
31 | 35 | |
36 | + TbMsgMetaData(Map<String, String> data) { | |
37 | + this.data = data; | |
38 | + } | |
39 | + | |
32 | 40 | public String getValue(String key) { |
33 | 41 | return data.get(key); |
34 | 42 | } |
... | ... | @@ -37,4 +45,7 @@ public final class TbMsgMetaData implements Serializable { |
37 | 45 | data.put(key, value); |
38 | 46 | } |
39 | 47 | |
48 | + public TbMsgMetaData copy() { | |
49 | + return new TbMsgMetaData(new ConcurrentHashMap<>(data)); | |
50 | + } | |
40 | 51 | } | ... | ... |
1 | 1 | /** |
2 | 2 | * Copyright © 2016-2018 The Thingsboard Authors |
3 | - * <p> | |
3 | + * | |
4 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | 5 | * you may not use this file except in compliance with the License. |
6 | 6 | * You may obtain a copy of the License at |
7 | - * <p> | |
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | - * <p> | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | 10 | * Unless required by applicable law or agreed to in writing, software |
11 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ... | ... |
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 | + */ | |
1 | 16 | package org.thingsboard.server.common.msg.system; |
2 | 17 | |
3 | 18 | import lombok.Data; | ... | ... |
... | ... | @@ -332,6 +332,8 @@ public class ModelConstants { |
332 | 332 | public static final String EVENT_BY_TYPE_AND_ID_VIEW_NAME = "event_by_type_and_id"; |
333 | 333 | public static final String EVENT_BY_ID_VIEW_NAME = "event_by_id"; |
334 | 334 | |
335 | + public static final String DEBUG_MODE = "debug_mode"; | |
336 | + | |
335 | 337 | /** |
336 | 338 | * Cassandra rule chain constants. |
337 | 339 | */ | ... | ... |
1 | 1 | /** |
2 | 2 | * Copyright © 2016-2018 The Thingsboard Authors |
3 | - * | |
3 | + * <p> | |
4 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | 5 | * you may not use this file except in compliance with the License. |
6 | 6 | * You may obtain a copy of the License at |
7 | - * | |
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | - * | |
7 | + * <p> | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * <p> | |
10 | 10 | * Unless required by applicable law or agreed to in writing, software |
11 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
... | ... | @@ -22,6 +22,8 @@ import com.datastax.driver.mapping.annotations.PartitionKey; |
22 | 22 | import com.datastax.driver.mapping.annotations.Table; |
23 | 23 | import com.fasterxml.jackson.databind.JsonNode; |
24 | 24 | import lombok.EqualsAndHashCode; |
25 | +import lombok.Getter; | |
26 | +import lombok.Setter; | |
25 | 27 | import lombok.ToString; |
26 | 28 | import org.thingsboard.server.common.data.id.RuleChainId; |
27 | 29 | import org.thingsboard.server.common.data.id.RuleNodeId; |
... | ... | @@ -54,6 +56,10 @@ public class RuleChainEntity implements SearchTextEntity<RuleChain> { |
54 | 56 | private UUID firstRuleNodeId; |
55 | 57 | @Column(name = RULE_CHAIN_ROOT_PROPERTY) |
56 | 58 | private boolean root; |
59 | + @Getter | |
60 | + @Setter | |
61 | + @Column(name = DEBUG_MODE) | |
62 | + private boolean debugMode; | |
57 | 63 | @Column(name = RULE_CHAIN_CONFIGURATION_PROPERTY, codec = JsonCodec.class) |
58 | 64 | private JsonNode configuration; |
59 | 65 | @Column(name = ADDITIONAL_INFO_PROPERTY, codec = JsonCodec.class) |
... | ... | @@ -71,6 +77,7 @@ public class RuleChainEntity implements SearchTextEntity<RuleChain> { |
71 | 77 | this.searchText = ruleChain.getName(); |
72 | 78 | this.firstRuleNodeId = DaoUtil.getId(ruleChain.getFirstRuleNodeId()); |
73 | 79 | this.root = ruleChain.isRoot(); |
80 | + this.debugMode = ruleChain.isDebugMode(); | |
74 | 81 | this.configuration = ruleChain.getConfiguration(); |
75 | 82 | this.additionalInfo = ruleChain.getAdditionalInfo(); |
76 | 83 | } |
... | ... | @@ -157,6 +164,7 @@ public class RuleChainEntity implements SearchTextEntity<RuleChain> { |
157 | 164 | ruleChain.setFirstRuleNodeId(new RuleNodeId(this.firstRuleNodeId)); |
158 | 165 | } |
159 | 166 | ruleChain.setRoot(this.root); |
167 | + ruleChain.setDebugMode(this.debugMode); | |
160 | 168 | ruleChain.setConfiguration(this.configuration); |
161 | 169 | ruleChain.setAdditionalInfo(this.additionalInfo); |
162 | 170 | return ruleChain; | ... | ... |
... | ... | @@ -21,6 +21,8 @@ import com.datastax.driver.mapping.annotations.PartitionKey; |
21 | 21 | import com.datastax.driver.mapping.annotations.Table; |
22 | 22 | import com.fasterxml.jackson.databind.JsonNode; |
23 | 23 | import lombok.EqualsAndHashCode; |
24 | +import lombok.Getter; | |
25 | +import lombok.Setter; | |
24 | 26 | import lombok.ToString; |
25 | 27 | import org.thingsboard.server.common.data.id.RuleNodeId; |
26 | 28 | import org.thingsboard.server.common.data.rule.RuleNode; |
... | ... | @@ -49,6 +51,11 @@ public class RuleNodeEntity implements SearchTextEntity<RuleNode> { |
49 | 51 | private JsonNode configuration; |
50 | 52 | @Column(name = ADDITIONAL_INFO_PROPERTY, codec = JsonCodec.class) |
51 | 53 | private JsonNode additionalInfo; |
54 | + @Getter | |
55 | + @Setter | |
56 | + @Column(name = DEBUG_MODE) | |
57 | + private boolean debugMode; | |
58 | + | |
52 | 59 | |
53 | 60 | public RuleNodeEntity() { |
54 | 61 | } |
... | ... | @@ -59,6 +66,7 @@ public class RuleNodeEntity implements SearchTextEntity<RuleNode> { |
59 | 66 | } |
60 | 67 | this.type = ruleNode.getType(); |
61 | 68 | this.name = ruleNode.getName(); |
69 | + this.debugMode = ruleNode.isDebugMode(); | |
62 | 70 | this.searchText = ruleNode.getName(); |
63 | 71 | this.configuration = ruleNode.getConfiguration(); |
64 | 72 | this.additionalInfo = ruleNode.getAdditionalInfo(); |
... | ... | @@ -126,6 +134,7 @@ public class RuleNodeEntity implements SearchTextEntity<RuleNode> { |
126 | 134 | ruleNode.setCreatedTime(UUIDs.unixTimestamp(id)); |
127 | 135 | ruleNode.setType(this.type); |
128 | 136 | ruleNode.setName(this.name); |
137 | + ruleNode.setDebugMode(this.debugMode); | |
129 | 138 | ruleNode.setConfiguration(this.configuration); |
130 | 139 | ruleNode.setAdditionalInfo(this.additionalInfo); |
131 | 140 | return ruleNode; | ... | ... |
... | ... | @@ -58,6 +58,9 @@ public class RuleChainEntity extends BaseSqlEntity<RuleChain> implements SearchT |
58 | 58 | @Column(name = ModelConstants.RULE_CHAIN_ROOT_PROPERTY) |
59 | 59 | private boolean root; |
60 | 60 | |
61 | + @Column(name = ModelConstants.DEBUG_MODE) | |
62 | + private boolean debugMode; | |
63 | + | |
61 | 64 | @Type(type = "json") |
62 | 65 | @Column(name = ModelConstants.RULE_CHAIN_CONFIGURATION_PROPERTY) |
63 | 66 | private JsonNode configuration; |
... | ... | @@ -80,6 +83,7 @@ public class RuleChainEntity extends BaseSqlEntity<RuleChain> implements SearchT |
80 | 83 | this.firstRuleNodeId = UUIDConverter.fromTimeUUID(ruleChain.getFirstRuleNodeId().getId()); |
81 | 84 | } |
82 | 85 | this.root = ruleChain.isRoot(); |
86 | + this.debugMode = ruleChain.isDebugMode(); | |
83 | 87 | this.configuration = ruleChain.getConfiguration(); |
84 | 88 | this.additionalInfo = ruleChain.getAdditionalInfo(); |
85 | 89 | } |
... | ... | @@ -104,6 +108,7 @@ public class RuleChainEntity extends BaseSqlEntity<RuleChain> implements SearchT |
104 | 108 | ruleChain.setFirstRuleNodeId(new RuleNodeId(UUIDConverter.fromString(firstRuleNodeId))); |
105 | 109 | } |
106 | 110 | ruleChain.setRoot(root); |
111 | + ruleChain.setDebugMode(debugMode); | |
107 | 112 | ruleChain.setConfiguration(configuration); |
108 | 113 | ruleChain.setAdditionalInfo(additionalInfo); |
109 | 114 | return ruleChain; | ... | ... |
... | ... | @@ -56,6 +56,9 @@ public class RuleNodeEntity extends BaseSqlEntity<RuleNode> implements SearchTex |
56 | 56 | @Column(name = ModelConstants.ADDITIONAL_INFO_PROPERTY) |
57 | 57 | private JsonNode additionalInfo; |
58 | 58 | |
59 | + @Column(name = ModelConstants.DEBUG_MODE) | |
60 | + private boolean debugMode; | |
61 | + | |
59 | 62 | public RuleNodeEntity() { |
60 | 63 | } |
61 | 64 | |
... | ... | @@ -65,6 +68,7 @@ public class RuleNodeEntity extends BaseSqlEntity<RuleNode> implements SearchTex |
65 | 68 | } |
66 | 69 | this.type = ruleNode.getType(); |
67 | 70 | this.name = ruleNode.getName(); |
71 | + this.debugMode = ruleNode.isDebugMode(); | |
68 | 72 | this.searchText = ruleNode.getName(); |
69 | 73 | this.configuration = ruleNode.getConfiguration(); |
70 | 74 | this.additionalInfo = ruleNode.getAdditionalInfo(); |
... | ... | @@ -86,6 +90,7 @@ public class RuleNodeEntity extends BaseSqlEntity<RuleNode> implements SearchTex |
86 | 90 | ruleNode.setCreatedTime(UUIDs.unixTimestamp(getId())); |
87 | 91 | ruleNode.setType(type); |
88 | 92 | ruleNode.setName(name); |
93 | + ruleNode.setDebugMode(debugMode); | |
89 | 94 | ruleNode.setConfiguration(configuration); |
90 | 95 | ruleNode.setAdditionalInfo(additionalInfo); |
91 | 96 | return ruleNode; | ... | ... |
... | ... | @@ -32,6 +32,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; |
32 | 32 | import org.springframework.context.annotation.Bean; |
33 | 33 | import org.springframework.context.annotation.ComponentScan; |
34 | 34 | import org.thingsboard.server.common.msg.TbMsg; |
35 | +import org.thingsboard.server.common.msg.TbMsgDataType; | |
35 | 36 | import org.thingsboard.server.common.msg.TbMsgMetaData; |
36 | 37 | |
37 | 38 | import javax.annotation.Nullable; |
... | ... | @@ -125,7 +126,7 @@ public class QueueBenchmark implements CommandLineRunner { |
125 | 126 | TbMsgMetaData metaData = new TbMsgMetaData(); |
126 | 127 | metaData.putValue("key", "value"); |
127 | 128 | String dataStr = "someContent"; |
128 | - return new TbMsg(UUIDs.timeBased(), "type", null, metaData, dataStr.getBytes()); | |
129 | + return new TbMsg(UUIDs.timeBased(), "type", null, metaData, TbMsgDataType.JSON, dataStr.getBytes()); | |
129 | 130 | } |
130 | 131 | |
131 | 132 | @Bean | ... | ... |
... | ... | @@ -220,6 +220,12 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC |
220 | 220 | } |
221 | 221 | |
222 | 222 | @Override |
223 | + public RuleNode findRuleNodeById(RuleNodeId ruleNodeId) { | |
224 | + Validator.validateId(ruleNodeId, "Incorrect rule node id for search request."); | |
225 | + return ruleNodeDao.findById(ruleNodeId.getId()); | |
226 | + } | |
227 | + | |
228 | + @Override | |
223 | 229 | public ListenableFuture<RuleChain> findRuleChainByIdAsync(RuleChainId ruleChainId) { |
224 | 230 | Validator.validateId(ruleChainId, "Incorrect rule chain id for search request."); |
225 | 231 | return ruleChainDao.findByIdAsync(ruleChainId.getId()); |
... | ... | @@ -325,7 +331,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC |
325 | 331 | } |
326 | 332 | if (ruleChain.isRoot()) { |
327 | 333 | RuleChain rootRuleChain = getRootTenantRuleChain(ruleChain.getTenantId()); |
328 | - if (ruleChain.getId() == null || !ruleChain.getId().equals(rootRuleChain.getId())) { | |
334 | + if (rootRuleChain != null && !rootRuleChain.getId().equals(ruleChain.getId())) { | |
329 | 335 | throw new DataValidationException("Another root rule chain is present in scope of current tenant!"); |
330 | 336 | } |
331 | 337 | } | ... | ... |
... | ... | @@ -42,6 +42,8 @@ public interface RuleChainService { |
42 | 42 | |
43 | 43 | RuleChain findRuleChainById(RuleChainId ruleChainId); |
44 | 44 | |
45 | + RuleNode findRuleNodeById(RuleNodeId ruleNodeId); | |
46 | + | |
45 | 47 | ListenableFuture<RuleChain> findRuleChainByIdAsync(RuleChainId ruleChainId); |
46 | 48 | |
47 | 49 | RuleChain getRootTenantRuleChain(TenantId tenantId); | ... | ... |
... | ... | @@ -669,6 +669,7 @@ CREATE TABLE IF NOT EXISTS thingsboard.rule_chain ( |
669 | 669 | search_text text, |
670 | 670 | first_rule_node_id uuid, |
671 | 671 | root boolean, |
672 | + debug_mode boolean, | |
672 | 673 | configuration text, |
673 | 674 | additional_info text, |
674 | 675 | PRIMARY KEY (id, tenant_id) |
... | ... | @@ -685,6 +686,7 @@ CREATE TABLE IF NOT EXISTS thingsboard.rule_node ( |
685 | 686 | id uuid, |
686 | 687 | type text, |
687 | 688 | name text, |
689 | + debug_mode boolean, | |
688 | 690 | search_text text, |
689 | 691 | configuration text, |
690 | 692 | additional_info text, | ... | ... |
... | ... | @@ -263,6 +263,7 @@ CREATE TABLE IF NOT EXISTS rule_chain ( |
263 | 263 | name varchar(255), |
264 | 264 | first_rule_node_id varchar(31), |
265 | 265 | root boolean, |
266 | + debug_mode boolean, | |
266 | 267 | search_text varchar(255), |
267 | 268 | tenant_id varchar(31) |
268 | 269 | ); |
... | ... | @@ -273,5 +274,6 @@ CREATE TABLE IF NOT EXISTS rule_node ( |
273 | 274 | configuration varchar(10000000), |
274 | 275 | type varchar(255), |
275 | 276 | name varchar(255), |
277 | + debug_mode boolean, | |
276 | 278 | search_text varchar(255) |
277 | 279 | ); | ... | ... |
... | ... | @@ -217,10 +217,10 @@ public abstract class AbstractServiceTest { |
217 | 217 | ruleMetaData.setWeight(weight); |
218 | 218 | ruleMetaData.setPluginToken(pluginToken); |
219 | 219 | |
220 | - ruleMetaData.setAction(createNode(ComponentScope.TENANT, ComponentType.ACTION, | |
220 | + ruleMetaData.setAction(createNode(ComponentScope.TENANT, ComponentType.OLD_ACTION, | |
221 | 221 | "org.thingsboard.component.ActionTest", "TestJsonDescriptor.json", "TestJsonData.json")); |
222 | - ruleMetaData.setProcessor(createNode(ComponentScope.TENANT, ComponentType.PROCESSOR, | |
223 | - "org.thingsboard.component.ProcessorTest", "TestJsonDescriptor.json", "TestJsonData.json")); | |
222 | +// ruleMetaData.setProcessor(createNode(ComponentScope.TENANT, ComponentType.PROCESSOR, | |
223 | +// "org.thingsboard.component.ProcessorTest", "TestJsonDescriptor.json", "TestJsonData.json")); | |
224 | 224 | ruleMetaData.setFilters(mapper.createArrayNode().add( |
225 | 225 | createNode(ComponentScope.TENANT, ComponentType.FILTER, |
226 | 226 | "org.thingsboard.component.FilterTest", "TestJsonDescriptor.json", "TestJsonData.json") | ... | ... |
... | ... | @@ -33,8 +33,8 @@ public class UnprocessedMsgFilterTest { |
33 | 33 | public void acknowledgedMsgsAreFilteredOut() { |
34 | 34 | UUID id1 = UUID.randomUUID(); |
35 | 35 | UUID id2 = UUID.randomUUID(); |
36 | - TbMsg msg1 = new TbMsg(id1, "T", null, null, null); | |
37 | - TbMsg msg2 = new TbMsg(id2, "T", null, null, null); | |
36 | + TbMsg msg1 = new TbMsg(id1, "T", null, null, null, null); | |
37 | + TbMsg msg2 = new TbMsg(id2, "T", null, null, null, null); | |
38 | 38 | List<TbMsg> msgs = Lists.newArrayList(msg1, msg2); |
39 | 39 | List<MsgAck> acks = Lists.newArrayList(new MsgAck(id2, UUID.randomUUID(), 1L, 1L)); |
40 | 40 | Collection<TbMsg> actual = msgFilter.filter(msgs, acks); | ... | ... |
... | ... | @@ -24,6 +24,7 @@ import org.junit.Test; |
24 | 24 | import org.springframework.beans.factory.annotation.Autowired; |
25 | 25 | import org.thingsboard.server.common.data.id.DeviceId; |
26 | 26 | import org.thingsboard.server.common.msg.TbMsg; |
27 | +import org.thingsboard.server.common.msg.TbMsgDataType; | |
27 | 28 | import org.thingsboard.server.common.msg.TbMsgMetaData; |
28 | 29 | import org.thingsboard.server.dao.service.AbstractServiceTest; |
29 | 30 | import org.thingsboard.server.dao.service.DaoNoSqlTest; |
... | ... | @@ -44,7 +45,7 @@ public class CassandraMsgRepositoryTest extends AbstractServiceTest { |
44 | 45 | |
45 | 46 | @Test |
46 | 47 | public void msgCanBeSavedAndRead() throws ExecutionException, InterruptedException { |
47 | - TbMsg msg = new TbMsg(UUIDs.timeBased(), "type", new DeviceId(UUIDs.timeBased()), null, new byte[4]); | |
48 | + TbMsg msg = new TbMsg(UUIDs.timeBased(), "type", new DeviceId(UUIDs.timeBased()), null, TbMsgDataType.JSON, new byte[4]); | |
48 | 49 | UUID nodeId = UUIDs.timeBased(); |
49 | 50 | ListenableFuture<Void> future = msgRepository.save(msg, nodeId, 1L, 1L, 1L); |
50 | 51 | future.get(); |
... | ... | @@ -54,7 +55,7 @@ public class CassandraMsgRepositoryTest extends AbstractServiceTest { |
54 | 55 | |
55 | 56 | @Test |
56 | 57 | public void expiredMsgsAreNotReturned() throws ExecutionException, InterruptedException { |
57 | - TbMsg msg = new TbMsg(UUIDs.timeBased(), "type", new DeviceId(UUIDs.timeBased()), null, new byte[4]); | |
58 | + TbMsg msg = new TbMsg(UUIDs.timeBased(), "type", new DeviceId(UUIDs.timeBased()), null, TbMsgDataType.JSON, new byte[4]); | |
58 | 59 | UUID nodeId = UUIDs.timeBased(); |
59 | 60 | ListenableFuture<Void> future = msgRepository.save(msg, nodeId, 2L, 2L, 2L); |
60 | 61 | future.get(); |
... | ... | @@ -67,7 +68,7 @@ public class CassandraMsgRepositoryTest extends AbstractServiceTest { |
67 | 68 | TbMsgMetaData metaData = new TbMsgMetaData(); |
68 | 69 | metaData.putValue("key", "value"); |
69 | 70 | String dataStr = "someContent"; |
70 | - TbMsg msg = new TbMsg(UUIDs.timeBased(), "type", new DeviceId(UUIDs.timeBased()), metaData, dataStr.getBytes()); | |
71 | + TbMsg msg = new TbMsg(UUIDs.timeBased(), "type", new DeviceId(UUIDs.timeBased()), metaData, TbMsgDataType.JSON, dataStr.getBytes()); | |
71 | 72 | UUID nodeId = UUIDs.timeBased(); |
72 | 73 | ListenableFuture<Void> future = msgRepository.save(msg, nodeId, 1L, 1L, 1L); |
73 | 74 | future.get(); | ... | ... |
... | ... | @@ -379,6 +379,11 @@ |
379 | 379 | <version>${project.version}</version> |
380 | 380 | </dependency> |
381 | 381 | <dependency> |
382 | + <groupId>org.thingsboard.rule-engine</groupId> | |
383 | + <artifactId>rule-engine-components</artifactId> | |
384 | + <version>${project.version}</version> | |
385 | + </dependency> | |
386 | + <dependency> | |
382 | 387 | <groupId>org.thingsboard.common</groupId> |
383 | 388 | <artifactId>message</artifactId> |
384 | 389 | <version>${project.version}</version> | ... | ... |
rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/ActionNode.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.rule.engine.api; | |
17 | + | |
18 | +import org.thingsboard.server.common.data.plugin.ComponentScope; | |
19 | +import org.thingsboard.server.extensions.api.component.EmptyComponentConfiguration; | |
20 | + | |
21 | +import java.lang.annotation.ElementType; | |
22 | +import java.lang.annotation.Retention; | |
23 | +import java.lang.annotation.RetentionPolicy; | |
24 | +import java.lang.annotation.Target; | |
25 | + | |
26 | +/** | |
27 | + * @author Andrew Shvayka | |
28 | + */ | |
29 | +@Retention(RetentionPolicy.RUNTIME) | |
30 | +@Target(ElementType.TYPE) | |
31 | +public @interface ActionNode { | |
32 | + | |
33 | + String name(); | |
34 | + | |
35 | + ComponentScope scope() default ComponentScope.TENANT; | |
36 | + | |
37 | + String descriptor() default "EmptyNodeDescriptor.json"; | |
38 | + | |
39 | + String[] relationTypes() default {"Success","Failure"}; | |
40 | + | |
41 | + boolean customRelations() default false; | |
42 | + | |
43 | +} | ... | ... |
rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/EnrichmentNode.java
renamed from
application/src/main/java/org/thingsboard/server/actors/rule/RuleProcessingMsg.java
... | ... | @@ -13,19 +13,30 @@ |
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.actors.rule; | |
16 | +package org.thingsboard.rule.engine.api; | |
17 | 17 | |
18 | -public class RuleProcessingMsg { | |
18 | +import org.thingsboard.server.common.data.plugin.ComponentScope; | |
19 | +import org.thingsboard.server.extensions.api.component.EmptyComponentConfiguration; | |
19 | 20 | |
20 | - private final ChainProcessingContext ctx; | |
21 | +import java.lang.annotation.ElementType; | |
22 | +import java.lang.annotation.Retention; | |
23 | +import java.lang.annotation.RetentionPolicy; | |
24 | +import java.lang.annotation.Target; | |
21 | 25 | |
22 | - public RuleProcessingMsg(ChainProcessingContext ctx) { | |
23 | - super(); | |
24 | - this.ctx = ctx; | |
25 | - } | |
26 | +/** | |
27 | + * @author Andrew Shvayka | |
28 | + */ | |
29 | +@Retention(RetentionPolicy.RUNTIME) | |
30 | +@Target(ElementType.TYPE) | |
31 | +public @interface EnrichmentNode { | |
32 | + | |
33 | + String name(); | |
34 | + | |
35 | + ComponentScope scope() default ComponentScope.TENANT; | |
36 | + | |
37 | + String descriptor() default "EmptyNodeDescriptor.json"; | |
26 | 38 | |
27 | - public ChainProcessingContext getCtx() { | |
28 | - return ctx; | |
29 | - } | |
39 | + String[] relationTypes() default {"Success","Failure"}; | |
30 | 40 | |
41 | + boolean customRelations() default false; | |
31 | 42 | } | ... | ... |
rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/FilterNode.java
renamed from
application/src/main/java/org/thingsboard/server/actors/rule/RuleContextAwareMsgProcessor.java
... | ... | @@ -13,21 +13,31 @@ |
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.actors.rule; | |
16 | +package org.thingsboard.rule.engine.api; | |
17 | 17 | |
18 | -import org.thingsboard.server.actors.ActorSystemContext; | |
19 | -import org.thingsboard.server.actors.shared.AbstractContextAwareMsgProcessor; | |
20 | -import org.thingsboard.server.common.data.id.RuleId; | |
18 | +import org.thingsboard.server.common.data.plugin.ComponentScope; | |
19 | +import org.thingsboard.server.extensions.api.component.EmptyComponentConfiguration; | |
21 | 20 | |
22 | -import akka.event.LoggingAdapter; | |
21 | +import java.lang.annotation.ElementType; | |
22 | +import java.lang.annotation.Retention; | |
23 | +import java.lang.annotation.RetentionPolicy; | |
24 | +import java.lang.annotation.Target; | |
23 | 25 | |
24 | -public class RuleContextAwareMsgProcessor extends AbstractContextAwareMsgProcessor { | |
26 | +/** | |
27 | + * @author Andrew Shvayka | |
28 | + */ | |
29 | +@Retention(RetentionPolicy.RUNTIME) | |
30 | +@Target(ElementType.TYPE) | |
31 | +public @interface FilterNode { | |
32 | + | |
33 | + String name(); | |
34 | + | |
35 | + ComponentScope scope() default ComponentScope.TENANT; | |
36 | + | |
37 | + String descriptor() default "EmptyNodeDescriptor.json"; | |
38 | + | |
39 | + String[] relationTypes() default {"Success","Failure"}; | |
25 | 40 | |
26 | - private final RuleId ruleId; | |
27 | - | |
28 | - protected RuleContextAwareMsgProcessor(ActorSystemContext systemContext, LoggingAdapter logger, RuleId ruleId) { | |
29 | - super(systemContext, logger); | |
30 | - this.ruleId = ruleId; | |
31 | - } | |
41 | + boolean customRelations() default false; | |
32 | 42 | |
33 | 43 | } | ... | ... |
rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TransformationNode.java
renamed from
application/src/main/java/org/thingsboard/server/actors/rule/RuleToPluginTimeoutMsg.java
... | ... | @@ -13,24 +13,31 @@ |
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.actors.rule; | |
16 | +package org.thingsboard.rule.engine.api; | |
17 | 17 | |
18 | -import java.io.Serializable; | |
19 | -import java.util.UUID; | |
18 | +import org.thingsboard.server.common.data.plugin.ComponentScope; | |
19 | +import org.thingsboard.server.extensions.api.component.EmptyComponentConfiguration; | |
20 | 20 | |
21 | -public class RuleToPluginTimeoutMsg implements Serializable { | |
21 | +import java.lang.annotation.ElementType; | |
22 | +import java.lang.annotation.Retention; | |
23 | +import java.lang.annotation.RetentionPolicy; | |
24 | +import java.lang.annotation.Target; | |
22 | 25 | |
23 | - private static final long serialVersionUID = 1L; | |
26 | +/** | |
27 | + * @author Andrew Shvayka | |
28 | + */ | |
29 | +@Retention(RetentionPolicy.RUNTIME) | |
30 | +@Target(ElementType.TYPE) | |
31 | +public @interface TransformationNode { | |
32 | + | |
33 | + String name(); | |
34 | + | |
35 | + ComponentScope scope() default ComponentScope.TENANT; | |
24 | 36 | |
25 | - private final UUID msgId; | |
37 | + String descriptor() default "EmptyNodeDescriptor.json"; | |
26 | 38 | |
27 | - public RuleToPluginTimeoutMsg(UUID msgId) { | |
28 | - super(); | |
29 | - this.msgId = msgId; | |
30 | - } | |
39 | + String[] relationTypes() default {"Success","Failure"}; | |
31 | 40 | |
32 | - public UUID getMsgId() { | |
33 | - return msgId; | |
34 | - } | |
41 | + boolean customRelations() default false; | |
35 | 42 | |
36 | 43 | } | ... | ... |
... | ... | @@ -88,11 +88,6 @@ |
88 | 88 | <artifactId>mockito-all</artifactId> |
89 | 89 | <scope>test</scope> |
90 | 90 | </dependency> |
91 | - <dependency> | |
92 | - <groupId>org.junit.jupiter</groupId> | |
93 | - <artifactId>junit-jupiter-api</artifactId> | |
94 | - <version>RELEASE</version> | |
95 | - </dependency> | |
96 | 91 | |
97 | 92 | <!--<dependency>--> |
98 | 93 | <!--<groupId>org.springframework.boot</groupId>--> | ... | ... |
1 | 1 | /** |
2 | 2 | * Copyright © 2016-2018 The Thingsboard Authors |
3 | - * | |
3 | + * <p> | |
4 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | 5 | * you may not use this file except in compliance with the License. |
6 | 6 | * You may obtain a copy of the License at |
7 | - * | |
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | - * | |
7 | + * <p> | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * <p> | |
10 | 10 | * Unless required by applicable law or agreed to in writing, software |
11 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
... | ... | @@ -15,6 +15,7 @@ |
15 | 15 | */ |
16 | 16 | package org.thingsboard.rule.engine.metadata; |
17 | 17 | |
18 | +import com.google.common.base.Function; | |
18 | 19 | import com.google.common.util.concurrent.AsyncFunction; |
19 | 20 | import com.google.common.util.concurrent.Futures; |
20 | 21 | import com.google.common.util.concurrent.ListenableFuture; |
... | ... | @@ -33,6 +34,7 @@ import static org.thingsboard.server.common.data.DataConstants.*; |
33 | 34 | * Created by ashvayka on 19.01.18. |
34 | 35 | */ |
35 | 36 | @Slf4j |
37 | +@EnrichmentNode(name = "Get Attributes Node") | |
36 | 38 | public class TbGetAttributesNode implements TbNode { |
37 | 39 | |
38 | 40 | private TbGetAttributesNodeConfiguration config; |
... | ... | @@ -52,14 +54,20 @@ public class TbGetAttributesNode implements TbNode { |
52 | 54 | withCallback(future, i -> ctx.tellNext(msg), t -> ctx.tellError(msg, t)); |
53 | 55 | } |
54 | 56 | |
55 | - private ListenableFuture<Void> putAttributesAsync(TbMsg msg, List<AttributeKvEntry> attributes, String prefix) { | |
56 | - attributes.forEach(r -> msg.getMetaData().putValue(prefix + r.getKey(), r.getValueAsString())); | |
57 | - return Futures.immediateFuture(null); | |
57 | + private Void putAttributesAsync(TbMsg msg, List<AttributeKvEntry> attributes, String prefix) { | |
58 | + if (attributes != null) { | |
59 | + attributes.forEach(r -> msg.getMetaData().putValue(prefix + r.getKey(), r.getValueAsString())); | |
60 | + } | |
61 | + return null; | |
58 | 62 | } |
59 | 63 | |
60 | 64 | private ListenableFuture<Void> putAttrAsync(TbContext ctx, TbMsg msg, String scope, List<String> attributes, String prefix) { |
61 | - return Futures.transform(ctx.getAttributesService().find(msg.getOriginator(), scope, attributes), | |
62 | - (AsyncFunction<List<AttributeKvEntry>, Void>) i -> putAttributesAsync(msg, i, prefix)); | |
65 | + if (attributes != null) { | |
66 | + return Futures.transform(ctx.getAttributesService().find(msg.getOriginator(), scope, attributes), | |
67 | + (Function<List<AttributeKvEntry>, Void>) i -> putAttributesAsync(msg, i, prefix)); | |
68 | + } else { | |
69 | + return Futures.immediateFuture(null); | |
70 | + } | |
63 | 71 | } |
64 | 72 | |
65 | 73 | ... | ... |
... | ... | @@ -18,11 +18,13 @@ package org.thingsboard.rule.engine.metadata; |
18 | 18 | import com.google.common.util.concurrent.AsyncFunction; |
19 | 19 | import com.google.common.util.concurrent.Futures; |
20 | 20 | import com.google.common.util.concurrent.ListenableFuture; |
21 | +import org.thingsboard.rule.engine.api.EnrichmentNode; | |
21 | 22 | import org.thingsboard.rule.engine.api.TbContext; |
22 | 23 | import org.thingsboard.rule.engine.api.TbNodeException; |
23 | 24 | import org.thingsboard.server.common.data.HasCustomerId; |
24 | 25 | import org.thingsboard.server.common.data.id.*; |
25 | 26 | |
27 | +@EnrichmentNode(name="Get Customer Attributes Node") | |
26 | 28 | public class TbGetCustomerAttributeNode extends TbEntityGetAttrNode<CustomerId> { |
27 | 29 | |
28 | 30 | @Override | ... | ... |
... | ... | @@ -20,10 +20,7 @@ import com.google.common.util.concurrent.Futures; |
20 | 20 | import com.google.common.util.concurrent.ListenableFuture; |
21 | 21 | import org.apache.commons.collections.CollectionUtils; |
22 | 22 | import org.thingsboard.rule.engine.TbNodeUtils; |
23 | -import org.thingsboard.rule.engine.api.TbContext; | |
24 | -import org.thingsboard.rule.engine.api.TbNodeConfiguration; | |
25 | -import org.thingsboard.rule.engine.api.TbNodeException; | |
26 | -import org.thingsboard.rule.engine.api.TbNodeState; | |
23 | +import org.thingsboard.rule.engine.api.*; | |
27 | 24 | import org.thingsboard.server.common.data.id.EntityId; |
28 | 25 | import org.thingsboard.server.common.data.relation.EntityRelation; |
29 | 26 | import org.thingsboard.server.common.data.relation.EntitySearchDirection; |
... | ... | @@ -33,6 +30,7 @@ import java.util.List; |
33 | 30 | |
34 | 31 | import static org.thingsboard.server.common.data.relation.RelationTypeGroup.COMMON; |
35 | 32 | |
33 | +@EnrichmentNode(name="Get Related Entity Attributes Node") | |
36 | 34 | public class TbGetRelatedAttributeNode extends TbEntityGetAttrNode<EntityId> { |
37 | 35 | |
38 | 36 | private TbGetRelatedAttrNodeConfiguration config; | ... | ... |
... | ... | @@ -19,6 +19,7 @@ import com.google.common.util.concurrent.AsyncFunction; |
19 | 19 | import com.google.common.util.concurrent.Futures; |
20 | 20 | import com.google.common.util.concurrent.ListenableFuture; |
21 | 21 | import lombok.extern.slf4j.Slf4j; |
22 | +import org.thingsboard.rule.engine.api.EnrichmentNode; | |
22 | 23 | import org.thingsboard.rule.engine.api.TbContext; |
23 | 24 | import org.thingsboard.rule.engine.api.TbNodeException; |
24 | 25 | import org.thingsboard.server.common.data.HasTenantId; |
... | ... | @@ -26,6 +27,7 @@ import org.thingsboard.server.common.data.alarm.AlarmId; |
26 | 27 | import org.thingsboard.server.common.data.id.*; |
27 | 28 | |
28 | 29 | @Slf4j |
30 | +@EnrichmentNode(name="Get Tenant Attributes Node") | |
29 | 31 | public class TbGetTenantAttributeNode extends TbEntityGetAttrNode<TenantId> { |
30 | 32 | |
31 | 33 | @Override |
... | ... | @@ -38,8 +40,6 @@ public class TbGetTenantAttributeNode extends TbEntityGetAttrNode<TenantId> { |
38 | 40 | return getTenantAsync(ctx.getCustomerService().findCustomerByIdAsync((CustomerId) originator)); |
39 | 41 | case USER: |
40 | 42 | return getTenantAsync(ctx.getUserService().findUserByIdAsync((UserId) originator)); |
41 | - case RULE: | |
42 | - return getTenantAsync(ctx.getRuleService().findRuleByIdAsync((RuleId) originator)); | |
43 | 43 | case PLUGIN: |
44 | 44 | return getTenantAsync(ctx.getPluginService().findPluginByIdAsync((PluginId) originator)); |
45 | 45 | case ASSET: | ... | ... |
... | ... | @@ -85,8 +85,7 @@ public class TbGetCustomerAttributeNodeTest { |
85 | 85 | config.setAttrMapping(attrMapping); |
86 | 86 | config.setTelemetry(false); |
87 | 87 | ObjectMapper mapper = new ObjectMapper(); |
88 | - TbNodeConfiguration nodeConfiguration = new TbNodeConfiguration(); | |
89 | - nodeConfiguration.setData(mapper.valueToTree(config)); | |
88 | + TbNodeConfiguration nodeConfiguration = new TbNodeConfiguration(mapper.valueToTree(config)); | |
90 | 89 | |
91 | 90 | node = new TbGetCustomerAttributeNode(); |
92 | 91 | node.init(nodeConfiguration, null); |
... | ... | @@ -224,8 +223,7 @@ public class TbGetCustomerAttributeNodeTest { |
224 | 223 | config.setAttrMapping(attrMapping); |
225 | 224 | config.setTelemetry(true); |
226 | 225 | ObjectMapper mapper = new ObjectMapper(); |
227 | - TbNodeConfiguration nodeConfiguration = new TbNodeConfiguration(); | |
228 | - nodeConfiguration.setData(mapper.valueToTree(config)); | |
226 | + TbNodeConfiguration nodeConfiguration = new TbNodeConfiguration(mapper.valueToTree(config)); | |
229 | 227 | |
230 | 228 | node = new TbGetCustomerAttributeNode(); |
231 | 229 | node.init(nodeConfiguration, null); | ... | ... |