Commit 070e5b5b625c378427a2380994fd86d6174f3d8d

Authored by Andrew Shvayka
1 parent 9764f27a

Query refactoring and improvements

Showing 51 changed files with 419 additions and 586 deletions
... ... @@ -16,11 +16,11 @@
16 16
17 17 CREATE TABLE IF NOT EXISTS thingsboard.msg_queue (
18 18 node_id timeuuid,
19   - clustered_hash bigint,
20   - partition bigint,
  19 + cluster_partition bigint,
  20 + ts_partition bigint,
21 21 ts bigint,
22 22 msg blob,
23   - PRIMARY KEY ((node_id, clustered_hash, partition), ts))
  23 + PRIMARY KEY ((node_id, cluster_partition, ts_partition), ts))
24 24 WITH CLUSTERING ORDER BY (ts DESC)
25 25 AND compaction = {
26 26 'class': 'org.apache.cassandra.db.compaction.DateTieredCompactionStrategy',
... ... @@ -33,10 +33,10 @@ AND compaction = {
33 33
34 34 CREATE TABLE IF NOT EXISTS thingsboard.msg_ack_queue (
35 35 node_id timeuuid,
36   - clustered_hash bigint,
37   - partition bigint,
  36 + cluster_partition bigint,
  37 + ts_partition bigint,
38 38 msg_id timeuuid,
39   - PRIMARY KEY ((node_id, clustered_hash, partition), msg_id))
  39 + PRIMARY KEY ((node_id, cluster_partition, ts_partition), msg_id))
40 40 WITH CLUSTERING ORDER BY (msg_id DESC)
41 41 AND compaction = {
42 42 'class': 'org.apache.cassandra.db.compaction.DateTieredCompactionStrategy',
... ... @@ -49,10 +49,10 @@ AND compaction = {
49 49
50 50 CREATE TABLE IF NOT EXISTS thingsboard.processed_msg_partitions (
51 51 node_id timeuuid,
52   - clustered_hash bigint,
53   - partition bigint,
54   - PRIMARY KEY ((node_id, clustered_hash), partition))
55   -WITH CLUSTERING ORDER BY (partition DESC)
  52 + cluster_partition bigint,
  53 + ts_partition bigint,
  54 + PRIMARY KEY ((node_id, cluster_partition), ts_partition))
  55 +WITH CLUSTERING ORDER BY (ts_partition DESC)
56 56 AND compaction = {
57 57 'class': 'org.apache.cassandra.db.compaction.DateTieredCompactionStrategy',
58 58 'min_threshold': '5',
... ...
... ... @@ -182,6 +182,12 @@ cassandra:
182 182 # Specify partitioning size for timestamp key-value storage. Example MINUTES, HOURS, DAYS, MONTHS
183 183 ts_key_value_partitioning: "${TS_KV_PARTITIONING:MONTHS}"
184 184
  185 + queue:
  186 + msg.ttl: 604800 # 7 days
  187 + ack.ttl: 604800 # 7 days
  188 + partitions.ttl: 604800 # 7 days
  189 + partitioning: "HOURS"
  190 +
185 191 # SQL configuration parameters
186 192 sql:
187 193 # Specify executor service type used to perform timeseries insert tasks: SINGLE FIXED CACHED
... ...
... ... @@ -57,6 +57,11 @@
57 57 <artifactId>logback-classic</artifactId>
58 58 </dependency>
59 59 <dependency>
  60 + <groupId>com.google.protobuf</groupId>
  61 + <artifactId>protobuf-java</artifactId>
  62 + <scope>provided</scope>
  63 + </dependency>
  64 + <dependency>
60 65 <groupId>junit</groupId>
61 66 <artifactId>junit</artifactId>
62 67 <scope>test</scope>
... ... @@ -70,6 +75,10 @@
70 75
71 76 <build>
72 77 <plugins>
  78 + <plugin>
  79 + <groupId>org.xolstice.maven.plugins</groupId>
  80 + <artifactId>protobuf-maven-plugin</artifactId>
  81 + </plugin>
73 82 </plugins>
74 83 </build>
75 84
... ...
common/message/src/main/java/org/thingsboard/server/common/msg/TbMsg.java renamed from rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbMsg.java
1 1 /**
2   - * Copyright © 2016-2017 The Thingsboard Authors
  2 + * Copyright © 2016-2018 The Thingsboard Authors
3 3 *
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
... ... @@ -13,12 +13,17 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.rule.engine.api;
  16 +package org.thingsboard.server.common.msg;
17 17
  18 +import com.google.protobuf.ByteString;
  19 +import com.google.protobuf.InvalidProtocolBufferException;
18 20 import lombok.Data;
19 21 import org.thingsboard.server.common.data.id.EntityId;
  22 +import org.thingsboard.server.common.data.id.EntityIdFactory;
  23 +import org.thingsboard.server.common.msg.gen.MsgProtos;
20 24
21 25 import java.io.Serializable;
  26 +import java.nio.ByteBuffer;
22 27 import java.util.UUID;
23 28
24 29 /**
... ... @@ -34,4 +39,42 @@ public final class TbMsg implements Serializable {
34 39
35 40 private final byte[] data;
36 41
  42 + public static ByteBuffer toBytes(TbMsg msg) {
  43 + MsgProtos.TbMsgProto.Builder builder = MsgProtos.TbMsgProto.newBuilder();
  44 + builder.setId(msg.getId().toString());
  45 + builder.setType(msg.getType());
  46 + if (msg.getOriginator() != null) {
  47 + builder.setEntityType(msg.getOriginator().getEntityType().name());
  48 + builder.setEntityId(msg.getOriginator().getId().toString());
  49 + }
  50 +
  51 + if (msg.getMetaData() != null) {
  52 + MsgProtos.TbMsgProto.TbMsgMetaDataProto.Builder metadataBuilder = MsgProtos.TbMsgProto.TbMsgMetaDataProto.newBuilder();
  53 + metadataBuilder.putAllData(msg.getMetaData().getData());
  54 + builder.addMetaData(metadataBuilder.build());
  55 + }
  56 +
  57 + builder.setData(ByteString.copyFrom(msg.getData()));
  58 + byte[] bytes = builder.build().toByteArray();
  59 + return ByteBuffer.wrap(bytes);
  60 + }
  61 +
  62 + public static TbMsg fromBytes(ByteBuffer buffer) {
  63 + try {
  64 + MsgProtos.TbMsgProto proto = MsgProtos.TbMsgProto.parseFrom(buffer.array());
  65 + TbMsgMetaData metaData = new TbMsgMetaData();
  66 + if (proto.getMetaDataCount() > 0) {
  67 + metaData.setData(proto.getMetaData(0).getDataMap());
  68 + }
  69 +
  70 + EntityId entityId = null;
  71 + if (proto.getEntityId() != null) {
  72 + entityId = EntityIdFactory.getByTypeAndId(proto.getEntityType(), proto.getEntityId());
  73 + }
  74 +
  75 + return new TbMsg(UUID.fromString(proto.getId()), proto.getType(), entityId, metaData, proto.getData().toByteArray());
  76 + } catch (InvalidProtocolBufferException e) {
  77 + throw new IllegalStateException("Could not parse protobuf for TbMsg", e);
  78 + }
  79 + }
37 80 }
... ...
common/message/src/main/java/org/thingsboard/server/common/msg/TbMsgMetaData.java renamed from rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbMsgMetaData.java
1 1 /**
2   - * Copyright © 2016-2017 The Thingsboard Authors
  2 + * Copyright © 2016-2018 The Thingsboard Authors
3 3 *
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
... ... @@ -13,7 +13,7 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.rule.engine.api;
  16 +package org.thingsboard.server.common.msg;
17 17
18 18 import lombok.Data;
19 19
... ...
common/message/src/main/proto/tbmsg.proto renamed from rule-engine/rule-engine-components/src/main/proto/msgqueue.proto
1 1 /**
2   - * Copyright © 2016-2017 The Thingsboard Authors
  2 + * Copyright © 2016-2018 The Thingsboard Authors
3 3 *
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
... ... @@ -16,8 +16,8 @@
16 16 syntax = "proto3";
17 17 package msgqueue;
18 18
19   -option java_package = "org.thingsboard.rule.engine.queue.cassandra.repository.gen";
20   -option java_outer_classname = "MsgQueueProtos";
  19 +option java_package = "org.thingsboard.server.common.msg.gen";
  20 +option java_outer_classname = "MsgProtos";
21 21
22 22
23 23 message TbMsgProto {
... ...
... ... @@ -38,7 +38,11 @@
38 38 <dependency>
39 39 <groupId>org.thingsboard.common</groupId>
40 40 <artifactId>data</artifactId>
41   - </dependency>
  41 + </dependency>
  42 + <dependency>
  43 + <groupId>org.thingsboard.common</groupId>
  44 + <artifactId>message</artifactId>
  45 + </dependency>
42 46 <dependency>
43 47 <groupId>org.slf4j</groupId>
44 48 <artifactId>slf4j-api</artifactId>
... ... @@ -141,6 +145,10 @@
141 145 <scope>test</scope>
142 146 </dependency>
143 147 <dependency>
  148 + <groupId>com.google.protobuf</groupId>
  149 + <artifactId>protobuf-java</artifactId>
  150 + </dependency>
  151 + <dependency>
144 152 <groupId>org.apache.curator</groupId>
145 153 <artifactId>curator-x-discovery</artifactId>
146 154 </dependency>
... ... @@ -198,6 +206,11 @@
198 206 <groupId>org.elasticsearch.client</groupId>
199 207 <artifactId>rest</artifactId>
200 208 </dependency>
  209 + <dependency>
  210 + <groupId>org.junit.jupiter</groupId>
  211 + <artifactId>junit-jupiter-api</artifactId>
  212 + <version>RELEASE</version>
  213 + </dependency>
201 214 </dependencies>
202 215 <build>
203 216 <plugins>
... ...
... ... @@ -22,12 +22,21 @@ import org.springframework.beans.factory.annotation.Autowired;
22 22 import org.thingsboard.server.dao.cassandra.CassandraCluster;
23 23 import org.thingsboard.server.dao.model.type.*;
24 24
  25 +import java.util.concurrent.ConcurrentHashMap;
  26 +import java.util.concurrent.ConcurrentMap;
  27 +
25 28 @Slf4j
26 29 public abstract class CassandraAbstractDao {
27 30
28 31 @Autowired
29 32 protected CassandraCluster cluster;
30 33
  34 + private ConcurrentMap<String, PreparedStatement> preparedStatementMap = new ConcurrentHashMap<>();
  35 +
  36 + protected PreparedStatement prepare(String query) {
  37 + return preparedStatementMap.computeIfAbsent(query, i -> getSession().prepare(i));
  38 + }
  39 +
31 40 private Session session;
32 41
33 42 private ConsistencyLevel defaultReadLevel;
... ...
... ... @@ -15,6 +15,7 @@
15 15 */
16 16 package org.thingsboard.server.dao.nosql;
17 17
  18 +import com.datastax.driver.core.PreparedStatement;
18 19 import com.datastax.driver.core.ResultSet;
19 20 import com.datastax.driver.core.ResultSetFuture;
20 21 import com.datastax.driver.core.Statement;
... ... @@ -37,6 +38,8 @@ import javax.annotation.Nullable;
37 38 import java.util.Collections;
38 39 import java.util.List;
39 40 import java.util.UUID;
  41 +import java.util.concurrent.ConcurrentHashMap;
  42 +import java.util.concurrent.ConcurrentMap;
40 43
41 44 import static com.datastax.driver.core.querybuilder.QueryBuilder.eq;
42 45 import static com.datastax.driver.core.querybuilder.QueryBuilder.select;
... ...
dao/src/main/java/org/thingsboard/server/dao/queue/MsqQueue.java renamed from rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/MsqQueue.java
1 1 /**
2   - * Copyright © 2016-2017 The Thingsboard Authors
  2 + * Copyright © 2016-2018 The Thingsboard Authors
3 3 *
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
... ... @@ -13,17 +13,18 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.rule.engine.api;
  16 +package org.thingsboard.server.dao.queue;
17 17
18 18 import com.google.common.util.concurrent.ListenableFuture;
  19 +import org.thingsboard.server.common.msg.TbMsg;
19 20
20 21 import java.util.UUID;
21 22
22 23 public interface MsqQueue {
23 24
24   - ListenableFuture<Void> put(TbMsg msg, UUID nodeId, long clusteredHash);
  25 + ListenableFuture<Void> put(TbMsg msg, UUID nodeId, long clusterPartition);
25 26
26   - ListenableFuture<Void> ack(TbMsg msg, UUID nodeId, long clusteredHash);
  27 + ListenableFuture<Void> ack(TbMsg msg, UUID nodeId, long clusterPartition);
27 28
28   - Iterable<TbMsg> findUnprocessed(UUID nodeId, long clusteredHash);
  29 + Iterable<TbMsg> findUnprocessed(UUID nodeId, long clusterPartition);
29 30 }
... ...
dao/src/main/java/org/thingsboard/server/dao/queue/QueueBenchmark.java renamed from rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/tool/QueueBenchmark.java
1   -package org.thingsboard.rule.engine.tool;
  1 +/**
  2 + * Copyright © 2016-2018 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.queue;
2 17
3 18 import com.datastax.driver.core.Cluster;
4 19 import com.datastax.driver.core.HostDistance;
... ... @@ -16,9 +31,8 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
16 31 import org.springframework.boot.autoconfigure.SpringBootApplication;
17 32 import org.springframework.context.annotation.Bean;
18 33 import org.springframework.context.annotation.ComponentScan;
19   -import org.thingsboard.rule.engine.api.MsqQueue;
20   -import org.thingsboard.rule.engine.api.TbMsg;
21   -import org.thingsboard.rule.engine.api.TbMsgMetaData;
  34 +import org.thingsboard.server.common.msg.TbMsg;
  35 +import org.thingsboard.server.common.msg.TbMsgMetaData;
22 36
23 37 import javax.annotation.Nullable;
24 38 import java.net.InetSocketAddress;
... ... @@ -29,9 +43,9 @@ import java.util.concurrent.Executors;
29 43 import java.util.concurrent.TimeUnit;
30 44 import java.util.concurrent.atomic.AtomicLong;
31 45
32   -@SpringBootApplication
33   -@EnableAutoConfiguration
34   -@ComponentScan({"org.thingsboard.rule.engine"})
  46 +//@SpringBootApplication
  47 +//@EnableAutoConfiguration
  48 +//@ComponentScan({"org.thingsboard.rule.engine"})
35 49 //@PropertySource("classpath:processing-pipeline.properties")
36 50 @Slf4j
37 51 public class QueueBenchmark implements CommandLineRunner {
... ...
dao/src/main/java/org/thingsboard/server/dao/queue/jpa/SqlMsgQueue.java renamed from rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/queue/jpa/SqlMsgQueue.java
1 1 /**
2   - * Copyright © 2016-2017 The Thingsboard Authors
  2 + * Copyright © 2016-2018 The Thingsboard Authors
3 3 *
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
... ... @@ -13,7 +13,7 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.rule.engine.queue.jpa;
  16 +package org.thingsboard.server.dao.queue.jpa;
17 17
18 18 //@todo-vp: implement
19 19 public class SqlMsgQueue {
... ...
dao/src/main/java/org/thingsboard/server/dao/service/queue/cassandra/CassandraMsqQueue.java renamed from rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/queue/cassandra/CassandraMsqQueue.java
1 1 /**
2   - * Copyright © 2016-2017 The Thingsboard Authors
  2 + * Copyright © 2016-2018 The Thingsboard Authors
3 3 *
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
... ... @@ -13,60 +13,57 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.rule.engine.queue.cassandra;
  16 +package org.thingsboard.server.dao.service.queue.cassandra;
17 17
18 18 import com.datastax.driver.core.utils.UUIDs;
19 19 import com.google.common.collect.Lists;
20 20 import com.google.common.util.concurrent.ListenableFuture;
21 21 import lombok.extern.slf4j.Slf4j;
  22 +import org.springframework.beans.factory.annotation.Autowired;
22 23 import org.springframework.stereotype.Component;
23   -import org.thingsboard.rule.engine.api.MsqQueue;
24   -import org.thingsboard.rule.engine.api.TbMsg;
25   -import org.thingsboard.rule.engine.queue.cassandra.repository.AckRepository;
26   -import org.thingsboard.rule.engine.queue.cassandra.repository.MsgRepository;
27   -import org.thingsboard.server.common.data.UUIDConverter;
  24 +import org.thingsboard.server.common.msg.TbMsg;
  25 +import org.thingsboard.server.dao.queue.MsqQueue;
  26 +import org.thingsboard.server.dao.service.queue.cassandra.repository.AckRepository;
  27 +import org.thingsboard.server.dao.service.queue.cassandra.repository.MsgRepository;
  28 +import org.thingsboard.server.dao.util.NoSqlDao;
28 29
29 30 import java.util.List;
30 31 import java.util.UUID;
31 32
32 33 @Component
33 34 @Slf4j
  35 +@NoSqlDao
34 36 public class CassandraMsqQueue implements MsqQueue {
35 37
36   - private final MsgRepository msgRepository;
37   - private final AckRepository ackRepository;
38   - private final UnprocessedMsgFilter unprocessedMsgFilter;
39   - private final QueuePartitioner queuePartitioner;
40   -
41   - public CassandraMsqQueue(MsgRepository msgRepository, AckRepository ackRepository,
42   - UnprocessedMsgFilter unprocessedMsgFilter, QueuePartitioner queuePartitioner) {
43   - this.msgRepository = msgRepository;
44   - this.ackRepository = ackRepository;
45   - this.unprocessedMsgFilter = unprocessedMsgFilter;
46   - this.queuePartitioner = queuePartitioner;
47   - }
48   -
  38 + @Autowired
  39 + private MsgRepository msgRepository;
  40 + @Autowired
  41 + private AckRepository ackRepository;
  42 + @Autowired
  43 + private UnprocessedMsgFilter unprocessedMsgFilter;
  44 + @Autowired
  45 + private QueuePartitioner queuePartitioner;
49 46
50 47 @Override
51   - public ListenableFuture<Void> put(TbMsg msg, UUID nodeId, long clusteredHash) {
  48 + public ListenableFuture<Void> put(TbMsg msg, UUID nodeId, long clusterPartition) {
52 49 long msgTime = getMsgTime(msg);
53   - long partition = queuePartitioner.getPartition(msgTime);
54   - return msgRepository.save(msg, nodeId, clusteredHash, partition, msgTime);
  50 + long tsPartition = queuePartitioner.getPartition(msgTime);
  51 + return msgRepository.save(msg, nodeId, clusterPartition, tsPartition, msgTime);
55 52 }
56 53
57 54 @Override
58   - public ListenableFuture<Void> ack(TbMsg msg, UUID nodeId, long clusteredHash) {
59   - long partition = queuePartitioner.getPartition(getMsgTime(msg));
60   - MsgAck ack = new MsgAck(msg.getId(), nodeId, clusteredHash, partition);
  55 + public ListenableFuture<Void> ack(TbMsg msg, UUID nodeId, long clusterPartition) {
  56 + long tsPartition = queuePartitioner.getPartition(getMsgTime(msg));
  57 + MsgAck ack = new MsgAck(msg.getId(), nodeId, clusterPartition, tsPartition);
61 58 return ackRepository.ack(ack);
62 59 }
63 60
64 61 @Override
65   - public Iterable<TbMsg> findUnprocessed(UUID nodeId, long clusteredHash) {
  62 + public Iterable<TbMsg> findUnprocessed(UUID nodeId, long clusterPartition) {
66 63 List<TbMsg> unprocessedMsgs = Lists.newArrayList();
67   - for (Long partition : queuePartitioner.findUnprocessedPartitions(nodeId, clusteredHash)) {
68   - List<TbMsg> msgs = msgRepository.findMsgs(nodeId, clusteredHash, partition);
69   - List<MsgAck> acks = ackRepository.findAcks(nodeId, clusteredHash, partition);
  64 + for (Long tsPartition : queuePartitioner.findUnprocessedPartitions(nodeId, clusterPartition)) {
  65 + List<TbMsg> msgs = msgRepository.findMsgs(nodeId, clusterPartition, tsPartition);
  66 + List<MsgAck> acks = ackRepository.findAcks(nodeId, clusterPartition, tsPartition);
70 67 unprocessedMsgs.addAll(unprocessedMsgFilter.filter(msgs, acks));
71 68 }
72 69 return unprocessedMsgs;
... ...
dao/src/main/java/org/thingsboard/server/dao/service/queue/cassandra/MsgAck.java renamed from rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/queue/cassandra/MsgAck.java
1 1 /**
2   - * Copyright © 2016-2017 The Thingsboard Authors
  2 + * Copyright © 2016-2018 The Thingsboard Authors
3 3 *
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
... ... @@ -13,13 +13,10 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.rule.engine.queue.cassandra;
  16 +package org.thingsboard.server.dao.service.queue.cassandra;
17 17
18   -import com.datastax.driver.core.utils.UUIDs;
19 18 import lombok.Data;
20 19 import lombok.EqualsAndHashCode;
21   -import org.thingsboard.rule.engine.api.TbMsg;
22   -import org.thingsboard.server.common.data.UUIDConverter;
23 20
24 21 import java.util.UUID;
25 22
... ... @@ -29,7 +26,7 @@ public class MsgAck {
29 26
30 27 private final UUID msgId;
31 28 private final UUID nodeId;
32   - private final long clusteredHash;
33   - private final long partition;
  29 + private final long clusteredPartition;
  30 + private final long tsPartition;
34 31
35 32 }
... ...
dao/src/main/java/org/thingsboard/server/dao/service/queue/cassandra/QueuePartitioner.java renamed from rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/queue/cassandra/QueuePartitioner.java
1 1 /**
2   - * Copyright © 2016-2017 The Thingsboard Authors
3   - * <p>
  2 + * Copyright © 2016-2018 The Thingsboard Authors
  3 + *
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
6 6 * You may obtain a copy of the License at
7   - * <p>
8   - * http://www.apache.org/licenses/LICENSE-2.0
9   - * <p>
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
10 10 * Unless required by applicable law or agreed to in writing, software
11 11 * distributed under the License is distributed on an "AS IS" BASIS,
12 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.rule.engine.queue.cassandra;
  16 +package org.thingsboard.server.dao.service.queue.cassandra;
17 17
18 18 import com.google.common.collect.Lists;
19 19 import lombok.extern.slf4j.Slf4j;
20 20 import org.springframework.beans.factory.annotation.Value;
21 21 import org.springframework.stereotype.Component;
22   -import org.thingsboard.rule.engine.queue.cassandra.repository.ProcessedPartitionRepository;
  22 +import org.thingsboard.server.dao.service.queue.cassandra.repository.ProcessedPartitionRepository;
23 23 import org.thingsboard.server.dao.timeseries.TsPartitionDate;
  24 +import org.thingsboard.server.dao.util.NoSqlDao;
24 25
25 26 import java.time.Clock;
26 27 import java.time.Instant;
... ... @@ -32,26 +33,27 @@ import java.util.UUID;
32 33
33 34 @Component
34 35 @Slf4j
  36 +@NoSqlDao
35 37 public class QueuePartitioner {
36 38
37   - private ProcessedPartitionRepository processedPartitionRepository;
38   -
39 39 private final TsPartitionDate tsFormat;
  40 + private ProcessedPartitionRepository processedPartitionRepository;
40 41 private Clock clock = Clock.systemUTC();
41 42
42   - public QueuePartitioner(@Value("${rule.queue.msg_partitioning}") String partitioning,
  43 + public QueuePartitioner(@Value("${cassandra.queue.partitioning}") String partitioning,
43 44 ProcessedPartitionRepository processedPartitionRepository) {
44 45 this.processedPartitionRepository = processedPartitionRepository;
45 46 Optional<TsPartitionDate> partition = TsPartitionDate.parse(partitioning);
46 47 if (partition.isPresent()) {
47 48 tsFormat = partition.get();
48 49 } else {
49   - log.warn("Incorrect configuration of partitioning {}", "MINUTES");
50   - throw new RuntimeException("Failed to parse partitioning property: " + "MINUTES" + "!");
  50 + log.warn("Incorrect configuration of partitioning {}", partitioning);
  51 + throw new RuntimeException("Failed to parse partitioning property: " + partitioning + "!");
51 52 }
52 53 }
53 54
54 55 public long getPartition(long ts) {
  56 + //TODO: use TsPartitionDate.truncateTo?
55 57 LocalDateTime time = LocalDateTime.ofInstant(Instant.ofEpochMilli(ts), ZoneOffset.UTC);
56 58 return tsFormat.truncatedTo(time).toInstant(ZoneOffset.UTC).toEpochMilli();
57 59 }
... ...
dao/src/main/java/org/thingsboard/server/dao/service/queue/cassandra/UnprocessedMsgFilter.java renamed from rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/queue/cassandra/UnprocessedMsgFilter.java
1 1 /**
2   - * Copyright © 2016-2017 The Thingsboard Authors
  2 + * Copyright © 2016-2018 The Thingsboard Authors
3 3 *
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
... ... @@ -13,10 +13,10 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.rule.engine.queue.cassandra;
  16 +package org.thingsboard.server.dao.service.queue.cassandra;
17 17
18 18 import org.springframework.stereotype.Component;
19   -import org.thingsboard.rule.engine.api.TbMsg;
  19 +import org.thingsboard.server.common.msg.TbMsg;
20 20
21 21 import java.util.Collection;
22 22 import java.util.List;
... ...
dao/src/main/java/org/thingsboard/server/dao/service/queue/cassandra/repository/AckRepository.java renamed from rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/queue/cassandra/repository/AckRepository.java
1 1 /**
2   - * Copyright © 2016-2017 The Thingsboard Authors
  2 + * Copyright © 2016-2018 The Thingsboard Authors
3 3 *
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
... ... @@ -13,10 +13,10 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.rule.engine.queue.cassandra.repository;
  16 +package org.thingsboard.server.dao.service.queue.cassandra.repository;
17 17
18 18 import com.google.common.util.concurrent.ListenableFuture;
19   -import org.thingsboard.rule.engine.queue.cassandra.MsgAck;
  19 +import org.thingsboard.server.dao.service.queue.cassandra.MsgAck;
20 20
21 21 import java.util.List;
22 22 import java.util.UUID;
... ... @@ -25,5 +25,5 @@ public interface AckRepository {
25 25
26 26 ListenableFuture<Void> ack(MsgAck msgAck);
27 27
28   - List<MsgAck> findAcks(UUID nodeId, long clusteredHash, long partition);
  28 + List<MsgAck> findAcks(UUID nodeId, long clusterPartition, long tsPartition);
29 29 }
... ...
dao/src/main/java/org/thingsboard/server/dao/service/queue/cassandra/repository/MsgRepository.java renamed from rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/queue/cassandra/repository/MsgRepository.java
1 1 /**
2   - * Copyright © 2016-2017 The Thingsboard Authors
  2 + * Copyright © 2016-2018 The Thingsboard Authors
3 3 *
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
... ... @@ -13,18 +13,18 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.rule.engine.queue.cassandra.repository;
  16 +package org.thingsboard.server.dao.service.queue.cassandra.repository;
17 17
18 18 import com.google.common.util.concurrent.ListenableFuture;
19   -import org.thingsboard.rule.engine.api.TbMsg;
  19 +import org.thingsboard.server.common.msg.TbMsg;
20 20
21 21 import java.util.List;
22 22 import java.util.UUID;
23 23
24 24 public interface MsgRepository {
25 25
26   - ListenableFuture<Void> save(TbMsg msg, UUID nodeId, long clusteredHash, long partition, long msgTs);
  26 + ListenableFuture<Void> save(TbMsg msg, UUID nodeId, long clusterPartition, long tsPartition, long msgTs);
27 27
28   - List<TbMsg> findMsgs(UUID nodeId, long clusteredHash, long partition);
  28 + List<TbMsg> findMsgs(UUID nodeId, long clusterPartition, long tsPartition);
29 29
30 30 }
... ...
dao/src/main/java/org/thingsboard/server/dao/service/queue/cassandra/repository/ProcessedPartitionRepository.java renamed from rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/queue/cassandra/repository/ProcessedPartitionRepository.java
1 1 /**
2   - * Copyright © 2016-2017 The Thingsboard Authors
  2 + * Copyright © 2016-2018 The Thingsboard Authors
3 3 *
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
... ... @@ -13,7 +13,7 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.rule.engine.queue.cassandra.repository;
  16 +package org.thingsboard.server.dao.service.queue.cassandra.repository;
17 17
18 18 import com.google.common.util.concurrent.ListenableFuture;
19 19
... ...
dao/src/main/java/org/thingsboard/server/dao/service/queue/cassandra/repository/impl/CassandraAckRepository.java renamed from rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/queue/cassandra/repository/impl/CassandraAckRepository.java
1 1 /**
2   - * Copyright © 2016-2017 The Thingsboard Authors
3   - * <p>
  2 + * Copyright © 2016-2018 The Thingsboard Authors
  3 + *
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
6 6 * You may obtain a copy of the License at
7   - * <p>
8   - * http://www.apache.org/licenses/LICENSE-2.0
9   - * <p>
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
10 10 * Unless required by applicable law or agreed to in writing, software
11 11 * distributed under the License is distributed on an "AS IS" BASIS,
12 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.rule.engine.queue.cassandra.repository.impl;
  16 +package org.thingsboard.server.dao.service.queue.cassandra.repository.impl;
17 17
18 18 import com.datastax.driver.core.*;
19 19 import com.google.common.base.Function;
20 20 import com.google.common.util.concurrent.Futures;
21 21 import com.google.common.util.concurrent.ListenableFuture;
  22 +import org.springframework.beans.factory.annotation.Value;
22 23 import org.springframework.stereotype.Component;
23   -import org.thingsboard.rule.engine.queue.cassandra.MsgAck;
24   -import org.thingsboard.rule.engine.queue.cassandra.repository.AckRepository;
  24 +import org.thingsboard.server.dao.nosql.CassandraAbstractDao;
  25 +import org.thingsboard.server.dao.service.queue.cassandra.MsgAck;
  26 +import org.thingsboard.server.dao.service.queue.cassandra.repository.AckRepository;
  27 +import org.thingsboard.server.dao.util.NoSqlDao;
25 28
26 29 import java.util.ArrayList;
27 30 import java.util.List;
28 31 import java.util.UUID;
29 32
30 33 @Component
31   -public class CassandraAckRepository extends SimpleAbstractCassandraDao implements AckRepository {
  34 +@NoSqlDao
  35 +public class CassandraAckRepository extends CassandraAbstractDao implements AckRepository {
32 36
33   - private final int ackQueueTtl;
34   -
35   - public CassandraAckRepository(Session session, int ackQueueTtl) {
36   - super(session);
37   - this.ackQueueTtl = ackQueueTtl;
38   - }
  37 + @Value("${cassandra.queue.ack.ttl}")
  38 + private int ackQueueTtl;
39 39
40 40 @Override
41 41 public ListenableFuture<Void> ack(MsgAck msgAck) {
42   - String insert = "INSERT INTO msg_ack_queue (node_id, clustered_hash, partition, msg_id) VALUES (?, ?, ?, ?) USING TTL ?";
  42 + String insert = "INSERT INTO msg_ack_queue (node_id, cluster_partition, ts_partition, msg_id) VALUES (?, ?, ?, ?) USING TTL ?";
43 43 PreparedStatement statement = prepare(insert);
44   - BoundStatement boundStatement = statement.bind(msgAck.getNodeId(), msgAck.getClusteredHash(),
45   - msgAck.getPartition(), msgAck.getMsgId(), ackQueueTtl);
  44 + BoundStatement boundStatement = statement.bind(msgAck.getNodeId(), msgAck.getClusteredPartition(),
  45 + msgAck.getTsPartition(), msgAck.getMsgId(), ackQueueTtl);
46 46 ResultSetFuture resultSetFuture = executeAsyncWrite(boundStatement);
47 47 return Futures.transform(resultSetFuture, (Function<ResultSet, Void>) input -> null);
48 48 }
49 49
50 50 @Override
51   - public List<MsgAck> findAcks(UUID nodeId, long clusteredHash, long partition) {
  51 + public List<MsgAck> findAcks(UUID nodeId, long clusterPartition, long tsPartition) {
52 52 String select = "SELECT msg_id FROM msg_ack_queue WHERE " +
53   - "node_id = ? AND clustered_hash = ? AND partition = ?";
  53 + "node_id = ? AND cluster_partition = ? AND ts_partition = ?";
54 54 PreparedStatement statement = prepare(select);
55   - BoundStatement boundStatement = statement.bind(nodeId, clusteredHash, partition);
  55 + BoundStatement boundStatement = statement.bind(nodeId, clusterPartition, tsPartition);
56 56 ResultSet rows = executeRead(boundStatement);
57 57 List<MsgAck> msgs = new ArrayList<>();
58 58 for (Row row : rows) {
59   - msgs.add(new MsgAck(row.getUUID("msg_id"), nodeId, clusteredHash, partition));
  59 + msgs.add(new MsgAck(row.getUUID("msg_id"), nodeId, clusterPartition, tsPartition));
60 60 }
61 61 return msgs;
62 62 }
... ...
  1 +/**
  2 + * Copyright © 2016-2018 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.service.queue.cassandra.repository.impl;
  17 +
  18 +import com.datastax.driver.core.*;
  19 +import com.google.common.base.Function;
  20 +import com.google.common.util.concurrent.Futures;
  21 +import com.google.common.util.concurrent.ListenableFuture;
  22 +import org.springframework.beans.factory.annotation.Value;
  23 +import org.springframework.stereotype.Component;
  24 +import org.thingsboard.server.common.msg.TbMsg;
  25 +import org.thingsboard.server.dao.nosql.CassandraAbstractDao;
  26 +import org.thingsboard.server.dao.service.queue.cassandra.repository.MsgRepository;
  27 +import org.thingsboard.server.dao.util.NoSqlDao;
  28 +
  29 +import java.util.ArrayList;
  30 +import java.util.List;
  31 +import java.util.UUID;
  32 +
  33 +@Component
  34 +@NoSqlDao
  35 +public class CassandraMsgRepository extends CassandraAbstractDao implements MsgRepository {
  36 +
  37 + @Value("${cassandra.queue.msg.ttl}")
  38 + private int msqQueueTtl;
  39 +
  40 + @Override
  41 + public ListenableFuture<Void> save(TbMsg msg, UUID nodeId, long clusterPartition, long tsPartition, long msgTs) {
  42 + String insert = "INSERT INTO msg_queue (node_id, cluster_partition, ts_partition, ts, msg) VALUES (?, ?, ?, ?, ?) USING TTL ?";
  43 + PreparedStatement statement = prepare(insert);
  44 + BoundStatement boundStatement = statement.bind(nodeId, clusterPartition, tsPartition, msgTs, TbMsg.toBytes(msg), msqQueueTtl);
  45 + ResultSetFuture resultSetFuture = executeAsyncWrite(boundStatement);
  46 + return Futures.transform(resultSetFuture, (Function<ResultSet, Void>) input -> null);
  47 + }
  48 +
  49 + @Override
  50 + public List<TbMsg> findMsgs(UUID nodeId, long clusterPartition, long tsPartition) {
  51 + String select = "SELECT node_id, cluster_partition, ts_partition, ts, msg FROM msg_queue WHERE " +
  52 + "node_id = ? AND cluster_partition = ? AND ts_partition = ?";
  53 + PreparedStatement statement = prepare(select);
  54 + BoundStatement boundStatement = statement.bind(nodeId, clusterPartition, tsPartition);
  55 + ResultSet rows = executeRead(boundStatement);
  56 + List<TbMsg> msgs = new ArrayList<>();
  57 + for (Row row : rows) {
  58 + msgs.add(TbMsg.fromBytes(row.getBytes("msg")));
  59 + }
  60 + return msgs;
  61 + }
  62 +
  63 +}
... ...
dao/src/main/java/org/thingsboard/server/dao/service/queue/cassandra/repository/impl/CassandraProcessedPartitionRepository.java renamed from rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/queue/cassandra/repository/impl/CassandraProcessedPartitionRepository.java
1 1 /**
2   - * Copyright © 2016-2017 The Thingsboard Authors
3   - * <p>
  2 + * Copyright © 2016-2018 The Thingsboard Authors
  3 + *
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
6 6 * You may obtain a copy of the License at
7   - * <p>
8   - * http://www.apache.org/licenses/LICENSE-2.0
9   - * <p>
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
10 10 * Unless required by applicable law or agreed to in writing, software
11 11 * distributed under the License is distributed on an "AS IS" BASIS,
12 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.rule.engine.queue.cassandra.repository.impl;
  16 +package org.thingsboard.server.dao.service.queue.cassandra.repository.impl;
17 17
18 18 import com.datastax.driver.core.*;
19 19 import com.google.common.base.Function;
20 20 import com.google.common.util.concurrent.Futures;
21 21 import com.google.common.util.concurrent.ListenableFuture;
  22 +import org.springframework.beans.factory.annotation.Value;
22 23 import org.springframework.stereotype.Component;
23   -import org.thingsboard.rule.engine.queue.cassandra.repository.ProcessedPartitionRepository;
  24 +import org.thingsboard.server.dao.nosql.CassandraAbstractDao;
  25 +import org.thingsboard.server.dao.service.queue.cassandra.repository.ProcessedPartitionRepository;
  26 +import org.thingsboard.server.dao.util.NoSqlDao;
24 27
25 28 import java.util.Optional;
26 29 import java.util.UUID;
27 30
28 31 @Component
29   -public class CassandraProcessedPartitionRepository extends SimpleAbstractCassandraDao implements ProcessedPartitionRepository {
  32 +@NoSqlDao
  33 +public class CassandraProcessedPartitionRepository extends CassandraAbstractDao implements ProcessedPartitionRepository {
30 34
31   - private final int repositoryTtl;
32   -
33   - public CassandraProcessedPartitionRepository(Session session, int repositoryTtl) {
34   - super(session);
35   - this.repositoryTtl = repositoryTtl;
36   - }
  35 + @Value("${cassandra.queue.partitions.ttl}")
  36 + private int partitionsTtl;
37 37
38 38 @Override
39   - public ListenableFuture<Void> partitionProcessed(UUID nodeId, long clusteredHash, long partition) {
40   - String insert = "INSERT INTO processed_msg_partitions (node_id, clustered_hash, partition) VALUES (?, ?, ?) USING TTL ?";
  39 + public ListenableFuture<Void> partitionProcessed(UUID nodeId, long clusterPartition, long tsPartition) {
  40 + String insert = "INSERT INTO processed_msg_partitions (node_id, cluster_partition, ts_partition) VALUES (?, ?, ?) USING TTL ?";
41 41 PreparedStatement prepared = prepare(insert);
42   - BoundStatement boundStatement = prepared.bind(nodeId, clusteredHash, partition, repositoryTtl);
  42 + BoundStatement boundStatement = prepared.bind(nodeId, clusterPartition, tsPartition, partitionsTtl);
43 43 ResultSetFuture resultSetFuture = executeAsyncWrite(boundStatement);
44 44 return Futures.transform(resultSetFuture, (Function<ResultSet, Void>) input -> null);
45 45 }
46 46
47 47 @Override
48 48 public Optional<Long> findLastProcessedPartition(UUID nodeId, long clusteredHash) {
49   - String select = "SELECT partition FROM processed_msg_partitions WHERE " +
50   - "node_id = ? AND clustered_hash = ?";
  49 + String select = "SELECT ts_partition FROM processed_msg_partitions WHERE " +
  50 + "node_id = ? AND cluster_partition = ?";
51 51 PreparedStatement prepared = prepare(select);
52 52 BoundStatement boundStatement = prepared.bind(nodeId, clusteredHash);
53 53 Row row = executeRead(boundStatement).one();
... ... @@ -55,6 +55,6 @@ public class CassandraProcessedPartitionRepository extends SimpleAbstractCassand
55 55 return Optional.empty();
56 56 }
57 57
58   - return Optional.of(row.getLong("partition"));
  58 + return Optional.of(row.getLong("ts_partition"));
59 59 }
60 60 }
... ...
... ... @@ -616,11 +616,11 @@ AND compaction = { 'class' : 'LeveledCompactionStrategy' };
616 616
617 617 CREATE TABLE IF NOT EXISTS thingsboard.msg_queue (
618 618 node_id timeuuid,
619   - clustered_hash bigint,
620   - partition bigint,
  619 + cluster_partition bigint,
  620 + ts_partition bigint,
621 621 ts bigint,
622 622 msg blob,
623   - PRIMARY KEY ((node_id, clustered_hash, partition), ts))
  623 + PRIMARY KEY ((node_id, cluster_partition, ts_partition), ts))
624 624 WITH CLUSTERING ORDER BY (ts DESC)
625 625 AND compaction = {
626 626 'class': 'org.apache.cassandra.db.compaction.DateTieredCompactionStrategy',
... ... @@ -633,10 +633,10 @@ AND compaction = {
633 633
634 634 CREATE TABLE IF NOT EXISTS thingsboard.msg_ack_queue (
635 635 node_id timeuuid,
636   - clustered_hash bigint,
637   - partition bigint,
  636 + cluster_partition bigint,
  637 + ts_partition bigint,
638 638 msg_id timeuuid,
639   - PRIMARY KEY ((node_id, clustered_hash, partition), msg_id))
  639 + PRIMARY KEY ((node_id, cluster_partition, ts_partition), msg_id))
640 640 WITH CLUSTERING ORDER BY (msg_id DESC)
641 641 AND compaction = {
642 642 'class': 'org.apache.cassandra.db.compaction.DateTieredCompactionStrategy',
... ... @@ -649,10 +649,10 @@ AND compaction = {
649 649
650 650 CREATE TABLE IF NOT EXISTS thingsboard.processed_msg_partitions (
651 651 node_id timeuuid,
652   - clustered_hash bigint,
653   - partition bigint,
654   - PRIMARY KEY ((node_id, clustered_hash), partition))
655   -WITH CLUSTERING ORDER BY (partition DESC)
  652 + cluster_partition bigint,
  653 + ts_partition bigint,
  654 + PRIMARY KEY ((node_id, cluster_partition), ts_partition))
  655 +WITH CLUSTERING ORDER BY (ts_partition DESC)
656 656 AND compaction = {
657 657 'class': 'org.apache.cassandra.db.compaction.DateTieredCompactionStrategy',
658 658 'min_threshold': '5',
... ...
... ... @@ -26,7 +26,9 @@ import java.util.Arrays;
26 26
27 27 @RunWith(ClasspathSuite.class)
28 28 @ClassnameFilters({
29   - "org.thingsboard.server.dao.service.*ServiceNoSqlTest"
  29 + "org.thingsboard.server.dao.service.*ServiceNoSqlTest",
  30 + "org.thingsboard.server.dao.service.queue.cassandra.*.*.*Test",
  31 + "org.thingsboard.server.dao.service.queue.cassandra.*Test"
30 32 })
31 33 public class NoSqlDaoServiceTestSuite {
32 34
... ...
dao/src/test/java/org/thingsboard/server/dao/service/queue/cassandra/QueuePartitionerTest.java renamed from rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/queue/cassandra/QueuePartitionerTest.java
1 1 /**
2   - * Copyright © 2016-2017 The Thingsboard Authors
3   - * <p>
  2 + * Copyright © 2016-2018 The Thingsboard Authors
  3 + *
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
6 6 * You may obtain a copy of the License at
7   - * <p>
8   - * http://www.apache.org/licenses/LICENSE-2.0
9   - * <p>
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
10 10 * Unless required by applicable law or agreed to in writing, software
11 11 * distributed under the License is distributed on an "AS IS" BASIS,
12 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.rule.engine.queue.cassandra;
  16 +package org.thingsboard.server.dao.service.queue.cassandra;
17 17
18 18
19 19 import org.junit.Before;
... ... @@ -21,7 +21,7 @@ import org.junit.Test;
21 21 import org.junit.runner.RunWith;
22 22 import org.mockito.Mock;
23 23 import org.mockito.runners.MockitoJUnitRunner;
24   -import org.thingsboard.rule.engine.queue.cassandra.repository.ProcessedPartitionRepository;
  24 +import org.thingsboard.server.dao.service.queue.cassandra.repository.ProcessedPartitionRepository;
25 25
26 26 import java.time.Clock;
27 27 import java.time.Instant;
... ...
dao/src/test/java/org/thingsboard/server/dao/service/queue/cassandra/UnprocessedMsgFilterTest.java renamed from rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/queue/cassandra/UnprocessedMsgFilterTest.java
1 1 /**
2   - * Copyright © 2016-2017 The Thingsboard Authors
  2 + * Copyright © 2016-2018 The Thingsboard Authors
3 3 *
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
... ... @@ -13,11 +13,11 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.rule.engine.queue.cassandra;
  16 +package org.thingsboard.server.dao.service.queue.cassandra;
17 17
18 18 import com.google.common.collect.Lists;
19 19 import org.junit.Test;
20   -import org.thingsboard.rule.engine.api.TbMsg;
  20 +import org.thingsboard.server.common.msg.TbMsg;
21 21
22 22 import java.util.Collection;
23 23 import java.util.List;
... ...
dao/src/test/java/org/thingsboard/server/dao/service/queue/cassandra/repository/impl/CassandraAckRepositoryTest.java renamed from rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/queue/cassandra/repository/impl/CassandraAckRepositoryTest.java
1 1 /**
2   - * Copyright © 2016-2017 The Thingsboard Authors
  2 + * Copyright © 2016-2018 The Thingsboard Authors
3 3 *
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
... ... @@ -13,14 +13,17 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.rule.engine.queue.cassandra.repository.impl;
  16 +package org.thingsboard.server.dao.service.queue.cassandra.repository.impl;
17 17
18 18 import com.datastax.driver.core.utils.UUIDs;
19 19 import com.google.common.collect.Lists;
20 20 import com.google.common.util.concurrent.ListenableFuture;
21 21 import org.junit.Before;
22 22 import org.junit.Test;
23   -import org.thingsboard.rule.engine.queue.cassandra.MsgAck;
  23 +import org.springframework.beans.factory.annotation.Autowired;
  24 +import org.thingsboard.server.dao.service.AbstractServiceTest;
  25 +import org.thingsboard.server.dao.service.DaoNoSqlTest;
  26 +import org.thingsboard.server.dao.service.queue.cassandra.MsgAck;
24 27
25 28 import java.util.List;
26 29 import java.util.UUID;
... ... @@ -30,15 +33,12 @@ import java.util.concurrent.TimeUnit;
30 33 import static org.junit.Assert.assertEquals;
31 34 import static org.junit.Assert.assertTrue;
32 35
33   -public class CassandraAckRepositoryTest extends SimpleAbstractCassandraDaoTest {
  36 +@DaoNoSqlTest
  37 +public class CassandraAckRepositoryTest extends AbstractServiceTest {
34 38
  39 + @Autowired
35 40 private CassandraAckRepository ackRepository;
36 41
37   - @Before
38   - public void init() {
39   - ackRepository = new CassandraAckRepository(cassandraUnit.session, 1);
40   - }
41   -
42 42 @Test
43 43 public void acksInPartitionCouldBeFound() {
44 44 UUID nodeId = UUID.fromString("055eee50-1883-11e8-b380-65b5d5335ba9");
... ...
dao/src/test/java/org/thingsboard/server/dao/service/queue/cassandra/repository/impl/CassandraMsgRepositoryTest.java renamed from rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/queue/cassandra/repository/impl/CassandraMsgRepositoryTest.java
1 1 /**
2   - * Copyright © 2016-2017 The Thingsboard Authors
3   - * <p>
  2 + * Copyright © 2016-2018 The Thingsboard Authors
  3 + *
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
6 6 * You may obtain a copy of the License at
7   - * <p>
8   - * http://www.apache.org/licenses/LICENSE-2.0
9   - * <p>
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
10 10 * Unless required by applicable law or agreed to in writing, software
11 11 * distributed under the License is distributed on an "AS IS" BASIS,
12 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.rule.engine.queue.cassandra.repository.impl;
  16 +package org.thingsboard.server.dao.service.queue.cassandra.repository.impl;
17 17
18 18 //import static org.junit.jupiter.api.Assertions.*;
19 19
... ... @@ -21,9 +21,12 @@ import com.datastax.driver.core.utils.UUIDs;
21 21 import com.google.common.util.concurrent.ListenableFuture;
22 22 import org.junit.Before;
23 23 import org.junit.Test;
24   -import org.thingsboard.rule.engine.api.TbMsg;
25   -import org.thingsboard.rule.engine.api.TbMsgMetaData;
  24 +import org.springframework.beans.factory.annotation.Autowired;
26 25 import org.thingsboard.server.common.data.id.DeviceId;
  26 +import org.thingsboard.server.common.msg.TbMsg;
  27 +import org.thingsboard.server.common.msg.TbMsgMetaData;
  28 +import org.thingsboard.server.dao.service.AbstractServiceTest;
  29 +import org.thingsboard.server.dao.service.DaoNoSqlTest;
27 30
28 31 import java.util.List;
29 32 import java.util.UUID;
... ... @@ -33,15 +36,12 @@ import java.util.concurrent.TimeUnit;
33 36 import static org.junit.Assert.assertEquals;
34 37 import static org.junit.Assert.assertTrue;
35 38
36   -public class CassandraMsgRepositoryTest extends SimpleAbstractCassandraDaoTest {
  39 +@DaoNoSqlTest
  40 +public class CassandraMsgRepositoryTest extends AbstractServiceTest {
37 41
  42 + @Autowired
38 43 private CassandraMsgRepository msgRepository;
39 44
40   - @Before
41   - public void init() {
42   - msgRepository = new CassandraMsgRepository(cassandraUnit.session, 1);
43   - }
44   -
45 45 @Test
46 46 public void msgCanBeSavedAndRead() throws ExecutionException, InterruptedException {
47 47 TbMsg msg = new TbMsg(UUIDs.timeBased(), "type", new DeviceId(UUIDs.timeBased()), null, new byte[4]);
... ... @@ -58,8 +58,6 @@ public class CassandraMsgRepositoryTest extends SimpleAbstractCassandraDaoTest {
58 58 UUID nodeId = UUIDs.timeBased();
59 59 ListenableFuture<Void> future = msgRepository.save(msg, nodeId, 2L, 2L, 2L);
60 60 future.get();
61   - List<TbMsg> msgs = msgRepository.findMsgs(nodeId, 2L, 2L);
62   - assertEquals(1, msgs.size());
63 61 TimeUnit.SECONDS.sleep(2);
64 62 assertTrue(msgRepository.findMsgs(nodeId, 2L, 2L).isEmpty());
65 63 }
... ...
dao/src/test/java/org/thingsboard/server/dao/service/queue/cassandra/repository/impl/CassandraProcessedPartitionRepositoryTest.java renamed from rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/queue/cassandra/repository/impl/CassandraProcessedPartitionRepositoryTest.java
1 1 /**
2   - * Copyright © 2016-2017 The Thingsboard Authors
  2 + * Copyright © 2016-2018 The Thingsboard Authors
3 3 *
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
... ... @@ -13,13 +13,16 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.rule.engine.queue.cassandra.repository.impl;
  16 +package org.thingsboard.server.dao.service.queue.cassandra.repository.impl;
17 17
18 18 import com.datastax.driver.core.utils.UUIDs;
19 19 import com.google.common.util.concurrent.Futures;
20 20 import com.google.common.util.concurrent.ListenableFuture;
21 21 import org.junit.Before;
22 22 import org.junit.Test;
  23 +import org.springframework.beans.factory.annotation.Autowired;
  24 +import org.thingsboard.server.dao.service.AbstractServiceTest;
  25 +import org.thingsboard.server.dao.service.DaoNoSqlTest;
23 26
24 27 import java.util.List;
25 28 import java.util.Optional;
... ... @@ -29,15 +32,12 @@ import java.util.concurrent.TimeUnit;
29 32
30 33 import static org.junit.Assert.*;
31 34
32   -public class CassandraProcessedPartitionRepositoryTest extends SimpleAbstractCassandraDaoTest {
  35 +@DaoNoSqlTest
  36 +public class CassandraProcessedPartitionRepositoryTest extends AbstractServiceTest {
33 37
  38 + @Autowired
34 39 private CassandraProcessedPartitionRepository partitionRepository;
35 40
36   - @Before
37   - public void init() {
38   - partitionRepository = new CassandraProcessedPartitionRepository(cassandraUnit.session, 1);
39   - }
40   -
41 41 @Test
42 42 public void lastProcessedPartitionCouldBeFound() {
43 43 UUID nodeId = UUID.fromString("055eee50-1883-11e8-b380-65b5d5335ba9");
... ...
1 1 TRUNCATE thingsboard.plugin;
2   -TRUNCATE thingsboard.rule;
\ No newline at end of file
  2 +TRUNCATE thingsboard.rule;
  3 +
  4 +-- msg_queue dataset
  5 +
  6 +INSERT INTO thingsboard.msg_queue (node_id, cluster_partition, ts_partition, ts, msg)
  7 + VALUES (055eee50-1883-11e8-b380-65b5d5335ba9, 101, 200, 201, null);
  8 +INSERT INTO thingsboard.msg_queue (node_id, cluster_partition, ts_partition, ts, msg)
  9 + VALUES (055eee50-1883-11e8-b380-65b5d5335ba9, 101, 200, 202, null);
  10 +INSERT INTO thingsboard.msg_queue (node_id, cluster_partition, ts_partition, ts, msg)
  11 + VALUES (055eee50-1883-11e8-b380-65b5d5335ba9, 101, 300, 301, null);
  12 +
  13 +-- ack_queue dataset
  14 +INSERT INTO thingsboard.msg_ack_queue (node_id, cluster_partition, ts_partition, msg_id)
  15 + VALUES (055eee50-1883-11e8-b380-65b5d5335ba9, 101, 300, bebaeb60-1888-11e8-bf21-65b5d5335ba9);
  16 +INSERT INTO thingsboard.msg_ack_queue (node_id, cluster_partition, ts_partition, msg_id)
  17 + VALUES (055eee50-1883-11e8-b380-65b5d5335ba9, 101, 300, 12baeb60-1888-11e8-bf21-65b5d5335ba9);
  18 +INSERT INTO thingsboard.msg_ack_queue (node_id, cluster_partition, ts_partition, msg_id)
  19 + VALUES (055eee50-1883-11e8-b380-65b5d5335ba9, 101, 200, 32baeb60-1888-11e8-bf21-65b5d5335ba9);
  20 +
  21 +-- processed partition dataset
  22 +INSERT INTO thingsboard.processed_msg_partitions (node_id, cluster_partition, ts_partition)
  23 + VALUES (055eee50-1883-11e8-b380-65b5d5335ba9, 101, 100);
  24 +INSERT INTO thingsboard.processed_msg_partitions (node_id, cluster_partition, ts_partition)
  25 + VALUES (055eee50-1883-11e8-b380-65b5d5335ba9, 101, 777);
  26 +INSERT INTO thingsboard.processed_msg_partitions (node_id, cluster_partition, ts_partition)
  27 + VALUES (055eee50-1883-11e8-b380-65b5d5335ba9, 202, 200);
\ No newline at end of file
... ...
1   -database.type=cassandra
\ No newline at end of file
  1 +database.type=cassandra
  2 +
  3 +cassandra.queue.partitioning=HOURS
  4 +cassandra.queue.ack.ttl=1
  5 +cassandra.queue.msg.ttl=1
  6 +cassandra.queue.partitions.ttl=1
\ No newline at end of file
... ...
... ... @@ -35,7 +35,7 @@
35 35 <spring-data-redis.version>1.8.10.RELEASE</spring-data-redis.version>
36 36 <jedis.version>2.9.0</jedis.version>
37 37 <jjwt.version>0.7.0</jjwt.version>
38   - <json-path.version>2.2.0</json-path.version>
  38 + <json-path.version>2.2.0</json-path.version>
39 39 <junit.version>4.12</junit.version>
40 40 <slf4j.version>1.7.7</slf4j.version>
41 41 <logback.version>1.2.3</logback.version>
... ... @@ -79,17 +79,19 @@
79 79 <dbunit.version>2.5.3</dbunit.version>
80 80 <spring-test-dbunit.version>1.2.1</spring-test-dbunit.version>
81 81 <postgresql.driver.version>9.4.1211</postgresql.driver.version>
82   - <sonar.exclusions>org/thingsboard/server/gen/**/*, org/thingsboard/server/extensions/core/plugin/telemetry/gen/**/*</sonar.exclusions>
  82 + <sonar.exclusions>org/thingsboard/server/gen/**/*,
  83 + org/thingsboard/server/extensions/core/plugin/telemetry/gen/**/*
  84 + </sonar.exclusions>
83 85 <elasticsearch.version>5.0.2</elasticsearch.version>
84 86 </properties>
85 87
86 88 <modules>
87 89 <module>common</module>
  90 + <module>rule-engine</module>
88 91 <module>dao</module>
89 92 <module>extensions-api</module>
90 93 <module>extensions-core</module>
91 94 <module>extensions</module>
92   - <module>rule-engine</module>
93 95 <module>transport</module>
94 96 <module>ui</module>
95 97 <module>tools</module>
... ... @@ -372,6 +374,11 @@
372 374 <version>${project.version}</version>
373 375 </dependency>
374 376 <dependency>
  377 + <groupId>org.thingsboard.rule-engine</groupId>
  378 + <artifactId>rule-engine-api</artifactId>
  379 + <version>${project.version}</version>
  380 + </dependency>
  381 + <dependency>
375 382 <groupId>org.thingsboard.common</groupId>
376 383 <artifactId>message</artifactId>
377 384 <version>${project.version}</version>
... ...
1 1 <!--
2 2
3   - Copyright © 2016-2017 The Thingsboard Authors
  3 + Copyright © 2016-2018 The Thingsboard Authors
4 4
5 5 Licensed under the Apache License, Version 2.0 (the "License");
6 6 you may not use this file except in compliance with the License.
... ... @@ -20,10 +20,9 @@
20 20 <modelVersion>4.0.0</modelVersion>
21 21 <parent>
22 22 <groupId>org.thingsboard</groupId>
23   - <version>1.4.0-SNAPSHOT</version>
  23 + <version>1.4.1-SNAPSHOT</version>
24 24 <artifactId>thingsboard</artifactId>
25 25 </parent>
26   - <groupId>org.thingsboard</groupId>
27 26 <artifactId>rule-engine</artifactId>
28 27 <packaging>pom</packaging>
29 28
... ...
1 1 <?xml version="1.0" encoding="UTF-8"?>
2 2 <!--
3 3
4   - Copyright © 2016-2017 The Thingsboard Authors
  4 + Copyright © 2016-2018 The Thingsboard Authors
5 5
6 6 Licensed under the Apache License, Version 2.0 (the "License");
7 7 you may not use this file except in compliance with the License.
... ... @@ -22,7 +22,7 @@
22 22 <modelVersion>4.0.0</modelVersion>
23 23 <parent>
24 24 <groupId>org.thingsboard</groupId>
25   - <version>1.4.0-SNAPSHOT</version>
  25 + <version>1.4.1-SNAPSHOT</version>
26 26 <artifactId>rule-engine</artifactId>
27 27 </parent>
28 28 <groupId>org.thingsboard.rule-engine</groupId>
... ... @@ -54,6 +54,11 @@
54 54 <scope>provided</scope>
55 55 </dependency>
56 56 <dependency>
  57 + <groupId>com.google.guava</groupId>
  58 + <artifactId>guava</artifactId>
  59 + <scope>provided</scope>
  60 + </dependency>
  61 + <dependency>
57 62 <groupId>ch.qos.logback</groupId>
58 63 <artifactId>logback-core</artifactId>
59 64 <scope>provided</scope>
... ...
1 1 /**
2   - * Copyright © 2016-2017 The Thingsboard Authors
  2 + * Copyright © 2016-2018 The Thingsboard Authors
3 3 *
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
... ... @@ -15,6 +15,7 @@
15 15 */
16 16 package org.thingsboard.rule.engine.api;
17 17
  18 +import org.thingsboard.server.common.msg.TbMsg;
18 19 import org.thingsboard.server.common.msg.cluster.ServerAddress;
19 20 import org.thingsboard.server.dao.attributes.AttributesService;
20 21
... ...
1 1 /**
2   - * Copyright © 2016-2017 The Thingsboard Authors
  2 + * Copyright © 2016-2018 The Thingsboard Authors
3 3 *
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
... ... @@ -15,6 +15,8 @@
15 15 */
16 16 package org.thingsboard.rule.engine.api;
17 17
  18 +import org.thingsboard.server.common.msg.TbMsg;
  19 +
18 20 import java.util.concurrent.ExecutionException;
19 21
20 22 /**
... ...
1 1 /**
2   - * Copyright © 2016-2017 The Thingsboard Authors
  2 + * Copyright © 2016-2018 The Thingsboard Authors
3 3 *
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
... ...
1 1 /**
2   - * Copyright © 2016-2017 The Thingsboard Authors
  2 + * Copyright © 2016-2018 The Thingsboard Authors
3 3 *
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
... ...
1 1 /**
2   - * Copyright © 2016-2017 The Thingsboard Authors
  2 + * Copyright © 2016-2018 The Thingsboard Authors
3 3 *
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
... ...
1 1 <?xml version="1.0" encoding="UTF-8"?>
2 2 <!--
3 3
4   - Copyright © 2016-2017 The Thingsboard Authors
  4 + Copyright © 2016-2018 The Thingsboard Authors
5 5
6 6 Licensed under the Apache License, Version 2.0 (the "License");
7 7 you may not use this file except in compliance with the License.
... ... @@ -22,7 +22,7 @@
22 22 <modelVersion>4.0.0</modelVersion>
23 23 <parent>
24 24 <groupId>org.thingsboard</groupId>
25   - <version>1.4.0-SNAPSHOT</version>
  25 + <version>1.4.1-SNAPSHOT</version>
26 26 <artifactId>rule-engine</artifactId>
27 27 </parent>
28 28 <groupId>org.thingsboard.rule-engine</groupId>
... ... @@ -61,31 +61,12 @@
61 61 <dependency>
62 62 <groupId>org.thingsboard.rule-engine</groupId>
63 63 <artifactId>rule-engine-api</artifactId>
64   - <version>1.4.0-SNAPSHOT</version>
65   - </dependency>
66   - <dependency>
67   - <groupId>com.google.protobuf</groupId>
68   - <artifactId>protobuf-java</artifactId>
69   - <scope>provided</scope>
70 64 </dependency>
71 65 <dependency>
72 66 <groupId>com.google.guava</groupId>
73 67 <artifactId>guava</artifactId>
74 68 </dependency>
75 69 <dependency>
76   - <groupId>com.datastax.cassandra</groupId>
77   - <artifactId>cassandra-driver-core</artifactId>
78   - </dependency>
79   - <dependency>
80   - <groupId>com.datastax.cassandra</groupId>
81   - <artifactId>cassandra-driver-mapping</artifactId>
82   - </dependency>
83   - <dependency>
84   - <groupId>com.datastax.cassandra</groupId>
85   - <artifactId>cassandra-driver-extras</artifactId>
86   - </dependency>
87   -
88   - <dependency>
89 70 <groupId>junit</groupId>
90 71 <artifactId>junit</artifactId>
91 72 <version>${junit.version}</version>
... ... @@ -127,22 +108,14 @@
127 108 <artifactId>maven-dependency-plugin</artifactId>
128 109 </plugin>
129 110 <plugin>
130   - <groupId>org.xolstice.maven.plugins</groupId>
131   - <artifactId>protobuf-maven-plugin</artifactId>
132   - </plugin>
133   - <plugin>
134 111 <groupId>org.codehaus.mojo</groupId>
135 112 <artifactId>build-helper-maven-plugin</artifactId>
136 113 </plugin>
137   -
138   -
139   -
140   -
141 114 <plugin>
142 115 <groupId>org.springframework.boot</groupId>
143 116 <artifactId>spring-boot-maven-plugin</artifactId>
144 117 <configuration>
145   - <mainClass>org.thingsboard.rule.engine.tool.QueueBenchmark</mainClass>
  118 + <mainClass>org.thingsboard.server.dao.queue.QueueBenchmark</mainClass>
146 119 <classifier>boot</classifier>
147 120 <layout>ZIP</layout>
148 121 <executable>true</executable>
... ...
1 1 /**
2   - * Copyright © 2016-2017 The Thingsboard Authors
  2 + * Copyright © 2016-2018 The Thingsboard Authors
3 3 *
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
... ...
1 1 /**
2   - * Copyright © 2016-2017 The Thingsboard Authors
  2 + * Copyright © 2016-2018 The Thingsboard Authors
3 3 *
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
... ... @@ -18,12 +18,7 @@ package org.thingsboard.rule.engine.filter;
18 18 import lombok.extern.slf4j.Slf4j;
19 19 import org.thingsboard.rule.engine.TbNodeUtils;
20 20 import org.thingsboard.rule.engine.api.*;
21   -import org.thingsboard.rule.engine.metadata.TbGetAttributesNodeConfiguration;
22   -import org.thingsboard.server.common.data.DataConstants;
23   -import org.thingsboard.server.common.data.kv.AttributeKvEntry;
24   -import org.thingsboard.server.dao.attributes.AttributesService;
25   -
26   -import java.util.List;
  21 +import org.thingsboard.server.common.msg.TbMsg;
27 22
28 23 /**
29 24 * Created by ashvayka on 19.01.18.
... ...
1 1 /**
2   - * Copyright © 2016-2017 The Thingsboard Authors
  2 + * Copyright © 2016-2018 The Thingsboard Authors
3 3 *
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
... ...
1 1 /**
2   - * Copyright © 2016-2017 The Thingsboard Authors
  2 + * Copyright © 2016-2018 The Thingsboard Authors
3 3 *
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
... ... @@ -20,6 +20,7 @@ import org.thingsboard.rule.engine.TbNodeUtils;
20 20 import org.thingsboard.rule.engine.api.*;
21 21 import org.thingsboard.server.common.data.DataConstants;
22 22 import org.thingsboard.server.common.data.kv.AttributeKvEntry;
  23 +import org.thingsboard.server.common.msg.TbMsg;
23 24 import org.thingsboard.server.dao.attributes.AttributesService;
24 25
25 26 import java.util.List;
... ...
1 1 /**
2   - * Copyright © 2016-2017 The Thingsboard Authors
  2 + * Copyright © 2016-2018 The Thingsboard Authors
3 3 *
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
... ...
1   -/**
2   - * Copyright © 2016-2017 The Thingsboard Authors
3   - * <p>
4   - * Licensed under the Apache License, Version 2.0 (the "License");
5   - * you may not use this file except in compliance with the License.
6   - * You may obtain a copy of the License at
7   - * <p>
8   - * http://www.apache.org/licenses/LICENSE-2.0
9   - * <p>
10   - * Unless required by applicable law or agreed to in writing, software
11   - * distributed under the License is distributed on an "AS IS" BASIS,
12   - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   - * See the License for the specific language governing permissions and
14   - * limitations under the License.
15   - */
16   -package org.thingsboard.rule.engine.queue.cassandra.repository.impl;
17   -
18   -import com.datastax.driver.core.*;
19   -import com.google.common.base.Function;
20   -import com.google.common.util.concurrent.Futures;
21   -import com.google.common.util.concurrent.ListenableFuture;
22   -import com.google.protobuf.ByteString;
23   -import com.google.protobuf.InvalidProtocolBufferException;
24   -import org.springframework.stereotype.Component;
25   -import org.thingsboard.rule.engine.api.TbMsg;
26   -import org.thingsboard.rule.engine.api.TbMsgMetaData;
27   -import org.thingsboard.rule.engine.queue.cassandra.repository.MsgRepository;
28   -import org.thingsboard.rule.engine.queue.cassandra.repository.gen.MsgQueueProtos;
29   -import org.thingsboard.server.common.data.id.EntityId;
30   -import org.thingsboard.server.common.data.id.EntityIdFactory;
31   -
32   -import java.nio.ByteBuffer;
33   -import java.util.ArrayList;
34   -import java.util.List;
35   -import java.util.UUID;
36   -
37   -@Component
38   -public class CassandraMsgRepository extends SimpleAbstractCassandraDao implements MsgRepository {
39   -
40   - private final int msqQueueTtl;
41   -
42   -
43   - public CassandraMsgRepository(Session session, int msqQueueTtl) {
44   - super(session);
45   - this.msqQueueTtl = msqQueueTtl;
46   - }
47   -
48   - @Override
49   - public ListenableFuture<Void> save(TbMsg msg, UUID nodeId, long clusteredHash, long partition, long msgTs) {
50   - String insert = "INSERT INTO msg_queue (node_id, clustered_hash, partition, ts, msg) VALUES (?, ?, ?, ?, ?) USING TTL ?";
51   - PreparedStatement statement = prepare(insert);
52   - BoundStatement boundStatement = statement.bind(nodeId, clusteredHash, partition, msgTs, toBytes(msg), msqQueueTtl);
53   - ResultSetFuture resultSetFuture = executeAsyncWrite(boundStatement);
54   - return Futures.transform(resultSetFuture, (Function<ResultSet, Void>) input -> null);
55   - }
56   -
57   - @Override
58   - public List<TbMsg> findMsgs(UUID nodeId, long clusteredHash, long partition) {
59   - String select = "SELECT node_id, clustered_hash, partition, ts, msg FROM msg_queue WHERE " +
60   - "node_id = ? AND clustered_hash = ? AND partition = ?";
61   - PreparedStatement statement = prepare(select);
62   - BoundStatement boundStatement = statement.bind(nodeId, clusteredHash, partition);
63   - ResultSet rows = executeRead(boundStatement);
64   - List<TbMsg> msgs = new ArrayList<>();
65   - for (Row row : rows) {
66   - msgs.add(fromBytes(row.getBytes("msg")));
67   - }
68   - return msgs;
69   - }
70   -
71   - private ByteBuffer toBytes(TbMsg msg) {
72   - MsgQueueProtos.TbMsgProto.Builder builder = MsgQueueProtos.TbMsgProto.newBuilder();
73   - builder.setId(msg.getId().toString());
74   - builder.setType(msg.getType());
75   - if (msg.getOriginator() != null) {
76   - builder.setEntityType(msg.getOriginator().getEntityType().name());
77   - builder.setEntityId(msg.getOriginator().getId().toString());
78   - }
79   -
80   - if (msg.getMetaData() != null) {
81   - MsgQueueProtos.TbMsgProto.TbMsgMetaDataProto.Builder metadataBuilder = MsgQueueProtos.TbMsgProto.TbMsgMetaDataProto.newBuilder();
82   - metadataBuilder.putAllData(msg.getMetaData().getData());
83   - builder.addMetaData(metadataBuilder.build());
84   - }
85   -
86   - builder.setData(ByteString.copyFrom(msg.getData()));
87   - byte[] bytes = builder.build().toByteArray();
88   - return ByteBuffer.wrap(bytes);
89   - }
90   -
91   - private TbMsg fromBytes(ByteBuffer buffer) {
92   - try {
93   - MsgQueueProtos.TbMsgProto proto = MsgQueueProtos.TbMsgProto.parseFrom(buffer.array());
94   - TbMsgMetaData metaData = new TbMsgMetaData();
95   - if (proto.getMetaDataCount() > 0) {
96   - metaData.setData(proto.getMetaData(0).getDataMap());
97   - }
98   -
99   - EntityId entityId = null;
100   - if (proto.getEntityId() != null) {
101   - entityId = EntityIdFactory.getByTypeAndId(proto.getEntityType(), proto.getEntityId());
102   - }
103   -
104   - return new TbMsg(UUID.fromString(proto.getId()), proto.getType(), entityId, metaData, proto.getData().toByteArray());
105   - } catch (InvalidProtocolBufferException e) {
106   - throw new IllegalStateException("Could not parse protobuf for TbMsg", e);
107   - }
108   - }
109   -}
1   -/**
2   - * Copyright © 2016-2017 The Thingsboard Authors
3   - * <p>
4   - * Licensed under the Apache License, Version 2.0 (the "License");
5   - * you may not use this file except in compliance with the License.
6   - * You may obtain a copy of the License at
7   - * <p>
8   - * http://www.apache.org/licenses/LICENSE-2.0
9   - * <p>
10   - * Unless required by applicable law or agreed to in writing, software
11   - * distributed under the License is distributed on an "AS IS" BASIS,
12   - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   - * See the License for the specific language governing permissions and
14   - * limitations under the License.
15   - */
16   -package org.thingsboard.rule.engine.queue.cassandra.repository.impl;
17   -
18   -import com.datastax.driver.core.*;
19   -import lombok.extern.slf4j.Slf4j;
20   -import org.springframework.stereotype.Component;
21   -
22   -import java.util.Map;
23   -import java.util.concurrent.ConcurrentHashMap;
24   -
25   -@Component
26   -@Slf4j
27   -public abstract class SimpleAbstractCassandraDao {
28   -
29   - private ConsistencyLevel defaultReadLevel = ConsistencyLevel.QUORUM;
30   - private ConsistencyLevel defaultWriteLevel = ConsistencyLevel.QUORUM;
31   - private Session session;
32   - private Map<String, PreparedStatement> preparedStatementMap = new ConcurrentHashMap<>();
33   -
34   - public SimpleAbstractCassandraDao(Session session) {
35   - this.session = session;
36   - }
37   -
38   - protected Session getSession() {
39   - return session;
40   - }
41   -
42   - protected ResultSet executeRead(Statement statement) {
43   - return execute(statement, defaultReadLevel);
44   - }
45   -
46   - protected ResultSet executeWrite(Statement statement) {
47   - return execute(statement, defaultWriteLevel);
48   - }
49   -
50   - protected ResultSetFuture executeAsyncRead(Statement statement) {
51   - return executeAsync(statement, defaultReadLevel);
52   - }
53   -
54   - protected ResultSetFuture executeAsyncWrite(Statement statement) {
55   - return executeAsync(statement, defaultWriteLevel);
56   - }
57   -
58   - protected PreparedStatement prepare(String query) {
59   - return preparedStatementMap.computeIfAbsent(query, i -> getSession().prepare(i));
60   - }
61   -
62   - private ResultSet execute(Statement statement, ConsistencyLevel level) {
63   - log.debug("Execute cassandra statement {}", statement);
64   - if (statement.getConsistencyLevel() == null) {
65   - statement.setConsistencyLevel(level);
66   - }
67   - return getSession().execute(statement);
68   - }
69   -
70   - private ResultSetFuture executeAsync(Statement statement, ConsistencyLevel level) {
71   - log.debug("Execute cassandra async statement {}", statement);
72   - if (statement.getConsistencyLevel() == null) {
73   - statement.setConsistencyLevel(level);
74   - }
75   - return getSession().executeAsync(statement);
76   - }
77   -}
1 1 /**
2   - * Copyright © 2016-2017 The Thingsboard Authors
  2 + * Copyright © 2016-2018 The Thingsboard Authors
3 3 *
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
... ... @@ -21,6 +21,7 @@ import org.thingsboard.rule.engine.api.*;
21 21 import org.thingsboard.rule.engine.metadata.TbGetAttributesNodeConfiguration;
22 22 import org.thingsboard.server.common.data.DataConstants;
23 23 import org.thingsboard.server.common.data.kv.AttributeKvEntry;
  24 +import org.thingsboard.server.common.msg.TbMsg;
24 25 import org.thingsboard.server.dao.attributes.AttributesService;
25 26
26 27 import java.util.List;
... ...
1   -/**
2   - * Copyright © 2016-2017 The Thingsboard Authors
3   - *
4   - * Licensed under the Apache License, Version 2.0 (the "License");
5   - * you may not use this file except in compliance with the License.
6   - * You may obtain a copy of the License at
7   - *
8   - * http://www.apache.org/licenses/LICENSE-2.0
9   - *
10   - * Unless required by applicable law or agreed to in writing, software
11   - * distributed under the License is distributed on an "AS IS" BASIS,
12   - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   - * See the License for the specific language governing permissions and
14   - * limitations under the License.
15   - */
16   -package org.thingsboard.rule.engine.queue.cassandra;
17   -
18   -import org.junit.Before;
19   -import org.junit.Test;
20   -import org.mockito.Mock;
21   -import org.thingsboard.rule.engine.queue.cassandra.repository.AckRepository;
22   -import org.thingsboard.rule.engine.queue.cassandra.repository.MsgRepository;
23   -
24   -public class CassandraMsqQueueTest {
25   -
26   - private CassandraMsqQueue msqQueue;
27   -
28   - @Mock
29   - private MsgRepository msgRepository;
30   - @Mock
31   - private AckRepository ackRepository;
32   - @Mock
33   - private UnprocessedMsgFilter unprocessedMsgFilter;
34   - @Mock
35   - private QueuePartitioner queuePartitioner;
36   -
37   - @Before
38   - public void init() {
39   - msqQueue = new CassandraMsqQueue(msgRepository, ackRepository, unprocessedMsgFilter, queuePartitioner);
40   - }
41   -
42   - @Test
43   - public void msgCanBeSaved() {
44   -// todo-vp: implement
45   - }
46   -
47   -
48   -}
\ No newline at end of file
1   -/**
2   - * Copyright © 2016-2017 The Thingsboard Authors
3   - *
4   - * Licensed under the Apache License, Version 2.0 (the "License");
5   - * you may not use this file except in compliance with the License.
6   - * You may obtain a copy of the License at
7   - *
8   - * http://www.apache.org/licenses/LICENSE-2.0
9   - *
10   - * Unless required by applicable law or agreed to in writing, software
11   - * distributed under the License is distributed on an "AS IS" BASIS,
12   - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   - * See the License for the specific language governing permissions and
14   - * limitations under the License.
15   - */
16   -package org.thingsboard.rule.engine.queue.cassandra.repository.impl;
17   -
18   -import org.cassandraunit.CassandraCQLUnit;
19   -import org.cassandraunit.dataset.cql.ClassPathCQLDataSet;
20   -import org.junit.ClassRule;
21   -
22   -
23   -public abstract class SimpleAbstractCassandraDaoTest {
24   -
25   - @ClassRule
26   - public static CassandraCQLUnit cassandraUnit = new CassandraCQLUnit(
27   - new ClassPathCQLDataSet("cassandra/system-test.cql", "thingsboard"));
28   -
29   -
30   -}
\ No newline at end of file
1   -CREATE TABLE IF NOT EXISTS thingsboard.msg_queue (
2   - node_id timeuuid,
3   - clustered_hash bigint,
4   - partition bigint,
5   - ts bigint,
6   - msg blob,
7   - PRIMARY KEY ((node_id, clustered_hash, partition), ts))
8   -WITH CLUSTERING ORDER BY (ts DESC)
9   -AND compaction = {
10   - 'class': 'org.apache.cassandra.db.compaction.DateTieredCompactionStrategy',
11   - 'min_threshold': '5',
12   - 'base_time_seconds': '43200',
13   - 'max_window_size_seconds': '43200',
14   - 'tombstone_threshold': '0.9',
15   - 'unchecked_tombstone_compaction': 'true'
16   -};
17   -
18   -
19   -CREATE TABLE IF NOT EXISTS thingsboard.msg_ack_queue (
20   - node_id timeuuid,
21   - clustered_hash bigint,
22   - partition bigint,
23   - msg_id timeuuid,
24   - PRIMARY KEY ((node_id, clustered_hash, partition), msg_id))
25   -WITH CLUSTERING ORDER BY (msg_id DESC)
26   -AND compaction = {
27   - 'class': 'org.apache.cassandra.db.compaction.DateTieredCompactionStrategy',
28   - 'min_threshold': '5',
29   - 'base_time_seconds': '43200',
30   - 'max_window_size_seconds': '43200',
31   - 'tombstone_threshold': '0.9',
32   - 'unchecked_tombstone_compaction': 'true'
33   -};
34   -
35   -CREATE TABLE IF NOT EXISTS thingsboard.processed_msg_partitions (
36   - node_id timeuuid,
37   - clustered_hash bigint,
38   - partition bigint,
39   - PRIMARY KEY ((node_id, clustered_hash), partition))
40   -WITH CLUSTERING ORDER BY (partition DESC)
41   -AND compaction = {
42   - 'class': 'org.apache.cassandra.db.compaction.DateTieredCompactionStrategy',
43   - 'min_threshold': '5',
44   - 'base_time_seconds': '43200',
45   - 'max_window_size_seconds': '43200',
46   - 'tombstone_threshold': '0.9',
47   - 'unchecked_tombstone_compaction': 'true'
48   -};
49   -
50   -
51   -
52   --- msg_queue dataset
53   -
54   -INSERT INTO thingsboard.msg_queue (node_id, clustered_hash, partition, ts, msg)
55   - VALUES (055eee50-1883-11e8-b380-65b5d5335ba9, 101, 200, 201, null);
56   -INSERT INTO thingsboard.msg_queue (node_id, clustered_hash, partition, ts, msg)
57   - VALUES (055eee50-1883-11e8-b380-65b5d5335ba9, 101, 200, 202, null);
58   -INSERT INTO thingsboard.msg_queue (node_id, clustered_hash, partition, ts, msg)
59   - VALUES (055eee50-1883-11e8-b380-65b5d5335ba9, 101, 300, 301, null);
60   -
61   --- ack_queue dataset
62   -INSERT INTO msg_ack_queue (node_id, clustered_hash, partition, msg_id)
63   - VALUES (055eee50-1883-11e8-b380-65b5d5335ba9, 101, 300, bebaeb60-1888-11e8-bf21-65b5d5335ba9);
64   -INSERT INTO msg_ack_queue (node_id, clustered_hash, partition, msg_id)
65   - VALUES (055eee50-1883-11e8-b380-65b5d5335ba9, 101, 300, 12baeb60-1888-11e8-bf21-65b5d5335ba9);
66   - INSERT INTO msg_ack_queue (node_id, clustered_hash, partition, msg_id)
67   - VALUES (055eee50-1883-11e8-b380-65b5d5335ba9, 101, 200, 32baeb60-1888-11e8-bf21-65b5d5335ba9);
68   -
69   --- processed partition dataset
70   -INSERT INTO processed_msg_partitions (node_id, clustered_hash, partition)
71   - VALUES (055eee50-1883-11e8-b380-65b5d5335ba9, 101, 100);
72   -INSERT INTO processed_msg_partitions (node_id, clustered_hash, partition)
73   - VALUES (055eee50-1883-11e8-b380-65b5d5335ba9, 101, 777);
74   -INSERT INTO processed_msg_partitions (node_id, clustered_hash, partition)
\ No newline at end of file