Commit 72682dbfb889785589ec8f8c75f025e6ad0d2789
Merge branch 'develop/1.5' of github.com:thingsboard/thingsboard into develop/1.5
Showing
67 changed files
with
1968 additions
and
1276 deletions
Too many changes to show.
To preserve performance only 67 of 336 files are displayed.
@@ -54,6 +54,14 @@ | @@ -54,6 +54,14 @@ | ||
54 | <artifactId>extensions-api</artifactId> | 54 | <artifactId>extensions-api</artifactId> |
55 | </dependency> | 55 | </dependency> |
56 | <dependency> | 56 | <dependency> |
57 | + <groupId>org.thingsboard.rule-engine</groupId> | ||
58 | + <artifactId>rule-engine-api</artifactId> | ||
59 | + </dependency> | ||
60 | + <dependency> | ||
61 | + <groupId>org.thingsboard.rule-engine</groupId> | ||
62 | + <artifactId>rule-engine-components</artifactId> | ||
63 | + </dependency> | ||
64 | + <dependency> | ||
57 | <groupId>org.thingsboard</groupId> | 65 | <groupId>org.thingsboard</groupId> |
58 | <artifactId>extensions-core</artifactId> | 66 | <artifactId>extensions-core</artifactId> |
59 | </dependency> | 67 | </dependency> |
@@ -69,6 +69,7 @@ CREATE TABLE IF NOT EXISTS thingsboard.rule_chain ( | @@ -69,6 +69,7 @@ CREATE TABLE IF NOT EXISTS thingsboard.rule_chain ( | ||
69 | search_text text, | 69 | search_text text, |
70 | first_rule_node_id uuid, | 70 | first_rule_node_id uuid, |
71 | root boolean, | 71 | root boolean, |
72 | + debug_mode boolean, | ||
72 | configuration text, | 73 | configuration text, |
73 | additional_info text, | 74 | additional_info text, |
74 | PRIMARY KEY (id, tenant_id) | 75 | PRIMARY KEY (id, tenant_id) |
@@ -85,9 +86,12 @@ CREATE TABLE IF NOT EXISTS thingsboard.rule_node ( | @@ -85,9 +86,12 @@ CREATE TABLE IF NOT EXISTS thingsboard.rule_node ( | ||
85 | id uuid, | 86 | id uuid, |
86 | type text, | 87 | type text, |
87 | name text, | 88 | name text, |
89 | + debug_mode boolean, | ||
88 | search_text text, | 90 | search_text text, |
89 | configuration text, | 91 | configuration text, |
90 | additional_info text, | 92 | additional_info text, |
91 | PRIMARY KEY (id) | 93 | PRIMARY KEY (id) |
92 | ); | 94 | ); |
93 | 95 | ||
96 | +ALTER TABLE thingsboard.device ADD last_connect bigint; | ||
97 | +ALTER TABLE thingsboard.device ADD last_update bigint; |
@@ -21,6 +21,7 @@ CREATE TABLE IF NOT EXISTS rule_chain ( | @@ -21,6 +21,7 @@ CREATE TABLE IF NOT EXISTS rule_chain ( | ||
21 | name varchar(255), | 21 | name varchar(255), |
22 | first_rule_node_id varchar(31), | 22 | first_rule_node_id varchar(31), |
23 | root boolean, | 23 | root boolean, |
24 | + debug_mode boolean, | ||
24 | search_text varchar(255), | 25 | search_text varchar(255), |
25 | tenant_id varchar(31) | 26 | tenant_id varchar(31) |
26 | ); | 27 | ); |
@@ -31,5 +32,9 @@ CREATE TABLE IF NOT EXISTS rule_node ( | @@ -31,5 +32,9 @@ CREATE TABLE IF NOT EXISTS rule_node ( | ||
31 | configuration varchar(10000000), | 32 | configuration varchar(10000000), |
32 | type varchar(255), | 33 | type varchar(255), |
33 | name varchar(255), | 34 | name varchar(255), |
35 | + debug_mode boolean, | ||
34 | search_text varchar(255) | 36 | search_text varchar(255) |
35 | -); | ||
37 | +); | ||
38 | + | ||
39 | +ALTER TABLE device ADD COLUMN IF NOT EXISTS last_connect BIGINT; | ||
40 | +ALTER TABLE device ADD COLUMN IF NOT EXISTS last_update BIGINT; |
@@ -19,6 +19,7 @@ import org.springframework.boot.SpringApplication; | @@ -19,6 +19,7 @@ import org.springframework.boot.SpringApplication; | ||
19 | import org.springframework.boot.SpringBootConfiguration; | 19 | import org.springframework.boot.SpringBootConfiguration; |
20 | import org.springframework.context.annotation.ComponentScan; | 20 | import org.springframework.context.annotation.ComponentScan; |
21 | import org.springframework.scheduling.annotation.EnableAsync; | 21 | import org.springframework.scheduling.annotation.EnableAsync; |
22 | +import org.springframework.scheduling.annotation.EnableScheduling; | ||
22 | import springfox.documentation.swagger2.annotations.EnableSwagger2; | 23 | import springfox.documentation.swagger2.annotations.EnableSwagger2; |
23 | 24 | ||
24 | import java.util.Arrays; | 25 | import java.util.Arrays; |
@@ -26,6 +27,7 @@ import java.util.Arrays; | @@ -26,6 +27,7 @@ import java.util.Arrays; | ||
26 | @SpringBootConfiguration | 27 | @SpringBootConfiguration |
27 | @EnableAsync | 28 | @EnableAsync |
28 | @EnableSwagger2 | 29 | @EnableSwagger2 |
30 | +@EnableScheduling | ||
29 | @ComponentScan({"org.thingsboard.server"}) | 31 | @ComponentScan({"org.thingsboard.server"}) |
30 | public class ThingsboardServerApplication { | 32 | public class ThingsboardServerApplication { |
31 | 33 |
@@ -25,15 +25,19 @@ import com.typesafe.config.Config; | @@ -25,15 +25,19 @@ import com.typesafe.config.Config; | ||
25 | import com.typesafe.config.ConfigFactory; | 25 | import com.typesafe.config.ConfigFactory; |
26 | import lombok.Getter; | 26 | import lombok.Getter; |
27 | import lombok.Setter; | 27 | import lombok.Setter; |
28 | +import lombok.extern.slf4j.Slf4j; | ||
28 | import org.springframework.beans.factory.annotation.Autowired; | 29 | import org.springframework.beans.factory.annotation.Autowired; |
29 | import org.springframework.beans.factory.annotation.Value; | 30 | import org.springframework.beans.factory.annotation.Value; |
30 | import org.springframework.stereotype.Component; | 31 | import org.springframework.stereotype.Component; |
32 | +import org.thingsboard.rule.engine.api.ListeningExecutor; | ||
33 | +import org.thingsboard.rule.engine.api.MailService; | ||
31 | import org.thingsboard.server.actors.service.ActorService; | 34 | import org.thingsboard.server.actors.service.ActorService; |
32 | import org.thingsboard.server.common.data.DataConstants; | 35 | import org.thingsboard.server.common.data.DataConstants; |
33 | import org.thingsboard.server.common.data.Event; | 36 | import org.thingsboard.server.common.data.Event; |
34 | import org.thingsboard.server.common.data.id.EntityId; | 37 | import org.thingsboard.server.common.data.id.EntityId; |
35 | import org.thingsboard.server.common.data.id.TenantId; | 38 | import org.thingsboard.server.common.data.id.TenantId; |
36 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; | 39 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; |
40 | +import org.thingsboard.server.common.msg.TbMsg; | ||
37 | import org.thingsboard.server.common.msg.cluster.ServerAddress; | 41 | import org.thingsboard.server.common.msg.cluster.ServerAddress; |
38 | import org.thingsboard.server.common.transport.auth.DeviceAuthService; | 42 | import org.thingsboard.server.common.transport.auth.DeviceAuthService; |
39 | import org.thingsboard.server.controller.plugin.PluginWebSocketMsgEndpoint; | 43 | import org.thingsboard.server.controller.plugin.PluginWebSocketMsgEndpoint; |
@@ -46,116 +50,200 @@ import org.thingsboard.server.dao.device.DeviceService; | @@ -46,116 +50,200 @@ import org.thingsboard.server.dao.device.DeviceService; | ||
46 | import org.thingsboard.server.dao.event.EventService; | 50 | import org.thingsboard.server.dao.event.EventService; |
47 | import org.thingsboard.server.dao.plugin.PluginService; | 51 | import org.thingsboard.server.dao.plugin.PluginService; |
48 | import org.thingsboard.server.dao.relation.RelationService; | 52 | import org.thingsboard.server.dao.relation.RelationService; |
53 | +import org.thingsboard.server.dao.rule.RuleChainService; | ||
49 | import org.thingsboard.server.dao.rule.RuleService; | 54 | import org.thingsboard.server.dao.rule.RuleService; |
50 | import org.thingsboard.server.dao.tenant.TenantService; | 55 | import org.thingsboard.server.dao.tenant.TenantService; |
51 | import org.thingsboard.server.dao.timeseries.TimeseriesService; | 56 | import org.thingsboard.server.dao.timeseries.TimeseriesService; |
57 | +import org.thingsboard.server.dao.user.UserService; | ||
52 | import org.thingsboard.server.service.cluster.discovery.DiscoveryService; | 58 | import org.thingsboard.server.service.cluster.discovery.DiscoveryService; |
53 | import org.thingsboard.server.service.cluster.routing.ClusterRoutingService; | 59 | import org.thingsboard.server.service.cluster.routing.ClusterRoutingService; |
54 | import org.thingsboard.server.service.cluster.rpc.ClusterRpcService; | 60 | import org.thingsboard.server.service.cluster.rpc.ClusterRpcService; |
55 | import org.thingsboard.server.service.component.ComponentDiscoveryService; | 61 | import org.thingsboard.server.service.component.ComponentDiscoveryService; |
62 | +import org.thingsboard.server.service.executors.DbCallbackExecutorService; | ||
63 | +import org.thingsboard.server.service.mail.MailExecutorService; | ||
64 | +import org.thingsboard.server.service.script.JsExecutorService; | ||
65 | +import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService; | ||
56 | 66 | ||
67 | +import java.io.IOException; | ||
57 | import java.io.PrintWriter; | 68 | import java.io.PrintWriter; |
58 | import java.io.StringWriter; | 69 | import java.io.StringWriter; |
59 | import java.util.Optional; | 70 | import java.util.Optional; |
60 | 71 | ||
72 | +@Slf4j | ||
61 | @Component | 73 | @Component |
62 | public class ActorSystemContext { | 74 | public class ActorSystemContext { |
63 | private static final String AKKA_CONF_FILE_NAME = "actor-system.conf"; | 75 | private static final String AKKA_CONF_FILE_NAME = "actor-system.conf"; |
64 | 76 | ||
65 | protected final ObjectMapper mapper = new ObjectMapper(); | 77 | protected final ObjectMapper mapper = new ObjectMapper(); |
66 | 78 | ||
67 | - @Getter @Setter private ActorService actorService; | 79 | + @Getter |
80 | + @Setter | ||
81 | + private ActorService actorService; | ||
68 | 82 | ||
69 | @Autowired | 83 | @Autowired |
70 | - @Getter private DiscoveryService discoveryService; | 84 | + @Getter |
85 | + private DiscoveryService discoveryService; | ||
71 | 86 | ||
72 | @Autowired | 87 | @Autowired |
73 | - @Getter @Setter private ComponentDiscoveryService componentService; | 88 | + @Getter |
89 | + @Setter | ||
90 | + private ComponentDiscoveryService componentService; | ||
74 | 91 | ||
75 | @Autowired | 92 | @Autowired |
76 | - @Getter private ClusterRoutingService routingService; | 93 | + @Getter |
94 | + private ClusterRoutingService routingService; | ||
77 | 95 | ||
78 | @Autowired | 96 | @Autowired |
79 | - @Getter private ClusterRpcService rpcService; | 97 | + @Getter |
98 | + private ClusterRpcService rpcService; | ||
80 | 99 | ||
81 | @Autowired | 100 | @Autowired |
82 | - @Getter private DeviceAuthService deviceAuthService; | 101 | + @Getter |
102 | + private DeviceAuthService deviceAuthService; | ||
83 | 103 | ||
84 | @Autowired | 104 | @Autowired |
85 | - @Getter private DeviceService deviceService; | 105 | + @Getter |
106 | + private DeviceService deviceService; | ||
86 | 107 | ||
87 | @Autowired | 108 | @Autowired |
88 | - @Getter private AssetService assetService; | 109 | + @Getter |
110 | + private AssetService assetService; | ||
89 | 111 | ||
90 | @Autowired | 112 | @Autowired |
91 | - @Getter private TenantService tenantService; | 113 | + @Getter |
114 | + private TenantService tenantService; | ||
92 | 115 | ||
93 | @Autowired | 116 | @Autowired |
94 | - @Getter private CustomerService customerService; | 117 | + @Getter |
118 | + private CustomerService customerService; | ||
95 | 119 | ||
96 | @Autowired | 120 | @Autowired |
97 | - @Getter private RuleService ruleService; | 121 | + @Getter |
122 | + private UserService userService; | ||
98 | 123 | ||
99 | @Autowired | 124 | @Autowired |
100 | - @Getter private PluginService pluginService; | 125 | + @Getter |
126 | + private RuleService ruleService; | ||
101 | 127 | ||
102 | @Autowired | 128 | @Autowired |
103 | - @Getter private TimeseriesService tsService; | 129 | + @Getter |
130 | + private RuleChainService ruleChainService; | ||
104 | 131 | ||
105 | @Autowired | 132 | @Autowired |
106 | - @Getter private AttributesService attributesService; | 133 | + @Getter |
134 | + private PluginService pluginService; | ||
107 | 135 | ||
108 | @Autowired | 136 | @Autowired |
109 | - @Getter private EventService eventService; | 137 | + @Getter |
138 | + private TimeseriesService tsService; | ||
110 | 139 | ||
111 | @Autowired | 140 | @Autowired |
112 | - @Getter private AlarmService alarmService; | 141 | + @Getter |
142 | + private AttributesService attributesService; | ||
113 | 143 | ||
114 | @Autowired | 144 | @Autowired |
115 | - @Getter private RelationService relationService; | 145 | + @Getter |
146 | + private EventService eventService; | ||
116 | 147 | ||
117 | @Autowired | 148 | @Autowired |
118 | - @Getter private AuditLogService auditLogService; | 149 | + @Getter |
150 | + private AlarmService alarmService; | ||
119 | 151 | ||
120 | @Autowired | 152 | @Autowired |
121 | - @Getter @Setter private PluginWebSocketMsgEndpoint wsMsgEndpoint; | 153 | + @Getter |
154 | + private RelationService relationService; | ||
155 | + | ||
156 | + @Autowired | ||
157 | + @Getter | ||
158 | + private AuditLogService auditLogService; | ||
159 | + | ||
160 | + @Autowired | ||
161 | + @Getter | ||
162 | + private TelemetrySubscriptionService tsSubService; | ||
163 | + | ||
164 | + @Autowired | ||
165 | + @Getter | ||
166 | + @Setter | ||
167 | + private PluginWebSocketMsgEndpoint wsMsgEndpoint; | ||
168 | + | ||
169 | + @Autowired | ||
170 | + @Getter | ||
171 | + private JsExecutorService jsExecutor; | ||
172 | + | ||
173 | + @Autowired | ||
174 | + @Getter | ||
175 | + private MailExecutorService mailExecutor; | ||
176 | + | ||
177 | + @Autowired | ||
178 | + @Getter | ||
179 | + private DbCallbackExecutorService dbCallbackExecutor; | ||
180 | + | ||
181 | + @Autowired | ||
182 | + @Getter | ||
183 | + private MailService mailService; | ||
122 | 184 | ||
123 | @Value("${actors.session.sync.timeout}") | 185 | @Value("${actors.session.sync.timeout}") |
124 | - @Getter private long syncSessionTimeout; | 186 | + @Getter |
187 | + private long syncSessionTimeout; | ||
125 | 188 | ||
126 | @Value("${actors.plugin.termination.delay}") | 189 | @Value("${actors.plugin.termination.delay}") |
127 | - @Getter private long pluginActorTerminationDelay; | 190 | + @Getter |
191 | + private long pluginActorTerminationDelay; | ||
128 | 192 | ||
129 | @Value("${actors.plugin.processing.timeout}") | 193 | @Value("${actors.plugin.processing.timeout}") |
130 | - @Getter private long pluginProcessingTimeout; | 194 | + @Getter |
195 | + private long pluginProcessingTimeout; | ||
131 | 196 | ||
132 | @Value("${actors.plugin.error_persist_frequency}") | 197 | @Value("${actors.plugin.error_persist_frequency}") |
133 | - @Getter private long pluginErrorPersistFrequency; | 198 | + @Getter |
199 | + private long pluginErrorPersistFrequency; | ||
200 | + | ||
201 | + @Value("${actors.rule.chain.error_persist_frequency}") | ||
202 | + @Getter | ||
203 | + private long ruleChainErrorPersistFrequency; | ||
204 | + | ||
205 | + @Value("${actors.rule.node.error_persist_frequency}") | ||
206 | + @Getter | ||
207 | + private long ruleNodeErrorPersistFrequency; | ||
134 | 208 | ||
135 | @Value("${actors.rule.termination.delay}") | 209 | @Value("${actors.rule.termination.delay}") |
136 | - @Getter private long ruleActorTerminationDelay; | 210 | + @Getter |
211 | + private long ruleActorTerminationDelay; | ||
137 | 212 | ||
138 | @Value("${actors.rule.error_persist_frequency}") | 213 | @Value("${actors.rule.error_persist_frequency}") |
139 | - @Getter private long ruleErrorPersistFrequency; | 214 | + @Getter |
215 | + private long ruleErrorPersistFrequency; | ||
140 | 216 | ||
141 | @Value("${actors.statistics.enabled}") | 217 | @Value("${actors.statistics.enabled}") |
142 | - @Getter private boolean statisticsEnabled; | 218 | + @Getter |
219 | + private boolean statisticsEnabled; | ||
143 | 220 | ||
144 | @Value("${actors.statistics.persist_frequency}") | 221 | @Value("${actors.statistics.persist_frequency}") |
145 | - @Getter private long statisticsPersistFrequency; | 222 | + @Getter |
223 | + private long statisticsPersistFrequency; | ||
146 | 224 | ||
147 | @Value("${actors.tenant.create_components_on_init}") | 225 | @Value("${actors.tenant.create_components_on_init}") |
148 | - @Getter private boolean tenantComponentsInitEnabled; | 226 | + @Getter |
227 | + private boolean tenantComponentsInitEnabled; | ||
149 | 228 | ||
150 | - @Getter @Setter private ActorSystem actorSystem; | 229 | + @Getter |
230 | + @Setter | ||
231 | + private ActorSystem actorSystem; | ||
151 | 232 | ||
152 | - @Getter @Setter private ActorRef appActor; | 233 | + @Getter |
234 | + @Setter | ||
235 | + private ActorRef appActor; | ||
153 | 236 | ||
154 | - @Getter @Setter private ActorRef sessionManagerActor; | 237 | + @Getter |
238 | + @Setter | ||
239 | + private ActorRef sessionManagerActor; | ||
155 | 240 | ||
156 | - @Getter @Setter private ActorRef statsActor; | 241 | + @Getter |
242 | + @Setter | ||
243 | + private ActorRef statsActor; | ||
157 | 244 | ||
158 | - @Getter private final Config config; | 245 | + @Getter |
246 | + private final Config config; | ||
159 | 247 | ||
160 | public ActorSystemContext() { | 248 | public ActorSystemContext() { |
161 | config = ConfigFactory.parseResources(AKKA_CONF_FILE_NAME).withFallback(ConfigFactory.load()); | 249 | config = ConfigFactory.parseResources(AKKA_CONF_FILE_NAME).withFallback(ConfigFactory.load()); |
@@ -187,7 +275,7 @@ public class ActorSystemContext { | @@ -187,7 +275,7 @@ public class ActorSystemContext { | ||
187 | eventService.save(event); | 275 | eventService.save(event); |
188 | } | 276 | } |
189 | 277 | ||
190 | - private String toString(Exception e) { | 278 | + private String toString(Throwable e) { |
191 | StringWriter sw = new StringWriter(); | 279 | StringWriter sw = new StringWriter(); |
192 | e.printStackTrace(new PrintWriter(sw)); | 280 | e.printStackTrace(new PrintWriter(sw)); |
193 | return sw.toString(); | 281 | return sw.toString(); |
@@ -207,4 +295,60 @@ public class ActorSystemContext { | @@ -207,4 +295,60 @@ public class ActorSystemContext { | ||
207 | private JsonNode toBodyJson(ServerAddress server, String method, String body) { | 295 | private JsonNode toBodyJson(ServerAddress server, String method, String body) { |
208 | return mapper.createObjectNode().put("server", server.toString()).put("method", method).put("error", body); | 296 | return mapper.createObjectNode().put("server", server.toString()).put("method", method).put("error", body); |
209 | } | 297 | } |
298 | + | ||
299 | + public String getServerAddress() { | ||
300 | + return discoveryService.getCurrentServer().getServerAddress().toString(); | ||
301 | + } | ||
302 | + | ||
303 | + public void persistDebugInput(TenantId tenantId, EntityId entityId, TbMsg tbMsg) { | ||
304 | + persistDebug(tenantId, entityId, "IN", tbMsg, null); | ||
305 | + } | ||
306 | + | ||
307 | + public void persistDebugInput(TenantId tenantId, EntityId entityId, TbMsg tbMsg, Throwable error) { | ||
308 | + persistDebug(tenantId, entityId, "IN", tbMsg, error); | ||
309 | + } | ||
310 | + | ||
311 | + public void persistDebugOutput(TenantId tenantId, EntityId entityId, TbMsg tbMsg, Throwable error) { | ||
312 | + persistDebug(tenantId, entityId, "OUT", tbMsg, error); | ||
313 | + } | ||
314 | + | ||
315 | + public void persistDebugOutput(TenantId tenantId, EntityId entityId, TbMsg tbMsg) { | ||
316 | + persistDebug(tenantId, entityId, "OUT", tbMsg, null); | ||
317 | + } | ||
318 | + | ||
319 | + private void persistDebug(TenantId tenantId, EntityId entityId, String type, TbMsg tbMsg, Throwable error) { | ||
320 | + try { | ||
321 | + Event event = new Event(); | ||
322 | + event.setTenantId(tenantId); | ||
323 | + event.setEntityId(entityId); | ||
324 | + event.setType(DataConstants.DEBUG_RULE_NODE); | ||
325 | + | ||
326 | + String metadata = mapper.writeValueAsString(tbMsg.getMetaData().getData()); | ||
327 | + | ||
328 | + ObjectNode node = mapper.createObjectNode() | ||
329 | + .put("type", type) | ||
330 | + .put("server", getServerAddress()) | ||
331 | + .put("entityId", tbMsg.getOriginator().getId().toString()) | ||
332 | + .put("entityName", tbMsg.getOriginator().getEntityType().name()) | ||
333 | + .put("msgId", tbMsg.getId().toString()) | ||
334 | + .put("msgType", tbMsg.getType()) | ||
335 | + .put("dataType", tbMsg.getDataType().name()) | ||
336 | + .put("data", tbMsg.getData()) | ||
337 | + .put("metadata", metadata); | ||
338 | + | ||
339 | + if (error != null) { | ||
340 | + node = node.put("error", toString(error)); | ||
341 | + } | ||
342 | + | ||
343 | + event.setBody(node); | ||
344 | + eventService.save(event); | ||
345 | + } catch (IOException ex) { | ||
346 | + log.warn("Failed to persist rule node debug message", ex); | ||
347 | + } | ||
348 | + } | ||
349 | + | ||
350 | + public static Exception toException(Throwable error) { | ||
351 | + return Exception.class.isInstance(error) ? (Exception) error : new Exception(error); | ||
352 | + } | ||
353 | + | ||
210 | } | 354 | } |
@@ -22,48 +22,41 @@ import akka.event.LoggingAdapter; | @@ -22,48 +22,41 @@ import akka.event.LoggingAdapter; | ||
22 | import akka.japi.Function; | 22 | import akka.japi.Function; |
23 | import org.thingsboard.server.actors.ActorSystemContext; | 23 | import org.thingsboard.server.actors.ActorSystemContext; |
24 | import org.thingsboard.server.actors.plugin.PluginTerminationMsg; | 24 | import org.thingsboard.server.actors.plugin.PluginTerminationMsg; |
25 | -import org.thingsboard.server.actors.service.ContextAwareActor; | 25 | +import org.thingsboard.server.actors.ruleChain.RuleChainManagerActor; |
26 | import org.thingsboard.server.actors.service.ContextBasedCreator; | 26 | import org.thingsboard.server.actors.service.ContextBasedCreator; |
27 | import org.thingsboard.server.actors.service.DefaultActorService; | 27 | import org.thingsboard.server.actors.service.DefaultActorService; |
28 | -import org.thingsboard.server.actors.shared.plugin.PluginManager; | ||
29 | import org.thingsboard.server.actors.shared.plugin.SystemPluginManager; | 28 | import org.thingsboard.server.actors.shared.plugin.SystemPluginManager; |
30 | -import org.thingsboard.server.actors.shared.rule.RuleManager; | ||
31 | -import org.thingsboard.server.actors.shared.rule.SystemRuleManager; | ||
32 | -import org.thingsboard.server.actors.tenant.RuleChainDeviceMsg; | 29 | +import org.thingsboard.server.actors.shared.rulechain.SystemRuleChainManager; |
33 | import org.thingsboard.server.actors.tenant.TenantActor; | 30 | import org.thingsboard.server.actors.tenant.TenantActor; |
34 | import org.thingsboard.server.common.data.Tenant; | 31 | import org.thingsboard.server.common.data.Tenant; |
35 | import org.thingsboard.server.common.data.id.PluginId; | 32 | import org.thingsboard.server.common.data.id.PluginId; |
36 | -import org.thingsboard.server.common.data.id.RuleId; | 33 | +import org.thingsboard.server.common.data.id.RuleChainId; |
37 | import org.thingsboard.server.common.data.id.TenantId; | 34 | import org.thingsboard.server.common.data.id.TenantId; |
38 | import org.thingsboard.server.common.data.page.PageDataIterable; | 35 | import org.thingsboard.server.common.data.page.PageDataIterable; |
36 | +import org.thingsboard.server.common.msg.TbActorMsg; | ||
39 | import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; | 37 | import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; |
40 | import org.thingsboard.server.common.msg.device.ToDeviceActorMsg; | 38 | import org.thingsboard.server.common.msg.device.ToDeviceActorMsg; |
41 | import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; | 39 | import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; |
40 | +import org.thingsboard.server.common.msg.system.ServiceToRuleEngineMsg; | ||
42 | import org.thingsboard.server.dao.model.ModelConstants; | 41 | import org.thingsboard.server.dao.model.ModelConstants; |
43 | import org.thingsboard.server.dao.tenant.TenantService; | 42 | import org.thingsboard.server.dao.tenant.TenantService; |
44 | import org.thingsboard.server.extensions.api.device.ToDeviceActorNotificationMsg; | 43 | import org.thingsboard.server.extensions.api.device.ToDeviceActorNotificationMsg; |
45 | import org.thingsboard.server.extensions.api.plugins.msg.ToPluginActorMsg; | 44 | import org.thingsboard.server.extensions.api.plugins.msg.ToPluginActorMsg; |
46 | -import org.thingsboard.server.extensions.api.rules.ToRuleActorMsg; | ||
47 | import scala.concurrent.duration.Duration; | 45 | import scala.concurrent.duration.Duration; |
48 | 46 | ||
49 | import java.util.HashMap; | 47 | import java.util.HashMap; |
50 | import java.util.Map; | 48 | import java.util.Map; |
51 | -import java.util.Optional; | ||
52 | 49 | ||
53 | -public class AppActor extends ContextAwareActor { | 50 | +public class AppActor extends RuleChainManagerActor { |
54 | 51 | ||
55 | private final LoggingAdapter logger = Logging.getLogger(getContext().system(), this); | 52 | private final LoggingAdapter logger = Logging.getLogger(getContext().system(), this); |
56 | 53 | ||
57 | public static final TenantId SYSTEM_TENANT = new TenantId(ModelConstants.NULL_UUID); | 54 | public static final TenantId SYSTEM_TENANT = new TenantId(ModelConstants.NULL_UUID); |
58 | - private final RuleManager ruleManager; | ||
59 | - private final PluginManager pluginManager; | ||
60 | private final TenantService tenantService; | 55 | private final TenantService tenantService; |
61 | private final Map<TenantId, ActorRef> tenantActors; | 56 | private final Map<TenantId, ActorRef> tenantActors; |
62 | 57 | ||
63 | private AppActor(ActorSystemContext systemContext) { | 58 | private AppActor(ActorSystemContext systemContext) { |
64 | - super(systemContext); | ||
65 | - this.ruleManager = new SystemRuleManager(systemContext); | ||
66 | - this.pluginManager = new SystemPluginManager(systemContext); | 59 | + super(systemContext, new SystemRuleChainManager(systemContext), new SystemPluginManager(systemContext)); |
67 | this.tenantService = systemContext.getTenantService(); | 60 | this.tenantService = systemContext.getTenantService(); |
68 | this.tenantActors = new HashMap<>(); | 61 | this.tenantActors = new HashMap<>(); |
69 | } | 62 | } |
@@ -77,8 +70,7 @@ public class AppActor extends ContextAwareActor { | @@ -77,8 +70,7 @@ public class AppActor extends ContextAwareActor { | ||
77 | public void preStart() { | 70 | public void preStart() { |
78 | logger.info("Starting main system actor."); | 71 | logger.info("Starting main system actor."); |
79 | try { | 72 | try { |
80 | - ruleManager.init(this.context()); | ||
81 | - pluginManager.init(this.context()); | 73 | + initRuleChains(); |
82 | 74 | ||
83 | if (systemContext.isTenantComponentsInitEnabled()) { | 75 | if (systemContext.isTenantComponentsInitEnabled()) { |
84 | PageDataIterable<Tenant> tenantIterator = new PageDataIterable<>(tenantService::findTenants, ENTITY_PACK_LIMIT); | 76 | PageDataIterable<Tenant> tenantIterator = new PageDataIterable<>(tenantService::findTenants, ENTITY_PACK_LIMIT); |
@@ -96,29 +88,51 @@ public class AppActor extends ContextAwareActor { | @@ -96,29 +88,51 @@ public class AppActor extends ContextAwareActor { | ||
96 | } | 88 | } |
97 | 89 | ||
98 | @Override | 90 | @Override |
99 | - public void onReceive(Object msg) throws Exception { | ||
100 | - logger.debug("Received message: {}", msg); | ||
101 | - if (msg instanceof ToDeviceActorMsg) { | ||
102 | - processDeviceMsg((ToDeviceActorMsg) msg); | ||
103 | - } else if (msg instanceof ToPluginActorMsg) { | ||
104 | - onToPluginMsg((ToPluginActorMsg) msg); | ||
105 | - } else if (msg instanceof ToRuleActorMsg) { | ||
106 | - onToRuleMsg((ToRuleActorMsg) msg); | ||
107 | - } else if (msg instanceof ToDeviceActorNotificationMsg) { | ||
108 | - onToDeviceActorMsg((ToDeviceActorNotificationMsg) msg); | ||
109 | - } else if (msg instanceof Terminated) { | ||
110 | - processTermination((Terminated) msg); | ||
111 | - } else if (msg instanceof ClusterEventMsg) { | ||
112 | - broadcast(msg); | ||
113 | - } else if (msg instanceof ComponentLifecycleMsg) { | ||
114 | - onComponentLifecycleMsg((ComponentLifecycleMsg) msg); | ||
115 | - } else if (msg instanceof PluginTerminationMsg) { | ||
116 | - onPluginTerminated((PluginTerminationMsg) msg); | 91 | + protected boolean process(TbActorMsg msg) { |
92 | + switch (msg.getMsgType()) { | ||
93 | + case COMPONENT_LIFE_CYCLE_MSG: | ||
94 | + onComponentLifecycleMsg((ComponentLifecycleMsg) msg); | ||
95 | + break; | ||
96 | + case SERVICE_TO_RULE_ENGINE_MSG: | ||
97 | + onServiceToRuleEngineMsg((ServiceToRuleEngineMsg) msg); | ||
98 | + break; | ||
99 | + default: | ||
100 | + return false; | ||
101 | + } | ||
102 | + return true; | ||
103 | + } | ||
104 | + | ||
105 | + private void onServiceToRuleEngineMsg(ServiceToRuleEngineMsg msg) { | ||
106 | + if (SYSTEM_TENANT.equals(msg.getTenantId())) { | ||
107 | + //TODO: ashvayka handle this. | ||
117 | } else { | 108 | } else { |
118 | - logger.warning("Unknown message: {}!", msg); | 109 | + getOrCreateTenantActor(msg.getTenantId()).tell(msg, self()); |
119 | } | 110 | } |
120 | } | 111 | } |
121 | 112 | ||
113 | + | ||
114 | +// @Override | ||
115 | +// public void onReceive(Object msg) throws Exception { | ||
116 | +// logger.debug("Received message: {}", msg); | ||
117 | +// if (msg instanceof ToDeviceActorMsg) { | ||
118 | +// processDeviceMsg((ToDeviceActorMsg) msg); | ||
119 | +// } else if (msg instanceof ToPluginActorMsg) { | ||
120 | +// onToPluginMsg((ToPluginActorMsg) msg); | ||
121 | +// } else if (msg instanceof ToDeviceActorNotificationMsg) { | ||
122 | +// onToDeviceActorMsg((ToDeviceActorNotificationMsg) msg); | ||
123 | +// } else if (msg instanceof Terminated) { | ||
124 | +// processTermination((Terminated) msg); | ||
125 | +// } else if (msg instanceof ClusterEventMsg) { | ||
126 | +// broadcast(msg); | ||
127 | +// } else if (msg instanceof ComponentLifecycleMsg) { | ||
128 | +// onComponentLifecycleMsg((ComponentLifecycleMsg) msg); | ||
129 | +// } else if (msg instanceof PluginTerminationMsg) { | ||
130 | +// onPluginTerminated((PluginTerminationMsg) msg); | ||
131 | +// } else { | ||
132 | +// logger.warning("Unknown message: {}!", msg); | ||
133 | +// } | ||
134 | +// } | ||
135 | + | ||
122 | private void onPluginTerminated(PluginTerminationMsg msg) { | 136 | private void onPluginTerminated(PluginTerminationMsg msg) { |
123 | pluginManager.remove(msg.getId()); | 137 | pluginManager.remove(msg.getId()); |
124 | } | 138 | } |
@@ -128,20 +142,10 @@ public class AppActor extends ContextAwareActor { | @@ -128,20 +142,10 @@ public class AppActor extends ContextAwareActor { | ||
128 | tenantActors.values().forEach(actorRef -> actorRef.tell(msg, ActorRef.noSender())); | 142 | tenantActors.values().forEach(actorRef -> actorRef.tell(msg, ActorRef.noSender())); |
129 | } | 143 | } |
130 | 144 | ||
131 | - private void onToRuleMsg(ToRuleActorMsg msg) { | ||
132 | - ActorRef target; | ||
133 | - if (SYSTEM_TENANT.equals(msg.getTenantId())) { | ||
134 | - target = ruleManager.getOrCreateRuleActor(this.context(), msg.getRuleId()); | ||
135 | - } else { | ||
136 | - target = getOrCreateTenantActor(msg.getTenantId()); | ||
137 | - } | ||
138 | - target.tell(msg, ActorRef.noSender()); | ||
139 | - } | ||
140 | - | ||
141 | private void onToPluginMsg(ToPluginActorMsg msg) { | 145 | private void onToPluginMsg(ToPluginActorMsg msg) { |
142 | ActorRef target; | 146 | ActorRef target; |
143 | if (SYSTEM_TENANT.equals(msg.getPluginTenantId())) { | 147 | if (SYSTEM_TENANT.equals(msg.getPluginTenantId())) { |
144 | - target = pluginManager.getOrCreatePluginActor(this.context(), msg.getPluginId()); | 148 | + target = pluginManager.getOrCreateActor(this.context(), msg.getPluginId()); |
145 | } else { | 149 | } else { |
146 | target = getOrCreateTenantActor(msg.getPluginTenantId()); | 150 | target = getOrCreateTenantActor(msg.getPluginTenantId()); |
147 | } | 151 | } |
@@ -149,26 +153,16 @@ public class AppActor extends ContextAwareActor { | @@ -149,26 +153,16 @@ public class AppActor extends ContextAwareActor { | ||
149 | } | 153 | } |
150 | 154 | ||
151 | private void onComponentLifecycleMsg(ComponentLifecycleMsg msg) { | 155 | private void onComponentLifecycleMsg(ComponentLifecycleMsg msg) { |
152 | - ActorRef target = null; | 156 | + ActorRef target; |
153 | if (SYSTEM_TENANT.equals(msg.getTenantId())) { | 157 | if (SYSTEM_TENANT.equals(msg.getTenantId())) { |
154 | - Optional<PluginId> pluginId = msg.getPluginId(); | ||
155 | - Optional<RuleId> ruleId = msg.getRuleId(); | ||
156 | - if (pluginId.isPresent()) { | ||
157 | - target = pluginManager.getOrCreatePluginActor(this.context(), pluginId.get()); | ||
158 | - } else if (ruleId.isPresent()) { | ||
159 | - Optional<ActorRef> ref = ruleManager.update(this.context(), ruleId.get(), msg.getEvent()); | ||
160 | - if (ref.isPresent()) { | ||
161 | - target = ref.get(); | ||
162 | - } else { | ||
163 | - logger.debug("Failed to find actor for rule: [{}]", ruleId); | ||
164 | - return; | ||
165 | - } | ||
166 | - } | 158 | + target = getEntityActorRef(msg.getEntityId()); |
167 | } else { | 159 | } else { |
168 | target = getOrCreateTenantActor(msg.getTenantId()); | 160 | target = getOrCreateTenantActor(msg.getTenantId()); |
169 | } | 161 | } |
170 | if (target != null) { | 162 | if (target != null) { |
171 | target.tell(msg, ActorRef.noSender()); | 163 | target.tell(msg, ActorRef.noSender()); |
164 | + } else { | ||
165 | + logger.debug("Invalid component lifecycle msg: {}", msg); | ||
172 | } | 166 | } |
173 | } | 167 | } |
174 | 168 | ||
@@ -180,7 +174,7 @@ public class AppActor extends ContextAwareActor { | @@ -180,7 +174,7 @@ public class AppActor extends ContextAwareActor { | ||
180 | TenantId tenantId = toDeviceActorMsg.getTenantId(); | 174 | TenantId tenantId = toDeviceActorMsg.getTenantId(); |
181 | ActorRef tenantActor = getOrCreateTenantActor(tenantId); | 175 | ActorRef tenantActor = getOrCreateTenantActor(tenantId); |
182 | if (toDeviceActorMsg.getPayload().getMsgType().requiresRulesProcessing()) { | 176 | if (toDeviceActorMsg.getPayload().getMsgType().requiresRulesProcessing()) { |
183 | - tenantActor.tell(new RuleChainDeviceMsg(toDeviceActorMsg, ruleManager.getRuleChain(this.context())), context().self()); | 177 | +// tenantActor.tell(new RuleChainDeviceMsg(toDeviceActorMsg, ruleManager.getRuleChain(this.context())), context().self()); |
184 | } else { | 178 | } else { |
185 | tenantActor.tell(toDeviceActorMsg, context().self()); | 179 | tenantActor.tell(toDeviceActorMsg, context().self()); |
186 | } | 180 | } |
@@ -18,19 +18,19 @@ package org.thingsboard.server.actors.device; | @@ -18,19 +18,19 @@ package org.thingsboard.server.actors.device; | ||
18 | import akka.event.Logging; | 18 | import akka.event.Logging; |
19 | import akka.event.LoggingAdapter; | 19 | import akka.event.LoggingAdapter; |
20 | import org.thingsboard.server.actors.ActorSystemContext; | 20 | import org.thingsboard.server.actors.ActorSystemContext; |
21 | -import org.thingsboard.server.actors.rule.RulesProcessedMsg; | ||
22 | import org.thingsboard.server.actors.service.ContextAwareActor; | 21 | import org.thingsboard.server.actors.service.ContextAwareActor; |
23 | import org.thingsboard.server.actors.service.ContextBasedCreator; | 22 | import org.thingsboard.server.actors.service.ContextBasedCreator; |
24 | -import org.thingsboard.server.actors.tenant.RuleChainDeviceMsg; | ||
25 | import org.thingsboard.server.common.data.id.DeviceId; | 23 | import org.thingsboard.server.common.data.id.DeviceId; |
26 | import org.thingsboard.server.common.data.id.TenantId; | 24 | import org.thingsboard.server.common.data.id.TenantId; |
25 | +import org.thingsboard.server.common.msg.TbActorMsg; | ||
27 | import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; | 26 | import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; |
28 | import org.thingsboard.server.common.msg.device.ToDeviceActorMsg; | 27 | import org.thingsboard.server.common.msg.device.ToDeviceActorMsg; |
29 | import org.thingsboard.server.extensions.api.device.DeviceAttributesEventNotificationMsg; | 28 | import org.thingsboard.server.extensions.api.device.DeviceAttributesEventNotificationMsg; |
30 | import org.thingsboard.server.extensions.api.device.DeviceCredentialsUpdateNotificationMsg; | 29 | import org.thingsboard.server.extensions.api.device.DeviceCredentialsUpdateNotificationMsg; |
31 | import org.thingsboard.server.extensions.api.device.DeviceNameOrTypeUpdateMsg; | 30 | import org.thingsboard.server.extensions.api.device.DeviceNameOrTypeUpdateMsg; |
32 | import org.thingsboard.server.extensions.api.device.ToDeviceActorNotificationMsg; | 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 | public class DeviceActor extends ContextAwareActor { | 35 | public class DeviceActor extends ContextAwareActor { |
36 | 36 | ||
@@ -48,12 +48,17 @@ public class DeviceActor extends ContextAwareActor { | @@ -48,12 +48,17 @@ public class DeviceActor extends ContextAwareActor { | ||
48 | } | 48 | } |
49 | 49 | ||
50 | @Override | 50 | @Override |
51 | + protected boolean process(TbActorMsg msg) { | ||
52 | + return false; | ||
53 | + } | ||
54 | + | ||
55 | + @Override | ||
51 | public void onReceive(Object msg) throws Exception { | 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 | processor.process(context(), (ToDeviceActorMsg) msg); | 62 | processor.process(context(), (ToDeviceActorMsg) msg); |
58 | } else if (msg instanceof ToDeviceActorNotificationMsg) { | 63 | } else if (msg instanceof ToDeviceActorNotificationMsg) { |
59 | if (msg instanceof DeviceAttributesEventNotificationMsg) { | 64 | if (msg instanceof DeviceAttributesEventNotificationMsg) { |
@@ -19,9 +19,7 @@ import akka.actor.ActorContext; | @@ -19,9 +19,7 @@ import akka.actor.ActorContext; | ||
19 | import akka.actor.ActorRef; | 19 | import akka.actor.ActorRef; |
20 | import akka.event.LoggingAdapter; | 20 | import akka.event.LoggingAdapter; |
21 | import org.thingsboard.server.actors.ActorSystemContext; | 21 | import org.thingsboard.server.actors.ActorSystemContext; |
22 | -import org.thingsboard.server.actors.rule.*; | ||
23 | import org.thingsboard.server.actors.shared.AbstractContextAwareMsgProcessor; | 22 | import org.thingsboard.server.actors.shared.AbstractContextAwareMsgProcessor; |
24 | -import org.thingsboard.server.actors.tenant.RuleChainDeviceMsg; | ||
25 | import org.thingsboard.server.common.data.DataConstants; | 23 | import org.thingsboard.server.common.data.DataConstants; |
26 | import org.thingsboard.server.common.data.Device; | 24 | import org.thingsboard.server.common.data.Device; |
27 | import org.thingsboard.server.common.data.id.DeviceId; | 25 | import org.thingsboard.server.common.data.id.DeviceId; |
@@ -37,15 +35,10 @@ import org.thingsboard.server.common.msg.session.FromDeviceMsg; | @@ -37,15 +35,10 @@ import org.thingsboard.server.common.msg.session.FromDeviceMsg; | ||
37 | import org.thingsboard.server.common.msg.session.MsgType; | 35 | import org.thingsboard.server.common.msg.session.MsgType; |
38 | import org.thingsboard.server.common.msg.session.SessionType; | 36 | import org.thingsboard.server.common.msg.session.SessionType; |
39 | import org.thingsboard.server.common.msg.session.ToDeviceMsg; | 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 | import java.util.*; | 43 | import java.util.*; |
51 | import java.util.concurrent.ExecutionException; | 44 | import java.util.concurrent.ExecutionException; |
@@ -230,18 +223,18 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso | @@ -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 | void processRpcResponses(ActorContext context, ToDeviceActorMsg msg) { | 239 | void processRpcResponses(ActorContext context, ToDeviceActorMsg msg) { |
247 | SessionId sessionId = msg.getSessionId(); | 240 | SessionId sessionId = msg.getSessionId(); |
@@ -302,18 +295,18 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso | @@ -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 | private void processSubscriptionCommands(ActorContext context, ToDeviceActorMsg msg) { | 311 | private void processSubscriptionCommands(ActorContext context, ToDeviceActorMsg msg) { |
319 | SessionId sessionId = msg.getSessionId(); | 312 | SessionId sessionId = msg.getSessionId(); |
@@ -23,6 +23,7 @@ import org.thingsboard.server.actors.service.ContextBasedCreator; | @@ -23,6 +23,7 @@ import org.thingsboard.server.actors.service.ContextBasedCreator; | ||
23 | import org.thingsboard.server.actors.stats.StatsPersistTick; | 23 | import org.thingsboard.server.actors.stats.StatsPersistTick; |
24 | import org.thingsboard.server.common.data.id.PluginId; | 24 | import org.thingsboard.server.common.data.id.PluginId; |
25 | import org.thingsboard.server.common.data.id.TenantId; | 25 | import org.thingsboard.server.common.data.id.TenantId; |
26 | +import org.thingsboard.server.common.msg.TbActorMsg; | ||
26 | import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; | 27 | import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; |
27 | import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; | 28 | import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; |
28 | import org.thingsboard.server.extensions.api.plugins.msg.TimeoutMsg; | 29 | import org.thingsboard.server.extensions.api.plugins.msg.TimeoutMsg; |
@@ -41,6 +42,12 @@ public class PluginActor extends ComponentActor<PluginId, PluginActorMessageProc | @@ -41,6 +42,12 @@ public class PluginActor extends ComponentActor<PluginId, PluginActorMessageProc | ||
41 | } | 42 | } |
42 | 43 | ||
43 | @Override | 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 | public void onReceive(Object msg) throws Exception { | 51 | public void onReceive(Object msg) throws Exception { |
45 | if (msg instanceof PluginWebsocketMsg) { | 52 | if (msg instanceof PluginWebsocketMsg) { |
46 | onWebsocketMsg((PluginWebsocketMsg<?>) msg); | 53 | onWebsocketMsg((PluginWebsocketMsg<?>) msg); |
@@ -28,9 +28,14 @@ import org.thingsboard.server.common.data.plugin.ComponentType; | @@ -28,9 +28,14 @@ import org.thingsboard.server.common.data.plugin.ComponentType; | ||
28 | import org.thingsboard.server.common.data.plugin.PluginMetaData; | 28 | import org.thingsboard.server.common.data.plugin.PluginMetaData; |
29 | import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; | 29 | import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; |
30 | import org.thingsboard.server.common.msg.cluster.ServerAddress; | 30 | import org.thingsboard.server.common.msg.cluster.ServerAddress; |
31 | +import org.thingsboard.server.common.msg.core.BasicStatusCodeResponse; | ||
32 | +import org.thingsboard.server.common.msg.session.FromDeviceRequestMsg; | ||
33 | +import org.thingsboard.server.common.msg.session.MsgType; | ||
31 | import org.thingsboard.server.extensions.api.plugins.Plugin; | 34 | import org.thingsboard.server.extensions.api.plugins.Plugin; |
32 | import org.thingsboard.server.extensions.api.plugins.PluginInitializationException; | 35 | import org.thingsboard.server.extensions.api.plugins.PluginInitializationException; |
33 | import org.thingsboard.server.extensions.api.plugins.msg.FromDeviceRpcResponse; | 36 | import org.thingsboard.server.extensions.api.plugins.msg.FromDeviceRpcResponse; |
37 | +import org.thingsboard.server.extensions.api.plugins.msg.ResponsePluginToRuleMsg; | ||
38 | +import org.thingsboard.server.extensions.api.plugins.msg.RuleToPluginMsg; | ||
34 | import org.thingsboard.server.extensions.api.plugins.msg.TimeoutMsg; | 39 | import org.thingsboard.server.extensions.api.plugins.msg.TimeoutMsg; |
35 | import org.thingsboard.server.extensions.api.plugins.rest.PluginRestMsg; | 40 | import org.thingsboard.server.extensions.api.plugins.rest.PluginRestMsg; |
36 | import org.thingsboard.server.extensions.api.plugins.rpc.PluginRpcMsg; | 41 | import org.thingsboard.server.extensions.api.plugins.rpc.PluginRpcMsg; |
@@ -57,7 +62,7 @@ public class PluginActorMessageProcessor extends ComponentMsgProcessor<PluginId> | @@ -57,7 +62,7 @@ public class PluginActorMessageProcessor extends ComponentMsgProcessor<PluginId> | ||
57 | } | 62 | } |
58 | 63 | ||
59 | @Override | 64 | @Override |
60 | - public void start() throws Exception { | 65 | + public void start(ActorContext context) throws Exception { |
61 | logger.info("[{}] Going to start plugin actor.", entityId); | 66 | logger.info("[{}] Going to start plugin actor.", entityId); |
62 | pluginMd = systemContext.getPluginService().findPluginById(entityId); | 67 | pluginMd = systemContext.getPluginService().findPluginById(entityId); |
63 | if (pluginMd == null) { | 68 | if (pluginMd == null) { |
@@ -76,7 +81,7 @@ public class PluginActorMessageProcessor extends ComponentMsgProcessor<PluginId> | @@ -76,7 +81,7 @@ public class PluginActorMessageProcessor extends ComponentMsgProcessor<PluginId> | ||
76 | } | 81 | } |
77 | 82 | ||
78 | @Override | 83 | @Override |
79 | - public void stop() throws Exception { | 84 | + public void stop(ActorContext context) throws Exception { |
80 | onStop(); | 85 | onStop(); |
81 | } | 86 | } |
82 | 87 | ||
@@ -98,7 +103,20 @@ public class PluginActorMessageProcessor extends ComponentMsgProcessor<PluginId> | @@ -98,7 +103,20 @@ public class PluginActorMessageProcessor extends ComponentMsgProcessor<PluginId> | ||
98 | 103 | ||
99 | public void onRuleToPluginMsg(RuleToPluginMsgWrapper msg) throws RuleException { | 104 | public void onRuleToPluginMsg(RuleToPluginMsgWrapper msg) throws RuleException { |
100 | if (state == ComponentLifecycleState.ACTIVE) { | 105 | if (state == ComponentLifecycleState.ACTIVE) { |
101 | - pluginImpl.process(trustedCtx, msg.getRuleTenantId(), msg.getRuleId(), msg.getMsg()); | 106 | + try { |
107 | + pluginImpl.process(trustedCtx, msg.getRuleTenantId(), msg.getRuleId(), msg.getMsg()); | ||
108 | + } catch (Exception ex) { | ||
109 | + logger.debug("[{}] Failed to process RuleToPlugin msg: [{}] [{}]", tenantId, msg.getMsg(), ex); | ||
110 | + RuleToPluginMsg ruleMsg = msg.getMsg(); | ||
111 | + MsgType responceMsgType = MsgType.RULE_ENGINE_ERROR; | ||
112 | + Integer requestId = 0; | ||
113 | + if (ruleMsg.getPayload() instanceof FromDeviceRequestMsg) { | ||
114 | + requestId = ((FromDeviceRequestMsg) ruleMsg.getPayload()).getRequestId(); | ||
115 | + } | ||
116 | + trustedCtx.reply( | ||
117 | + new ResponsePluginToRuleMsg(ruleMsg.getUid(), tenantId, msg.getRuleId(), | ||
118 | + BasicStatusCodeResponse.onError(responceMsgType, requestId, ex))); | ||
119 | + } | ||
102 | } else { | 120 | } else { |
103 | //TODO: reply with plugin suspended message | 121 | //TODO: reply with plugin suspended message |
104 | } | 122 | } |
@@ -191,7 +209,7 @@ public class PluginActorMessageProcessor extends ComponentMsgProcessor<PluginId> | @@ -191,7 +209,7 @@ public class PluginActorMessageProcessor extends ComponentMsgProcessor<PluginId> | ||
191 | if (pluginImpl != null) { | 209 | if (pluginImpl != null) { |
192 | pluginImpl.stop(trustedCtx); | 210 | pluginImpl.stop(trustedCtx); |
193 | } | 211 | } |
194 | - start(); | 212 | + start(context); |
195 | } | 213 | } |
196 | } | 214 | } |
197 | 215 | ||
@@ -217,7 +235,7 @@ public class PluginActorMessageProcessor extends ComponentMsgProcessor<PluginId> | @@ -217,7 +235,7 @@ public class PluginActorMessageProcessor extends ComponentMsgProcessor<PluginId> | ||
217 | pluginImpl.resume(trustedCtx); | 235 | pluginImpl.resume(trustedCtx); |
218 | logger.info("[{}] Plugin resumed.", entityId); | 236 | logger.info("[{}] Plugin resumed.", entityId); |
219 | } else { | 237 | } else { |
220 | - start(); | 238 | + start(context); |
221 | } | 239 | } |
222 | } | 240 | } |
223 | 241 |
@@ -36,6 +36,7 @@ import org.thingsboard.server.common.data.page.TextPageLink; | @@ -36,6 +36,7 @@ import org.thingsboard.server.common.data.page.TextPageLink; | ||
36 | import org.thingsboard.server.common.data.plugin.PluginMetaData; | 36 | import org.thingsboard.server.common.data.plugin.PluginMetaData; |
37 | import org.thingsboard.server.common.data.relation.EntityRelation; | 37 | import org.thingsboard.server.common.data.relation.EntityRelation; |
38 | import org.thingsboard.server.common.data.relation.RelationTypeGroup; | 38 | import org.thingsboard.server.common.data.relation.RelationTypeGroup; |
39 | +import org.thingsboard.server.common.data.rule.RuleChain; | ||
39 | import org.thingsboard.server.common.data.rule.RuleMetaData; | 40 | import org.thingsboard.server.common.data.rule.RuleMetaData; |
40 | import org.thingsboard.server.common.msg.cluster.ServerAddress; | 41 | import org.thingsboard.server.common.msg.cluster.ServerAddress; |
41 | import org.thingsboard.server.extensions.api.device.DeviceAttributesEventNotificationMsg; | 42 | import org.thingsboard.server.extensions.api.device.DeviceAttributesEventNotificationMsg; |
@@ -330,6 +331,9 @@ public final class PluginProcessingContext implements PluginContext { | @@ -330,6 +331,9 @@ public final class PluginProcessingContext implements PluginContext { | ||
330 | case RULE: | 331 | case RULE: |
331 | validateRule(ctx, entityId, callback); | 332 | validateRule(ctx, entityId, callback); |
332 | return; | 333 | return; |
334 | + case RULE_CHAIN: | ||
335 | + validateRuleChain(ctx, entityId, callback); | ||
336 | + return; | ||
333 | case PLUGIN: | 337 | case PLUGIN: |
334 | validatePlugin(ctx, entityId, callback); | 338 | validatePlugin(ctx, entityId, callback); |
335 | return; | 339 | return; |
@@ -411,6 +415,28 @@ public final class PluginProcessingContext implements PluginContext { | @@ -411,6 +415,28 @@ public final class PluginProcessingContext implements PluginContext { | ||
411 | } | 415 | } |
412 | } | 416 | } |
413 | 417 | ||
418 | + private void validateRuleChain(final PluginApiCallSecurityContext ctx, EntityId entityId, ValidationCallback callback) { | ||
419 | + if (ctx.isCustomerUser()) { | ||
420 | + callback.onSuccess(this, ValidationResult.accessDenied(CUSTOMER_USER_IS_NOT_ALLOWED_TO_PERFORM_THIS_OPERATION)); | ||
421 | + } else { | ||
422 | + ListenableFuture<RuleChain> ruleChainFuture = pluginCtx.ruleChainService.findRuleChainByIdAsync(new RuleChainId(entityId.getId())); | ||
423 | + Futures.addCallback(ruleChainFuture, getCallback(callback, ruleChain -> { | ||
424 | + if (ruleChain == null) { | ||
425 | + return ValidationResult.entityNotFound("Rule chain with requested id wasn't found!"); | ||
426 | + } else { | ||
427 | + if (ctx.isTenantAdmin() && !ruleChain.getTenantId().equals(ctx.getTenantId())) { | ||
428 | + return ValidationResult.accessDenied("Rule chain doesn't belong to the current Tenant!"); | ||
429 | + } else if (ctx.isSystemAdmin() && !ruleChain.getTenantId().isNullUid()) { | ||
430 | + return ValidationResult.accessDenied("Rule chain is not in system scope!"); | ||
431 | + } else { | ||
432 | + return ValidationResult.ok(); | ||
433 | + } | ||
434 | + } | ||
435 | + })); | ||
436 | + } | ||
437 | + } | ||
438 | + | ||
439 | + | ||
414 | private void validatePlugin(final PluginApiCallSecurityContext ctx, EntityId entityId, ValidationCallback callback) { | 440 | private void validatePlugin(final PluginApiCallSecurityContext ctx, EntityId entityId, ValidationCallback callback) { |
415 | if (ctx.isCustomerUser()) { | 441 | if (ctx.isCustomerUser()) { |
416 | callback.onSuccess(this, ValidationResult.accessDenied(CUSTOMER_USER_IS_NOT_ALLOWED_TO_PERFORM_THIS_OPERATION)); | 442 | callback.onSuccess(this, ValidationResult.accessDenied(CUSTOMER_USER_IS_NOT_ALLOWED_TO_PERFORM_THIS_OPERATION)); |
@@ -32,6 +32,7 @@ import org.thingsboard.server.dao.customer.CustomerService; | @@ -32,6 +32,7 @@ import org.thingsboard.server.dao.customer.CustomerService; | ||
32 | import org.thingsboard.server.dao.device.DeviceService; | 32 | import org.thingsboard.server.dao.device.DeviceService; |
33 | import org.thingsboard.server.dao.plugin.PluginService; | 33 | import org.thingsboard.server.dao.plugin.PluginService; |
34 | import org.thingsboard.server.dao.relation.RelationService; | 34 | import org.thingsboard.server.dao.relation.RelationService; |
35 | +import org.thingsboard.server.dao.rule.RuleChainService; | ||
35 | import org.thingsboard.server.dao.rule.RuleService; | 36 | import org.thingsboard.server.dao.rule.RuleService; |
36 | import org.thingsboard.server.dao.tenant.TenantService; | 37 | import org.thingsboard.server.dao.tenant.TenantService; |
37 | import org.thingsboard.server.dao.timeseries.TimeseriesService; | 38 | import org.thingsboard.server.dao.timeseries.TimeseriesService; |
@@ -56,6 +57,7 @@ public final class SharedPluginProcessingContext { | @@ -56,6 +57,7 @@ public final class SharedPluginProcessingContext { | ||
56 | final AssetService assetService; | 57 | final AssetService assetService; |
57 | final DeviceService deviceService; | 58 | final DeviceService deviceService; |
58 | final RuleService ruleService; | 59 | final RuleService ruleService; |
60 | + final RuleChainService ruleChainService; | ||
59 | final PluginService pluginService; | 61 | final PluginService pluginService; |
60 | final CustomerService customerService; | 62 | final CustomerService customerService; |
61 | final TenantService tenantService; | 63 | final TenantService tenantService; |
@@ -84,6 +86,7 @@ public final class SharedPluginProcessingContext { | @@ -84,6 +86,7 @@ public final class SharedPluginProcessingContext { | ||
84 | this.rpcService = sysContext.getRpcService(); | 86 | this.rpcService = sysContext.getRpcService(); |
85 | this.routingService = sysContext.getRoutingService(); | 87 | this.routingService = sysContext.getRoutingService(); |
86 | this.ruleService = sysContext.getRuleService(); | 88 | this.ruleService = sysContext.getRuleService(); |
89 | + this.ruleChainService = sysContext.getRuleChainService(); | ||
87 | this.pluginService = sysContext.getPluginService(); | 90 | this.pluginService = sysContext.getPluginService(); |
88 | this.customerService = sysContext.getCustomerService(); | 91 | this.customerService = sysContext.getCustomerService(); |
89 | this.tenantService = sysContext.getTenantService(); | 92 | this.tenantService = sysContext.getTenantService(); |
@@ -23,6 +23,7 @@ import org.thingsboard.server.actors.ActorSystemContext; | @@ -23,6 +23,7 @@ import org.thingsboard.server.actors.ActorSystemContext; | ||
23 | import org.thingsboard.server.actors.service.ContextAwareActor; | 23 | import org.thingsboard.server.actors.service.ContextAwareActor; |
24 | import org.thingsboard.server.actors.service.ContextBasedCreator; | 24 | import org.thingsboard.server.actors.service.ContextBasedCreator; |
25 | import org.thingsboard.server.actors.service.DefaultActorService; | 25 | import org.thingsboard.server.actors.service.DefaultActorService; |
26 | +import org.thingsboard.server.common.msg.TbActorMsg; | ||
26 | import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; | 27 | import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; |
27 | import org.thingsboard.server.common.msg.cluster.ServerAddress; | 28 | import org.thingsboard.server.common.msg.cluster.ServerAddress; |
28 | import org.thingsboard.server.gen.cluster.ClusterAPIProtos; | 29 | import org.thingsboard.server.gen.cluster.ClusterAPIProtos; |
@@ -57,6 +58,12 @@ public class RpcManagerActor extends ContextAwareActor { | @@ -57,6 +58,12 @@ public class RpcManagerActor extends ContextAwareActor { | ||
57 | } | 58 | } |
58 | 59 | ||
59 | @Override | 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 | public void onReceive(Object msg) throws Exception { | 67 | public void onReceive(Object msg) throws Exception { |
61 | if (msg instanceof RpcSessionTellMsg) { | 68 | if (msg instanceof RpcSessionTellMsg) { |
62 | onMsg((RpcSessionTellMsg) msg); | 69 | onMsg((RpcSessionTellMsg) msg); |
@@ -23,6 +23,7 @@ import io.grpc.stub.StreamObserver; | @@ -23,6 +23,7 @@ import io.grpc.stub.StreamObserver; | ||
23 | import org.thingsboard.server.actors.ActorSystemContext; | 23 | import org.thingsboard.server.actors.ActorSystemContext; |
24 | import org.thingsboard.server.actors.service.ContextAwareActor; | 24 | import org.thingsboard.server.actors.service.ContextAwareActor; |
25 | import org.thingsboard.server.actors.service.ContextBasedCreator; | 25 | import org.thingsboard.server.actors.service.ContextBasedCreator; |
26 | +import org.thingsboard.server.common.msg.TbActorMsg; | ||
26 | import org.thingsboard.server.common.msg.cluster.ServerAddress; | 27 | import org.thingsboard.server.common.msg.cluster.ServerAddress; |
27 | import org.thingsboard.server.gen.cluster.ClusterAPIProtos; | 28 | import org.thingsboard.server.gen.cluster.ClusterAPIProtos; |
28 | import org.thingsboard.server.gen.cluster.ClusterRpcServiceGrpc; | 29 | import org.thingsboard.server.gen.cluster.ClusterRpcServiceGrpc; |
@@ -48,6 +49,12 @@ public class RpcSessionActor extends ContextAwareActor { | @@ -48,6 +49,12 @@ public class RpcSessionActor extends ContextAwareActor { | ||
48 | } | 49 | } |
49 | 50 | ||
50 | @Override | 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 | public void onReceive(Object msg) throws Exception { | 58 | public void onReceive(Object msg) throws Exception { |
52 | if (msg instanceof RpcSessionTellMsg) { | 59 | if (msg instanceof RpcSessionTellMsg) { |
53 | tell((RpcSessionTellMsg) msg); | 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/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() 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() 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 | -} |
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.ruleChain; | ||
17 | + | ||
18 | +import akka.actor.ActorRef; | ||
19 | +import akka.actor.Cancellable; | ||
20 | +import com.google.common.base.Function; | ||
21 | +import org.thingsboard.rule.engine.api.*; | ||
22 | +import org.thingsboard.server.actors.ActorSystemContext; | ||
23 | +import org.thingsboard.server.common.data.id.RuleNodeId; | ||
24 | +import org.thingsboard.server.common.data.id.TenantId; | ||
25 | +import org.thingsboard.server.common.data.rule.RuleNode; | ||
26 | +import org.thingsboard.server.common.msg.TbMsg; | ||
27 | +import org.thingsboard.server.common.msg.cluster.ServerAddress; | ||
28 | +import org.thingsboard.server.dao.alarm.AlarmService; | ||
29 | +import org.thingsboard.server.dao.asset.AssetService; | ||
30 | +import org.thingsboard.server.dao.attributes.AttributesService; | ||
31 | +import org.thingsboard.server.dao.customer.CustomerService; | ||
32 | +import org.thingsboard.server.dao.device.DeviceService; | ||
33 | +import org.thingsboard.server.dao.plugin.PluginService; | ||
34 | +import org.thingsboard.server.dao.relation.RelationService; | ||
35 | +import org.thingsboard.server.dao.rule.RuleChainService; | ||
36 | +import org.thingsboard.server.dao.timeseries.TimeseriesService; | ||
37 | +import org.thingsboard.server.dao.user.UserService; | ||
38 | +import org.thingsboard.server.service.script.NashornJsEngine; | ||
39 | +import scala.concurrent.duration.Duration; | ||
40 | + | ||
41 | +import java.util.List; | ||
42 | +import java.util.Set; | ||
43 | +import java.util.concurrent.TimeUnit; | ||
44 | + | ||
45 | +/** | ||
46 | + * Created by ashvayka on 19.03.18. | ||
47 | + */ | ||
48 | +class DefaultTbContext implements TbContext { | ||
49 | + | ||
50 | + private static final Function<? super List<Void>, ? extends Void> LIST_VOID_FUNCTION = v -> null; | ||
51 | + private final ActorSystemContext mainCtx; | ||
52 | + private final RuleNodeCtx nodeCtx; | ||
53 | + | ||
54 | + public DefaultTbContext(ActorSystemContext mainCtx, RuleNodeCtx nodeCtx) { | ||
55 | + this.mainCtx = mainCtx; | ||
56 | + this.nodeCtx = nodeCtx; | ||
57 | + } | ||
58 | + | ||
59 | + @Override | ||
60 | + public void tellNext(TbMsg msg) { | ||
61 | + tellNext(msg, (String) null); | ||
62 | + } | ||
63 | + | ||
64 | + @Override | ||
65 | + public void tellNext(TbMsg msg, String relationType) { | ||
66 | + if (nodeCtx.getSelf().isDebugMode()) { | ||
67 | + mainCtx.persistDebugOutput(nodeCtx.getTenantId(), nodeCtx.getSelf().getId(), msg); | ||
68 | + } | ||
69 | + nodeCtx.getChainActor().tell(new RuleNodeToRuleChainTellNextMsg(nodeCtx.getSelf().getId(), relationType, msg), nodeCtx.getSelfActor()); | ||
70 | + } | ||
71 | + | ||
72 | + @Override | ||
73 | + public void tellSelf(TbMsg msg, long delayMs) { | ||
74 | + //TODO: add persistence layer | ||
75 | + scheduleMsgWithDelay(new RuleNodeToSelfMsg(msg), delayMs, nodeCtx.getSelfActor()); | ||
76 | + } | ||
77 | + | ||
78 | + private void scheduleMsgWithDelay(Object msg, long delayInMs, ActorRef target) { | ||
79 | + mainCtx.getScheduler().scheduleOnce(Duration.create(delayInMs, TimeUnit.MILLISECONDS), target, msg, mainCtx.getActorSystem().dispatcher(), nodeCtx.getSelfActor()); | ||
80 | + } | ||
81 | + | ||
82 | + @Override | ||
83 | + public void tellOthers(TbMsg msg) { | ||
84 | + throw new RuntimeException("Not Implemented!"); | ||
85 | + } | ||
86 | + | ||
87 | + @Override | ||
88 | + public void tellSibling(TbMsg msg, ServerAddress address) { | ||
89 | + throw new RuntimeException("Not Implemented!"); | ||
90 | + } | ||
91 | + | ||
92 | + @Override | ||
93 | + public void spawn(TbMsg msg) { | ||
94 | + throw new RuntimeException("Not Implemented!"); | ||
95 | + } | ||
96 | + | ||
97 | + @Override | ||
98 | + public void ack(TbMsg msg) { | ||
99 | + | ||
100 | + } | ||
101 | + | ||
102 | + @Override | ||
103 | + public void tellError(TbMsg msg, Throwable th) { | ||
104 | + if (nodeCtx.getSelf().isDebugMode()) { | ||
105 | + mainCtx.persistDebugOutput(nodeCtx.getTenantId(), nodeCtx.getSelf().getId(), msg, th); | ||
106 | + } | ||
107 | + nodeCtx.getSelfActor().tell(new RuleNodeToSelfErrorMsg(msg, th), nodeCtx.getSelfActor()); | ||
108 | + } | ||
109 | + | ||
110 | + @Override | ||
111 | + public void updateSelf(RuleNode self) { | ||
112 | + nodeCtx.setSelf(self); | ||
113 | + } | ||
114 | + | ||
115 | + @Override | ||
116 | + public RuleNodeId getSelfId() { | ||
117 | + return nodeCtx.getSelf().getId(); | ||
118 | + } | ||
119 | + | ||
120 | + @Override | ||
121 | + public TenantId getTenantId() { | ||
122 | + return nodeCtx.getTenantId(); | ||
123 | + } | ||
124 | + | ||
125 | + @Override | ||
126 | + public void tellNext(TbMsg msg, Set<String> relationTypes) { | ||
127 | + relationTypes.forEach(type -> tellNext(msg, type)); | ||
128 | + } | ||
129 | + | ||
130 | + @Override | ||
131 | + public ListeningExecutor getJsExecutor() { | ||
132 | + return mainCtx.getJsExecutor(); | ||
133 | + } | ||
134 | + | ||
135 | + @Override | ||
136 | + public ListeningExecutor getMailExecutor() { | ||
137 | + return mainCtx.getMailExecutor(); | ||
138 | + } | ||
139 | + | ||
140 | + @Override | ||
141 | + public ListeningExecutor getDbCallbackExecutor() { | ||
142 | + return mainCtx.getDbCallbackExecutor(); | ||
143 | + } | ||
144 | + | ||
145 | + @Override | ||
146 | + public ScriptEngine createJsScriptEngine(String script, String functionName, String... argNames) { | ||
147 | + return new NashornJsEngine(script, functionName, argNames); | ||
148 | + } | ||
149 | + | ||
150 | + @Override | ||
151 | + public AttributesService getAttributesService() { | ||
152 | + return mainCtx.getAttributesService(); | ||
153 | + } | ||
154 | + | ||
155 | + @Override | ||
156 | + public CustomerService getCustomerService() { | ||
157 | + return mainCtx.getCustomerService(); | ||
158 | + } | ||
159 | + | ||
160 | + @Override | ||
161 | + public UserService getUserService() { | ||
162 | + return mainCtx.getUserService(); | ||
163 | + } | ||
164 | + | ||
165 | + @Override | ||
166 | + public PluginService getPluginService() { | ||
167 | + return mainCtx.getPluginService(); | ||
168 | + } | ||
169 | + | ||
170 | + @Override | ||
171 | + public AssetService getAssetService() { | ||
172 | + return mainCtx.getAssetService(); | ||
173 | + } | ||
174 | + | ||
175 | + @Override | ||
176 | + public DeviceService getDeviceService() { | ||
177 | + return mainCtx.getDeviceService(); | ||
178 | + } | ||
179 | + | ||
180 | + @Override | ||
181 | + public AlarmService getAlarmService() { | ||
182 | + return mainCtx.getAlarmService(); | ||
183 | + } | ||
184 | + | ||
185 | + @Override | ||
186 | + public RuleChainService getRuleChainService() { | ||
187 | + return mainCtx.getRuleChainService(); | ||
188 | + } | ||
189 | + | ||
190 | + @Override | ||
191 | + public TimeseriesService getTimeseriesService() { | ||
192 | + return mainCtx.getTsService(); | ||
193 | + } | ||
194 | + | ||
195 | + @Override | ||
196 | + public RuleEngineTelemetryService getTelemetryService() { | ||
197 | + return mainCtx.getTsSubService(); | ||
198 | + } | ||
199 | + | ||
200 | + @Override | ||
201 | + public RelationService getRelationService() { | ||
202 | + return mainCtx.getRelationService(); | ||
203 | + } | ||
204 | + | ||
205 | + @Override | ||
206 | + public MailService getMailService() { | ||
207 | + return mainCtx.getMailService(); | ||
208 | + } | ||
209 | +} |
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.ruleChain; | ||
17 | + | ||
18 | +import akka.actor.OneForOneStrategy; | ||
19 | +import akka.actor.SupervisorStrategy; | ||
20 | +import org.thingsboard.server.actors.ActorSystemContext; | ||
21 | +import org.thingsboard.server.actors.service.ComponentActor; | ||
22 | +import org.thingsboard.server.actors.service.ContextBasedCreator; | ||
23 | +import org.thingsboard.server.common.data.id.RuleChainId; | ||
24 | +import org.thingsboard.server.common.data.id.TenantId; | ||
25 | +import org.thingsboard.server.common.msg.TbActorMsg; | ||
26 | +import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; | ||
27 | +import org.thingsboard.server.common.msg.system.ServiceToRuleEngineMsg; | ||
28 | +import scala.concurrent.duration.Duration; | ||
29 | + | ||
30 | +public class RuleChainActor extends ComponentActor<RuleChainId, RuleChainActorMessageProcessor> { | ||
31 | + | ||
32 | + private RuleChainActor(ActorSystemContext systemContext, TenantId tenantId, RuleChainId ruleChainId) { | ||
33 | + super(systemContext, tenantId, ruleChainId); | ||
34 | + setProcessor(new RuleChainActorMessageProcessor(tenantId, ruleChainId, systemContext, | ||
35 | + logger, context().parent(), context().self())); | ||
36 | + } | ||
37 | + | ||
38 | + @Override | ||
39 | + protected boolean process(TbActorMsg msg) { | ||
40 | + switch (msg.getMsgType()) { | ||
41 | + case COMPONENT_LIFE_CYCLE_MSG: | ||
42 | + onComponentLifecycleMsg((ComponentLifecycleMsg) msg); | ||
43 | + break; | ||
44 | + case SERVICE_TO_RULE_ENGINE_MSG: | ||
45 | + processor.onServiceToRuleEngineMsg((ServiceToRuleEngineMsg) msg); | ||
46 | + break; | ||
47 | + case RULE_TO_RULE_CHAIN_TELL_NEXT_MSG: | ||
48 | + processor.onTellNext((RuleNodeToRuleChainTellNextMsg) msg); | ||
49 | + break; | ||
50 | + default: | ||
51 | + return false; | ||
52 | + } | ||
53 | + return true; | ||
54 | + } | ||
55 | + | ||
56 | + public static class ActorCreator extends ContextBasedCreator<RuleChainActor> { | ||
57 | + private static final long serialVersionUID = 1L; | ||
58 | + | ||
59 | + private final TenantId tenantId; | ||
60 | + private final RuleChainId ruleChainId; | ||
61 | + | ||
62 | + public ActorCreator(ActorSystemContext context, TenantId tenantId, RuleChainId pluginId) { | ||
63 | + super(context); | ||
64 | + this.tenantId = tenantId; | ||
65 | + this.ruleChainId = pluginId; | ||
66 | + } | ||
67 | + | ||
68 | + @Override | ||
69 | + public RuleChainActor create() throws Exception { | ||
70 | + return new RuleChainActor(context, tenantId, ruleChainId); | ||
71 | + } | ||
72 | + } | ||
73 | + | ||
74 | + @Override | ||
75 | + protected long getErrorPersistFrequency() { | ||
76 | + return systemContext.getRuleChainErrorPersistFrequency(); | ||
77 | + } | ||
78 | + | ||
79 | + @Override | ||
80 | + public SupervisorStrategy supervisorStrategy() { | ||
81 | + return strategy; | ||
82 | + } | ||
83 | + | ||
84 | + private final SupervisorStrategy strategy = new OneForOneStrategy(3, Duration.create("1 minute"), t -> { | ||
85 | + logAndPersist("Unknown Failure", ActorSystemContext.toException(t)); | ||
86 | + return SupervisorStrategy.resume(); | ||
87 | + }); | ||
88 | +} |
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.ruleChain; | ||
17 | + | ||
18 | +import akka.actor.ActorContext; | ||
19 | +import akka.actor.ActorRef; | ||
20 | +import akka.actor.Props; | ||
21 | +import akka.event.LoggingAdapter; | ||
22 | +import org.thingsboard.server.actors.ActorSystemContext; | ||
23 | +import org.thingsboard.server.actors.service.DefaultActorService; | ||
24 | +import org.thingsboard.server.actors.shared.ComponentMsgProcessor; | ||
25 | +import org.thingsboard.server.common.data.EntityType; | ||
26 | +import org.thingsboard.server.common.data.id.EntityId; | ||
27 | +import org.thingsboard.server.common.data.id.RuleChainId; | ||
28 | +import org.thingsboard.server.common.data.id.RuleNodeId; | ||
29 | +import org.thingsboard.server.common.data.id.TenantId; | ||
30 | +import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; | ||
31 | +import org.thingsboard.server.common.data.plugin.ComponentLifecycleState; | ||
32 | +import org.thingsboard.server.common.data.relation.EntityRelation; | ||
33 | +import org.thingsboard.server.common.data.rule.RuleChain; | ||
34 | +import org.thingsboard.server.common.data.rule.RuleNode; | ||
35 | +import org.thingsboard.server.common.msg.TbMsg; | ||
36 | +import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; | ||
37 | +import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; | ||
38 | +import org.thingsboard.server.common.msg.system.ServiceToRuleEngineMsg; | ||
39 | +import org.thingsboard.server.dao.rule.RuleChainService; | ||
40 | + | ||
41 | +import java.util.ArrayList; | ||
42 | +import java.util.HashMap; | ||
43 | +import java.util.List; | ||
44 | +import java.util.Map; | ||
45 | +import java.util.Set; | ||
46 | +import java.util.stream.Collectors; | ||
47 | + | ||
48 | +/** | ||
49 | + * @author Andrew Shvayka | ||
50 | + */ | ||
51 | +public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleChainId> { | ||
52 | + | ||
53 | + private final ActorRef parent; | ||
54 | + private final ActorRef self; | ||
55 | + private final Map<RuleNodeId, RuleNodeCtx> nodeActors; | ||
56 | + private final Map<RuleNodeId, List<RuleNodeRelation>> nodeRoutes; | ||
57 | + private final RuleChainService service; | ||
58 | + | ||
59 | + private RuleNodeId firstId; | ||
60 | + private RuleNodeCtx firstNode; | ||
61 | + | ||
62 | + RuleChainActorMessageProcessor(TenantId tenantId, RuleChainId ruleChainId, ActorSystemContext systemContext | ||
63 | + , LoggingAdapter logger, ActorRef parent, ActorRef self) { | ||
64 | + super(systemContext, logger, tenantId, ruleChainId); | ||
65 | + this.parent = parent; | ||
66 | + this.self = self; | ||
67 | + this.nodeActors = new HashMap<>(); | ||
68 | + this.nodeRoutes = new HashMap<>(); | ||
69 | + this.service = systemContext.getRuleChainService(); | ||
70 | + } | ||
71 | + | ||
72 | + @Override | ||
73 | + public void start(ActorContext context) throws Exception { | ||
74 | + RuleChain ruleChain = service.findRuleChainById(entityId); | ||
75 | + List<RuleNode> ruleNodeList = service.getRuleChainNodes(entityId); | ||
76 | + // Creating and starting the actors; | ||
77 | + for (RuleNode ruleNode : ruleNodeList) { | ||
78 | + ActorRef ruleNodeActor = createRuleNodeActor(context, ruleNode); | ||
79 | + nodeActors.put(ruleNode.getId(), new RuleNodeCtx(tenantId, self, ruleNodeActor, ruleNode)); | ||
80 | + } | ||
81 | + initRoutes(ruleChain, ruleNodeList); | ||
82 | + } | ||
83 | + | ||
84 | + @Override | ||
85 | + public void onUpdate(ActorContext context) throws Exception { | ||
86 | + RuleChain ruleChain = service.findRuleChainById(entityId); | ||
87 | + List<RuleNode> ruleNodeList = service.getRuleChainNodes(entityId); | ||
88 | + | ||
89 | + for (RuleNode ruleNode : ruleNodeList) { | ||
90 | + RuleNodeCtx existing = nodeActors.get(ruleNode.getId()); | ||
91 | + if (existing == null) { | ||
92 | + ActorRef ruleNodeActor = createRuleNodeActor(context, ruleNode); | ||
93 | + nodeActors.put(ruleNode.getId(), new RuleNodeCtx(tenantId, self, ruleNodeActor, ruleNode)); | ||
94 | + } else { | ||
95 | + existing.setSelf(ruleNode); | ||
96 | + existing.getSelfActor().tell(new ComponentLifecycleMsg(tenantId, existing.getSelf().getId(), ComponentLifecycleEvent.UPDATED), self); | ||
97 | + } | ||
98 | + } | ||
99 | + | ||
100 | + Set<RuleNodeId> existingNodes = ruleNodeList.stream().map(RuleNode::getId).collect(Collectors.toSet()); | ||
101 | + List<RuleNodeId> removedRules = nodeActors.keySet().stream().filter(node -> !existingNodes.contains(node)).collect(Collectors.toList()); | ||
102 | + removedRules.forEach(ruleNodeId -> { | ||
103 | + RuleNodeCtx removed = nodeActors.remove(ruleNodeId); | ||
104 | + removed.getSelfActor().tell(new ComponentLifecycleMsg(tenantId, removed.getSelf().getId(), ComponentLifecycleEvent.DELETED), self); | ||
105 | + }); | ||
106 | + | ||
107 | + initRoutes(ruleChain, ruleNodeList); | ||
108 | + } | ||
109 | + | ||
110 | + @Override | ||
111 | + public void stop(ActorContext context) throws Exception { | ||
112 | + nodeActors.values().stream().map(RuleNodeCtx::getSelfActor).forEach(context::stop); | ||
113 | + nodeActors.clear(); | ||
114 | + nodeRoutes.clear(); | ||
115 | + context.stop(self); | ||
116 | + } | ||
117 | + | ||
118 | + @Override | ||
119 | + public void onClusterEventMsg(ClusterEventMsg msg) throws Exception { | ||
120 | + | ||
121 | + } | ||
122 | + | ||
123 | + private ActorRef createRuleNodeActor(ActorContext context, RuleNode ruleNode) { | ||
124 | + String dispatcherName = tenantId.getId().equals(EntityId.NULL_UUID) ? | ||
125 | + DefaultActorService.SYSTEM_RULE_DISPATCHER_NAME : DefaultActorService.TENANT_RULE_DISPATCHER_NAME; | ||
126 | + return context.actorOf( | ||
127 | + Props.create(new RuleNodeActor.ActorCreator(systemContext, tenantId, entityId, ruleNode.getId())) | ||
128 | + .withDispatcher(dispatcherName), ruleNode.getId().toString()); | ||
129 | + } | ||
130 | + | ||
131 | + private void initRoutes(RuleChain ruleChain, List<RuleNode> ruleNodeList) { | ||
132 | + nodeRoutes.clear(); | ||
133 | + // Populating the routes map; | ||
134 | + for (RuleNode ruleNode : ruleNodeList) { | ||
135 | + List<EntityRelation> relations = service.getRuleNodeRelations(ruleNode.getId()); | ||
136 | + for (EntityRelation relation : relations) { | ||
137 | + if (relation.getTo().getEntityType() == EntityType.RULE_NODE) { | ||
138 | + RuleNodeCtx ruleNodeCtx = nodeActors.get(new RuleNodeId(relation.getTo().getId())); | ||
139 | + if (ruleNodeCtx == null) { | ||
140 | + throw new IllegalArgumentException("Rule Node [" + relation.getFrom() + "] has invalid relation to Rule node [" + relation.getTo() + "]"); | ||
141 | + } | ||
142 | + } | ||
143 | + nodeRoutes.computeIfAbsent(ruleNode.getId(), k -> new ArrayList<>()) | ||
144 | + .add(new RuleNodeRelation(ruleNode.getId(), relation.getTo(), relation.getType())); | ||
145 | + } | ||
146 | + } | ||
147 | + | ||
148 | + firstId = ruleChain.getFirstRuleNodeId(); | ||
149 | + firstNode = nodeActors.get(ruleChain.getFirstRuleNodeId()); | ||
150 | + state = ComponentLifecycleState.ACTIVE; | ||
151 | + } | ||
152 | + | ||
153 | + void onServiceToRuleEngineMsg(ServiceToRuleEngineMsg envelope) { | ||
154 | + checkActive(); | ||
155 | + TbMsg tbMsg = envelope.getTbMsg(); | ||
156 | + //TODO: push to queue and act on ack in async way | ||
157 | + pushMsgToNode(firstNode, tbMsg); | ||
158 | + } | ||
159 | + | ||
160 | + void onTellNext(RuleNodeToRuleChainTellNextMsg envelope) { | ||
161 | + checkActive(); | ||
162 | + RuleNodeId originator = envelope.getOriginator(); | ||
163 | + String targetRelationType = envelope.getRelationType(); | ||
164 | + List<RuleNodeRelation> relations = nodeRoutes.get(originator); | ||
165 | + if (relations == null) { | ||
166 | + return; | ||
167 | + } | ||
168 | + boolean copy = relations.size() > 1; | ||
169 | + for (RuleNodeRelation relation : relations) { | ||
170 | + TbMsg msg = envelope.getMsg(); | ||
171 | + if (copy) { | ||
172 | + msg = msg.copy(); | ||
173 | + } | ||
174 | + if (targetRelationType == null || targetRelationType.equalsIgnoreCase(relation.getType())) { | ||
175 | + switch (relation.getOut().getEntityType()) { | ||
176 | + case RULE_NODE: | ||
177 | + RuleNodeId targetRuleNodeId = new RuleNodeId(relation.getOut().getId()); | ||
178 | + RuleNodeCtx targetRuleNode = nodeActors.get(targetRuleNodeId); | ||
179 | + pushMsgToNode(targetRuleNode, msg); | ||
180 | + break; | ||
181 | + case RULE_CHAIN: | ||
182 | +// TODO: implement | ||
183 | + break; | ||
184 | + } | ||
185 | + } | ||
186 | + } | ||
187 | + } | ||
188 | + | ||
189 | + private void pushMsgToNode(RuleNodeCtx nodeCtx, TbMsg msg) { | ||
190 | + if (nodeCtx != null) { | ||
191 | + nodeCtx.getSelfActor().tell(new RuleChainToRuleNodeMsg(new DefaultTbContext(systemContext, nodeCtx), msg), self); | ||
192 | + } | ||
193 | + } | ||
194 | + | ||
195 | +} |
application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleChainManagerActor.java
0 → 100644
1 | +/** | ||
2 | + * Copyright © 2016-2018 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.actors.ruleChain; | ||
17 | + | ||
18 | +import akka.actor.ActorRef; | ||
19 | +import org.thingsboard.server.actors.ActorSystemContext; | ||
20 | +import org.thingsboard.server.actors.service.ContextAwareActor; | ||
21 | +import org.thingsboard.server.actors.shared.plugin.PluginManager; | ||
22 | +import org.thingsboard.server.actors.shared.rulechain.RuleChainManager; | ||
23 | +import org.thingsboard.server.common.data.id.EntityId; | ||
24 | +import org.thingsboard.server.common.data.id.PluginId; | ||
25 | +import org.thingsboard.server.common.data.id.RuleChainId; | ||
26 | +import org.thingsboard.server.dao.rule.RuleChainService; | ||
27 | + | ||
28 | +/** | ||
29 | + * Created by ashvayka on 15.03.18. | ||
30 | + */ | ||
31 | +public abstract class RuleChainManagerActor extends ContextAwareActor { | ||
32 | + | ||
33 | + protected final RuleChainManager ruleChainManager; | ||
34 | + protected final PluginManager pluginManager; | ||
35 | + protected final RuleChainService ruleChainService; | ||
36 | + | ||
37 | + public RuleChainManagerActor(ActorSystemContext systemContext, RuleChainManager ruleChainManager, PluginManager pluginManager) { | ||
38 | + super(systemContext); | ||
39 | + this.ruleChainManager = ruleChainManager; | ||
40 | + this.pluginManager = pluginManager; | ||
41 | + this.ruleChainService = systemContext.getRuleChainService(); | ||
42 | + } | ||
43 | + | ||
44 | + protected void initRuleChains() { | ||
45 | + pluginManager.init(this.context()); | ||
46 | + ruleChainManager.init(this.context()); | ||
47 | + } | ||
48 | + | ||
49 | + protected ActorRef getEntityActorRef(EntityId entityId) { | ||
50 | + ActorRef target = null; | ||
51 | + switch (entityId.getEntityType()) { | ||
52 | + case PLUGIN: | ||
53 | + target = pluginManager.getOrCreateActor(this.context(), (PluginId) entityId); | ||
54 | + break; | ||
55 | + case RULE_CHAIN: | ||
56 | + target = ruleChainManager.getOrCreateActor(this.context(), (RuleChainId) entityId); | ||
57 | + break; | ||
58 | + } | ||
59 | + return target; | ||
60 | + } | ||
61 | +} |
application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleChainToRuleNodeMsg.java
0 → 100644
1 | +/** | ||
2 | + * Copyright © 2016-2018 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.actors.ruleChain; | ||
17 | + | ||
18 | +import lombok.Data; | ||
19 | +import org.thingsboard.rule.engine.api.TbContext; | ||
20 | +import org.thingsboard.server.common.msg.MsgType; | ||
21 | +import org.thingsboard.server.common.msg.TbActorMsg; | ||
22 | +import org.thingsboard.server.common.msg.TbMsg; | ||
23 | + | ||
24 | +/** | ||
25 | + * Created by ashvayka on 19.03.18. | ||
26 | + */ | ||
27 | +@Data | ||
28 | +final class RuleChainToRuleNodeMsg implements TbActorMsg { | ||
29 | + | ||
30 | + private final TbContext ctx; | ||
31 | + private final TbMsg msg; | ||
32 | + | ||
33 | + @Override | ||
34 | + public MsgType getMsgType() { | ||
35 | + return MsgType.RULE_CHAIN_TO_RULE_MSG; | ||
36 | + } | ||
37 | +} |
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.ruleChain; | ||
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.common.data.id.RuleChainId; | ||
22 | +import org.thingsboard.server.common.data.id.RuleNodeId; | ||
23 | +import org.thingsboard.server.common.data.id.TenantId; | ||
24 | +import org.thingsboard.server.common.msg.TbActorMsg; | ||
25 | +import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; | ||
26 | + | ||
27 | +public class RuleNodeActor extends ComponentActor<RuleNodeId, RuleNodeActorMessageProcessor> { | ||
28 | + | ||
29 | + private final RuleChainId ruleChainId; | ||
30 | + | ||
31 | + private RuleNodeActor(ActorSystemContext systemContext, TenantId tenantId, RuleChainId ruleChainId, RuleNodeId ruleNodeId) { | ||
32 | + super(systemContext, tenantId, ruleNodeId); | ||
33 | + this.ruleChainId = ruleChainId; | ||
34 | + setProcessor(new RuleNodeActorMessageProcessor(tenantId, ruleChainId, ruleNodeId, systemContext, | ||
35 | + logger, context().parent(), context().self())); | ||
36 | + } | ||
37 | + | ||
38 | + @Override | ||
39 | + protected boolean process(TbActorMsg msg) { | ||
40 | + switch (msg.getMsgType()) { | ||
41 | + case COMPONENT_LIFE_CYCLE_MSG: | ||
42 | + onComponentLifecycleMsg((ComponentLifecycleMsg) msg); | ||
43 | + break; | ||
44 | + case RULE_CHAIN_TO_RULE_MSG: | ||
45 | + onRuleChainToRuleNodeMsg((RuleChainToRuleNodeMsg) msg); | ||
46 | + break; | ||
47 | + case RULE_TO_SELF_ERROR_MSG: | ||
48 | + onRuleNodeToSelfErrorMsg((RuleNodeToSelfErrorMsg) msg); | ||
49 | + break; | ||
50 | + case RULE_TO_SELF_MSG: | ||
51 | + onRuleNodeToSelfMsg((RuleNodeToSelfMsg) msg); | ||
52 | + break; | ||
53 | + default: | ||
54 | + return false; | ||
55 | + } | ||
56 | + return true; | ||
57 | + } | ||
58 | + | ||
59 | + private void onRuleNodeToSelfMsg(RuleNodeToSelfMsg msg) { | ||
60 | + logger.debug("[{}] Going to process rule msg: {}", id, msg.getMsg()); | ||
61 | + try { | ||
62 | + processor.onRuleToSelfMsg(msg); | ||
63 | + increaseMessagesProcessedCount(); | ||
64 | + } catch (Exception e) { | ||
65 | + logAndPersist("onRuleMsg", e); | ||
66 | + } | ||
67 | + } | ||
68 | + | ||
69 | + private void onRuleChainToRuleNodeMsg(RuleChainToRuleNodeMsg msg) { | ||
70 | + logger.debug("[{}] Going to process rule msg: {}", id, msg.getMsg()); | ||
71 | + try { | ||
72 | + processor.onRuleChainToRuleNodeMsg(msg); | ||
73 | + increaseMessagesProcessedCount(); | ||
74 | + } catch (Exception e) { | ||
75 | + logAndPersist("onRuleMsg", e); | ||
76 | + } | ||
77 | + } | ||
78 | + | ||
79 | + private void onRuleNodeToSelfErrorMsg(RuleNodeToSelfErrorMsg msg) { | ||
80 | + logAndPersist("onRuleMsg", ActorSystemContext.toException(msg.getError())); | ||
81 | + } | ||
82 | + | ||
83 | + public static class ActorCreator extends ContextBasedCreator<RuleNodeActor> { | ||
84 | + private static final long serialVersionUID = 1L; | ||
85 | + | ||
86 | + private final TenantId tenantId; | ||
87 | + private final RuleChainId ruleChainId; | ||
88 | + private final RuleNodeId ruleNodeId; | ||
89 | + | ||
90 | + public ActorCreator(ActorSystemContext context, TenantId tenantId, RuleChainId ruleChainId, RuleNodeId ruleNodeId) { | ||
91 | + super(context); | ||
92 | + this.tenantId = tenantId; | ||
93 | + this.ruleChainId = ruleChainId; | ||
94 | + this.ruleNodeId = ruleNodeId; | ||
95 | + | ||
96 | + } | ||
97 | + | ||
98 | + @Override | ||
99 | + public RuleNodeActor create() throws Exception { | ||
100 | + return new RuleNodeActor(context, tenantId, ruleChainId, ruleNodeId); | ||
101 | + } | ||
102 | + } | ||
103 | + | ||
104 | + @Override | ||
105 | + protected long getErrorPersistFrequency() { | ||
106 | + return systemContext.getRuleNodeErrorPersistFrequency(); | ||
107 | + } | ||
108 | + | ||
109 | +} |
application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeActorMessageProcessor.java
0 → 100644
1 | +/** | ||
2 | + * Copyright © 2016-2018 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.actors.ruleChain; | ||
17 | + | ||
18 | +import akka.actor.ActorContext; | ||
19 | +import akka.actor.ActorRef; | ||
20 | +import akka.event.LoggingAdapter; | ||
21 | +import org.thingsboard.rule.engine.api.TbContext; | ||
22 | +import org.thingsboard.rule.engine.api.TbNode; | ||
23 | +import org.thingsboard.rule.engine.api.TbNodeConfiguration; | ||
24 | +import org.thingsboard.rule.engine.api.TbNodeException; | ||
25 | +import org.thingsboard.server.actors.ActorSystemContext; | ||
26 | +import org.thingsboard.server.actors.shared.ComponentMsgProcessor; | ||
27 | +import org.thingsboard.server.common.data.id.RuleChainId; | ||
28 | +import org.thingsboard.server.common.data.id.RuleNodeId; | ||
29 | +import org.thingsboard.server.common.data.id.TenantId; | ||
30 | +import org.thingsboard.server.common.data.plugin.ComponentLifecycleState; | ||
31 | +import org.thingsboard.server.common.data.rule.RuleNode; | ||
32 | +import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; | ||
33 | +import org.thingsboard.server.dao.rule.RuleChainService; | ||
34 | + | ||
35 | +import java.util.concurrent.ExecutionException; | ||
36 | + | ||
37 | +/** | ||
38 | + * @author Andrew Shvayka | ||
39 | + */ | ||
40 | +public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor<RuleNodeId> { | ||
41 | + | ||
42 | + private final ActorRef parent; | ||
43 | + private final ActorRef self; | ||
44 | + private final RuleChainService service; | ||
45 | + private RuleNode ruleNode; | ||
46 | + private TbNode tbNode; | ||
47 | + private TbContext defaultCtx; | ||
48 | + | ||
49 | + RuleNodeActorMessageProcessor(TenantId tenantId, RuleChainId ruleChainId, RuleNodeId ruleNodeId, ActorSystemContext systemContext | ||
50 | + , LoggingAdapter logger, ActorRef parent, ActorRef self) { | ||
51 | + super(systemContext, logger, tenantId, ruleNodeId); | ||
52 | + this.parent = parent; | ||
53 | + this.self = self; | ||
54 | + this.service = systemContext.getRuleChainService(); | ||
55 | + this.ruleNode = systemContext.getRuleChainService().findRuleNodeById(entityId); | ||
56 | + this.defaultCtx = new DefaultTbContext(systemContext, new RuleNodeCtx(tenantId, parent, self, ruleNode)); | ||
57 | + } | ||
58 | + | ||
59 | + @Override | ||
60 | + public void start(ActorContext context) throws Exception { | ||
61 | + tbNode = initComponent(ruleNode); | ||
62 | + state = ComponentLifecycleState.ACTIVE; | ||
63 | + } | ||
64 | + | ||
65 | + @Override | ||
66 | + public void onUpdate(ActorContext context) throws Exception { | ||
67 | + RuleNode newRuleNode = systemContext.getRuleChainService().findRuleNodeById(entityId); | ||
68 | + boolean restartRequired = !(ruleNode.getType().equals(newRuleNode.getType()) | ||
69 | + && ruleNode.getConfiguration().equals(newRuleNode.getConfiguration())); | ||
70 | + this.ruleNode = newRuleNode; | ||
71 | + this.defaultCtx.updateSelf(newRuleNode); | ||
72 | + if (restartRequired) { | ||
73 | + if (tbNode != null) { | ||
74 | + tbNode.destroy(); | ||
75 | + } | ||
76 | + start(context); | ||
77 | + } | ||
78 | + } | ||
79 | + | ||
80 | + @Override | ||
81 | + public void stop(ActorContext context) throws Exception { | ||
82 | + if (tbNode != null) { | ||
83 | + tbNode.destroy(); | ||
84 | + } | ||
85 | + context.stop(self); | ||
86 | + } | ||
87 | + | ||
88 | + @Override | ||
89 | + public void onClusterEventMsg(ClusterEventMsg msg) throws Exception { | ||
90 | + | ||
91 | + } | ||
92 | + | ||
93 | + public void onRuleToSelfMsg(RuleNodeToSelfMsg msg) throws Exception { | ||
94 | + checkActive(); | ||
95 | + if (ruleNode.isDebugMode()) { | ||
96 | + systemContext.persistDebugInput(tenantId, entityId, msg.getMsg()); | ||
97 | + } | ||
98 | + tbNode.onMsg(defaultCtx, msg.getMsg()); | ||
99 | + } | ||
100 | + | ||
101 | + void onRuleChainToRuleNodeMsg(RuleChainToRuleNodeMsg msg) throws Exception { | ||
102 | + checkActive(); | ||
103 | + if (ruleNode.isDebugMode()) { | ||
104 | + systemContext.persistDebugInput(tenantId, entityId, msg.getMsg()); | ||
105 | + } | ||
106 | + tbNode.onMsg(msg.getCtx(), msg.getMsg()); | ||
107 | + } | ||
108 | + | ||
109 | + private TbNode initComponent(RuleNode ruleNode) throws Exception { | ||
110 | + Class<?> componentClazz = Class.forName(ruleNode.getType()); | ||
111 | + TbNode tbNode = (TbNode) (componentClazz.newInstance()); | ||
112 | + tbNode.init(defaultCtx, new TbNodeConfiguration(ruleNode.getConfiguration())); | ||
113 | + return tbNode; | ||
114 | + } | ||
115 | + | ||
116 | +} |
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.ruleChain; | ||
17 | + | ||
18 | +import akka.actor.ActorRef; | ||
19 | +import lombok.AllArgsConstructor; | ||
20 | +import lombok.Data; | ||
21 | +import org.thingsboard.server.common.data.id.TenantId; | ||
22 | +import org.thingsboard.server.common.data.rule.RuleNode; | ||
23 | + | ||
24 | +/** | ||
25 | + * Created by ashvayka on 19.03.18. | ||
26 | + */ | ||
27 | +@Data | ||
28 | +@AllArgsConstructor | ||
29 | +final class RuleNodeCtx { | ||
30 | + private final TenantId tenantId; | ||
31 | + private final ActorRef chainActor; | ||
32 | + private final ActorRef selfActor; | ||
33 | + private RuleNode self; | ||
34 | +} |
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.ruleChain; | ||
17 | + | ||
18 | +import lombok.Data; | ||
19 | +import org.thingsboard.server.common.data.id.EntityId; | ||
20 | + | ||
21 | +/** | ||
22 | + * Created by ashvayka on 19.03.18. | ||
23 | + */ | ||
24 | + | ||
25 | +@Data | ||
26 | +final class RuleNodeRelation { | ||
27 | + | ||
28 | + private final EntityId in; | ||
29 | + private final EntityId out; | ||
30 | + private final String type; | ||
31 | + | ||
32 | +} |
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.ruleChain; | ||
17 | + | ||
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; | ||
23 | + | ||
24 | +/** | ||
25 | + * Created by ashvayka on 19.03.18. | ||
26 | + */ | ||
27 | +@Data | ||
28 | +final class RuleNodeToRuleChainTellNextMsg implements TbActorMsg { | ||
29 | + | ||
30 | + private final RuleNodeId originator; | ||
31 | + private final String relationType; | ||
32 | + private final TbMsg msg; | ||
33 | + | ||
34 | + @Override | ||
35 | + public MsgType getMsgType() { | ||
36 | + return MsgType.RULE_TO_RULE_CHAIN_TELL_NEXT_MSG; | ||
37 | + } | ||
38 | + | ||
39 | +} |
application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeToSelfErrorMsg.java
0 → 100644
1 | +/** | ||
2 | + * Copyright © 2016-2018 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.actors.ruleChain; | ||
17 | + | ||
18 | +import lombok.Data; | ||
19 | +import org.thingsboard.server.common.msg.MsgType; | ||
20 | +import org.thingsboard.server.common.msg.TbActorMsg; | ||
21 | +import org.thingsboard.server.common.msg.TbMsg; | ||
22 | + | ||
23 | +/** | ||
24 | + * Created by ashvayka on 19.03.18. | ||
25 | + */ | ||
26 | +@Data | ||
27 | +final class RuleNodeToSelfErrorMsg implements TbActorMsg { | ||
28 | + | ||
29 | + private final TbMsg msg; | ||
30 | + private final Throwable error; | ||
31 | + | ||
32 | + @Override | ||
33 | + public MsgType getMsgType() { | ||
34 | + return MsgType.RULE_TO_SELF_ERROR_MSG; | ||
35 | + } | ||
36 | + | ||
37 | +} |
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.ruleChain; | ||
17 | + | ||
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; | ||
23 | + | ||
24 | +/** | ||
25 | + * Created by ashvayka on 19.03.18. | ||
26 | + */ | ||
27 | +@Data | ||
28 | +final class RuleNodeToSelfMsg implements TbActorMsg { | ||
29 | + | ||
30 | + private final TbMsg msg; | ||
31 | + | ||
32 | + @Override | ||
33 | + public MsgType getMsgType() { | ||
34 | + return MsgType.RULE_TO_SELF_MSG; | ||
35 | + } | ||
36 | + | ||
37 | +} |
@@ -15,20 +15,19 @@ | @@ -15,20 +15,19 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.actors.service; | 16 | package org.thingsboard.server.actors.service; |
17 | 17 | ||
18 | -import org.thingsboard.server.common.data.id.DeviceId; | ||
19 | -import org.thingsboard.server.common.data.id.PluginId; | ||
20 | -import org.thingsboard.server.common.data.id.RuleId; | ||
21 | -import org.thingsboard.server.common.data.id.TenantId; | 18 | +import org.thingsboard.server.common.data.id.*; |
22 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; | 19 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; |
20 | +import org.thingsboard.server.common.msg.TbMsg; | ||
21 | +import org.thingsboard.server.common.msg.system.ServiceToRuleEngineMsg; | ||
23 | import org.thingsboard.server.common.transport.SessionMsgProcessor; | 22 | import org.thingsboard.server.common.transport.SessionMsgProcessor; |
24 | import org.thingsboard.server.service.cluster.discovery.DiscoveryServiceListener; | 23 | import org.thingsboard.server.service.cluster.discovery.DiscoveryServiceListener; |
25 | import org.thingsboard.server.service.cluster.rpc.RpcMsgListener; | 24 | import org.thingsboard.server.service.cluster.rpc.RpcMsgListener; |
26 | 25 | ||
27 | public interface ActorService extends SessionMsgProcessor, WebSocketMsgProcessor, RestMsgProcessor, RpcMsgListener, DiscoveryServiceListener { | 26 | public interface ActorService extends SessionMsgProcessor, WebSocketMsgProcessor, RestMsgProcessor, RpcMsgListener, DiscoveryServiceListener { |
28 | 27 | ||
29 | - void onPluginStateChange(TenantId tenantId, PluginId pluginId, ComponentLifecycleEvent state); | 28 | + void onEntityStateChange(TenantId tenantId, EntityId entityId, ComponentLifecycleEvent state); |
30 | 29 | ||
31 | - void onRuleStateChange(TenantId tenantId, RuleId ruleId, ComponentLifecycleEvent state); | 30 | + void onMsg(ServiceToRuleEngineMsg msg); |
32 | 31 | ||
33 | void onCredentialsUpdate(TenantId tenantId, DeviceId deviceId); | 32 | void onCredentialsUpdate(TenantId tenantId, DeviceId deviceId); |
34 | 33 |
@@ -54,7 +54,7 @@ public abstract class ComponentActor<T extends EntityId, P extends ComponentMsgP | @@ -54,7 +54,7 @@ public abstract class ComponentActor<T extends EntityId, P extends ComponentMsgP | ||
54 | @Override | 54 | @Override |
55 | public void preStart() { | 55 | public void preStart() { |
56 | try { | 56 | try { |
57 | - processor.start(); | 57 | + processor.start(context()); |
58 | logLifecycleEvent(ComponentLifecycleEvent.STARTED); | 58 | logLifecycleEvent(ComponentLifecycleEvent.STARTED); |
59 | if (systemContext.isStatisticsEnabled()) { | 59 | if (systemContext.isStatisticsEnabled()) { |
60 | scheduleStatsPersistTick(); | 60 | scheduleStatsPersistTick(); |
@@ -78,7 +78,7 @@ public abstract class ComponentActor<T extends EntityId, P extends ComponentMsgP | @@ -78,7 +78,7 @@ public abstract class ComponentActor<T extends EntityId, P extends ComponentMsgP | ||
78 | @Override | 78 | @Override |
79 | public void postStop() { | 79 | public void postStop() { |
80 | try { | 80 | try { |
81 | - processor.stop(); | 81 | + processor.stop(context()); |
82 | logLifecycleEvent(ComponentLifecycleEvent.STOPPED); | 82 | logLifecycleEvent(ComponentLifecycleEvent.STOPPED); |
83 | } catch (Exception e) { | 83 | } catch (Exception e) { |
84 | logger.warning("[{}][{}] Failed to stop {} processor: {}", tenantId, id, id.getEntityType(), e.getMessage()); | 84 | logger.warning("[{}][{}] Failed to stop {} processor: {}", tenantId, id, id.getEntityType(), e.getMessage()); |
@@ -141,7 +141,6 @@ public abstract class ComponentActor<T extends EntityId, P extends ComponentMsgP | @@ -141,7 +141,6 @@ public abstract class ComponentActor<T extends EntityId, P extends ComponentMsgP | ||
141 | messagesProcessed++; | 141 | messagesProcessed++; |
142 | } | 142 | } |
143 | 143 | ||
144 | - | ||
145 | protected void logAndPersist(String method, Exception e) { | 144 | protected void logAndPersist(String method, Exception e) { |
146 | logAndPersist(method, e, false); | 145 | logAndPersist(method, e, false); |
147 | } | 146 | } |
@@ -16,9 +16,13 @@ | @@ -16,9 +16,13 @@ | ||
16 | package org.thingsboard.server.actors.service; | 16 | package org.thingsboard.server.actors.service; |
17 | 17 | ||
18 | import akka.actor.UntypedActor; | 18 | import akka.actor.UntypedActor; |
19 | +import akka.event.Logging; | ||
20 | +import akka.event.LoggingAdapter; | ||
19 | import org.thingsboard.server.actors.ActorSystemContext; | 21 | import org.thingsboard.server.actors.ActorSystemContext; |
22 | +import org.thingsboard.server.common.msg.TbActorMsg; | ||
20 | 23 | ||
21 | public abstract class ContextAwareActor extends UntypedActor { | 24 | public abstract class ContextAwareActor extends UntypedActor { |
25 | + protected final LoggingAdapter logger = Logging.getLogger(getContext().system(), this); | ||
22 | 26 | ||
23 | public static final int ENTITY_PACK_LIMIT = 1024; | 27 | public static final int ENTITY_PACK_LIMIT = 1024; |
24 | 28 | ||
@@ -28,4 +32,20 @@ public abstract class ContextAwareActor extends UntypedActor { | @@ -28,4 +32,20 @@ public abstract class ContextAwareActor extends UntypedActor { | ||
28 | super(); | 32 | super(); |
29 | this.systemContext = systemContext; | 33 | this.systemContext = systemContext; |
30 | } | 34 | } |
35 | + | ||
36 | + @Override | ||
37 | + public void onReceive(Object msg) throws Exception { | ||
38 | + if (logger.isDebugEnabled()) { | ||
39 | + logger.debug("Processing msg: {}", msg); | ||
40 | + } | ||
41 | + if (msg instanceof TbActorMsg) { | ||
42 | + if(!process((TbActorMsg) msg)){ | ||
43 | + logger.warning("Unknown message: {}!", msg); | ||
44 | + } | ||
45 | + } else { | ||
46 | + logger.warning("Unknown message: {}!", msg); | ||
47 | + } | ||
48 | + } | ||
49 | + | ||
50 | + protected abstract boolean process(TbActorMsg msg); | ||
31 | } | 51 | } |
@@ -30,16 +30,14 @@ import org.thingsboard.server.actors.rpc.RpcSessionCreateRequestMsg; | @@ -30,16 +30,14 @@ import org.thingsboard.server.actors.rpc.RpcSessionCreateRequestMsg; | ||
30 | import org.thingsboard.server.actors.rpc.RpcSessionTellMsg; | 30 | import org.thingsboard.server.actors.rpc.RpcSessionTellMsg; |
31 | import org.thingsboard.server.actors.session.SessionManagerActor; | 31 | import org.thingsboard.server.actors.session.SessionManagerActor; |
32 | import org.thingsboard.server.actors.stats.StatsActor; | 32 | import org.thingsboard.server.actors.stats.StatsActor; |
33 | -import org.thingsboard.server.common.data.id.DeviceId; | ||
34 | -import org.thingsboard.server.common.data.id.PluginId; | ||
35 | -import org.thingsboard.server.common.data.id.RuleId; | ||
36 | -import org.thingsboard.server.common.data.id.TenantId; | 33 | +import org.thingsboard.server.common.data.id.*; |
37 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; | 34 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; |
38 | import org.thingsboard.server.common.msg.aware.SessionAwareMsg; | 35 | import org.thingsboard.server.common.msg.aware.SessionAwareMsg; |
39 | import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; | 36 | import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; |
40 | import org.thingsboard.server.common.msg.cluster.ServerAddress; | 37 | import org.thingsboard.server.common.msg.cluster.ServerAddress; |
41 | import org.thingsboard.server.common.msg.cluster.ToAllNodesMsg; | 38 | import org.thingsboard.server.common.msg.cluster.ToAllNodesMsg; |
42 | import org.thingsboard.server.common.msg.core.ToDeviceSessionActorMsg; | 39 | import org.thingsboard.server.common.msg.core.ToDeviceSessionActorMsg; |
40 | +import org.thingsboard.server.common.msg.system.ServiceToRuleEngineMsg; | ||
43 | import org.thingsboard.server.extensions.api.device.DeviceNameOrTypeUpdateMsg; | 41 | import org.thingsboard.server.extensions.api.device.DeviceNameOrTypeUpdateMsg; |
44 | import org.thingsboard.server.common.msg.device.ToDeviceActorMsg; | 42 | import org.thingsboard.server.common.msg.device.ToDeviceActorMsg; |
45 | import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; | 43 | import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; |
@@ -129,6 +127,11 @@ public class DefaultActorService implements ActorService { | @@ -129,6 +127,11 @@ public class DefaultActorService implements ActorService { | ||
129 | } | 127 | } |
130 | 128 | ||
131 | @Override | 129 | @Override |
130 | + public void onMsg(ServiceToRuleEngineMsg msg) { | ||
131 | + appActor.tell(msg, ActorRef.noSender()); | ||
132 | + } | ||
133 | + | ||
134 | + @Override | ||
132 | public void process(SessionAwareMsg msg) { | 135 | public void process(SessionAwareMsg msg) { |
133 | log.debug("Processing session aware msg: {}", msg); | 136 | log.debug("Processing session aware msg: {}", msg); |
134 | sessionManagerActor.tell(msg, ActorRef.noSender()); | 137 | sessionManagerActor.tell(msg, ActorRef.noSender()); |
@@ -212,15 +215,9 @@ public class DefaultActorService implements ActorService { | @@ -212,15 +215,9 @@ public class DefaultActorService implements ActorService { | ||
212 | } | 215 | } |
213 | 216 | ||
214 | @Override | 217 | @Override |
215 | - public void onPluginStateChange(TenantId tenantId, PluginId pluginId, ComponentLifecycleEvent state) { | ||
216 | - log.trace("[{}] Processing onPluginStateChange event: {}", pluginId, state); | ||
217 | - broadcast(ComponentLifecycleMsg.forPlugin(tenantId, pluginId, state)); | ||
218 | - } | ||
219 | - | ||
220 | - @Override | ||
221 | - public void onRuleStateChange(TenantId tenantId, RuleId ruleId, ComponentLifecycleEvent state) { | ||
222 | - log.trace("[{}] Processing onRuleStateChange event: {}", ruleId, state); | ||
223 | - broadcast(ComponentLifecycleMsg.forRule(tenantId, ruleId, state)); | 218 | + public void onEntityStateChange(TenantId tenantId, EntityId entityId, ComponentLifecycleEvent state) { |
219 | + log.trace("[{}] Processing {} state change event: {}", tenantId, entityId.getEntityType(), state); | ||
220 | + broadcast(new ComponentLifecycleMsg(tenantId, entityId, state)); | ||
224 | } | 221 | } |
225 | 222 | ||
226 | @Override | 223 | @Override |
@@ -23,6 +23,7 @@ import org.thingsboard.server.actors.service.ContextAwareActor; | @@ -23,6 +23,7 @@ import org.thingsboard.server.actors.service.ContextAwareActor; | ||
23 | import org.thingsboard.server.actors.service.ContextBasedCreator; | 23 | import org.thingsboard.server.actors.service.ContextBasedCreator; |
24 | import org.thingsboard.server.actors.shared.SessionTimeoutMsg; | 24 | import org.thingsboard.server.actors.shared.SessionTimeoutMsg; |
25 | import org.thingsboard.server.common.data.id.SessionId; | 25 | import org.thingsboard.server.common.data.id.SessionId; |
26 | +import org.thingsboard.server.common.msg.TbActorMsg; | ||
26 | import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; | 27 | import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; |
27 | import org.thingsboard.server.common.msg.core.ToDeviceSessionActorMsg; | 28 | import org.thingsboard.server.common.msg.core.ToDeviceSessionActorMsg; |
28 | import org.thingsboard.server.common.msg.session.ToDeviceActorSessionMsg; | 29 | import org.thingsboard.server.common.msg.session.ToDeviceActorSessionMsg; |
@@ -61,6 +62,12 @@ public class SessionActor extends ContextAwareActor { | @@ -61,6 +62,12 @@ public class SessionActor extends ContextAwareActor { | ||
61 | } | 62 | } |
62 | 63 | ||
63 | @Override | 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 | public void onReceive(Object msg) throws Exception { | 71 | public void onReceive(Object msg) throws Exception { |
65 | logger.debug("[{}] Processing: {}.", sessionId, msg); | 72 | logger.debug("[{}] Processing: {}.", sessionId, msg); |
66 | if (msg instanceof ToDeviceActorSessionMsg) { | 73 | if (msg instanceof ToDeviceActorSessionMsg) { |
@@ -26,6 +26,7 @@ import org.thingsboard.server.actors.service.ContextBasedCreator; | @@ -26,6 +26,7 @@ import org.thingsboard.server.actors.service.ContextBasedCreator; | ||
26 | import org.thingsboard.server.actors.service.DefaultActorService; | 26 | import org.thingsboard.server.actors.service.DefaultActorService; |
27 | import org.thingsboard.server.actors.shared.SessionTimeoutMsg; | 27 | import org.thingsboard.server.actors.shared.SessionTimeoutMsg; |
28 | import org.thingsboard.server.common.data.id.SessionId; | 28 | import org.thingsboard.server.common.data.id.SessionId; |
29 | +import org.thingsboard.server.common.msg.TbActorMsg; | ||
29 | import org.thingsboard.server.common.msg.aware.SessionAwareMsg; | 30 | import org.thingsboard.server.common.msg.aware.SessionAwareMsg; |
30 | 31 | ||
31 | import akka.event.Logging; | 32 | import akka.event.Logging; |
@@ -49,6 +50,12 @@ public class SessionManagerActor extends ContextAwareActor { | @@ -49,6 +50,12 @@ public class SessionManagerActor extends ContextAwareActor { | ||
49 | } | 50 | } |
50 | 51 | ||
51 | @Override | 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 | public void onReceive(Object msg) throws Exception { | 59 | public void onReceive(Object msg) throws Exception { |
53 | if (msg instanceof SessionCtrlMsg) { | 60 | if (msg instanceof SessionCtrlMsg) { |
54 | onSessionCtrlMsg((SessionCtrlMsg) msg); | 61 | onSessionCtrlMsg((SessionCtrlMsg) msg); |
application/src/main/java/org/thingsboard/server/actors/shared/AbstractContextAwareMsgProcessor.java
@@ -102,9 +102,6 @@ public abstract class AbstractContextAwareMsgProcessor { | @@ -102,9 +102,6 @@ public abstract class AbstractContextAwareMsgProcessor { | ||
102 | case FILTER: | 102 | case FILTER: |
103 | configurationClazz = ((Filter) componentClazz.getAnnotation(Filter.class)).configuration(); | 103 | configurationClazz = ((Filter) componentClazz.getAnnotation(Filter.class)).configuration(); |
104 | break; | 104 | break; |
105 | - case PROCESSOR: | ||
106 | - configurationClazz = ((Processor) componentClazz.getAnnotation(Processor.class)).configuration(); | ||
107 | - break; | ||
108 | case ACTION: | 105 | case ACTION: |
109 | configurationClazz = ((Action) componentClazz.getAnnotation(Action.class)).configuration(); | 106 | configurationClazz = ((Action) componentClazz.getAnnotation(Action.class)).configuration(); |
110 | break; | 107 | break; |
@@ -20,12 +20,14 @@ import akka.event.LoggingAdapter; | @@ -20,12 +20,14 @@ import akka.event.LoggingAdapter; | ||
20 | import org.thingsboard.server.actors.ActorSystemContext; | 20 | import org.thingsboard.server.actors.ActorSystemContext; |
21 | import org.thingsboard.server.actors.stats.StatsPersistTick; | 21 | import org.thingsboard.server.actors.stats.StatsPersistTick; |
22 | import org.thingsboard.server.common.data.id.TenantId; | 22 | import org.thingsboard.server.common.data.id.TenantId; |
23 | +import org.thingsboard.server.common.data.plugin.ComponentLifecycleState; | ||
23 | import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; | 24 | import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; |
24 | 25 | ||
25 | public abstract class ComponentMsgProcessor<T> extends AbstractContextAwareMsgProcessor { | 26 | public abstract class ComponentMsgProcessor<T> extends AbstractContextAwareMsgProcessor { |
26 | 27 | ||
27 | protected final TenantId tenantId; | 28 | protected final TenantId tenantId; |
28 | protected final T entityId; | 29 | protected final T entityId; |
30 | + protected ComponentLifecycleState state; | ||
29 | 31 | ||
30 | protected ComponentMsgProcessor(ActorSystemContext systemContext, LoggingAdapter logger, TenantId tenantId, T id) { | 32 | protected ComponentMsgProcessor(ActorSystemContext systemContext, LoggingAdapter logger, TenantId tenantId, T id) { |
31 | super(systemContext, logger); | 33 | super(systemContext, logger); |
@@ -33,23 +35,44 @@ public abstract class ComponentMsgProcessor<T> extends AbstractContextAwareMsgPr | @@ -33,23 +35,44 @@ public abstract class ComponentMsgProcessor<T> extends AbstractContextAwareMsgPr | ||
33 | this.entityId = id; | 35 | this.entityId = id; |
34 | } | 36 | } |
35 | 37 | ||
36 | - public abstract void start() throws Exception; | 38 | + public abstract void start(ActorContext context) throws Exception; |
37 | 39 | ||
38 | - public abstract void stop() throws Exception; | 40 | + public abstract void stop(ActorContext context) throws Exception; |
39 | 41 | ||
40 | - public abstract void onCreated(ActorContext context) throws Exception; | 42 | + public abstract void onClusterEventMsg(ClusterEventMsg msg) throws Exception; |
41 | 43 | ||
42 | - public abstract void onUpdate(ActorContext context) throws Exception; | 44 | + public void onCreated(ActorContext context) throws Exception { |
45 | + start(context); | ||
46 | + } | ||
43 | 47 | ||
44 | - public abstract void onActivate(ActorContext context) throws Exception; | 48 | + public void onUpdate(ActorContext context) throws Exception { |
49 | + restart(context); | ||
50 | + } | ||
45 | 51 | ||
46 | - public abstract void onSuspend(ActorContext context) throws Exception; | 52 | + public void onActivate(ActorContext context) throws Exception { |
53 | + restart(context); | ||
54 | + } | ||
47 | 55 | ||
48 | - public abstract void onStop(ActorContext context) throws Exception; | 56 | + public void onSuspend(ActorContext context) throws Exception { |
57 | + stop(context); | ||
58 | + } | ||
49 | 59 | ||
50 | - public abstract void onClusterEventMsg(ClusterEventMsg msg) throws Exception; | 60 | + public void onStop(ActorContext context) throws Exception { |
61 | + stop(context); | ||
62 | + } | ||
63 | + | ||
64 | + private void restart(ActorContext context) throws Exception { | ||
65 | + stop(context); | ||
66 | + start(context); | ||
67 | + } | ||
51 | 68 | ||
52 | public void scheduleStatsPersistTick(ActorContext context, long statsPersistFrequency) { | 69 | public void scheduleStatsPersistTick(ActorContext context, long statsPersistFrequency) { |
53 | schedulePeriodicMsgWithDelay(context, new StatsPersistTick(), statsPersistFrequency, statsPersistFrequency); | 70 | schedulePeriodicMsgWithDelay(context, new StatsPersistTick(), statsPersistFrequency, statsPersistFrequency); |
54 | } | 71 | } |
72 | + | ||
73 | + protected void checkActive() { | ||
74 | + if (state != ComponentLifecycleState.ACTIVE) { | ||
75 | + throw new IllegalStateException("Rule chain is not active!"); | ||
76 | + } | ||
77 | + } | ||
55 | } | 78 | } |
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; | ||
17 | + | ||
18 | +import akka.actor.ActorContext; | ||
19 | +import akka.actor.ActorRef; | ||
20 | +import akka.actor.Props; | ||
21 | +import akka.actor.UntypedActor; | ||
22 | +import akka.japi.Creator; | ||
23 | +import lombok.extern.slf4j.Slf4j; | ||
24 | +import org.thingsboard.server.actors.ActorSystemContext; | ||
25 | +import org.thingsboard.server.actors.service.ContextAwareActor; | ||
26 | +import org.thingsboard.server.common.data.SearchTextBased; | ||
27 | +import org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo; | ||
28 | +import org.thingsboard.server.common.data.id.EntityId; | ||
29 | +import org.thingsboard.server.common.data.id.TenantId; | ||
30 | +import org.thingsboard.server.common.data.id.UUIDBased; | ||
31 | +import org.thingsboard.server.common.data.page.PageDataIterable; | ||
32 | +import org.thingsboard.server.common.data.plugin.PluginMetaData; | ||
33 | + | ||
34 | +import java.util.HashMap; | ||
35 | +import java.util.Map; | ||
36 | + | ||
37 | +/** | ||
38 | + * Created by ashvayka on 15.03.18. | ||
39 | + */ | ||
40 | +@Slf4j | ||
41 | +public abstract class EntityActorsManager<T extends EntityId, A extends UntypedActor, M extends SearchTextBased<? extends UUIDBased>> { | ||
42 | + | ||
43 | + protected final ActorSystemContext systemContext; | ||
44 | + protected final Map<T, ActorRef> actors; | ||
45 | + | ||
46 | + public EntityActorsManager(ActorSystemContext systemContext) { | ||
47 | + this.systemContext = systemContext; | ||
48 | + this.actors = new HashMap<>(); | ||
49 | + } | ||
50 | + | ||
51 | + protected abstract TenantId getTenantId(); | ||
52 | + | ||
53 | + protected abstract String getDispatcherName(); | ||
54 | + | ||
55 | + protected abstract Creator<A> creator(T entityId); | ||
56 | + | ||
57 | + protected abstract PageDataIterable.FetchFunction<M> getFetchEntitiesFunction(); | ||
58 | + | ||
59 | + public void init(ActorContext context) { | ||
60 | + for (M entity : new PageDataIterable<>(getFetchEntitiesFunction(), ContextAwareActor.ENTITY_PACK_LIMIT)) { | ||
61 | + T entityId = (T) entity.getId(); | ||
62 | + log.debug("[{}|{}] Creating entity actor", entityId.getEntityType(), entityId.getId()); | ||
63 | + //TODO: remove this cast making UUIDBased subclass of EntityId an interface and vice versa. | ||
64 | + ActorRef actorRef = getOrCreateActor(context, entityId); | ||
65 | + visit(entity, actorRef); | ||
66 | + log.debug("[{}|{}] Entity actor created.", entityId.getEntityType(), entityId.getId()); | ||
67 | + } | ||
68 | + } | ||
69 | + | ||
70 | + protected void visit(M entity, ActorRef actorRef) {} | ||
71 | + | ||
72 | + public ActorRef getOrCreateActor(ActorContext context, T entityId) { | ||
73 | + return actors.computeIfAbsent(entityId, eId -> | ||
74 | + context.actorOf(Props.create(creator(eId)) | ||
75 | + .withDispatcher(getDispatcherName()), eId.toString())); | ||
76 | + } | ||
77 | + | ||
78 | + public void broadcast(Object msg) { | ||
79 | + actors.values().forEach(actorRef -> actorRef.tell(msg, ActorRef.noSender())); | ||
80 | + } | ||
81 | + | ||
82 | + public void remove(T id) { | ||
83 | + actors.remove(id); | ||
84 | + } | ||
85 | + | ||
86 | +} |
@@ -15,63 +15,28 @@ | @@ -15,63 +15,28 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.actors.shared.plugin; | 16 | package org.thingsboard.server.actors.shared.plugin; |
17 | 17 | ||
18 | -import akka.actor.ActorContext; | ||
19 | -import akka.actor.ActorRef; | ||
20 | -import akka.actor.Props; | 18 | +import akka.japi.Creator; |
21 | import lombok.extern.slf4j.Slf4j; | 19 | import lombok.extern.slf4j.Slf4j; |
22 | import org.thingsboard.server.actors.ActorSystemContext; | 20 | import org.thingsboard.server.actors.ActorSystemContext; |
23 | import org.thingsboard.server.actors.plugin.PluginActor; | 21 | import org.thingsboard.server.actors.plugin.PluginActor; |
24 | -import org.thingsboard.server.actors.service.ContextAwareActor; | 22 | +import org.thingsboard.server.actors.shared.EntityActorsManager; |
25 | import org.thingsboard.server.common.data.id.PluginId; | 23 | import org.thingsboard.server.common.data.id.PluginId; |
26 | -import org.thingsboard.server.common.data.id.TenantId; | ||
27 | -import org.thingsboard.server.common.data.page.PageDataIterable; | ||
28 | -import org.thingsboard.server.common.data.page.PageDataIterable.FetchFunction; | ||
29 | import org.thingsboard.server.common.data.plugin.PluginMetaData; | 24 | import org.thingsboard.server.common.data.plugin.PluginMetaData; |
30 | import org.thingsboard.server.dao.plugin.PluginService; | 25 | import org.thingsboard.server.dao.plugin.PluginService; |
31 | 26 | ||
32 | -import java.util.HashMap; | ||
33 | -import java.util.Map; | ||
34 | - | ||
35 | @Slf4j | 27 | @Slf4j |
36 | -public abstract class PluginManager { | 28 | +public abstract class PluginManager extends EntityActorsManager<PluginId, PluginActor, PluginMetaData> { |
37 | 29 | ||
38 | - protected final ActorSystemContext systemContext; | ||
39 | protected final PluginService pluginService; | 30 | protected final PluginService pluginService; |
40 | - protected final Map<PluginId, ActorRef> pluginActors; | ||
41 | 31 | ||
42 | public PluginManager(ActorSystemContext systemContext) { | 32 | public PluginManager(ActorSystemContext systemContext) { |
43 | - this.systemContext = systemContext; | 33 | + super(systemContext); |
44 | this.pluginService = systemContext.getPluginService(); | 34 | this.pluginService = systemContext.getPluginService(); |
45 | - this.pluginActors = new HashMap<>(); | ||
46 | } | 35 | } |
47 | 36 | ||
48 | - public void init(ActorContext context) { | ||
49 | - PageDataIterable<PluginMetaData> pluginIterator = new PageDataIterable<>(getFetchPluginsFunction(), | ||
50 | - ContextAwareActor.ENTITY_PACK_LIMIT); | ||
51 | - for (PluginMetaData plugin : pluginIterator) { | ||
52 | - log.debug("[{}] Creating plugin actor", plugin.getId()); | ||
53 | - getOrCreatePluginActor(context, plugin.getId()); | ||
54 | - log.debug("Plugin actor created."); | ||
55 | - } | 37 | + @Override |
38 | + public Creator<PluginActor> creator(PluginId entityId){ | ||
39 | + return new PluginActor.ActorCreator(systemContext, getTenantId(), entityId); | ||
56 | } | 40 | } |
57 | 41 | ||
58 | - abstract FetchFunction<PluginMetaData> getFetchPluginsFunction(); | ||
59 | - | ||
60 | - abstract TenantId getTenantId(); | ||
61 | - | ||
62 | - abstract String getDispatcherName(); | ||
63 | - | ||
64 | - public ActorRef getOrCreatePluginActor(ActorContext context, PluginId pluginId) { | ||
65 | - return pluginActors.computeIfAbsent(pluginId, pId -> | ||
66 | - context.actorOf(Props.create(new PluginActor.ActorCreator(systemContext, getTenantId(), pId)) | ||
67 | - .withDispatcher(getDispatcherName()), pId.toString())); | ||
68 | - } | ||
69 | - | ||
70 | - public void broadcast(Object msg) { | ||
71 | - pluginActors.values().forEach(actorRef -> actorRef.tell(msg, ActorRef.noSender())); | ||
72 | - } | ||
73 | - | ||
74 | - public void remove(PluginId id) { | ||
75 | - pluginActors.remove(id); | ||
76 | - } | ||
77 | } | 42 | } |
@@ -29,12 +29,12 @@ public class SystemPluginManager extends PluginManager { | @@ -29,12 +29,12 @@ public class SystemPluginManager extends PluginManager { | ||
29 | } | 29 | } |
30 | 30 | ||
31 | @Override | 31 | @Override |
32 | - FetchFunction<PluginMetaData> getFetchPluginsFunction() { | 32 | + protected FetchFunction<PluginMetaData> getFetchEntitiesFunction() { |
33 | return pluginService::findSystemPlugins; | 33 | return pluginService::findSystemPlugins; |
34 | } | 34 | } |
35 | 35 | ||
36 | @Override | 36 | @Override |
37 | - TenantId getTenantId() { | 37 | + protected TenantId getTenantId() { |
38 | return BasePluginService.SYSTEM_TENANT; | 38 | return BasePluginService.SYSTEM_TENANT; |
39 | } | 39 | } |
40 | 40 |
@@ -19,6 +19,7 @@ import akka.actor.ActorContext; | @@ -19,6 +19,7 @@ import akka.actor.ActorContext; | ||
19 | import org.thingsboard.server.actors.ActorSystemContext; | 19 | import org.thingsboard.server.actors.ActorSystemContext; |
20 | import org.thingsboard.server.actors.service.DefaultActorService; | 20 | import org.thingsboard.server.actors.service.DefaultActorService; |
21 | import org.thingsboard.server.common.data.id.TenantId; | 21 | import org.thingsboard.server.common.data.id.TenantId; |
22 | +import org.thingsboard.server.common.data.page.PageDataIterable; | ||
22 | import org.thingsboard.server.common.data.page.PageDataIterable.FetchFunction; | 23 | import org.thingsboard.server.common.data.page.PageDataIterable.FetchFunction; |
23 | import org.thingsboard.server.common.data.plugin.PluginMetaData; | 24 | import org.thingsboard.server.common.data.plugin.PluginMetaData; |
24 | 25 | ||
@@ -39,12 +40,12 @@ public class TenantPluginManager extends PluginManager { | @@ -39,12 +40,12 @@ public class TenantPluginManager extends PluginManager { | ||
39 | } | 40 | } |
40 | 41 | ||
41 | @Override | 42 | @Override |
42 | - FetchFunction<PluginMetaData> getFetchPluginsFunction() { | 43 | + protected FetchFunction<PluginMetaData> getFetchEntitiesFunction() { |
43 | return link -> pluginService.findTenantPlugins(tenantId, link); | 44 | return link -> pluginService.findTenantPlugins(tenantId, link); |
44 | } | 45 | } |
45 | 46 | ||
46 | @Override | 47 | @Override |
47 | - TenantId getTenantId() { | 48 | + protected TenantId getTenantId() { |
48 | return tenantId; | 49 | return tenantId; |
49 | } | 50 | } |
50 | 51 |
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/rulechain/RuleChainManager.java
0 → 100644
1 | +/** | ||
2 | + * Copyright © 2016-2018 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.actors.shared.rulechain; | ||
17 | + | ||
18 | +import akka.actor.ActorRef; | ||
19 | +import akka.japi.Creator; | ||
20 | +import lombok.Getter; | ||
21 | +import lombok.extern.slf4j.Slf4j; | ||
22 | +import org.thingsboard.server.actors.ActorSystemContext; | ||
23 | +import org.thingsboard.server.actors.ruleChain.RuleChainActor; | ||
24 | +import org.thingsboard.server.actors.shared.EntityActorsManager; | ||
25 | +import org.thingsboard.server.common.data.id.RuleChainId; | ||
26 | +import org.thingsboard.server.common.data.rule.RuleChain; | ||
27 | +import org.thingsboard.server.dao.rule.RuleChainService; | ||
28 | + | ||
29 | +/** | ||
30 | + * Created by ashvayka on 15.03.18. | ||
31 | + */ | ||
32 | +@Slf4j | ||
33 | +public abstract class RuleChainManager extends EntityActorsManager<RuleChainId, RuleChainActor, RuleChain> { | ||
34 | + | ||
35 | + protected final RuleChainService service; | ||
36 | + @Getter | ||
37 | + protected RuleChain rootChain; | ||
38 | + @Getter | ||
39 | + protected ActorRef rootChainActor; | ||
40 | + | ||
41 | + public RuleChainManager(ActorSystemContext systemContext) { | ||
42 | + super(systemContext); | ||
43 | + this.service = systemContext.getRuleChainService(); | ||
44 | + } | ||
45 | + | ||
46 | + @Override | ||
47 | + public Creator<RuleChainActor> creator(RuleChainId entityId) { | ||
48 | + return new RuleChainActor.ActorCreator(systemContext, getTenantId(), entityId); | ||
49 | + } | ||
50 | + | ||
51 | + @Override | ||
52 | + protected void visit(RuleChain entity, ActorRef actorRef) { | ||
53 | + if (entity.isRoot()) { | ||
54 | + rootChain = entity; | ||
55 | + rootChainActor = actorRef; | ||
56 | + } | ||
57 | + } | ||
58 | + | ||
59 | +} |
application/src/main/java/org/thingsboard/server/actors/shared/rulechain/SystemRuleChainManager.java
renamed from
application/src/main/java/org/thingsboard/server/actors/shared/rule/SystemRuleManager.java
@@ -13,28 +13,35 @@ | @@ -13,28 +13,35 @@ | ||
13 | * See the License for the specific language governing permissions and | 13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | -package org.thingsboard.server.actors.shared.rule; | 16 | +package org.thingsboard.server.actors.shared.rulechain; |
17 | 17 | ||
18 | import org.thingsboard.server.actors.ActorSystemContext; | 18 | import org.thingsboard.server.actors.ActorSystemContext; |
19 | import org.thingsboard.server.actors.service.DefaultActorService; | 19 | import org.thingsboard.server.actors.service.DefaultActorService; |
20 | +import org.thingsboard.server.actors.shared.plugin.PluginManager; | ||
20 | import org.thingsboard.server.common.data.id.TenantId; | 21 | 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.page.PageDataIterable.FetchFunction; |
22 | -import org.thingsboard.server.common.data.rule.RuleMetaData; | ||
23 | -import org.thingsboard.server.dao.model.ModelConstants; | 23 | +import org.thingsboard.server.common.data.plugin.PluginMetaData; |
24 | +import org.thingsboard.server.common.data.rule.RuleChain; | ||
25 | +import org.thingsboard.server.dao.plugin.BasePluginService; | ||
24 | 26 | ||
25 | -public class SystemRuleManager extends RuleManager { | 27 | +public class SystemRuleChainManager extends RuleChainManager { |
26 | 28 | ||
27 | - public SystemRuleManager(ActorSystemContext systemContext) { | ||
28 | - super(systemContext, new TenantId(ModelConstants.NULL_UUID)); | 29 | + public SystemRuleChainManager(ActorSystemContext systemContext) { |
30 | + super(systemContext); | ||
29 | } | 31 | } |
30 | 32 | ||
31 | @Override | 33 | @Override |
32 | - FetchFunction<RuleMetaData> getFetchRulesFunction() { | ||
33 | - return ruleService::findSystemRules; | 34 | + protected FetchFunction<RuleChain> getFetchEntitiesFunction() { |
35 | + return service::findSystemRuleChains; | ||
34 | } | 36 | } |
35 | 37 | ||
36 | @Override | 38 | @Override |
37 | - String getDispatcherName() { | 39 | + protected TenantId getTenantId() { |
40 | + return BasePluginService.SYSTEM_TENANT; | ||
41 | + } | ||
42 | + | ||
43 | + @Override | ||
44 | + protected String getDispatcherName() { | ||
38 | return DefaultActorService.SYSTEM_RULE_DISPATCHER_NAME; | 45 | return DefaultActorService.SYSTEM_RULE_DISPATCHER_NAME; |
39 | } | 46 | } |
40 | } | 47 | } |
application/src/main/java/org/thingsboard/server/actors/shared/rulechain/TenantRuleChainManager.java
renamed from
application/src/main/java/org/thingsboard/server/actors/shared/rule/TenantRuleManager.java
@@ -13,19 +13,22 @@ | @@ -13,19 +13,22 @@ | ||
13 | * See the License for the specific language governing permissions and | 13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | -package org.thingsboard.server.actors.shared.rule; | 16 | +package org.thingsboard.server.actors.shared.rulechain; |
17 | 17 | ||
18 | import akka.actor.ActorContext; | 18 | import akka.actor.ActorContext; |
19 | import org.thingsboard.server.actors.ActorSystemContext; | 19 | import org.thingsboard.server.actors.ActorSystemContext; |
20 | import org.thingsboard.server.actors.service.DefaultActorService; | 20 | import org.thingsboard.server.actors.service.DefaultActorService; |
21 | import org.thingsboard.server.common.data.id.TenantId; | 21 | import org.thingsboard.server.common.data.id.TenantId; |
22 | import org.thingsboard.server.common.data.page.PageDataIterable.FetchFunction; | 22 | import org.thingsboard.server.common.data.page.PageDataIterable.FetchFunction; |
23 | -import org.thingsboard.server.common.data.rule.RuleMetaData; | 23 | +import org.thingsboard.server.common.data.rule.RuleChain; |
24 | 24 | ||
25 | -public class TenantRuleManager extends RuleManager { | ||
26 | - | ||
27 | - public TenantRuleManager(ActorSystemContext systemContext, TenantId tenantId) { | ||
28 | - super(systemContext, tenantId); | 25 | +public class TenantRuleChainManager extends RuleChainManager { |
26 | + | ||
27 | + private final TenantId tenantId; | ||
28 | + | ||
29 | + public TenantRuleChainManager(ActorSystemContext systemContext, TenantId tenantId) { | ||
30 | + super(systemContext); | ||
31 | + this.tenantId = tenantId; | ||
29 | } | 32 | } |
30 | 33 | ||
31 | @Override | 34 | @Override |
@@ -36,13 +39,17 @@ public class TenantRuleManager extends RuleManager { | @@ -36,13 +39,17 @@ public class TenantRuleManager extends RuleManager { | ||
36 | } | 39 | } |
37 | 40 | ||
38 | @Override | 41 | @Override |
39 | - FetchFunction<RuleMetaData> getFetchRulesFunction() { | ||
40 | - return link -> ruleService.findTenantRules(tenantId, link); | 42 | + protected TenantId getTenantId() { |
43 | + return tenantId; | ||
41 | } | 44 | } |
42 | 45 | ||
43 | @Override | 46 | @Override |
44 | - String getDispatcherName() { | 47 | + protected String getDispatcherName() { |
45 | return DefaultActorService.TENANT_RULE_DISPATCHER_NAME; | 48 | return DefaultActorService.TENANT_RULE_DISPATCHER_NAME; |
46 | } | 49 | } |
47 | 50 | ||
51 | + @Override | ||
52 | + protected FetchFunction<RuleChain> getFetchEntitiesFunction() { | ||
53 | + return link -> service.findTenantRuleChains(tenantId, link); | ||
54 | + } | ||
48 | } | 55 | } |
@@ -24,6 +24,7 @@ import org.thingsboard.server.actors.service.ContextAwareActor; | @@ -24,6 +24,7 @@ import org.thingsboard.server.actors.service.ContextAwareActor; | ||
24 | import org.thingsboard.server.actors.service.ContextBasedCreator; | 24 | import org.thingsboard.server.actors.service.ContextBasedCreator; |
25 | import org.thingsboard.server.common.data.DataConstants; | 25 | import org.thingsboard.server.common.data.DataConstants; |
26 | import org.thingsboard.server.common.data.Event; | 26 | import org.thingsboard.server.common.data.Event; |
27 | +import org.thingsboard.server.common.msg.TbActorMsg; | ||
27 | import org.thingsboard.server.common.msg.cluster.ServerAddress; | 28 | import org.thingsboard.server.common.msg.cluster.ServerAddress; |
28 | 29 | ||
29 | public class StatsActor extends ContextAwareActor { | 30 | public class StatsActor extends ContextAwareActor { |
@@ -36,6 +37,12 @@ public class StatsActor extends ContextAwareActor { | @@ -36,6 +37,12 @@ public class StatsActor extends ContextAwareActor { | ||
36 | } | 37 | } |
37 | 38 | ||
38 | @Override | 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 | public void onReceive(Object msg) throws Exception { | 46 | public void onReceive(Object msg) throws Exception { |
40 | logger.debug("Received message: {}", msg); | 47 | logger.debug("Received message: {}", msg); |
41 | if (msg instanceof StatsPersistMsg) { | 48 | if (msg instanceof StatsPersistMsg) { |
@@ -15,52 +15,38 @@ | @@ -15,52 +15,38 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.actors.tenant; | 16 | package org.thingsboard.server.actors.tenant; |
17 | 17 | ||
18 | -import java.util.HashMap; | ||
19 | -import java.util.Map; | ||
20 | -import java.util.Optional; | ||
21 | - | 18 | +import akka.actor.ActorRef; |
19 | +import akka.actor.Props; | ||
20 | +import akka.event.Logging; | ||
21 | +import akka.event.LoggingAdapter; | ||
22 | import org.thingsboard.server.actors.ActorSystemContext; | 22 | import org.thingsboard.server.actors.ActorSystemContext; |
23 | import org.thingsboard.server.actors.device.DeviceActor; | 23 | import org.thingsboard.server.actors.device.DeviceActor; |
24 | import org.thingsboard.server.actors.plugin.PluginTerminationMsg; | 24 | import org.thingsboard.server.actors.plugin.PluginTerminationMsg; |
25 | -import org.thingsboard.server.actors.rule.ComplexRuleActorChain; | ||
26 | -import org.thingsboard.server.actors.rule.RuleActorChain; | ||
27 | -import org.thingsboard.server.actors.service.ContextAwareActor; | 25 | +import org.thingsboard.server.actors.ruleChain.RuleChainManagerActor; |
28 | import org.thingsboard.server.actors.service.ContextBasedCreator; | 26 | import org.thingsboard.server.actors.service.ContextBasedCreator; |
29 | import org.thingsboard.server.actors.service.DefaultActorService; | 27 | import org.thingsboard.server.actors.service.DefaultActorService; |
30 | -import org.thingsboard.server.actors.shared.plugin.PluginManager; | ||
31 | import org.thingsboard.server.actors.shared.plugin.TenantPluginManager; | 28 | import org.thingsboard.server.actors.shared.plugin.TenantPluginManager; |
32 | -import org.thingsboard.server.actors.shared.rule.RuleManager; | ||
33 | -import org.thingsboard.server.actors.shared.rule.TenantRuleManager; | 29 | +import org.thingsboard.server.actors.shared.rulechain.TenantRuleChainManager; |
34 | import org.thingsboard.server.common.data.id.DeviceId; | 30 | import org.thingsboard.server.common.data.id.DeviceId; |
35 | -import org.thingsboard.server.common.data.id.PluginId; | ||
36 | -import org.thingsboard.server.common.data.id.RuleId; | ||
37 | import org.thingsboard.server.common.data.id.TenantId; | 31 | import org.thingsboard.server.common.data.id.TenantId; |
38 | -import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; | 32 | +import org.thingsboard.server.common.msg.TbActorMsg; |
39 | import org.thingsboard.server.common.msg.device.ToDeviceActorMsg; | 33 | import org.thingsboard.server.common.msg.device.ToDeviceActorMsg; |
40 | - | ||
41 | -import akka.actor.ActorRef; | ||
42 | -import akka.actor.Props; | ||
43 | -import akka.event.Logging; | ||
44 | -import akka.event.LoggingAdapter; | ||
45 | import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; | 34 | import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; |
35 | +import org.thingsboard.server.common.msg.system.ServiceToRuleEngineMsg; | ||
46 | import org.thingsboard.server.extensions.api.device.ToDeviceActorNotificationMsg; | 36 | import org.thingsboard.server.extensions.api.device.ToDeviceActorNotificationMsg; |
47 | import org.thingsboard.server.extensions.api.plugins.msg.ToPluginActorMsg; | 37 | import org.thingsboard.server.extensions.api.plugins.msg.ToPluginActorMsg; |
48 | -import org.thingsboard.server.extensions.api.rules.ToRuleActorMsg; | ||
49 | 38 | ||
50 | -public class TenantActor extends ContextAwareActor { | 39 | +import java.util.HashMap; |
40 | +import java.util.Map; | ||
51 | 41 | ||
52 | - private final LoggingAdapter logger = Logging.getLogger(getContext().system(), this); | 42 | +public class TenantActor extends RuleChainManagerActor { |
53 | 43 | ||
54 | private final TenantId tenantId; | 44 | private final TenantId tenantId; |
55 | - private final RuleManager ruleManager; | ||
56 | - private final PluginManager pluginManager; | ||
57 | private final Map<DeviceId, ActorRef> deviceActors; | 45 | private final Map<DeviceId, ActorRef> deviceActors; |
58 | 46 | ||
59 | private TenantActor(ActorSystemContext systemContext, TenantId tenantId) { | 47 | private TenantActor(ActorSystemContext systemContext, TenantId tenantId) { |
60 | - super(systemContext); | 48 | + super(systemContext, new TenantRuleChainManager(systemContext, tenantId), new TenantPluginManager(systemContext, tenantId)); |
61 | this.tenantId = tenantId; | 49 | this.tenantId = tenantId; |
62 | - this.ruleManager = new TenantRuleManager(systemContext, tenantId); | ||
63 | - this.pluginManager = new TenantPluginManager(systemContext, tenantId); | ||
64 | this.deviceActors = new HashMap<>(); | 50 | this.deviceActors = new HashMap<>(); |
65 | } | 51 | } |
66 | 52 | ||
@@ -68,8 +54,7 @@ public class TenantActor extends ContextAwareActor { | @@ -68,8 +54,7 @@ public class TenantActor extends ContextAwareActor { | ||
68 | public void preStart() { | 54 | public void preStart() { |
69 | logger.info("[{}] Starting tenant actor.", tenantId); | 55 | logger.info("[{}] Starting tenant actor.", tenantId); |
70 | try { | 56 | try { |
71 | - ruleManager.init(this.context()); | ||
72 | - pluginManager.init(this.context()); | 57 | + initRuleChains(); |
73 | logger.info("[{}] Tenant actor started.", tenantId); | 58 | logger.info("[{}] Tenant actor started.", tenantId); |
74 | } catch (Exception e) { | 59 | } catch (Exception e) { |
75 | logger.error(e, "[{}] Unknown failure", tenantId); | 60 | logger.error(e, "[{}] Unknown failure", tenantId); |
@@ -77,29 +62,45 @@ public class TenantActor extends ContextAwareActor { | @@ -77,29 +62,45 @@ public class TenantActor extends ContextAwareActor { | ||
77 | } | 62 | } |
78 | 63 | ||
79 | @Override | 64 | @Override |
80 | - public void onReceive(Object msg) throws Exception { | ||
81 | - logger.debug("[{}] Received message: {}", tenantId, msg); | ||
82 | - if (msg instanceof RuleChainDeviceMsg) { | ||
83 | - process((RuleChainDeviceMsg) msg); | ||
84 | - } else if (msg instanceof ToDeviceActorMsg) { | ||
85 | - onToDeviceActorMsg((ToDeviceActorMsg) msg); | ||
86 | - } else if (msg instanceof ToPluginActorMsg) { | ||
87 | - onToPluginMsg((ToPluginActorMsg) msg); | ||
88 | - } else if (msg instanceof ToRuleActorMsg) { | ||
89 | - onToRuleMsg((ToRuleActorMsg) msg); | ||
90 | - } else if (msg instanceof ToDeviceActorNotificationMsg) { | ||
91 | - onToDeviceActorMsg((ToDeviceActorNotificationMsg) msg); | ||
92 | - } else if (msg instanceof ClusterEventMsg) { | ||
93 | - broadcast(msg); | ||
94 | - } else if (msg instanceof ComponentLifecycleMsg) { | ||
95 | - onComponentLifecycleMsg((ComponentLifecycleMsg) msg); | ||
96 | - } else if (msg instanceof PluginTerminationMsg) { | ||
97 | - onPluginTerminated((PluginTerminationMsg) msg); | ||
98 | - } else { | ||
99 | - logger.warning("[{}] Unknown message: {}!", tenantId, msg); | 65 | + protected boolean process(TbActorMsg msg) { |
66 | + switch (msg.getMsgType()) { | ||
67 | + case COMPONENT_LIFE_CYCLE_MSG: | ||
68 | + onComponentLifecycleMsg((ComponentLifecycleMsg) msg); | ||
69 | + break; | ||
70 | + case SERVICE_TO_RULE_ENGINE_MSG: | ||
71 | + onServiceToRuleEngineMsg((ServiceToRuleEngineMsg) msg); | ||
72 | + break; | ||
73 | + default: | ||
74 | + return false; | ||
100 | } | 75 | } |
76 | + return true; | ||
101 | } | 77 | } |
102 | 78 | ||
79 | + private void onServiceToRuleEngineMsg(ServiceToRuleEngineMsg msg) { | ||
80 | + ruleChainManager.getRootChainActor().tell(msg, self()); | ||
81 | + } | ||
82 | + | ||
83 | + | ||
84 | +// @Override | ||
85 | +// public void onReceive(Object msg) throws Exception { | ||
86 | +// logger.debug("[{}] Received message: {}", tenantId, msg); | ||
87 | +// if (msg instanceof ToDeviceActorMsg) { | ||
88 | +// onToDeviceActorMsg((ToDeviceActorMsg) msg); | ||
89 | +// } else if (msg instanceof ToPluginActorMsg) { | ||
90 | +// onToPluginMsg((ToPluginActorMsg) msg); | ||
91 | +// } else if (msg instanceof ToDeviceActorNotificationMsg) { | ||
92 | +// onToDeviceActorMsg((ToDeviceActorNotificationMsg) msg); | ||
93 | +// } else if (msg instanceof ClusterEventMsg) { | ||
94 | +// broadcast(msg); | ||
95 | +// } else if (msg instanceof ComponentLifecycleMsg) { | ||
96 | +// onComponentLifecycleMsg((ComponentLifecycleMsg) msg); | ||
97 | +// } else if (msg instanceof PluginTerminationMsg) { | ||
98 | +// onPluginTerminated((PluginTerminationMsg) msg); | ||
99 | +// } else { | ||
100 | +// logger.warning("[{}] Unknown message: {}!", tenantId, msg); | ||
101 | +// } | ||
102 | +// } | ||
103 | + | ||
103 | private void broadcast(Object msg) { | 104 | private void broadcast(Object msg) { |
104 | pluginManager.broadcast(msg); | 105 | pluginManager.broadcast(msg); |
105 | deviceActors.values().forEach(actorRef -> actorRef.tell(msg, ActorRef.noSender())); | 106 | deviceActors.values().forEach(actorRef -> actorRef.tell(msg, ActorRef.noSender())); |
@@ -113,14 +114,9 @@ public class TenantActor extends ContextAwareActor { | @@ -113,14 +114,9 @@ public class TenantActor extends ContextAwareActor { | ||
113 | getOrCreateDeviceActor(msg.getDeviceId()).tell(msg, ActorRef.noSender()); | 114 | getOrCreateDeviceActor(msg.getDeviceId()).tell(msg, ActorRef.noSender()); |
114 | } | 115 | } |
115 | 116 | ||
116 | - private void onToRuleMsg(ToRuleActorMsg msg) { | ||
117 | - ActorRef target = ruleManager.getOrCreateRuleActor(this.context(), msg.getRuleId()); | ||
118 | - target.tell(msg, ActorRef.noSender()); | ||
119 | - } | ||
120 | - | ||
121 | private void onToPluginMsg(ToPluginActorMsg msg) { | 117 | private void onToPluginMsg(ToPluginActorMsg msg) { |
122 | if (msg.getPluginTenantId().equals(tenantId)) { | 118 | if (msg.getPluginTenantId().equals(tenantId)) { |
123 | - ActorRef pluginActor = pluginManager.getOrCreatePluginActor(this.context(), msg.getPluginId()); | 119 | + ActorRef pluginActor = pluginManager.getOrCreateActor(this.context(), msg.getPluginId()); |
124 | pluginActor.tell(msg, ActorRef.noSender()); | 120 | pluginActor.tell(msg, ActorRef.noSender()); |
125 | } else { | 121 | } else { |
126 | context().parent().tell(msg, ActorRef.noSender()); | 122 | context().parent().tell(msg, ActorRef.noSender()); |
@@ -128,23 +124,11 @@ public class TenantActor extends ContextAwareActor { | @@ -128,23 +124,11 @@ public class TenantActor extends ContextAwareActor { | ||
128 | } | 124 | } |
129 | 125 | ||
130 | private void onComponentLifecycleMsg(ComponentLifecycleMsg msg) { | 126 | private void onComponentLifecycleMsg(ComponentLifecycleMsg msg) { |
131 | - Optional<PluginId> pluginId = msg.getPluginId(); | ||
132 | - Optional<RuleId> ruleId = msg.getRuleId(); | ||
133 | - if (pluginId.isPresent()) { | ||
134 | - ActorRef pluginActor = pluginManager.getOrCreatePluginActor(this.context(), pluginId.get()); | ||
135 | - pluginActor.tell(msg, ActorRef.noSender()); | ||
136 | - } else if (ruleId.isPresent()) { | ||
137 | - ActorRef target; | ||
138 | - Optional<ActorRef> ref = ruleManager.update(this.context(), ruleId.get(), msg.getEvent()); | ||
139 | - if (ref.isPresent()) { | ||
140 | - target = ref.get(); | ||
141 | - } else { | ||
142 | - logger.debug("Failed to find actor for rule: [{}]", ruleId); | ||
143 | - return; | ||
144 | - } | 127 | + ActorRef target = getEntityActorRef(msg.getEntityId()); |
128 | + if (target != null) { | ||
145 | target.tell(msg, ActorRef.noSender()); | 129 | target.tell(msg, ActorRef.noSender()); |
146 | } else { | 130 | } else { |
147 | - logger.debug("[{}] Invalid component lifecycle msg.", tenantId); | 131 | + logger.debug("Invalid component lifecycle msg: {}", msg); |
148 | } | 132 | } |
149 | } | 133 | } |
150 | 134 | ||
@@ -152,13 +136,6 @@ public class TenantActor extends ContextAwareActor { | @@ -152,13 +136,6 @@ public class TenantActor extends ContextAwareActor { | ||
152 | pluginManager.remove(msg.getId()); | 136 | pluginManager.remove(msg.getId()); |
153 | } | 137 | } |
154 | 138 | ||
155 | - private void process(RuleChainDeviceMsg msg) { | ||
156 | - ToDeviceActorMsg toDeviceActorMsg = msg.getToDeviceActorMsg(); | ||
157 | - ActorRef deviceActor = getOrCreateDeviceActor(toDeviceActorMsg.getDeviceId()); | ||
158 | - RuleActorChain tenantChain = ruleManager.getRuleChain(this.context()); | ||
159 | - RuleActorChain chain = new ComplexRuleActorChain(msg.getRuleChain(), tenantChain); | ||
160 | - deviceActor.tell(new RuleChainDeviceMsg(toDeviceActorMsg, chain), context().self()); | ||
161 | - } | ||
162 | 139 | ||
163 | private ActorRef getOrCreateDeviceActor(DeviceId deviceId) { | 140 | private ActorRef getOrCreateDeviceActor(DeviceId deviceId) { |
164 | return deviceActors.computeIfAbsent(deviceId, k -> context().actorOf(Props.create(new DeviceActor.ActorCreator(systemContext, tenantId, deviceId)) | 141 | return deviceActors.computeIfAbsent(deviceId, k -> context().actorOf(Props.create(new DeviceActor.ActorCreator(systemContext, tenantId, deviceId)) |
@@ -20,7 +20,6 @@ import org.springframework.beans.factory.annotation.Autowired; | @@ -20,7 +20,6 @@ import org.springframework.beans.factory.annotation.Autowired; | ||
20 | import org.springframework.beans.factory.annotation.Qualifier; | 20 | import org.springframework.beans.factory.annotation.Qualifier; |
21 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; | 21 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; |
22 | import org.springframework.boot.autoconfigure.security.SecurityProperties; | 22 | import org.springframework.boot.autoconfigure.security.SecurityProperties; |
23 | -import org.springframework.boot.context.properties.EnableConfigurationProperties; | ||
24 | import org.springframework.context.annotation.Bean; | 23 | import org.springframework.context.annotation.Bean; |
25 | import org.springframework.context.annotation.Configuration; | 24 | import org.springframework.context.annotation.Configuration; |
26 | import org.springframework.core.annotation.Order; | 25 | import org.springframework.core.annotation.Order; |
@@ -37,7 +36,6 @@ import org.springframework.security.web.authentication.AuthenticationFailureHand | @@ -37,7 +36,6 @@ import org.springframework.security.web.authentication.AuthenticationFailureHand | ||
37 | import org.springframework.security.web.authentication.AuthenticationSuccessHandler; | 36 | import org.springframework.security.web.authentication.AuthenticationSuccessHandler; |
38 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; | 37 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; |
39 | import org.springframework.security.web.util.matcher.AntPathRequestMatcher; | 38 | import org.springframework.security.web.util.matcher.AntPathRequestMatcher; |
40 | -import org.springframework.web.cors.CorsUtils; | ||
41 | import org.springframework.web.cors.UrlBasedCorsConfigurationSource; | 39 | import org.springframework.web.cors.UrlBasedCorsConfigurationSource; |
42 | import org.springframework.web.filter.CorsFilter; | 40 | import org.springframework.web.filter.CorsFilter; |
43 | import org.thingsboard.server.dao.audit.AuditLogLevelFilter; | 41 | import org.thingsboard.server.dao.audit.AuditLogLevelFilter; |
@@ -17,9 +17,9 @@ package org.thingsboard.server.config; | @@ -17,9 +17,9 @@ package org.thingsboard.server.config; | ||
17 | 17 | ||
18 | import java.util.Map; | 18 | import java.util.Map; |
19 | 19 | ||
20 | -import org.thingsboard.server.exception.ThingsboardErrorCode; | ||
21 | -import org.thingsboard.server.exception.ThingsboardException; | ||
22 | -import org.thingsboard.server.controller.plugin.PluginWebSocketHandler; | 20 | +import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; |
21 | +import org.thingsboard.server.common.data.exception.ThingsboardException; | ||
22 | +import org.thingsboard.server.controller.plugin.TbWebSocketHandler; | ||
23 | import org.thingsboard.server.service.security.model.SecurityUser; | 23 | import org.thingsboard.server.service.security.model.SecurityUser; |
24 | import org.springframework.context.annotation.Bean; | 24 | import org.springframework.context.annotation.Bean; |
25 | import org.springframework.context.annotation.Configuration; | 25 | import org.springframework.context.annotation.Configuration; |
@@ -54,7 +54,7 @@ public class WebSocketConfiguration implements WebSocketConfigurer { | @@ -54,7 +54,7 @@ public class WebSocketConfiguration implements WebSocketConfigurer { | ||
54 | 54 | ||
55 | @Override | 55 | @Override |
56 | public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { | 56 | public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { |
57 | - registry.addHandler(pluginWsHandler(), WS_PLUGIN_MAPPING).setAllowedOrigins("*") | 57 | + registry.addHandler(wsHandler(), WS_PLUGIN_MAPPING).setAllowedOrigins("*") |
58 | .addInterceptors(new HttpSessionHandshakeInterceptor(), new HandshakeInterceptor() { | 58 | .addInterceptors(new HttpSessionHandshakeInterceptor(), new HandshakeInterceptor() { |
59 | 59 | ||
60 | @Override | 60 | @Override |
@@ -82,8 +82,8 @@ public class WebSocketConfiguration implements WebSocketConfigurer { | @@ -82,8 +82,8 @@ public class WebSocketConfiguration implements WebSocketConfigurer { | ||
82 | } | 82 | } |
83 | 83 | ||
84 | @Bean | 84 | @Bean |
85 | - public WebSocketHandler pluginWsHandler() { | ||
86 | - return new PluginWebSocketHandler(); | 85 | + public WebSocketHandler wsHandler() { |
86 | + return new TbWebSocketHandler(); | ||
87 | } | 87 | } |
88 | 88 | ||
89 | protected SecurityUser getCurrentUser() throws ThingsboardException { | 89 | protected SecurityUser getCurrentUser() throws ThingsboardException { |
@@ -20,8 +20,8 @@ import org.springframework.security.access.prepost.PreAuthorize; | @@ -20,8 +20,8 @@ import org.springframework.security.access.prepost.PreAuthorize; | ||
20 | import org.springframework.web.bind.annotation.*; | 20 | import org.springframework.web.bind.annotation.*; |
21 | import org.thingsboard.server.common.data.AdminSettings; | 21 | import org.thingsboard.server.common.data.AdminSettings; |
22 | import org.thingsboard.server.dao.settings.AdminSettingsService; | 22 | import org.thingsboard.server.dao.settings.AdminSettingsService; |
23 | -import org.thingsboard.server.exception.ThingsboardException; | ||
24 | -import org.thingsboard.server.service.mail.MailService; | 23 | +import org.thingsboard.server.common.data.exception.ThingsboardException; |
24 | +import org.thingsboard.rule.engine.api.MailService; | ||
25 | import org.thingsboard.server.service.update.UpdateService; | 25 | import org.thingsboard.server.service.update.UpdateService; |
26 | import org.thingsboard.server.service.update.model.UpdateMessage; | 26 | import org.thingsboard.server.service.update.model.UpdateMessage; |
27 | 27 |
@@ -23,8 +23,8 @@ import org.thingsboard.server.common.data.alarm.*; | @@ -23,8 +23,8 @@ import org.thingsboard.server.common.data.alarm.*; | ||
23 | import org.thingsboard.server.common.data.id.*; | 23 | import org.thingsboard.server.common.data.id.*; |
24 | import org.thingsboard.server.common.data.page.TimePageData; | 24 | import org.thingsboard.server.common.data.page.TimePageData; |
25 | import org.thingsboard.server.common.data.page.TimePageLink; | 25 | import org.thingsboard.server.common.data.page.TimePageLink; |
26 | -import org.thingsboard.server.exception.ThingsboardErrorCode; | ||
27 | -import org.thingsboard.server.exception.ThingsboardException; | 26 | +import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; |
27 | +import org.thingsboard.server.common.data.exception.ThingsboardException; | ||
28 | 28 | ||
29 | @RestController | 29 | @RestController |
30 | @RequestMapping("/api") | 30 | @RequestMapping("/api") |
@@ -33,8 +33,8 @@ import org.thingsboard.server.common.data.asset.AssetSearchQuery; | @@ -33,8 +33,8 @@ import org.thingsboard.server.common.data.asset.AssetSearchQuery; | ||
33 | import org.thingsboard.server.common.data.security.Authority; | 33 | import org.thingsboard.server.common.data.security.Authority; |
34 | import org.thingsboard.server.dao.exception.IncorrectParameterException; | 34 | import org.thingsboard.server.dao.exception.IncorrectParameterException; |
35 | import org.thingsboard.server.dao.model.ModelConstants; | 35 | import org.thingsboard.server.dao.model.ModelConstants; |
36 | -import org.thingsboard.server.exception.ThingsboardErrorCode; | ||
37 | -import org.thingsboard.server.exception.ThingsboardException; | 36 | +import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; |
37 | +import org.thingsboard.server.common.data.exception.ThingsboardException; | ||
38 | import org.thingsboard.server.service.security.model.SecurityUser; | 38 | import org.thingsboard.server.service.security.model.SecurityUser; |
39 | 39 | ||
40 | import java.util.ArrayList; | 40 | import java.util.ArrayList; |
@@ -24,7 +24,7 @@ import org.thingsboard.server.common.data.id.TenantId; | @@ -24,7 +24,7 @@ import org.thingsboard.server.common.data.id.TenantId; | ||
24 | import org.thingsboard.server.common.data.id.UserId; | 24 | import org.thingsboard.server.common.data.id.UserId; |
25 | import org.thingsboard.server.common.data.page.TimePageData; | 25 | import org.thingsboard.server.common.data.page.TimePageData; |
26 | import org.thingsboard.server.common.data.page.TimePageLink; | 26 | import org.thingsboard.server.common.data.page.TimePageLink; |
27 | -import org.thingsboard.server.exception.ThingsboardException; | 27 | +import org.thingsboard.server.common.data.exception.ThingsboardException; |
28 | 28 | ||
29 | import java.util.UUID; | 29 | import java.util.UUID; |
30 | 30 |
@@ -28,9 +28,9 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; | @@ -28,9 +28,9 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; | ||
28 | import org.springframework.web.bind.annotation.*; | 28 | import org.springframework.web.bind.annotation.*; |
29 | import org.thingsboard.server.common.data.User; | 29 | import org.thingsboard.server.common.data.User; |
30 | import org.thingsboard.server.common.data.security.UserCredentials; | 30 | import org.thingsboard.server.common.data.security.UserCredentials; |
31 | -import org.thingsboard.server.exception.ThingsboardErrorCode; | ||
32 | -import org.thingsboard.server.exception.ThingsboardException; | ||
33 | -import org.thingsboard.server.service.mail.MailService; | 31 | +import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; |
32 | +import org.thingsboard.server.common.data.exception.ThingsboardException; | ||
33 | +import org.thingsboard.rule.engine.api.MailService; | ||
34 | import org.thingsboard.server.service.security.auth.jwt.RefreshTokenRepository; | 34 | import org.thingsboard.server.service.security.auth.jwt.RefreshTokenRepository; |
35 | import org.thingsboard.server.service.security.model.SecurityUser; | 35 | import org.thingsboard.server.service.security.model.SecurityUser; |
36 | import org.thingsboard.server.service.security.model.UserPrincipal; | 36 | import org.thingsboard.server.service.security.model.UserPrincipal; |
@@ -15,12 +15,9 @@ | @@ -15,12 +15,9 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.controller; | 16 | package org.thingsboard.server.controller; |
17 | 17 | ||
18 | -import com.fasterxml.jackson.databind.JsonNode; | ||
19 | -import com.fasterxml.jackson.databind.ObjectMapper; | ||
20 | import lombok.extern.slf4j.Slf4j; | 18 | import lombok.extern.slf4j.Slf4j; |
21 | import org.apache.commons.lang3.StringUtils; | 19 | import org.apache.commons.lang3.StringUtils; |
22 | import org.springframework.beans.factory.annotation.Autowired; | 20 | import org.springframework.beans.factory.annotation.Autowired; |
23 | -import org.springframework.beans.factory.annotation.Value; | ||
24 | import org.springframework.security.core.Authentication; | 21 | import org.springframework.security.core.Authentication; |
25 | import org.springframework.security.core.context.SecurityContextHolder; | 22 | import org.springframework.security.core.context.SecurityContextHolder; |
26 | import org.springframework.web.bind.annotation.ExceptionHandler; | 23 | import org.springframework.web.bind.annotation.ExceptionHandler; |
@@ -30,7 +27,6 @@ import org.thingsboard.server.common.data.alarm.Alarm; | @@ -30,7 +27,6 @@ import org.thingsboard.server.common.data.alarm.Alarm; | ||
30 | import org.thingsboard.server.common.data.alarm.AlarmId; | 27 | import org.thingsboard.server.common.data.alarm.AlarmId; |
31 | import org.thingsboard.server.common.data.alarm.AlarmInfo; | 28 | import org.thingsboard.server.common.data.alarm.AlarmInfo; |
32 | import org.thingsboard.server.common.data.asset.Asset; | 29 | import org.thingsboard.server.common.data.asset.Asset; |
33 | -import org.thingsboard.server.common.data.audit.ActionStatus; | ||
34 | import org.thingsboard.server.common.data.audit.ActionType; | 30 | import org.thingsboard.server.common.data.audit.ActionType; |
35 | import org.thingsboard.server.common.data.id.*; | 31 | import org.thingsboard.server.common.data.id.*; |
36 | import org.thingsboard.server.common.data.page.TextPageLink; | 32 | import org.thingsboard.server.common.data.page.TextPageLink; |
@@ -49,6 +45,7 @@ import org.thingsboard.server.dao.audit.AuditLogService; | @@ -49,6 +45,7 @@ import org.thingsboard.server.dao.audit.AuditLogService; | ||
49 | import org.thingsboard.server.dao.customer.CustomerService; | 45 | import org.thingsboard.server.dao.customer.CustomerService; |
50 | import org.thingsboard.server.dao.dashboard.DashboardService; | 46 | import org.thingsboard.server.dao.dashboard.DashboardService; |
51 | import org.thingsboard.server.dao.device.DeviceCredentialsService; | 47 | import org.thingsboard.server.dao.device.DeviceCredentialsService; |
48 | +import org.thingsboard.server.dao.device.DeviceOfflineService; | ||
52 | import org.thingsboard.server.dao.device.DeviceService; | 49 | import org.thingsboard.server.dao.device.DeviceService; |
53 | import org.thingsboard.server.dao.exception.DataValidationException; | 50 | import org.thingsboard.server.dao.exception.DataValidationException; |
54 | import org.thingsboard.server.dao.exception.IncorrectParameterException; | 51 | import org.thingsboard.server.dao.exception.IncorrectParameterException; |
@@ -57,12 +54,13 @@ import org.thingsboard.server.dao.plugin.PluginService; | @@ -57,12 +54,13 @@ import org.thingsboard.server.dao.plugin.PluginService; | ||
57 | import org.thingsboard.server.dao.relation.RelationService; | 54 | import org.thingsboard.server.dao.relation.RelationService; |
58 | import org.thingsboard.server.dao.rule.RuleChainService; | 55 | import org.thingsboard.server.dao.rule.RuleChainService; |
59 | import org.thingsboard.server.dao.rule.RuleService; | 56 | import org.thingsboard.server.dao.rule.RuleService; |
57 | +import org.thingsboard.server.dao.tenant.TenantService; | ||
60 | import org.thingsboard.server.dao.user.UserService; | 58 | import org.thingsboard.server.dao.user.UserService; |
61 | import org.thingsboard.server.dao.widget.WidgetTypeService; | 59 | import org.thingsboard.server.dao.widget.WidgetTypeService; |
62 | import org.thingsboard.server.dao.widget.WidgetsBundleService; | 60 | import org.thingsboard.server.dao.widget.WidgetsBundleService; |
63 | -import org.thingsboard.server.exception.ThingsboardErrorCode; | 61 | +import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; |
64 | import org.thingsboard.server.exception.ThingsboardErrorResponseHandler; | 62 | import org.thingsboard.server.exception.ThingsboardErrorResponseHandler; |
65 | -import org.thingsboard.server.exception.ThingsboardException; | 63 | +import org.thingsboard.server.common.data.exception.ThingsboardException; |
66 | import org.thingsboard.server.service.component.ComponentDiscoveryService; | 64 | import org.thingsboard.server.service.component.ComponentDiscoveryService; |
67 | import org.thingsboard.server.service.security.model.SecurityUser; | 65 | import org.thingsboard.server.service.security.model.SecurityUser; |
68 | 66 | ||
@@ -71,6 +69,7 @@ import javax.servlet.http.HttpServletRequest; | @@ -71,6 +69,7 @@ import javax.servlet.http.HttpServletRequest; | ||
71 | import javax.servlet.http.HttpServletResponse; | 69 | import javax.servlet.http.HttpServletResponse; |
72 | import java.util.List; | 70 | import java.util.List; |
73 | import java.util.Optional; | 71 | import java.util.Optional; |
72 | +import java.util.Set; | ||
74 | import java.util.UUID; | 73 | import java.util.UUID; |
75 | 74 | ||
76 | import static org.thingsboard.server.dao.service.Validator.validateId; | 75 | import static org.thingsboard.server.dao.service.Validator.validateId; |
@@ -85,6 +84,9 @@ public abstract class BaseController { | @@ -85,6 +84,9 @@ public abstract class BaseController { | ||
85 | private ThingsboardErrorResponseHandler errorResponseHandler; | 84 | private ThingsboardErrorResponseHandler errorResponseHandler; |
86 | 85 | ||
87 | @Autowired | 86 | @Autowired |
87 | + protected TenantService tenantService; | ||
88 | + | ||
89 | + @Autowired | ||
88 | protected CustomerService customerService; | 90 | protected CustomerService customerService; |
89 | 91 | ||
90 | @Autowired | 92 | @Autowired |
@@ -132,6 +134,9 @@ public abstract class BaseController { | @@ -132,6 +134,9 @@ public abstract class BaseController { | ||
132 | @Autowired | 134 | @Autowired |
133 | protected AuditLogService auditLogService; | 135 | protected AuditLogService auditLogService; |
134 | 136 | ||
137 | + @Autowired | ||
138 | + protected DeviceOfflineService offlineService; | ||
139 | + | ||
135 | @ExceptionHandler(ThingsboardException.class) | 140 | @ExceptionHandler(ThingsboardException.class) |
136 | public void handleThingsboardException(ThingsboardException ex, HttpServletResponse response) { | 141 | public void handleThingsboardException(ThingsboardException ex, HttpServletResponse response) { |
137 | errorResponseHandler.handle(ex, response); | 142 | errorResponseHandler.handle(ex, response); |
@@ -480,6 +485,15 @@ public abstract class BaseController { | @@ -480,6 +485,15 @@ public abstract class BaseController { | ||
480 | } | 485 | } |
481 | } | 486 | } |
482 | 487 | ||
488 | + List<ComponentDescriptor> checkComponentDescriptorsByTypes(Set<ComponentType> types) throws ThingsboardException { | ||
489 | + try { | ||
490 | + log.debug("[{}] Lookup component descriptors", types); | ||
491 | + return componentDescriptorService.getComponents(types); | ||
492 | + } catch (Exception e) { | ||
493 | + throw handleException(e, false); | ||
494 | + } | ||
495 | + } | ||
496 | + | ||
483 | List<ComponentDescriptor> checkPluginActionsByPluginClazz(String pluginClazz) throws ThingsboardException { | 497 | List<ComponentDescriptor> checkPluginActionsByPluginClazz(String pluginClazz) throws ThingsboardException { |
484 | try { | 498 | try { |
485 | checkComponentDescriptorByClazz(pluginClazz); | 499 | checkComponentDescriptorByClazz(pluginClazz); |
@@ -550,6 +564,8 @@ public abstract class BaseController { | @@ -550,6 +564,8 @@ public abstract class BaseController { | ||
550 | throw new ThingsboardException(YOU_DON_T_HAVE_PERMISSION_TO_PERFORM_THIS_OPERATION, | 564 | throw new ThingsboardException(YOU_DON_T_HAVE_PERMISSION_TO_PERFORM_THIS_OPERATION, |
551 | ThingsboardErrorCode.PERMISSION_DENIED); | 565 | ThingsboardErrorCode.PERMISSION_DENIED); |
552 | 566 | ||
567 | + } else if (tenantId.getId().equals(ModelConstants.NULL_UUID)) { | ||
568 | + ruleChain.setConfiguration(null); | ||
553 | } | 569 | } |
554 | } | 570 | } |
555 | return ruleChain; | 571 | return ruleChain; |
@@ -590,5 +606,8 @@ public abstract class BaseController { | @@ -590,5 +606,8 @@ public abstract class BaseController { | ||
590 | auditLogService.logEntityAction(user.getTenantId(), customerId, user.getId(), user.getName(), entityId, entity, actionType, e, additionalInfo); | 606 | auditLogService.logEntityAction(user.getTenantId(), customerId, user.getId(), user.getName(), entityId, entity, actionType, e, additionalInfo); |
591 | } | 607 | } |
592 | 608 | ||
609 | + protected static Exception toException(Throwable error) { | ||
610 | + return Exception.class.isInstance(error) ? (Exception) error : new Exception(error); | ||
611 | + } | ||
593 | 612 | ||
594 | } | 613 | } |
@@ -19,9 +19,11 @@ import org.springframework.security.access.prepost.PreAuthorize; | @@ -19,9 +19,11 @@ import org.springframework.security.access.prepost.PreAuthorize; | ||
19 | import org.springframework.web.bind.annotation.*; | 19 | import org.springframework.web.bind.annotation.*; |
20 | import org.thingsboard.server.common.data.plugin.ComponentDescriptor; | 20 | import org.thingsboard.server.common.data.plugin.ComponentDescriptor; |
21 | import org.thingsboard.server.common.data.plugin.ComponentType; | 21 | import org.thingsboard.server.common.data.plugin.ComponentType; |
22 | -import org.thingsboard.server.exception.ThingsboardException; | 22 | +import org.thingsboard.server.common.data.exception.ThingsboardException; |
23 | 23 | ||
24 | +import java.util.HashSet; | ||
24 | import java.util.List; | 25 | import java.util.List; |
26 | +import java.util.Set; | ||
25 | 27 | ||
26 | @RestController | 28 | @RestController |
27 | @RequestMapping("/api") | 29 | @RequestMapping("/api") |
@@ -52,6 +54,22 @@ public class ComponentDescriptorController extends BaseController { | @@ -52,6 +54,22 @@ public class ComponentDescriptorController extends BaseController { | ||
52 | } | 54 | } |
53 | 55 | ||
54 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN','TENANT_ADMIN')") | 56 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN','TENANT_ADMIN')") |
57 | + @RequestMapping(value = "/components", params = {"componentTypes"}, method = RequestMethod.GET) | ||
58 | + @ResponseBody | ||
59 | + public List<ComponentDescriptor> getComponentDescriptorsByTypes(@RequestParam("componentTypes") String[] strComponentTypes) throws ThingsboardException { | ||
60 | + checkArrayParameter("componentTypes", strComponentTypes); | ||
61 | + try { | ||
62 | + Set<ComponentType> componentTypes = new HashSet<>(); | ||
63 | + for (String strComponentType : strComponentTypes) { | ||
64 | + componentTypes.add(ComponentType.valueOf(strComponentType)); | ||
65 | + } | ||
66 | + return checkComponentDescriptorsByTypes(componentTypes); | ||
67 | + } catch (Exception e) { | ||
68 | + throw handleException(e); | ||
69 | + } | ||
70 | + } | ||
71 | + | ||
72 | + @PreAuthorize("hasAnyAuthority('SYS_ADMIN','TENANT_ADMIN')") | ||
55 | @RequestMapping(value = "/components/actions/{pluginClazz:.+}", method = RequestMethod.GET) | 73 | @RequestMapping(value = "/components/actions/{pluginClazz:.+}", method = RequestMethod.GET) |
56 | @ResponseBody | 74 | @ResponseBody |
57 | public List<ComponentDescriptor> getPluginActionsByPluginClazz(@PathVariable("pluginClazz") String pluginClazz) throws ThingsboardException { | 75 | public List<ComponentDescriptor> getPluginActionsByPluginClazz(@PathVariable("pluginClazz") String pluginClazz) throws ThingsboardException { |
@@ -28,7 +28,7 @@ import org.thingsboard.server.common.data.id.CustomerId; | @@ -28,7 +28,7 @@ import org.thingsboard.server.common.data.id.CustomerId; | ||
28 | import org.thingsboard.server.common.data.id.TenantId; | 28 | import org.thingsboard.server.common.data.id.TenantId; |
29 | import org.thingsboard.server.common.data.page.TextPageData; | 29 | import org.thingsboard.server.common.data.page.TextPageData; |
30 | import org.thingsboard.server.common.data.page.TextPageLink; | 30 | import org.thingsboard.server.common.data.page.TextPageLink; |
31 | -import org.thingsboard.server.exception.ThingsboardException; | 31 | +import org.thingsboard.server.common.data.exception.ThingsboardException; |
32 | 32 | ||
33 | @RestController | 33 | @RestController |
34 | @RequestMapping("/api") | 34 | @RequestMapping("/api") |
@@ -27,9 +27,7 @@ import org.thingsboard.server.common.data.page.TextPageData; | @@ -27,9 +27,7 @@ import org.thingsboard.server.common.data.page.TextPageData; | ||
27 | import org.thingsboard.server.common.data.page.TextPageLink; | 27 | import org.thingsboard.server.common.data.page.TextPageLink; |
28 | import org.thingsboard.server.common.data.page.TimePageData; | 28 | import org.thingsboard.server.common.data.page.TimePageData; |
29 | import org.thingsboard.server.common.data.page.TimePageLink; | 29 | import org.thingsboard.server.common.data.page.TimePageLink; |
30 | -import org.thingsboard.server.dao.exception.IncorrectParameterException; | ||
31 | -import org.thingsboard.server.dao.model.ModelConstants; | ||
32 | -import org.thingsboard.server.exception.ThingsboardException; | 30 | +import org.thingsboard.server.common.data.exception.ThingsboardException; |
33 | 31 | ||
34 | import java.util.HashSet; | 32 | import java.util.HashSet; |
35 | import java.util.Set; | 33 | import java.util.Set; |
@@ -23,9 +23,11 @@ import org.thingsboard.server.common.data.Customer; | @@ -23,9 +23,11 @@ import org.thingsboard.server.common.data.Customer; | ||
23 | import org.thingsboard.server.common.data.Device; | 23 | import org.thingsboard.server.common.data.Device; |
24 | import org.thingsboard.server.common.data.EntitySubtype; | 24 | import org.thingsboard.server.common.data.EntitySubtype; |
25 | import org.thingsboard.server.common.data.EntityType; | 25 | import org.thingsboard.server.common.data.EntityType; |
26 | -import org.thingsboard.server.common.data.audit.ActionStatus; | ||
27 | import org.thingsboard.server.common.data.audit.ActionType; | 26 | import org.thingsboard.server.common.data.audit.ActionType; |
28 | import org.thingsboard.server.common.data.device.DeviceSearchQuery; | 27 | import org.thingsboard.server.common.data.device.DeviceSearchQuery; |
28 | +import org.thingsboard.server.common.data.device.DeviceStatusQuery; | ||
29 | +import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; | ||
30 | +import org.thingsboard.server.common.data.exception.ThingsboardException; | ||
29 | import org.thingsboard.server.common.data.id.CustomerId; | 31 | import org.thingsboard.server.common.data.id.CustomerId; |
30 | import org.thingsboard.server.common.data.id.DeviceId; | 32 | import org.thingsboard.server.common.data.id.DeviceId; |
31 | import org.thingsboard.server.common.data.id.TenantId; | 33 | import org.thingsboard.server.common.data.id.TenantId; |
@@ -35,8 +37,6 @@ import org.thingsboard.server.common.data.security.Authority; | @@ -35,8 +37,6 @@ import org.thingsboard.server.common.data.security.Authority; | ||
35 | import org.thingsboard.server.common.data.security.DeviceCredentials; | 37 | import org.thingsboard.server.common.data.security.DeviceCredentials; |
36 | import org.thingsboard.server.dao.exception.IncorrectParameterException; | 38 | import org.thingsboard.server.dao.exception.IncorrectParameterException; |
37 | import org.thingsboard.server.dao.model.ModelConstants; | 39 | import org.thingsboard.server.dao.model.ModelConstants; |
38 | -import org.thingsboard.server.exception.ThingsboardErrorCode; | ||
39 | -import org.thingsboard.server.exception.ThingsboardException; | ||
40 | import org.thingsboard.server.service.security.model.SecurityUser; | 40 | import org.thingsboard.server.service.security.model.SecurityUser; |
41 | 41 | ||
42 | import java.util.ArrayList; | 42 | import java.util.ArrayList; |
@@ -70,7 +70,7 @@ public class DeviceController extends BaseController { | @@ -70,7 +70,7 @@ public class DeviceController extends BaseController { | ||
70 | device.setTenantId(getCurrentUser().getTenantId()); | 70 | device.setTenantId(getCurrentUser().getTenantId()); |
71 | if (getCurrentUser().getAuthority() == Authority.CUSTOMER_USER) { | 71 | if (getCurrentUser().getAuthority() == Authority.CUSTOMER_USER) { |
72 | if (device.getId() == null || device.getId().isNullUid() || | 72 | if (device.getId() == null || device.getId().isNullUid() || |
73 | - device.getCustomerId() == null || device.getCustomerId().isNullUid()) { | 73 | + device.getCustomerId() == null || device.getCustomerId().isNullUid()) { |
74 | throw new ThingsboardException("You don't have permission to perform this operation!", | 74 | throw new ThingsboardException("You don't have permission to perform this operation!", |
75 | ThingsboardErrorCode.PERMISSION_DENIED); | 75 | ThingsboardErrorCode.PERMISSION_DENIED); |
76 | } else { | 76 | } else { |
@@ -368,4 +368,32 @@ public class DeviceController extends BaseController { | @@ -368,4 +368,32 @@ public class DeviceController extends BaseController { | ||
368 | throw handleException(e); | 368 | throw handleException(e); |
369 | } | 369 | } |
370 | } | 370 | } |
371 | + | ||
372 | + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") | ||
373 | + @RequestMapping(value = "/device/offline", method = RequestMethod.GET) | ||
374 | + @ResponseBody | ||
375 | + public List<Device> getOfflineDevices(@RequestParam("contactType") DeviceStatusQuery.ContactType contactType, | ||
376 | + @RequestParam("threshold") long threshold) throws ThingsboardException { | ||
377 | + try { | ||
378 | + TenantId tenantId = getCurrentUser().getTenantId(); | ||
379 | + ListenableFuture<List<Device>> offlineDevices = offlineService.findOfflineDevices(tenantId.getId(), contactType, threshold); | ||
380 | + return checkNotNull(offlineDevices.get()); | ||
381 | + } catch (Exception e) { | ||
382 | + throw handleException(e); | ||
383 | + } | ||
384 | + } | ||
385 | + | ||
386 | + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") | ||
387 | + @RequestMapping(value = "/device/online", method = RequestMethod.GET) | ||
388 | + @ResponseBody | ||
389 | + public List<Device> getOnlineDevices(@RequestParam("contactType") DeviceStatusQuery.ContactType contactType, | ||
390 | + @RequestParam("threshold") long threshold) throws ThingsboardException { | ||
391 | + try { | ||
392 | + TenantId tenantId = getCurrentUser().getTenantId(); | ||
393 | + ListenableFuture<List<Device>> offlineDevices = offlineService.findOnlineDevices(tenantId.getId(), contactType, threshold); | ||
394 | + return checkNotNull(offlineDevices.get()); | ||
395 | + } catch (Exception e) { | ||
396 | + throw handleException(e); | ||
397 | + } | ||
398 | + } | ||
371 | } | 399 | } |
@@ -24,8 +24,8 @@ import org.thingsboard.server.common.data.relation.EntityRelation; | @@ -24,8 +24,8 @@ import org.thingsboard.server.common.data.relation.EntityRelation; | ||
24 | import org.thingsboard.server.common.data.relation.EntityRelationInfo; | 24 | import org.thingsboard.server.common.data.relation.EntityRelationInfo; |
25 | import org.thingsboard.server.common.data.relation.RelationTypeGroup; | 25 | import org.thingsboard.server.common.data.relation.RelationTypeGroup; |
26 | import org.thingsboard.server.common.data.relation.EntityRelationsQuery; | 26 | import org.thingsboard.server.common.data.relation.EntityRelationsQuery; |
27 | -import org.thingsboard.server.exception.ThingsboardErrorCode; | ||
28 | -import org.thingsboard.server.exception.ThingsboardException; | 27 | +import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; |
28 | +import org.thingsboard.server.common.data.exception.ThingsboardException; | ||
29 | 29 | ||
30 | import java.util.List; | 30 | import java.util.List; |
31 | 31 |
@@ -24,8 +24,8 @@ import org.thingsboard.server.common.data.page.TimePageData; | @@ -24,8 +24,8 @@ import org.thingsboard.server.common.data.page.TimePageData; | ||
24 | import org.thingsboard.server.common.data.page.TimePageLink; | 24 | import org.thingsboard.server.common.data.page.TimePageLink; |
25 | import org.thingsboard.server.dao.event.EventService; | 25 | import org.thingsboard.server.dao.event.EventService; |
26 | import org.thingsboard.server.dao.model.ModelConstants; | 26 | import org.thingsboard.server.dao.model.ModelConstants; |
27 | -import org.thingsboard.server.exception.ThingsboardErrorCode; | ||
28 | -import org.thingsboard.server.exception.ThingsboardException; | 27 | +import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; |
28 | +import org.thingsboard.server.common.data.exception.ThingsboardException; | ||
29 | 29 | ||
30 | @RestController | 30 | @RestController |
31 | @RequestMapping("/api") | 31 | @RequestMapping("/api") |
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.controller; | ||
17 | + | ||
18 | +import com.google.common.util.concurrent.FutureCallback; | ||
19 | +import org.springframework.http.ResponseEntity; | ||
20 | +import org.springframework.web.context.request.async.DeferredResult; | ||
21 | +import org.thingsboard.server.service.security.ValidationCallback; | ||
22 | + | ||
23 | +/** | ||
24 | + * Created by ashvayka on 21.02.17. | ||
25 | + */ | ||
26 | +public class HttpValidationCallback extends ValidationCallback<DeferredResult<ResponseEntity>> { | ||
27 | + | ||
28 | + public HttpValidationCallback(DeferredResult<ResponseEntity> response, FutureCallback<DeferredResult<ResponseEntity>> action) { | ||
29 | + super(response, action); | ||
30 | + } | ||
31 | + | ||
32 | +} |
@@ -28,7 +28,7 @@ import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; | @@ -28,7 +28,7 @@ import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; | ||
28 | import org.thingsboard.server.common.data.plugin.PluginMetaData; | 28 | import org.thingsboard.server.common.data.plugin.PluginMetaData; |
29 | import org.thingsboard.server.common.data.security.Authority; | 29 | import org.thingsboard.server.common.data.security.Authority; |
30 | import org.thingsboard.server.dao.model.ModelConstants; | 30 | import org.thingsboard.server.dao.model.ModelConstants; |
31 | -import org.thingsboard.server.exception.ThingsboardException; | 31 | +import org.thingsboard.server.common.data.exception.ThingsboardException; |
32 | 32 | ||
33 | import java.util.List; | 33 | import java.util.List; |
34 | 34 | ||
@@ -71,7 +71,7 @@ public class PluginController extends BaseController { | @@ -71,7 +71,7 @@ public class PluginController extends BaseController { | ||
71 | boolean created = source.getId() == null; | 71 | boolean created = source.getId() == null; |
72 | source.setTenantId(getCurrentUser().getTenantId()); | 72 | source.setTenantId(getCurrentUser().getTenantId()); |
73 | PluginMetaData plugin = checkNotNull(pluginService.savePlugin(source)); | 73 | PluginMetaData plugin = checkNotNull(pluginService.savePlugin(source)); |
74 | - actorService.onPluginStateChange(plugin.getTenantId(), plugin.getId(), | 74 | + actorService.onEntityStateChange(plugin.getTenantId(), plugin.getId(), |
75 | created ? ComponentLifecycleEvent.CREATED : ComponentLifecycleEvent.UPDATED); | 75 | created ? ComponentLifecycleEvent.CREATED : ComponentLifecycleEvent.UPDATED); |
76 | 76 | ||
77 | logEntityAction(plugin.getId(), plugin, | 77 | logEntityAction(plugin.getId(), plugin, |
@@ -97,7 +97,7 @@ public class PluginController extends BaseController { | @@ -97,7 +97,7 @@ public class PluginController extends BaseController { | ||
97 | PluginId pluginId = new PluginId(toUUID(strPluginId)); | 97 | PluginId pluginId = new PluginId(toUUID(strPluginId)); |
98 | PluginMetaData plugin = checkPlugin(pluginService.findPluginById(pluginId)); | 98 | PluginMetaData plugin = checkPlugin(pluginService.findPluginById(pluginId)); |
99 | pluginService.activatePluginById(pluginId); | 99 | pluginService.activatePluginById(pluginId); |
100 | - actorService.onPluginStateChange(plugin.getTenantId(), plugin.getId(), ComponentLifecycleEvent.ACTIVATED); | 100 | + actorService.onEntityStateChange(plugin.getTenantId(), plugin.getId(), ComponentLifecycleEvent.ACTIVATED); |
101 | 101 | ||
102 | logEntityAction(plugin.getId(), plugin, | 102 | logEntityAction(plugin.getId(), plugin, |
103 | null, | 103 | null, |
@@ -123,7 +123,7 @@ public class PluginController extends BaseController { | @@ -123,7 +123,7 @@ public class PluginController extends BaseController { | ||
123 | PluginId pluginId = new PluginId(toUUID(strPluginId)); | 123 | PluginId pluginId = new PluginId(toUUID(strPluginId)); |
124 | PluginMetaData plugin = checkPlugin(pluginService.findPluginById(pluginId)); | 124 | PluginMetaData plugin = checkPlugin(pluginService.findPluginById(pluginId)); |
125 | pluginService.suspendPluginById(pluginId); | 125 | pluginService.suspendPluginById(pluginId); |
126 | - actorService.onPluginStateChange(plugin.getTenantId(), plugin.getId(), ComponentLifecycleEvent.SUSPENDED); | 126 | + actorService.onEntityStateChange(plugin.getTenantId(), plugin.getId(), ComponentLifecycleEvent.SUSPENDED); |
127 | 127 | ||
128 | logEntityAction(plugin.getId(), plugin, | 128 | logEntityAction(plugin.getId(), plugin, |
129 | null, | 129 | null, |
@@ -221,7 +221,7 @@ public class PluginController extends BaseController { | @@ -221,7 +221,7 @@ public class PluginController extends BaseController { | ||
221 | PluginId pluginId = new PluginId(toUUID(strPluginId)); | 221 | PluginId pluginId = new PluginId(toUUID(strPluginId)); |
222 | PluginMetaData plugin = checkPlugin(pluginService.findPluginById(pluginId)); | 222 | PluginMetaData plugin = checkPlugin(pluginService.findPluginById(pluginId)); |
223 | pluginService.deletePluginById(pluginId); | 223 | pluginService.deletePluginById(pluginId); |
224 | - actorService.onPluginStateChange(plugin.getTenantId(), plugin.getId(), ComponentLifecycleEvent.DELETED); | 224 | + actorService.onEntityStateChange(plugin.getTenantId(), plugin.getId(), ComponentLifecycleEvent.DELETED); |
225 | 225 | ||
226 | logEntityAction(pluginId, plugin, | 226 | logEntityAction(pluginId, plugin, |
227 | null, | 227 | null, |
@@ -15,31 +15,46 @@ | @@ -15,31 +15,46 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.controller; | 16 | package org.thingsboard.server.controller; |
17 | 17 | ||
18 | +import com.datastax.driver.core.utils.UUIDs; | ||
19 | +import com.fasterxml.jackson.core.type.TypeReference; | ||
20 | +import com.fasterxml.jackson.databind.JsonNode; | ||
21 | +import com.fasterxml.jackson.databind.ObjectMapper; | ||
22 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
23 | +import lombok.extern.slf4j.Slf4j; | ||
18 | import org.springframework.http.HttpStatus; | 24 | import org.springframework.http.HttpStatus; |
19 | import org.springframework.security.access.prepost.PreAuthorize; | 25 | import org.springframework.security.access.prepost.PreAuthorize; |
26 | +import org.springframework.util.StringUtils; | ||
20 | import org.springframework.web.bind.annotation.*; | 27 | import org.springframework.web.bind.annotation.*; |
28 | +import org.thingsboard.rule.engine.api.ScriptEngine; | ||
21 | import org.thingsboard.server.common.data.EntityType; | 29 | import org.thingsboard.server.common.data.EntityType; |
22 | import org.thingsboard.server.common.data.audit.ActionType; | 30 | import org.thingsboard.server.common.data.audit.ActionType; |
23 | -import org.thingsboard.server.common.data.id.PluginId; | ||
24 | import org.thingsboard.server.common.data.id.RuleChainId; | 31 | import org.thingsboard.server.common.data.id.RuleChainId; |
25 | import org.thingsboard.server.common.data.id.TenantId; | 32 | import org.thingsboard.server.common.data.id.TenantId; |
26 | import org.thingsboard.server.common.data.page.TextPageData; | 33 | import org.thingsboard.server.common.data.page.TextPageData; |
27 | import org.thingsboard.server.common.data.page.TextPageLink; | 34 | import org.thingsboard.server.common.data.page.TextPageLink; |
28 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; | 35 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; |
29 | -import org.thingsboard.server.common.data.plugin.PluginMetaData; | ||
30 | import org.thingsboard.server.common.data.rule.RuleChain; | 36 | import org.thingsboard.server.common.data.rule.RuleChain; |
37 | +import org.thingsboard.server.common.data.rule.RuleChainMetaData; | ||
31 | import org.thingsboard.server.common.data.security.Authority; | 38 | import org.thingsboard.server.common.data.security.Authority; |
39 | +import org.thingsboard.server.common.msg.TbMsg; | ||
40 | +import org.thingsboard.server.common.msg.TbMsgMetaData; | ||
32 | import org.thingsboard.server.dao.model.ModelConstants; | 41 | import org.thingsboard.server.dao.model.ModelConstants; |
33 | -import org.thingsboard.server.exception.ThingsboardException; | 42 | +import org.thingsboard.server.common.data.exception.ThingsboardException; |
43 | +import org.thingsboard.server.service.script.NashornJsEngine; | ||
34 | 44 | ||
35 | import java.util.List; | 45 | import java.util.List; |
46 | +import java.util.Map; | ||
47 | +import java.util.Set; | ||
36 | 48 | ||
49 | +@Slf4j | ||
37 | @RestController | 50 | @RestController |
38 | @RequestMapping("/api") | 51 | @RequestMapping("/api") |
39 | public class RuleChainController extends BaseController { | 52 | public class RuleChainController extends BaseController { |
40 | 53 | ||
41 | public static final String RULE_CHAIN_ID = "ruleChainId"; | 54 | public static final String RULE_CHAIN_ID = "ruleChainId"; |
42 | 55 | ||
56 | + private static final ObjectMapper objectMapper = new ObjectMapper(); | ||
57 | + | ||
43 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") | 58 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") |
44 | @RequestMapping(value = "/ruleChain/{ruleChainId}", method = RequestMethod.GET) | 59 | @RequestMapping(value = "/ruleChain/{ruleChainId}", method = RequestMethod.GET) |
45 | @ResponseBody | 60 | @ResponseBody |
@@ -54,6 +69,21 @@ public class RuleChainController extends BaseController { | @@ -54,6 +69,21 @@ public class RuleChainController extends BaseController { | ||
54 | } | 69 | } |
55 | 70 | ||
56 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") | 71 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") |
72 | + @RequestMapping(value = "/ruleChain/{ruleChainId}/metadata", method = RequestMethod.GET) | ||
73 | + @ResponseBody | ||
74 | + public RuleChainMetaData getRuleChainMetaData(@PathVariable(RULE_CHAIN_ID) String strRuleChainId) throws ThingsboardException { | ||
75 | + checkParameter(RULE_CHAIN_ID, strRuleChainId); | ||
76 | + try { | ||
77 | + RuleChainId ruleChainId = new RuleChainId(toUUID(strRuleChainId)); | ||
78 | + checkRuleChain(ruleChainId); | ||
79 | + return ruleChainService.loadRuleChainMetaData(ruleChainId); | ||
80 | + } catch (Exception e) { | ||
81 | + throw handleException(e); | ||
82 | + } | ||
83 | + } | ||
84 | + | ||
85 | + | ||
86 | + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") | ||
57 | @RequestMapping(value = "/ruleChain", method = RequestMethod.POST) | 87 | @RequestMapping(value = "/ruleChain", method = RequestMethod.POST) |
58 | @ResponseBody | 88 | @ResponseBody |
59 | public RuleChain saveRuleChain(@RequestBody RuleChain ruleChain) throws ThingsboardException { | 89 | public RuleChain saveRuleChain(@RequestBody RuleChain ruleChain) throws ThingsboardException { |
@@ -62,6 +92,9 @@ public class RuleChainController extends BaseController { | @@ -62,6 +92,9 @@ public class RuleChainController extends BaseController { | ||
62 | ruleChain.setTenantId(getCurrentUser().getTenantId()); | 92 | ruleChain.setTenantId(getCurrentUser().getTenantId()); |
63 | RuleChain savedRuleChain = checkNotNull(ruleChainService.saveRuleChain(ruleChain)); | 93 | RuleChain savedRuleChain = checkNotNull(ruleChainService.saveRuleChain(ruleChain)); |
64 | 94 | ||
95 | + actorService.onEntityStateChange(ruleChain.getTenantId(), savedRuleChain.getId(), | ||
96 | + created ? ComponentLifecycleEvent.CREATED : ComponentLifecycleEvent.UPDATED); | ||
97 | + | ||
65 | logEntityAction(savedRuleChain.getId(), savedRuleChain, | 98 | logEntityAction(savedRuleChain.getId(), savedRuleChain, |
66 | null, | 99 | null, |
67 | created ? ActionType.ADDED : ActionType.UPDATED, null); | 100 | created ? ActionType.ADDED : ActionType.UPDATED, null); |
@@ -77,6 +110,30 @@ public class RuleChainController extends BaseController { | @@ -77,6 +110,30 @@ public class RuleChainController extends BaseController { | ||
77 | } | 110 | } |
78 | 111 | ||
79 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") | 112 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") |
113 | + @RequestMapping(value = "/ruleChain/metadata", method = RequestMethod.POST) | ||
114 | + @ResponseBody | ||
115 | + public RuleChainMetaData saveRuleChainMetaData(@RequestBody RuleChainMetaData ruleChainMetaData) throws ThingsboardException { | ||
116 | + try { | ||
117 | + RuleChain ruleChain = checkRuleChain(ruleChainMetaData.getRuleChainId()); | ||
118 | + RuleChainMetaData savedRuleChainMetaData = checkNotNull(ruleChainService.saveRuleChainMetaData(ruleChainMetaData)); | ||
119 | + | ||
120 | + actorService.onEntityStateChange(ruleChain.getTenantId(), ruleChain.getId(), ComponentLifecycleEvent.UPDATED); | ||
121 | + | ||
122 | + logEntityAction(ruleChain.getId(), ruleChain, | ||
123 | + null, | ||
124 | + ActionType.UPDATED, null, ruleChainMetaData); | ||
125 | + | ||
126 | + return savedRuleChainMetaData; | ||
127 | + } catch (Exception e) { | ||
128 | + | ||
129 | + logEntityAction(emptyId(EntityType.RULE_CHAIN), null, | ||
130 | + null, ActionType.UPDATED, e, ruleChainMetaData); | ||
131 | + | ||
132 | + throw handleException(e); | ||
133 | + } | ||
134 | + } | ||
135 | + | ||
136 | + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") | ||
80 | @RequestMapping(value = "/ruleChains", params = {"limit"}, method = RequestMethod.GET) | 137 | @RequestMapping(value = "/ruleChains", params = {"limit"}, method = RequestMethod.GET) |
81 | @ResponseBody | 138 | @ResponseBody |
82 | public TextPageData<RuleChain> getRuleChains( | 139 | public TextPageData<RuleChain> getRuleChains( |
@@ -145,6 +202,8 @@ public class RuleChainController extends BaseController { | @@ -145,6 +202,8 @@ public class RuleChainController extends BaseController { | ||
145 | RuleChain ruleChain = checkRuleChain(ruleChainId); | 202 | RuleChain ruleChain = checkRuleChain(ruleChainId); |
146 | ruleChainService.deleteRuleChainById(ruleChainId); | 203 | ruleChainService.deleteRuleChainById(ruleChainId); |
147 | 204 | ||
205 | + actorService.onEntityStateChange(ruleChain.getTenantId(), ruleChain.getId(), ComponentLifecycleEvent.DELETED); | ||
206 | + | ||
148 | logEntityAction(ruleChainId, ruleChain, | 207 | logEntityAction(ruleChainId, ruleChain, |
149 | null, | 208 | null, |
150 | ActionType.DELETED, null, strRuleChainId); | 209 | ActionType.DELETED, null, strRuleChainId); |
@@ -158,4 +217,78 @@ public class RuleChainController extends BaseController { | @@ -158,4 +217,78 @@ public class RuleChainController extends BaseController { | ||
158 | } | 217 | } |
159 | } | 218 | } |
160 | 219 | ||
220 | + @PreAuthorize("hasAuthority('TENANT_ADMIN')") | ||
221 | + @RequestMapping(value = "/ruleChain/testScript", method = RequestMethod.POST) | ||
222 | + @ResponseBody | ||
223 | + public JsonNode testScript(@RequestBody JsonNode inputParams) throws ThingsboardException { | ||
224 | + try { | ||
225 | + String script = inputParams.get("script").asText(); | ||
226 | + String scriptType = inputParams.get("scriptType").asText(); | ||
227 | + String functionName = inputParams.get("functionName").asText(); | ||
228 | + JsonNode argNamesJson = inputParams.get("argNames"); | ||
229 | + String[] argNames = objectMapper.treeToValue(argNamesJson, String[].class); | ||
230 | + | ||
231 | + String data = inputParams.get("msg").asText(); | ||
232 | + JsonNode metadataJson = inputParams.get("metadata"); | ||
233 | + Map<String, String> metadata = objectMapper.convertValue(metadataJson, new TypeReference<Map<String, String>>() {}); | ||
234 | + String msgType = inputParams.get("msgType").asText(); | ||
235 | + String output = ""; | ||
236 | + String errorText = ""; | ||
237 | + ScriptEngine engine = null; | ||
238 | + try { | ||
239 | + engine = new NashornJsEngine(script, functionName, argNames); | ||
240 | + TbMsg inMsg = new TbMsg(UUIDs.timeBased(), msgType, null, new TbMsgMetaData(metadata), data); | ||
241 | + switch (scriptType) { | ||
242 | + case "update": | ||
243 | + output = msgToOutput(engine.executeUpdate(inMsg)); | ||
244 | + break; | ||
245 | + case "generate": | ||
246 | + output = msgToOutput(engine.executeGenerate(inMsg)); | ||
247 | + break; | ||
248 | + case "filter": | ||
249 | + boolean result = engine.executeFilter(inMsg); | ||
250 | + output = Boolean.toString(result); | ||
251 | + break; | ||
252 | + case "switch": | ||
253 | + Set<String> states = engine.executeSwitch(inMsg); | ||
254 | + output = objectMapper.writeValueAsString(states); | ||
255 | + break; | ||
256 | + case "json": | ||
257 | + JsonNode json = engine.executeJson(inMsg); | ||
258 | + output = objectMapper.writeValueAsString(json); | ||
259 | + break; | ||
260 | + case "string": | ||
261 | + output = engine.executeToString(inMsg); | ||
262 | + break; | ||
263 | + default: | ||
264 | + throw new IllegalArgumentException("Unsupported script type: " + scriptType); | ||
265 | + } | ||
266 | + } catch (Exception e) { | ||
267 | + log.error("Error evaluating JS function", e); | ||
268 | + errorText = e.getMessage(); | ||
269 | + } finally { | ||
270 | + if (engine != null) { | ||
271 | + engine.destroy(); | ||
272 | + } | ||
273 | + } | ||
274 | + ObjectNode result = objectMapper.createObjectNode(); | ||
275 | + result.put("output", output); | ||
276 | + result.put("error", errorText); | ||
277 | + return result; | ||
278 | + } catch (Exception e) { | ||
279 | + throw handleException(e); | ||
280 | + } | ||
281 | + } | ||
282 | + | ||
283 | + private String msgToOutput(TbMsg msg) throws Exception { | ||
284 | + ObjectNode msgData = objectMapper.createObjectNode(); | ||
285 | + if (!StringUtils.isEmpty(msg.getData())) { | ||
286 | + msgData.set("msg", objectMapper.readTree(msg.getData())); | ||
287 | + } | ||
288 | + Map<String, String> metadata = msg.getMetaData().getData(); | ||
289 | + msgData.set("metadata", objectMapper.valueToTree(metadata)); | ||
290 | + msgData.put("msgType", msg.getType()); | ||
291 | + return objectMapper.writeValueAsString(msgData); | ||
292 | + } | ||
293 | + | ||
161 | } | 294 | } |
@@ -28,7 +28,7 @@ import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; | @@ -28,7 +28,7 @@ import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; | ||
28 | import org.thingsboard.server.common.data.plugin.PluginMetaData; | 28 | import org.thingsboard.server.common.data.plugin.PluginMetaData; |
29 | import org.thingsboard.server.common.data.rule.RuleMetaData; | 29 | import org.thingsboard.server.common.data.rule.RuleMetaData; |
30 | import org.thingsboard.server.common.data.security.Authority; | 30 | import org.thingsboard.server.common.data.security.Authority; |
31 | -import org.thingsboard.server.exception.ThingsboardException; | 31 | +import org.thingsboard.server.common.data.exception.ThingsboardException; |
32 | 32 | ||
33 | import java.util.List; | 33 | import java.util.List; |
34 | 34 | ||
@@ -73,7 +73,7 @@ public class RuleController extends BaseController { | @@ -73,7 +73,7 @@ public class RuleController extends BaseController { | ||
73 | boolean created = source.getId() == null; | 73 | boolean created = source.getId() == null; |
74 | source.setTenantId(getCurrentUser().getTenantId()); | 74 | source.setTenantId(getCurrentUser().getTenantId()); |
75 | RuleMetaData rule = checkNotNull(ruleService.saveRule(source)); | 75 | RuleMetaData rule = checkNotNull(ruleService.saveRule(source)); |
76 | - actorService.onRuleStateChange(rule.getTenantId(), rule.getId(), | 76 | + actorService.onEntityStateChange(rule.getTenantId(), rule.getId(), |
77 | created ? ComponentLifecycleEvent.CREATED : ComponentLifecycleEvent.UPDATED); | 77 | created ? ComponentLifecycleEvent.CREATED : ComponentLifecycleEvent.UPDATED); |
78 | 78 | ||
79 | logEntityAction(rule.getId(), rule, | 79 | logEntityAction(rule.getId(), rule, |
@@ -99,7 +99,7 @@ public class RuleController extends BaseController { | @@ -99,7 +99,7 @@ public class RuleController extends BaseController { | ||
99 | RuleId ruleId = new RuleId(toUUID(strRuleId)); | 99 | RuleId ruleId = new RuleId(toUUID(strRuleId)); |
100 | RuleMetaData rule = checkRule(ruleService.findRuleById(ruleId)); | 100 | RuleMetaData rule = checkRule(ruleService.findRuleById(ruleId)); |
101 | ruleService.activateRuleById(ruleId); | 101 | ruleService.activateRuleById(ruleId); |
102 | - actorService.onRuleStateChange(rule.getTenantId(), rule.getId(), ComponentLifecycleEvent.ACTIVATED); | 102 | + actorService.onEntityStateChange(rule.getTenantId(), rule.getId(), ComponentLifecycleEvent.ACTIVATED); |
103 | 103 | ||
104 | logEntityAction(rule.getId(), rule, | 104 | logEntityAction(rule.getId(), rule, |
105 | null, | 105 | null, |
@@ -125,7 +125,7 @@ public class RuleController extends BaseController { | @@ -125,7 +125,7 @@ public class RuleController extends BaseController { | ||
125 | RuleId ruleId = new RuleId(toUUID(strRuleId)); | 125 | RuleId ruleId = new RuleId(toUUID(strRuleId)); |
126 | RuleMetaData rule = checkRule(ruleService.findRuleById(ruleId)); | 126 | RuleMetaData rule = checkRule(ruleService.findRuleById(ruleId)); |
127 | ruleService.suspendRuleById(ruleId); | 127 | ruleService.suspendRuleById(ruleId); |
128 | - actorService.onRuleStateChange(rule.getTenantId(), rule.getId(), ComponentLifecycleEvent.SUSPENDED); | 128 | + actorService.onEntityStateChange(rule.getTenantId(), rule.getId(), ComponentLifecycleEvent.SUSPENDED); |
129 | 129 | ||
130 | logEntityAction(rule.getId(), rule, | 130 | logEntityAction(rule.getId(), rule, |
131 | null, | 131 | null, |
@@ -219,7 +219,7 @@ public class RuleController extends BaseController { | @@ -219,7 +219,7 @@ public class RuleController extends BaseController { | ||
219 | RuleId ruleId = new RuleId(toUUID(strRuleId)); | 219 | RuleId ruleId = new RuleId(toUUID(strRuleId)); |
220 | RuleMetaData rule = checkRule(ruleService.findRuleById(ruleId)); | 220 | RuleMetaData rule = checkRule(ruleService.findRuleById(ruleId)); |
221 | ruleService.deleteRuleById(ruleId); | 221 | ruleService.deleteRuleById(ruleId); |
222 | - actorService.onRuleStateChange(rule.getTenantId(), rule.getId(), ComponentLifecycleEvent.DELETED); | 222 | + actorService.onEntityStateChange(rule.getTenantId(), rule.getId(), ComponentLifecycleEvent.DELETED); |
223 | 223 | ||
224 | logEntityAction(ruleId, rule, | 224 | logEntityAction(ruleId, rule, |
225 | null, | 225 | null, |