Commit c2b4d9c8ae2653a8a94907791eb059215a495bac

Authored by Igor Kulikov
2 parents 745648a5 6a4c2791

Merge with master

Showing 61 changed files with 161 additions and 96 deletions
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 <modelVersion>4.0.0</modelVersion> 20 <modelVersion>4.0.0</modelVersion>
21 <parent> 21 <parent>
22 <groupId>org.thingsboard</groupId> 22 <groupId>org.thingsboard</groupId>
23 - <version>3.1.2-SNAPSHOT</version> 23 + <version>3.2.0-SNAPSHOT</version>
24 <artifactId>thingsboard</artifactId> 24 <artifactId>thingsboard</artifactId>
25 </parent> 25 </parent>
26 <artifactId>application</artifactId> 26 <artifactId>application</artifactId>
@@ -166,7 +166,7 @@ @@ -166,7 +166,7 @@
166 "controllerScript": "self.onInit = function() {\n self.ctx.flot = new TbFlot(self.ctx, 'state'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.flot.update();\n}\n\nself.onResize = function() {\n self.ctx.flot.resize();\n}\n\nself.typeParameters = function() {\n return {\n stateData: true\n };\n}\n\nself.onEditModeChanged = function() {\n self.ctx.flot.checkMouseEvents();\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.flot.checkMouseEvents();\n}\n\nself.getSettingsSchema = function() {\n return TbFlot.settingsSchema('graph');\n}\n\nself.getDataKeySettingsSchema = function() {\n return TbFlot.datakeySettingsSchema(true, 'graph');\n}\n\nself.onDestroy = function() {\n self.ctx.flot.destroy();\n}\n", 166 "controllerScript": "self.onInit = function() {\n self.ctx.flot = new TbFlot(self.ctx, 'state'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.flot.update();\n}\n\nself.onResize = function() {\n self.ctx.flot.resize();\n}\n\nself.typeParameters = function() {\n return {\n stateData: true\n };\n}\n\nself.onEditModeChanged = function() {\n self.ctx.flot.checkMouseEvents();\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.flot.checkMouseEvents();\n}\n\nself.getSettingsSchema = function() {\n return TbFlot.settingsSchema('graph');\n}\n\nself.getDataKeySettingsSchema = function() {\n return TbFlot.datakeySettingsSchema(true, 'graph');\n}\n\nself.onDestroy = function() {\n self.ctx.flot.destroy();\n}\n",
167 "settingsSchema": "{}", 167 "settingsSchema": "{}",
168 "dataKeySettingsSchema": "{}", 168 "dataKeySettingsSchema": "{}",
169 - "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Switch 1\",\"color\":\"#2196f3\",\"settings\":{\"showLines\":true,\"fillLines\":true,\"showPoints\":false,\"axisPosition\":\"left\",\"showSeparateAxis\":false},\"_hash\":0.8587686344902596,\"funcBody\":\"return Math.random() > 0.5 ? 1 : 0;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Switch 2\",\"color\":\"#ffc107\",\"settings\":{\"showLines\":true,\"fillLines\":false,\"showPoints\":false,\"axisPosition\":\"left\"},\"_hash\":0.12775350966079668,\"funcBody\":\"return Math.random() <= 0.5 ? 1 : 0;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"shadowSize\":4,\"fontColor\":\"#545454\",\"fontSize\":10,\"xaxis\":{\"showLabels\":true,\"color\":\"#545454\"},\"yaxis\":{\"showLabels\":true,\"color\":\"#545454\",\"ticksFormatter\":\"if (value > 0 && value <= 1) {\\n return 'On';\\n} else if (value === 0) {\\n return 'Off';\\n} else {\\n return '';\\n}\"},\"grid\":{\"color\":\"#545454\",\"tickColor\":\"#DDDDDD\",\"verticalLines\":true,\"horizontalLines\":true,\"outlineWidth\":1},\"stack\":false,\"tooltipIndividual\":false,\"tooltipValueFormatter\":\"if (value > 0 && value <= 1) {\\n return 'On';\\n} else if (value === 0) {\\n return 'Off';\\n} else {\\n return '';\\n}\",\"smoothLines\":false},\"title\":\"State Chart\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"mobileHeight\":null,\"widgetStyle\":{},\"useDashboardTimewindow\":true,\"showLegend\":true,\"actions\":{},\"legendConfig\":{\"position\":\"bottom\",\"showMin\":false,\"showMax\":false,\"showAvg\":false,\"showTotal\":false}}" 169 + "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Switch 1\",\"color\":\"#2196f3\",\"settings\":{\"showLines\":true,\"fillLines\":true,\"showPoints\":false,\"axisPosition\":\"left\",\"showSeparateAxis\":false},\"_hash\":0.8587686344902596,\"funcBody\":\"return Math.random() > 0.5 ? 1 : 0;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Switch 2\",\"color\":\"#ffc107\",\"settings\":{\"showLines\":true,\"fillLines\":false,\"showPoints\":false,\"axisPosition\":\"left\"},\"_hash\":0.12775350966079668,\"funcBody\":\"return Math.random() <= 0.5 ? 1 : 0;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"shadowSize\":4,\"fontColor\":\"#545454\",\"fontSize\":10,\"xaxis\":{\"showLabels\":true,\"color\":\"#545454\"},\"yaxis\":{\"showLabels\":true,\"color\":\"#545454\",\"ticksFormatter\":\"if (value > 0 && value <= 1) {\\n return 'On';\\n} else if (value === 0) {\\n return 'Off';\\n} else {\\n return '';\\n}\"},\"grid\":{\"color\":\"#545454\",\"tickColor\":\"#DDDDDD\",\"verticalLines\":true,\"horizontalLines\":true,\"outlineWidth\":1},\"stack\":false,\"tooltipIndividual\":false,\"tooltipValueFormatter\":\"if (value > 0 && value <= 1) {\\n return 'On';\\n} else if (value === 0) {\\n return 'Off';\\n} else {\\n return '';\\n}\",\"smoothLines\":false},\"title\":\"State Chart\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"mobileHeight\":null,\"widgetStyle\":{},\"useDashboardTimewindow\":true,\"showLegend\":true,\"actions\":{},\"legendConfig\":{\"direction\":\"column\",\",position\":\"bottom\",\"showMin\":false,\"showMax\":false,\"showAvg\":false,\"showTotal\":false}}"
170 } 170 }
171 } 171 }
172 ] 172 ]
@@ -247,4 +247,4 @@ public class PsqlTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgradeSe @@ -247,4 +247,4 @@ public class PsqlTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgradeSe
247 log.info("Failed to load PostgreSQL upgrade functions due to: {}", e.getMessage()); 247 log.info("Failed to load PostgreSQL upgrade functions due to: {}", e.getMessage());
248 } 248 }
249 } 249 }
250 -}  
  250 +}
@@ -209,4 +209,4 @@ public class TimescaleTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgr @@ -209,4 +209,4 @@ public class TimescaleTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgr
209 log.info("Failed to load PostgreSQL upgrade functions due to: {}", e.getMessage()); 209 log.info("Failed to load PostgreSQL upgrade functions due to: {}", e.getMessage());
210 } 210 }
211 } 211 }
212 -}  
  212 +}
@@ -39,8 +39,7 @@ public abstract class AbstractCleanUpService { @@ -39,8 +39,7 @@ public abstract class AbstractCleanUpService {
39 protected String dbPassword; 39 protected String dbPassword;
40 40
41 protected long executeQuery(Connection conn, String query) throws SQLException { 41 protected long executeQuery(Connection conn, String query) throws SQLException {
42 - try (Statement statement = conn.createStatement()) {  
43 - ResultSet resultSet = statement.executeQuery(query); 42 + try (Statement statement = conn.createStatement(); ResultSet resultSet = statement.executeQuery(query)) {
44 if (log.isDebugEnabled()) { 43 if (log.isDebugEnabled()) {
45 getWarnings(statement); 44 getWarnings(statement);
46 } 45 }
@@ -33,4 +33,4 @@ public class TimescaleTimeseriesCleanUpService extends AbstractTimeseriesCleanUp @@ -33,4 +33,4 @@ public class TimescaleTimeseriesCleanUpService extends AbstractTimeseriesCleanUp
33 long totalEntitiesTelemetryRemoved = executeQuery(connection, "call cleanup_timeseries_by_ttl('" + ModelConstants.NULL_UUID + "'," + systemTtl + ", 0);"); 33 long totalEntitiesTelemetryRemoved = executeQuery(connection, "call cleanup_timeseries_by_ttl('" + ModelConstants.NULL_UUID + "'," + systemTtl + ", 0);");
34 log.info("Total telemetry removed stats by TTL for entities: [{}]", totalEntitiesTelemetryRemoved); 34 log.info("Total telemetry removed stats by TTL for entities: [{}]", totalEntitiesTelemetryRemoved);
35 } 35 }
36 -}  
  36 +}
@@ -284,6 +284,8 @@ sql: @@ -284,6 +284,8 @@ sql:
284 batch_max_delay: "${SQL_TS_LATEST_BATCH_MAX_DELAY_MS:100}" 284 batch_max_delay: "${SQL_TS_LATEST_BATCH_MAX_DELAY_MS:100}"
285 stats_print_interval_ms: "${SQL_TS_LATEST_BATCH_STATS_PRINT_MS:10000}" 285 stats_print_interval_ms: "${SQL_TS_LATEST_BATCH_STATS_PRINT_MS:10000}"
286 batch_threads: "${SQL_TS_LATEST_BATCH_THREADS:4}" 286 batch_threads: "${SQL_TS_LATEST_BATCH_THREADS:4}"
  287 + # Specify whether to sort entities before batch update. Should be enabled for cluster mode to avoid deadlocks
  288 + batch_sort: "${SQL_BATCH_SORT:false}"
287 # Specify whether to remove null characters from strValue of attributes and timeseries before insert 289 # Specify whether to remove null characters from strValue of attributes and timeseries before insert
288 remove_null_chars: "${SQL_REMOVE_NULL_CHARS:true}" 290 remove_null_chars: "${SQL_REMOVE_NULL_CHARS:true}"
289 # Specify whether to log database queries and their parameters generated by entity query repository 291 # Specify whether to log database queries and their parameters generated by entity query repository
@@ -651,11 +653,11 @@ queue: @@ -651,11 +653,11 @@ queue:
651 security.protocol: "${TB_QUEUE_KAFKA_CONFLUENT_SECURITY_PROTOCOL:SASL_SSL}" 653 security.protocol: "${TB_QUEUE_KAFKA_CONFLUENT_SECURITY_PROTOCOL:SASL_SSL}"
652 other: 654 other:
653 topic-properties: 655 topic-properties:
654 - rule-engine: "${TB_QUEUE_KAFKA_RE_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000}"  
655 - core: "${TB_QUEUE_KAFKA_CORE_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000}"  
656 - transport-api: "${TB_QUEUE_KAFKA_TA_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000}"  
657 - notifications: "${TB_QUEUE_KAFKA_NOTIFICATIONS_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000}"  
658 - js-executor: "${TB_QUEUE_KAFKA_JE_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:104857600}" 656 + rule-engine: "${TB_QUEUE_KAFKA_RE_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000;partitions:1}"
  657 + core: "${TB_QUEUE_KAFKA_CORE_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000;partitions:1}"
  658 + transport-api: "${TB_QUEUE_KAFKA_TA_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000;partitions:1}"
  659 + notifications: "${TB_QUEUE_KAFKA_NOTIFICATIONS_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000;partitions:1}"
  660 + js-executor: "${TB_QUEUE_KAFKA_JE_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:104857600;partitions:100}"
659 aws_sqs: 661 aws_sqs:
660 use_default_credential_provider_chain: "${TB_QUEUE_AWS_SQS_USE_DEFAULT_CREDENTIAL_PROVIDER_CHAIN:false}" 662 use_default_credential_provider_chain: "${TB_QUEUE_AWS_SQS_USE_DEFAULT_CREDENTIAL_PROVIDER_CHAIN:false}"
661 access_key_id: "${TB_QUEUE_AWS_SQS_ACCESS_KEY_ID:YOUR_KEY}" 663 access_key_id: "${TB_QUEUE_AWS_SQS_ACCESS_KEY_ID:YOUR_KEY}"
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 <modelVersion>4.0.0</modelVersion> 20 <modelVersion>4.0.0</modelVersion>
21 <parent> 21 <parent>
22 <groupId>org.thingsboard</groupId> 22 <groupId>org.thingsboard</groupId>
23 - <version>3.1.2-SNAPSHOT</version> 23 + <version>3.2.0-SNAPSHOT</version>
24 <artifactId>common</artifactId> 24 <artifactId>common</artifactId>
25 </parent> 25 </parent>
26 <groupId>org.thingsboard.common</groupId> 26 <groupId>org.thingsboard.common</groupId>
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 <modelVersion>4.0.0</modelVersion> 20 <modelVersion>4.0.0</modelVersion>
21 <parent> 21 <parent>
22 <groupId>org.thingsboard</groupId> 22 <groupId>org.thingsboard</groupId>
23 - <version>3.1.2-SNAPSHOT</version> 23 + <version>3.2.0-SNAPSHOT</version>
24 <artifactId>common</artifactId> 24 <artifactId>common</artifactId>
25 </parent> 25 </parent>
26 <groupId>org.thingsboard.common</groupId> 26 <groupId>org.thingsboard.common</groupId>
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 <modelVersion>4.0.0</modelVersion> 20 <modelVersion>4.0.0</modelVersion>
21 <parent> 21 <parent>
22 <groupId>org.thingsboard</groupId> 22 <groupId>org.thingsboard</groupId>
23 - <version>3.1.2-SNAPSHOT</version> 23 + <version>3.2.0-SNAPSHOT</version>
24 <artifactId>common</artifactId> 24 <artifactId>common</artifactId>
25 </parent> 25 </parent>
26 <groupId>org.thingsboard.common</groupId> 26 <groupId>org.thingsboard.common</groupId>
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 <modelVersion>4.0.0</modelVersion> 20 <modelVersion>4.0.0</modelVersion>
21 <parent> 21 <parent>
22 <groupId>org.thingsboard</groupId> 22 <groupId>org.thingsboard</groupId>
23 - <version>3.1.2-SNAPSHOT</version> 23 + <version>3.2.0-SNAPSHOT</version>
24 <artifactId>common</artifactId> 24 <artifactId>common</artifactId>
25 </parent> 25 </parent>
26 <groupId>org.thingsboard.common</groupId> 26 <groupId>org.thingsboard.common</groupId>
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 <modelVersion>4.0.0</modelVersion> 20 <modelVersion>4.0.0</modelVersion>
21 <parent> 21 <parent>
22 <groupId>org.thingsboard</groupId> 22 <groupId>org.thingsboard</groupId>
23 - <version>3.1.2-SNAPSHOT</version> 23 + <version>3.2.0-SNAPSHOT</version>
24 <artifactId>thingsboard</artifactId> 24 <artifactId>thingsboard</artifactId>
25 </parent> 25 </parent>
26 <artifactId>common</artifactId> 26 <artifactId>common</artifactId>
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 <modelVersion>4.0.0</modelVersion> 20 <modelVersion>4.0.0</modelVersion>
21 <parent> 21 <parent>
22 <groupId>org.thingsboard</groupId> 22 <groupId>org.thingsboard</groupId>
23 - <version>3.1.2-SNAPSHOT</version> 23 + <version>3.2.0-SNAPSHOT</version>
24 <artifactId>common</artifactId> 24 <artifactId>common</artifactId>
25 </parent> 25 </parent>
26 <groupId>org.thingsboard.common</groupId> 26 <groupId>org.thingsboard.common</groupId>
@@ -37,6 +37,7 @@ public class TbKafkaAdmin implements TbQueueAdmin { @@ -37,6 +37,7 @@ public class TbKafkaAdmin implements TbQueueAdmin {
37 private final AdminClient client; 37 private final AdminClient client;
38 private final Map<String, String> topicConfigs; 38 private final Map<String, String> topicConfigs;
39 private final Set<String> topics = ConcurrentHashMap.newKeySet(); 39 private final Set<String> topics = ConcurrentHashMap.newKeySet();
  40 + private final int numPartitions;
40 41
41 private final short replicationFactor; 42 private final short replicationFactor;
42 43
@@ -50,6 +51,13 @@ public class TbKafkaAdmin implements TbQueueAdmin { @@ -50,6 +51,13 @@ public class TbKafkaAdmin implements TbQueueAdmin {
50 log.error("Failed to get all topics.", e); 51 log.error("Failed to get all topics.", e);
51 } 52 }
52 53
  54 + String numPartitionsStr = topicConfigs.get("partitions");
  55 + if (numPartitionsStr != null) {
  56 + numPartitions = Integer.parseInt(numPartitionsStr);
  57 + topicConfigs.remove("partitions");
  58 + } else {
  59 + numPartitions = 1;
  60 + }
53 replicationFactor = settings.getReplicationFactor(); 61 replicationFactor = settings.getReplicationFactor();
54 } 62 }
55 63
@@ -59,7 +67,7 @@ public class TbKafkaAdmin implements TbQueueAdmin { @@ -59,7 +67,7 @@ public class TbKafkaAdmin implements TbQueueAdmin {
59 return; 67 return;
60 } 68 }
61 try { 69 try {
62 - NewTopic newTopic = new NewTopic(topic, 1, replicationFactor).configs(topicConfigs); 70 + NewTopic newTopic = new NewTopic(topic, numPartitions, replicationFactor).configs(topicConfigs);
63 createTopic(newTopic).values().get(topic).get(); 71 createTopic(newTopic).values().get(topic).get();
64 topics.add(topic); 72 topics.add(topic);
65 } catch (ExecutionException ee) { 73 } catch (ExecutionException ee) {
@@ -22,7 +22,7 @@ @@ -22,7 +22,7 @@
22 <modelVersion>4.0.0</modelVersion> 22 <modelVersion>4.0.0</modelVersion>
23 <parent> 23 <parent>
24 <groupId>org.thingsboard</groupId> 24 <groupId>org.thingsboard</groupId>
25 - <version>3.1.2-SNAPSHOT</version> 25 + <version>3.2.0-SNAPSHOT</version>
26 <artifactId>common</artifactId> 26 <artifactId>common</artifactId>
27 </parent> 27 </parent>
28 <groupId>org.thingsboard.common</groupId> 28 <groupId>org.thingsboard.common</groupId>
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 <modelVersion>4.0.0</modelVersion> 20 <modelVersion>4.0.0</modelVersion>
21 <parent> 21 <parent>
22 <groupId>org.thingsboard.common</groupId> 22 <groupId>org.thingsboard.common</groupId>
23 - <version>3.1.2-SNAPSHOT</version> 23 + <version>3.2.0-SNAPSHOT</version>
24 <artifactId>transport</artifactId> 24 <artifactId>transport</artifactId>
25 </parent> 25 </parent>
26 <groupId>org.thingsboard.common.transport</groupId> 26 <groupId>org.thingsboard.common.transport</groupId>
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 <modelVersion>4.0.0</modelVersion> 20 <modelVersion>4.0.0</modelVersion>
21 <parent> 21 <parent>
22 <groupId>org.thingsboard.common</groupId> 22 <groupId>org.thingsboard.common</groupId>
23 - <version>3.1.2-SNAPSHOT</version> 23 + <version>3.2.0-SNAPSHOT</version>
24 <artifactId>transport</artifactId> 24 <artifactId>transport</artifactId>
25 </parent> 25 </parent>
26 <groupId>org.thingsboard.common.transport</groupId> 26 <groupId>org.thingsboard.common.transport</groupId>
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 <modelVersion>4.0.0</modelVersion> 20 <modelVersion>4.0.0</modelVersion>
21 <parent> 21 <parent>
22 <groupId>org.thingsboard.common</groupId> 22 <groupId>org.thingsboard.common</groupId>
23 - <version>3.1.2-SNAPSHOT</version> 23 + <version>3.2.0-SNAPSHOT</version>
24 <artifactId>transport</artifactId> 24 <artifactId>transport</artifactId>
25 </parent> 25 </parent>
26 <groupId>org.thingsboard.common.transport</groupId> 26 <groupId>org.thingsboard.common.transport</groupId>
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 <modelVersion>4.0.0</modelVersion> 20 <modelVersion>4.0.0</modelVersion>
21 <parent> 21 <parent>
22 <groupId>org.thingsboard</groupId> 22 <groupId>org.thingsboard</groupId>
23 - <version>3.1.2-SNAPSHOT</version> 23 + <version>3.2.0-SNAPSHOT</version>
24 <artifactId>common</artifactId> 24 <artifactId>common</artifactId>
25 </parent> 25 </parent>
26 <groupId>org.thingsboard.common</groupId> 26 <groupId>org.thingsboard.common</groupId>
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 <modelVersion>4.0.0</modelVersion> 20 <modelVersion>4.0.0</modelVersion>
21 <parent> 21 <parent>
22 <groupId>org.thingsboard.common</groupId> 22 <groupId>org.thingsboard.common</groupId>
23 - <version>3.1.2-SNAPSHOT</version> 23 + <version>3.2.0-SNAPSHOT</version>
24 <artifactId>transport</artifactId> 24 <artifactId>transport</artifactId>
25 </parent> 25 </parent>
26 <groupId>org.thingsboard.common.transport</groupId> 26 <groupId>org.thingsboard.common.transport</groupId>
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 <modelVersion>4.0.0</modelVersion> 20 <modelVersion>4.0.0</modelVersion>
21 <parent> 21 <parent>
22 <groupId>org.thingsboard</groupId> 22 <groupId>org.thingsboard</groupId>
23 - <version>3.1.2-SNAPSHOT</version> 23 + <version>3.2.0-SNAPSHOT</version>
24 <artifactId>common</artifactId> 24 <artifactId>common</artifactId>
25 </parent> 25 </parent>
26 <groupId>org.thingsboard.common</groupId> 26 <groupId>org.thingsboard.common</groupId>
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 <modelVersion>4.0.0</modelVersion> 20 <modelVersion>4.0.0</modelVersion>
21 <parent> 21 <parent>
22 <groupId>org.thingsboard</groupId> 22 <groupId>org.thingsboard</groupId>
23 - <version>3.1.2-SNAPSHOT</version> 23 + <version>3.2.0-SNAPSHOT</version>
24 <artifactId>thingsboard</artifactId> 24 <artifactId>thingsboard</artifactId>
25 </parent> 25 </parent>
26 <artifactId>dao</artifactId> 26 <artifactId>dao</artifactId>
@@ -22,6 +22,7 @@ import org.thingsboard.common.util.ThingsBoardThreadFactory; @@ -22,6 +22,7 @@ import org.thingsboard.common.util.ThingsBoardThreadFactory;
22 import org.thingsboard.server.common.stats.MessagesStats; 22 import org.thingsboard.server.common.stats.MessagesStats;
23 23
24 import java.util.ArrayList; 24 import java.util.ArrayList;
  25 +import java.util.Comparator;
25 import java.util.List; 26 import java.util.List;
26 import java.util.concurrent.BlockingQueue; 27 import java.util.concurrent.BlockingQueue;
27 import java.util.concurrent.ExecutorService; 28 import java.util.concurrent.ExecutorService;
@@ -30,6 +31,7 @@ import java.util.concurrent.LinkedBlockingQueue; @@ -30,6 +31,7 @@ import java.util.concurrent.LinkedBlockingQueue;
30 import java.util.concurrent.TimeUnit; 31 import java.util.concurrent.TimeUnit;
31 import java.util.function.Consumer; 32 import java.util.function.Consumer;
32 import java.util.stream.Collectors; 33 import java.util.stream.Collectors;
  34 +import java.util.stream.Stream;
33 35
34 @Slf4j 36 @Slf4j
35 public class TbSqlBlockingQueue<E> implements TbSqlQueue<E> { 37 public class TbSqlBlockingQueue<E> implements TbSqlQueue<E> {
@@ -46,7 +48,7 @@ public class TbSqlBlockingQueue<E> implements TbSqlQueue<E> { @@ -46,7 +48,7 @@ public class TbSqlBlockingQueue<E> implements TbSqlQueue<E> {
46 } 48 }
47 49
48 @Override 50 @Override
49 - public void init(ScheduledLogExecutorComponent logExecutor, Consumer<List<E>> saveFunction, int index) { 51 + public void init(ScheduledLogExecutorComponent logExecutor, Consumer<List<E>> saveFunction, Comparator<E> batchUpdateComparator, int index) {
50 executor = Executors.newSingleThreadExecutor(ThingsBoardThreadFactory.forName("sql-queue-" + index + "-" + params.getLogName().toLowerCase())); 52 executor = Executors.newSingleThreadExecutor(ThingsBoardThreadFactory.forName("sql-queue-" + index + "-" + params.getLogName().toLowerCase()));
51 executor.submit(() -> { 53 executor.submit(() -> {
52 String logName = params.getLogName(); 54 String logName = params.getLogName();
@@ -65,7 +67,11 @@ public class TbSqlBlockingQueue<E> implements TbSqlQueue<E> { @@ -65,7 +67,11 @@ public class TbSqlBlockingQueue<E> implements TbSqlQueue<E> {
65 queue.drainTo(entities, batchSize - 1); 67 queue.drainTo(entities, batchSize - 1);
66 boolean fullPack = entities.size() == batchSize; 68 boolean fullPack = entities.size() == batchSize;
67 log.debug("[{}] Going to save {} entities", logName, entities.size()); 69 log.debug("[{}] Going to save {} entities", logName, entities.size());
68 - saveFunction.accept(entities.stream().map(TbSqlQueueElement::getEntity).collect(Collectors.toList())); 70 + Stream<E> entitiesStream = entities.stream().map(TbSqlQueueElement::getEntity);
  71 + saveFunction.accept(
  72 + (params.isBatchSortEnabled() ? entitiesStream.sorted(batchUpdateComparator) : entitiesStream)
  73 + .collect(Collectors.toList())
  74 + );
69 entities.forEach(v -> v.getFuture().set(null)); 75 entities.forEach(v -> v.getFuture().set(null));
70 stats.incrementSuccessful(entities.size()); 76 stats.incrementSuccessful(entities.size());
71 if (!fullPack) { 77 if (!fullPack) {
@@ -31,4 +31,5 @@ public class TbSqlBlockingQueueParams { @@ -31,4 +31,5 @@ public class TbSqlBlockingQueueParams {
31 private final long maxDelay; 31 private final long maxDelay;
32 private final long statsPrintIntervalMs; 32 private final long statsPrintIntervalMs;
33 private final String statsNamePrefix; 33 private final String statsNamePrefix;
  34 + private final boolean batchSortEnabled;
34 } 35 }
@@ -21,6 +21,7 @@ import lombok.extern.slf4j.Slf4j; @@ -21,6 +21,7 @@ import lombok.extern.slf4j.Slf4j;
21 import org.thingsboard.server.common.stats.MessagesStats; 21 import org.thingsboard.server.common.stats.MessagesStats;
22 import org.thingsboard.server.common.stats.StatsFactory; 22 import org.thingsboard.server.common.stats.StatsFactory;
23 23
  24 +import java.util.Comparator;
24 import java.util.List; 25 import java.util.List;
25 import java.util.concurrent.CopyOnWriteArrayList; 26 import java.util.concurrent.CopyOnWriteArrayList;
26 import java.util.function.Consumer; 27 import java.util.function.Consumer;
@@ -36,12 +37,20 @@ public class TbSqlBlockingQueueWrapper<E> { @@ -36,12 +37,20 @@ public class TbSqlBlockingQueueWrapper<E> {
36 private final int maxThreads; 37 private final int maxThreads;
37 private final StatsFactory statsFactory; 38 private final StatsFactory statsFactory;
38 39
39 - public void init(ScheduledLogExecutorComponent logExecutor, Consumer<List<E>> saveFunction) { 40 + /**
  41 + * Starts TbSqlBlockingQueues.
  42 + *
  43 + * @param logExecutor executor that will be printing logs and statistics
  44 + * @param saveFunction function to save entities in database
  45 + * @param batchUpdateComparator comparator to sort entities by primary key to avoid deadlocks in cluster mode
  46 + * NOTE: you must use all of primary key parts in your comparator
  47 + */
  48 + public void init(ScheduledLogExecutorComponent logExecutor, Consumer<List<E>> saveFunction, Comparator<E> batchUpdateComparator) {
40 for (int i = 0; i < maxThreads; i++) { 49 for (int i = 0; i < maxThreads; i++) {
41 MessagesStats stats = statsFactory.createMessagesStats(params.getStatsNamePrefix() + ".queue." + i); 50 MessagesStats stats = statsFactory.createMessagesStats(params.getStatsNamePrefix() + ".queue." + i);
42 TbSqlBlockingQueue<E> queue = new TbSqlBlockingQueue<>(params, stats); 51 TbSqlBlockingQueue<E> queue = new TbSqlBlockingQueue<>(params, stats);
43 queues.add(queue); 52 queues.add(queue);
44 - queue.init(logExecutor, saveFunction, i); 53 + queue.init(logExecutor, saveFunction, batchUpdateComparator, i);
45 } 54 }
46 } 55 }
47 56
@@ -17,12 +17,13 @@ package org.thingsboard.server.dao.sql; @@ -17,12 +17,13 @@ package org.thingsboard.server.dao.sql;
17 17
18 import com.google.common.util.concurrent.ListenableFuture; 18 import com.google.common.util.concurrent.ListenableFuture;
19 19
  20 +import java.util.Comparator;
20 import java.util.List; 21 import java.util.List;
21 import java.util.function.Consumer; 22 import java.util.function.Consumer;
22 23
23 public interface TbSqlQueue<E> { 24 public interface TbSqlQueue<E> {
24 25
25 - void init(ScheduledLogExecutorComponent logExecutor, Consumer<List<E>> saveFunction, int queueIndex); 26 + void init(ScheduledLogExecutorComponent logExecutor, Consumer<List<E>> saveFunction, Comparator<E> batchUpdateComparator, int queueIndex);
26 27
27 void destroy(); 28 void destroy();
28 29
@@ -38,6 +38,7 @@ import org.thingsboard.server.dao.sql.TbSqlBlockingQueueWrapper; @@ -38,6 +38,7 @@ import org.thingsboard.server.dao.sql.TbSqlBlockingQueueWrapper;
38 import javax.annotation.PostConstruct; 38 import javax.annotation.PostConstruct;
39 import javax.annotation.PreDestroy; 39 import javax.annotation.PreDestroy;
40 import java.util.Collection; 40 import java.util.Collection;
  41 +import java.util.Comparator;
41 import java.util.List; 42 import java.util.List;
42 import java.util.Optional; 43 import java.util.Optional;
43 import java.util.function.Function; 44 import java.util.function.Function;
@@ -71,6 +72,9 @@ public class JpaAttributeDao extends JpaAbstractDaoListeningExecutorService impl @@ -71,6 +72,9 @@ public class JpaAttributeDao extends JpaAbstractDaoListeningExecutorService impl
71 @Value("${sql.attributes.batch_threads:4}") 72 @Value("${sql.attributes.batch_threads:4}")
72 private int batchThreads; 73 private int batchThreads;
73 74
  75 + @Value("${sql.batch_sort:false}")
  76 + private boolean batchSortEnabled;
  77 +
74 private TbSqlBlockingQueueWrapper<AttributeKvEntity> queue; 78 private TbSqlBlockingQueueWrapper<AttributeKvEntity> queue;
75 79
76 @PostConstruct 80 @PostConstruct
@@ -81,11 +85,17 @@ public class JpaAttributeDao extends JpaAbstractDaoListeningExecutorService impl @@ -81,11 +85,17 @@ public class JpaAttributeDao extends JpaAbstractDaoListeningExecutorService impl
81 .maxDelay(maxDelay) 85 .maxDelay(maxDelay)
82 .statsPrintIntervalMs(statsPrintIntervalMs) 86 .statsPrintIntervalMs(statsPrintIntervalMs)
83 .statsNamePrefix("attributes") 87 .statsNamePrefix("attributes")
  88 + .batchSortEnabled(batchSortEnabled)
84 .build(); 89 .build();
85 90
86 Function<AttributeKvEntity, Integer> hashcodeFunction = entity -> entity.getId().getEntityId().hashCode(); 91 Function<AttributeKvEntity, Integer> hashcodeFunction = entity -> entity.getId().getEntityId().hashCode();
87 queue = new TbSqlBlockingQueueWrapper<>(params, hashcodeFunction, batchThreads, statsFactory); 92 queue = new TbSqlBlockingQueueWrapper<>(params, hashcodeFunction, batchThreads, statsFactory);
88 - queue.init(logExecutor, v -> attributeKvInsertRepository.saveOrUpdate(v)); 93 + queue.init(logExecutor, v -> attributeKvInsertRepository.saveOrUpdate(v),
  94 + Comparator.comparing((AttributeKvEntity attributeKvEntity) -> attributeKvEntity.getId().getEntityId())
  95 + .thenComparing(attributeKvEntity -> attributeKvEntity.getId().getEntityType().name())
  96 + .thenComparing(attributeKvEntity -> attributeKvEntity.getId().getAttributeType())
  97 + .thenComparing(attributeKvEntity -> attributeKvEntity.getId().getAttributeKey())
  98 + );
89 } 99 }
90 100
91 @PreDestroy 101 @PreDestroy
@@ -21,6 +21,7 @@ import com.google.common.util.concurrent.MoreExecutors; @@ -21,6 +21,7 @@ import com.google.common.util.concurrent.MoreExecutors;
21 import com.google.common.util.concurrent.SettableFuture; 21 import com.google.common.util.concurrent.SettableFuture;
22 import lombok.extern.slf4j.Slf4j; 22 import lombok.extern.slf4j.Slf4j;
23 import org.springframework.beans.factory.annotation.Autowired; 23 import org.springframework.beans.factory.annotation.Autowired;
  24 +import org.springframework.beans.factory.annotation.Value;
24 import org.springframework.data.domain.PageRequest; 25 import org.springframework.data.domain.PageRequest;
25 import org.springframework.data.domain.Sort; 26 import org.springframework.data.domain.Sort;
26 import org.thingsboard.server.common.data.id.EntityId; 27 import org.thingsboard.server.common.data.id.EntityId;
@@ -31,6 +32,7 @@ import org.thingsboard.server.common.data.kv.ReadTsKvQuery; @@ -31,6 +32,7 @@ import org.thingsboard.server.common.data.kv.ReadTsKvQuery;
31 import org.thingsboard.server.common.data.kv.TsKvEntry; 32 import org.thingsboard.server.common.data.kv.TsKvEntry;
32 import org.thingsboard.server.common.stats.StatsFactory; 33 import org.thingsboard.server.common.stats.StatsFactory;
33 import org.thingsboard.server.dao.DaoUtil; 34 import org.thingsboard.server.dao.DaoUtil;
  35 +import org.thingsboard.server.dao.model.sql.AbstractTsKvEntity;
34 import org.thingsboard.server.dao.model.sqlts.ts.TsKvEntity; 36 import org.thingsboard.server.dao.model.sqlts.ts.TsKvEntity;
35 import org.thingsboard.server.dao.sql.TbSqlBlockingQueueParams; 37 import org.thingsboard.server.dao.sql.TbSqlBlockingQueueParams;
36 import org.thingsboard.server.dao.sql.TbSqlBlockingQueueWrapper; 38 import org.thingsboard.server.dao.sql.TbSqlBlockingQueueWrapper;
@@ -40,9 +42,7 @@ import org.thingsboard.server.dao.timeseries.TimeseriesDao; @@ -40,9 +42,7 @@ import org.thingsboard.server.dao.timeseries.TimeseriesDao;
40 42
41 import javax.annotation.PostConstruct; 43 import javax.annotation.PostConstruct;
42 import javax.annotation.PreDestroy; 44 import javax.annotation.PreDestroy;
43 -import java.util.ArrayList;  
44 -import java.util.List;  
45 -import java.util.Optional; 45 +import java.util.*;
46 import java.util.concurrent.CompletableFuture; 46 import java.util.concurrent.CompletableFuture;
47 import java.util.function.Function; 47 import java.util.function.Function;
48 import java.util.stream.Collectors; 48 import java.util.stream.Collectors;
@@ -68,11 +68,16 @@ public abstract class AbstractChunkedAggregationTimeseriesDao extends AbstractSq @@ -68,11 +68,16 @@ public abstract class AbstractChunkedAggregationTimeseriesDao extends AbstractSq
68 .maxDelay(tsMaxDelay) 68 .maxDelay(tsMaxDelay)
69 .statsPrintIntervalMs(tsStatsPrintIntervalMs) 69 .statsPrintIntervalMs(tsStatsPrintIntervalMs)
70 .statsNamePrefix("ts") 70 .statsNamePrefix("ts")
  71 + .batchSortEnabled(batchSortEnabled)
71 .build(); 72 .build();
72 73
73 Function<TsKvEntity, Integer> hashcodeFunction = entity -> entity.getEntityId().hashCode(); 74 Function<TsKvEntity, Integer> hashcodeFunction = entity -> entity.getEntityId().hashCode();
74 tsQueue = new TbSqlBlockingQueueWrapper<>(tsParams, hashcodeFunction, tsBatchThreads, statsFactory); 75 tsQueue = new TbSqlBlockingQueueWrapper<>(tsParams, hashcodeFunction, tsBatchThreads, statsFactory);
75 - tsQueue.init(logExecutor, v -> insertRepository.saveOrUpdate(v)); 76 + tsQueue.init(logExecutor, v -> insertRepository.saveOrUpdate(v),
  77 + Comparator.comparing((Function<TsKvEntity, UUID>) AbstractTsKvEntity::getEntityId)
  78 + .thenComparing(AbstractTsKvEntity::getKey)
  79 + .thenComparing(AbstractTsKvEntity::getTs)
  80 + );
76 } 81 }
77 82
78 @PreDestroy 83 @PreDestroy
@@ -53,6 +53,9 @@ public abstract class AbstractSqlTimeseriesDao extends BaseAbstractSqlTimeseries @@ -53,6 +53,9 @@ public abstract class AbstractSqlTimeseriesDao extends BaseAbstractSqlTimeseries
53 @Value("${sql.timescale.batch_threads:4}") 53 @Value("${sql.timescale.batch_threads:4}")
54 protected int timescaleBatchThreads; 54 protected int timescaleBatchThreads;
55 55
  56 + @Value("${sql.batch_sort:false}")
  57 + protected boolean batchSortEnabled;
  58 +
56 protected ListenableFuture<List<TsKvEntry>> processFindAllAsync(TenantId tenantId, EntityId entityId, List<ReadTsKvQuery> queries) { 59 protected ListenableFuture<List<TsKvEntry>> processFindAllAsync(TenantId tenantId, EntityId entityId, List<ReadTsKvQuery> queries) {
57 List<ListenableFuture<List<TsKvEntry>>> futures = queries 60 List<ListenableFuture<List<TsKvEntry>>> futures = queries
58 .stream() 61 .stream()
@@ -35,6 +35,7 @@ import org.thingsboard.server.common.data.kv.StringDataEntry; @@ -35,6 +35,7 @@ import org.thingsboard.server.common.data.kv.StringDataEntry;
35 import org.thingsboard.server.common.data.kv.TsKvEntry; 35 import org.thingsboard.server.common.data.kv.TsKvEntry;
36 import org.thingsboard.server.common.stats.StatsFactory; 36 import org.thingsboard.server.common.stats.StatsFactory;
37 import org.thingsboard.server.dao.DaoUtil; 37 import org.thingsboard.server.dao.DaoUtil;
  38 +import org.thingsboard.server.dao.model.sql.AbstractTsKvEntity;
38 import org.thingsboard.server.dao.model.sqlts.latest.TsKvLatestCompositeKey; 39 import org.thingsboard.server.dao.model.sqlts.latest.TsKvLatestCompositeKey;
39 import org.thingsboard.server.dao.model.sqlts.latest.TsKvLatestEntity; 40 import org.thingsboard.server.dao.model.sqlts.latest.TsKvLatestEntity;
40 import org.thingsboard.server.dao.sql.ScheduledLogExecutorComponent; 41 import org.thingsboard.server.dao.sql.ScheduledLogExecutorComponent;
@@ -50,12 +51,10 @@ import org.thingsboard.server.dao.util.SqlTsLatestAnyDao; @@ -50,12 +51,10 @@ import org.thingsboard.server.dao.util.SqlTsLatestAnyDao;
50 import javax.annotation.Nullable; 51 import javax.annotation.Nullable;
51 import javax.annotation.PostConstruct; 52 import javax.annotation.PostConstruct;
52 import javax.annotation.PreDestroy; 53 import javax.annotation.PreDestroy;
53 -import java.util.ArrayList;  
54 -import java.util.HashMap;  
55 -import java.util.List;  
56 -import java.util.Map;  
57 -import java.util.Optional; 54 +import java.util.*;
58 import java.util.concurrent.ExecutionException; 55 import java.util.concurrent.ExecutionException;
  56 +import java.util.function.Function;
  57 +import java.util.stream.Collectors;
59 58
60 @Slf4j 59 @Slf4j
61 @Component 60 @Component
@@ -90,6 +89,9 @@ public class SqlTimeseriesLatestDao extends BaseAbstractSqlTimeseriesDao impleme @@ -90,6 +89,9 @@ public class SqlTimeseriesLatestDao extends BaseAbstractSqlTimeseriesDao impleme
90 @Value("${sql.ts_latest.batch_threads:4}") 89 @Value("${sql.ts_latest.batch_threads:4}")
91 private int tsLatestBatchThreads; 90 private int tsLatestBatchThreads;
92 91
  92 + @Value("${sql.batch_sort:false}")
  93 + protected boolean batchSortEnabled;
  94 +
93 @Autowired 95 @Autowired
94 protected ScheduledLogExecutorComponent logExecutor; 96 protected ScheduledLogExecutorComponent logExecutor;
95 97
@@ -104,6 +106,7 @@ public class SqlTimeseriesLatestDao extends BaseAbstractSqlTimeseriesDao impleme @@ -104,6 +106,7 @@ public class SqlTimeseriesLatestDao extends BaseAbstractSqlTimeseriesDao impleme
104 .maxDelay(tsLatestMaxDelay) 106 .maxDelay(tsLatestMaxDelay)
105 .statsPrintIntervalMs(tsLatestStatsPrintIntervalMs) 107 .statsPrintIntervalMs(tsLatestStatsPrintIntervalMs)
106 .statsNamePrefix("ts.latest") 108 .statsNamePrefix("ts.latest")
  109 + .batchSortEnabled(false)
107 .build(); 110 .build();
108 111
109 java.util.function.Function<TsKvLatestEntity, Integer> hashcodeFunction = entity -> entity.getEntityId().hashCode(); 112 java.util.function.Function<TsKvLatestEntity, Integer> hashcodeFunction = entity -> entity.getEntityId().hashCode();
@@ -113,14 +116,15 @@ public class SqlTimeseriesLatestDao extends BaseAbstractSqlTimeseriesDao impleme @@ -113,14 +116,15 @@ public class SqlTimeseriesLatestDao extends BaseAbstractSqlTimeseriesDao impleme
113 Map<TsKey, TsKvLatestEntity> trueLatest = new HashMap<>(); 116 Map<TsKey, TsKvLatestEntity> trueLatest = new HashMap<>();
114 v.forEach(ts -> { 117 v.forEach(ts -> {
115 TsKey key = new TsKey(ts.getEntityId(), ts.getKey()); 118 TsKey key = new TsKey(ts.getEntityId(), ts.getKey());
116 - TsKvLatestEntity old = trueLatest.get(key);  
117 - if (old == null || old.getTs() < ts.getTs()) {  
118 - trueLatest.put(key, ts);  
119 - } 119 + trueLatest.merge(key, ts, (oldTs, newTs) -> oldTs.getTs() < newTs.getTs() ? newTs : oldTs);
120 }); 120 });
121 List<TsKvLatestEntity> latestEntities = new ArrayList<>(trueLatest.values()); 121 List<TsKvLatestEntity> latestEntities = new ArrayList<>(trueLatest.values());
  122 + if (batchSortEnabled) {
  123 + latestEntities.sort(Comparator.comparing((Function<TsKvLatestEntity, UUID>) AbstractTsKvEntity::getEntityId)
  124 + .thenComparingInt(AbstractTsKvEntity::getKey));
  125 + }
122 insertLatestTsRepository.saveOrUpdate(latestEntities); 126 insertLatestTsRepository.saveOrUpdate(latestEntities);
123 - }); 127 + }, (l, r) -> 0);
124 } 128 }
125 129
126 @PreDestroy 130 @PreDestroy
@@ -33,6 +33,7 @@ import org.thingsboard.server.common.data.kv.ReadTsKvQuery; @@ -33,6 +33,7 @@ import org.thingsboard.server.common.data.kv.ReadTsKvQuery;
33 import org.thingsboard.server.common.data.kv.TsKvEntry; 33 import org.thingsboard.server.common.data.kv.TsKvEntry;
34 import org.thingsboard.server.common.stats.StatsFactory; 34 import org.thingsboard.server.common.stats.StatsFactory;
35 import org.thingsboard.server.dao.DaoUtil; 35 import org.thingsboard.server.dao.DaoUtil;
  36 +import org.thingsboard.server.dao.model.sql.AbstractTsKvEntity;
36 import org.thingsboard.server.dao.model.sqlts.timescale.ts.TimescaleTsKvEntity; 37 import org.thingsboard.server.dao.model.sqlts.timescale.ts.TimescaleTsKvEntity;
37 import org.thingsboard.server.dao.sql.TbSqlBlockingQueueParams; 38 import org.thingsboard.server.dao.sql.TbSqlBlockingQueueParams;
38 import org.thingsboard.server.dao.sql.TbSqlBlockingQueueWrapper; 39 import org.thingsboard.server.dao.sql.TbSqlBlockingQueueWrapper;
@@ -43,11 +44,7 @@ import org.thingsboard.server.dao.util.TimescaleDBTsDao; @@ -43,11 +44,7 @@ import org.thingsboard.server.dao.util.TimescaleDBTsDao;
43 44
44 import javax.annotation.PostConstruct; 45 import javax.annotation.PostConstruct;
45 import javax.annotation.PreDestroy; 46 import javax.annotation.PreDestroy;
46 -import java.util.ArrayList;  
47 -import java.util.Collections;  
48 -import java.util.List;  
49 -import java.util.Optional;  
50 -import java.util.UUID; 47 +import java.util.*;
51 import java.util.concurrent.CompletableFuture; 48 import java.util.concurrent.CompletableFuture;
52 import java.util.function.Function; 49 import java.util.function.Function;
53 50
@@ -78,12 +75,17 @@ public class TimescaleTimeseriesDao extends AbstractSqlTimeseriesDao implements @@ -78,12 +75,17 @@ public class TimescaleTimeseriesDao extends AbstractSqlTimeseriesDao implements
78 .maxDelay(tsMaxDelay) 75 .maxDelay(tsMaxDelay)
79 .statsPrintIntervalMs(tsStatsPrintIntervalMs) 76 .statsPrintIntervalMs(tsStatsPrintIntervalMs)
80 .statsNamePrefix("ts.timescale") 77 .statsNamePrefix("ts.timescale")
  78 + .batchSortEnabled(batchSortEnabled)
81 .build(); 79 .build();
82 80
83 Function<TimescaleTsKvEntity, Integer> hashcodeFunction = entity -> entity.getEntityId().hashCode(); 81 Function<TimescaleTsKvEntity, Integer> hashcodeFunction = entity -> entity.getEntityId().hashCode();
84 tsQueue = new TbSqlBlockingQueueWrapper<>(tsParams, hashcodeFunction, timescaleBatchThreads, statsFactory); 82 tsQueue = new TbSqlBlockingQueueWrapper<>(tsParams, hashcodeFunction, timescaleBatchThreads, statsFactory);
85 83
86 - tsQueue.init(logExecutor, v -> insertRepository.saveOrUpdate(v)); 84 + tsQueue.init(logExecutor, v -> insertRepository.saveOrUpdate(v),
  85 + Comparator.comparing((Function<TimescaleTsKvEntity, UUID>) AbstractTsKvEntity::getEntityId)
  86 + .thenComparing(AbstractTsKvEntity::getKey)
  87 + .thenComparing(AbstractTsKvEntity::getTs)
  88 + );
87 } 89 }
88 90
89 @PreDestroy 91 @PreDestroy
1 TB_QUEUE_TYPE=kafka 1 TB_QUEUE_TYPE=kafka
2 TB_KAFKA_SERVERS=kafka:9092 2 TB_KAFKA_SERVERS=kafka:9092
  3 +TB_QUEUE_KAFKA_JE_TOPIC_PROPERTIES=retention.ms:604800000;segment.bytes:26214400;retention.bytes:104857600;partitions:100
@@ -21,7 +21,7 @@ @@ -21,7 +21,7 @@
21 21
22 <parent> 22 <parent>
23 <groupId>org.thingsboard</groupId> 23 <groupId>org.thingsboard</groupId>
24 - <version>3.1.2-SNAPSHOT</version> 24 + <version>3.2.0-SNAPSHOT</version>
25 <artifactId>msa</artifactId> 25 <artifactId>msa</artifactId>
26 </parent> 26 </parent>
27 <groupId>org.thingsboard.msa</groupId> 27 <groupId>org.thingsboard.msa</groupId>
@@ -25,7 +25,7 @@ kafka: @@ -25,7 +25,7 @@ kafka:
25 # Kafka Bootstrap Servers 25 # Kafka Bootstrap Servers
26 servers: "localhost:9092" 26 servers: "localhost:9092"
27 replication_factor: "1" 27 replication_factor: "1"
28 - topic_properties: "retention.ms:604800000;segment.bytes:26214400;retention.bytes:104857600" 28 + topic_properties: "retention.ms:604800000;segment.bytes:26214400;retention.bytes:104857600;partitions:100"
29 use_confluent_cloud: false 29 use_confluent_cloud: false
30 confluent: 30 confluent:
31 sasl: 31 sasl:
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 <modelVersion>4.0.0</modelVersion> 20 <modelVersion>4.0.0</modelVersion>
21 <parent> 21 <parent>
22 <groupId>org.thingsboard</groupId> 22 <groupId>org.thingsboard</groupId>
23 - <version>3.1.2-SNAPSHOT</version> 23 + <version>3.2.0-SNAPSHOT</version>
24 <artifactId>msa</artifactId> 24 <artifactId>msa</artifactId>
25 </parent> 25 </parent>
26 <groupId>org.thingsboard.msa</groupId> 26 <groupId>org.thingsboard.msa</groupId>
@@ -34,7 +34,7 @@ function KafkaProducer() { @@ -34,7 +34,7 @@ function KafkaProducer() {
34 this.send = async (responseTopic, scriptId, rawResponse, headers) => { 34 this.send = async (responseTopic, scriptId, rawResponse, headers) => {
35 35
36 if (!topics.includes(responseTopic)) { 36 if (!topics.includes(responseTopic)) {
37 - let createResponseTopicResult = await createTopic(responseTopic); 37 + let createResponseTopicResult = await createTopic(responseTopic, 1);
38 topics.push(responseTopic); 38 topics.push(responseTopic);
39 if (createResponseTopicResult) { 39 if (createResponseTopicResult) {
40 logger.info('Created new topic: %s', requestTopic); 40 logger.info('Created new topic: %s', requestTopic);
@@ -88,7 +88,18 @@ function KafkaProducer() { @@ -88,7 +88,18 @@ function KafkaProducer() {
88 kafkaAdmin = kafkaClient.admin(); 88 kafkaAdmin = kafkaClient.admin();
89 await kafkaAdmin.connect(); 89 await kafkaAdmin.connect();
90 90
91 - let createRequestTopicResult = await createTopic(requestTopic); 91 + let partitions = 1;
  92 +
  93 + for (let i = 0; i < configEntries.length; i++) {
  94 + let param = configEntries[i];
  95 + if (param.name === 'partitions') {
  96 + partitions = param.value;
  97 + configEntries.splice(i, 1);
  98 + break;
  99 + }
  100 + }
  101 +
  102 + let createRequestTopicResult = await createTopic(requestTopic, partitions);
92 103
93 if (createRequestTopicResult) { 104 if (createRequestTopicResult) {
94 logger.info('Created new topic: %s', requestTopic); 105 logger.info('Created new topic: %s', requestTopic);
@@ -121,10 +132,11 @@ function KafkaProducer() { @@ -121,10 +132,11 @@ function KafkaProducer() {
121 } 132 }
122 })(); 133 })();
123 134
124 -function createTopic(topic) { 135 +function createTopic(topic, partitions) {
125 return kafkaAdmin.createTopics({ 136 return kafkaAdmin.createTopics({
126 topics: [{ 137 topics: [{
127 topic: topic, 138 topic: topic,
  139 + numPartitions: partitions,
128 replicationFactor: replicationFactor, 140 replicationFactor: replicationFactor,
129 configEntries: configEntries 141 configEntries: configEntries
130 }] 142 }]
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 <modelVersion>4.0.0</modelVersion> 20 <modelVersion>4.0.0</modelVersion>
21 <parent> 21 <parent>
22 <groupId>org.thingsboard</groupId> 22 <groupId>org.thingsboard</groupId>
23 - <version>3.1.2-SNAPSHOT</version> 23 + <version>3.2.0-SNAPSHOT</version>
24 <artifactId>thingsboard</artifactId> 24 <artifactId>thingsboard</artifactId>
25 </parent> 25 </parent>
26 <artifactId>msa</artifactId> 26 <artifactId>msa</artifactId>
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 <modelVersion>4.0.0</modelVersion> 20 <modelVersion>4.0.0</modelVersion>
21 <parent> 21 <parent>
22 <groupId>org.thingsboard</groupId> 22 <groupId>org.thingsboard</groupId>
23 - <version>3.1.2-SNAPSHOT</version> 23 + <version>3.2.0-SNAPSHOT</version>
24 <artifactId>msa</artifactId> 24 <artifactId>msa</artifactId>
25 </parent> 25 </parent>
26 <groupId>org.thingsboard.msa</groupId> 26 <groupId>org.thingsboard.msa</groupId>
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 <modelVersion>4.0.0</modelVersion> 20 <modelVersion>4.0.0</modelVersion>
21 <parent> 21 <parent>
22 <groupId>org.thingsboard</groupId> 22 <groupId>org.thingsboard</groupId>
23 - <version>3.1.2-SNAPSHOT</version> 23 + <version>3.2.0-SNAPSHOT</version>
24 <artifactId>msa</artifactId> 24 <artifactId>msa</artifactId>
25 </parent> 25 </parent>
26 <groupId>org.thingsboard.msa</groupId> 26 <groupId>org.thingsboard.msa</groupId>
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 <modelVersion>4.0.0</modelVersion> 20 <modelVersion>4.0.0</modelVersion>
21 <parent> 21 <parent>
22 <groupId>org.thingsboard.msa</groupId> 22 <groupId>org.thingsboard.msa</groupId>
23 - <version>3.1.2-SNAPSHOT</version> 23 + <version>3.2.0-SNAPSHOT</version>
24 <artifactId>transport</artifactId> 24 <artifactId>transport</artifactId>
25 </parent> 25 </parent>
26 <groupId>org.thingsboard.msa.transport</groupId> 26 <groupId>org.thingsboard.msa.transport</groupId>
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 <modelVersion>4.0.0</modelVersion> 20 <modelVersion>4.0.0</modelVersion>
21 <parent> 21 <parent>
22 <groupId>org.thingsboard.msa</groupId> 22 <groupId>org.thingsboard.msa</groupId>
23 - <version>3.1.2-SNAPSHOT</version> 23 + <version>3.2.0-SNAPSHOT</version>
24 <artifactId>transport</artifactId> 24 <artifactId>transport</artifactId>
25 </parent> 25 </parent>
26 <groupId>org.thingsboard.msa.transport</groupId> 26 <groupId>org.thingsboard.msa.transport</groupId>
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 <modelVersion>4.0.0</modelVersion> 20 <modelVersion>4.0.0</modelVersion>
21 <parent> 21 <parent>
22 <groupId>org.thingsboard.msa</groupId> 22 <groupId>org.thingsboard.msa</groupId>
23 - <version>3.1.2-SNAPSHOT</version> 23 + <version>3.2.0-SNAPSHOT</version>
24 <artifactId>transport</artifactId> 24 <artifactId>transport</artifactId>
25 </parent> 25 </parent>
26 <groupId>org.thingsboard.msa.transport</groupId> 26 <groupId>org.thingsboard.msa.transport</groupId>
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 <modelVersion>4.0.0</modelVersion> 20 <modelVersion>4.0.0</modelVersion>
21 <parent> 21 <parent>
22 <groupId>org.thingsboard</groupId> 22 <groupId>org.thingsboard</groupId>
23 - <version>3.1.2-SNAPSHOT</version> 23 + <version>3.2.0-SNAPSHOT</version>
24 <artifactId>msa</artifactId> 24 <artifactId>msa</artifactId>
25 </parent> 25 </parent>
26 <groupId>org.thingsboard.msa</groupId> 26 <groupId>org.thingsboard.msa</groupId>
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 <modelVersion>4.0.0</modelVersion> 20 <modelVersion>4.0.0</modelVersion>
21 <parent> 21 <parent>
22 <groupId>org.thingsboard</groupId> 22 <groupId>org.thingsboard</groupId>
23 - <version>3.1.2-SNAPSHOT</version> 23 + <version>3.2.0-SNAPSHOT</version>
24 <artifactId>msa</artifactId> 24 <artifactId>msa</artifactId>
25 </parent> 25 </parent>
26 <groupId>org.thingsboard.msa</groupId> 26 <groupId>org.thingsboard.msa</groupId>
@@ -19,11 +19,11 @@ @@ -19,11 +19,11 @@
19 <modelVersion>4.0.0</modelVersion> 19 <modelVersion>4.0.0</modelVersion>
20 <parent> 20 <parent>
21 <groupId>org.thingsboard</groupId> 21 <groupId>org.thingsboard</groupId>
22 - <version>3.1.2-SNAPSHOT</version> 22 + <version>3.2.0-SNAPSHOT</version>
23 <artifactId>thingsboard</artifactId> 23 <artifactId>thingsboard</artifactId>
24 </parent> 24 </parent>
25 <artifactId>netty-mqtt</artifactId> 25 <artifactId>netty-mqtt</artifactId>
26 - <version>3.1.2-SNAPSHOT</version> 26 + <version>3.2.0-SNAPSHOT</version>
27 <packaging>jar</packaging> 27 <packaging>jar</packaging>
28 28
29 <name>Netty MQTT Client</name> 29 <name>Netty MQTT Client</name>
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 <modelVersion>4.0.0</modelVersion> 20 <modelVersion>4.0.0</modelVersion>
21 <groupId>org.thingsboard</groupId> 21 <groupId>org.thingsboard</groupId>
22 <artifactId>thingsboard</artifactId> 22 <artifactId>thingsboard</artifactId>
23 - <version>3.1.2-SNAPSHOT</version> 23 + <version>3.2.0-SNAPSHOT</version>
24 <packaging>pom</packaging> 24 <packaging>pom</packaging>
25 25
26 <name>Thingsboard</name> 26 <name>Thingsboard</name>
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 <modelVersion>4.0.0</modelVersion> 20 <modelVersion>4.0.0</modelVersion>
21 <parent> 21 <parent>
22 <groupId>org.thingsboard</groupId> 22 <groupId>org.thingsboard</groupId>
23 - <version>3.1.2-SNAPSHOT</version> 23 + <version>3.2.0-SNAPSHOT</version>
24 <artifactId>thingsboard</artifactId> 24 <artifactId>thingsboard</artifactId>
25 </parent> 25 </parent>
26 <artifactId>rest-client</artifactId> 26 <artifactId>rest-client</artifactId>
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 <modelVersion>4.0.0</modelVersion> 20 <modelVersion>4.0.0</modelVersion>
21 <parent> 21 <parent>
22 <groupId>org.thingsboard</groupId> 22 <groupId>org.thingsboard</groupId>
23 - <version>3.1.2-SNAPSHOT</version> 23 + <version>3.2.0-SNAPSHOT</version>
24 <artifactId>thingsboard</artifactId> 24 <artifactId>thingsboard</artifactId>
25 </parent> 25 </parent>
26 <artifactId>rule-engine</artifactId> 26 <artifactId>rule-engine</artifactId>
@@ -22,7 +22,7 @@ @@ -22,7 +22,7 @@
22 <modelVersion>4.0.0</modelVersion> 22 <modelVersion>4.0.0</modelVersion>
23 <parent> 23 <parent>
24 <groupId>org.thingsboard</groupId> 24 <groupId>org.thingsboard</groupId>
25 - <version>3.1.2-SNAPSHOT</version> 25 + <version>3.2.0-SNAPSHOT</version>
26 <artifactId>rule-engine</artifactId> 26 <artifactId>rule-engine</artifactId>
27 </parent> 27 </parent>
28 <groupId>org.thingsboard.rule-engine</groupId> 28 <groupId>org.thingsboard.rule-engine</groupId>
@@ -22,7 +22,7 @@ @@ -22,7 +22,7 @@
22 <modelVersion>4.0.0</modelVersion> 22 <modelVersion>4.0.0</modelVersion>
23 <parent> 23 <parent>
24 <groupId>org.thingsboard</groupId> 24 <groupId>org.thingsboard</groupId>
25 - <version>3.1.2-SNAPSHOT</version> 25 + <version>3.2.0-SNAPSHOT</version>
26 <artifactId>rule-engine</artifactId> 26 <artifactId>rule-engine</artifactId>
27 </parent> 27 </parent>
28 <groupId>org.thingsboard.rule-engine</groupId> 28 <groupId>org.thingsboard.rule-engine</groupId>
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 <modelVersion>4.0.0</modelVersion> 20 <modelVersion>4.0.0</modelVersion>
21 <parent> 21 <parent>
22 <groupId>org.thingsboard</groupId> 22 <groupId>org.thingsboard</groupId>
23 - <version>3.1.2-SNAPSHOT</version> 23 + <version>3.2.0-SNAPSHOT</version>
24 <artifactId>thingsboard</artifactId> 24 <artifactId>thingsboard</artifactId>
25 </parent> 25 </parent>
26 <artifactId>tools</artifactId> 26 <artifactId>tools</artifactId>
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 <modelVersion>4.0.0</modelVersion> 20 <modelVersion>4.0.0</modelVersion>
21 <parent> 21 <parent>
22 <groupId>org.thingsboard</groupId> 22 <groupId>org.thingsboard</groupId>
23 - <version>3.1.2-SNAPSHOT</version> 23 + <version>3.2.0-SNAPSHOT</version>
24 <artifactId>transport</artifactId> 24 <artifactId>transport</artifactId>
25 </parent> 25 </parent>
26 <groupId>org.thingsboard.transport</groupId> 26 <groupId>org.thingsboard.transport</groupId>
@@ -77,11 +77,11 @@ queue: @@ -77,11 +77,11 @@ queue:
77 security.protocol: "${TB_QUEUE_KAFKA_CONFLUENT_SECURITY_PROTOCOL:SASL_SSL}" 77 security.protocol: "${TB_QUEUE_KAFKA_CONFLUENT_SECURITY_PROTOCOL:SASL_SSL}"
78 other: 78 other:
79 topic-properties: 79 topic-properties:
80 - rule-engine: "${TB_QUEUE_KAFKA_RE_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000}"  
81 - core: "${TB_QUEUE_KAFKA_CORE_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000}"  
82 - transport-api: "${TB_QUEUE_KAFKA_TA_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000}"  
83 - notifications: "${TB_QUEUE_KAFKA_NOTIFICATIONS_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000}"  
84 - js-executor: "${TB_QUEUE_KAFKA_JE_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:104857600}" 80 + rule-engine: "${TB_QUEUE_KAFKA_RE_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000;partitions:1}"
  81 + core: "${TB_QUEUE_KAFKA_CORE_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000;partitions:1}"
  82 + transport-api: "${TB_QUEUE_KAFKA_TA_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000;partitions:1}"
  83 + notifications: "${TB_QUEUE_KAFKA_NOTIFICATIONS_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000;partitions:1}"
  84 + js-executor: "${TB_QUEUE_KAFKA_JE_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:104857600;partitions:100}"
85 aws_sqs: 85 aws_sqs:
86 use_default_credential_provider_chain: "${TB_QUEUE_AWS_SQS_USE_DEFAULT_CREDENTIAL_PROVIDER_CHAIN:false}" 86 use_default_credential_provider_chain: "${TB_QUEUE_AWS_SQS_USE_DEFAULT_CREDENTIAL_PROVIDER_CHAIN:false}"
87 access_key_id: "${TB_QUEUE_AWS_SQS_ACCESS_KEY_ID:YOUR_KEY}" 87 access_key_id: "${TB_QUEUE_AWS_SQS_ACCESS_KEY_ID:YOUR_KEY}"
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 <modelVersion>4.0.0</modelVersion> 20 <modelVersion>4.0.0</modelVersion>
21 <parent> 21 <parent>
22 <groupId>org.thingsboard</groupId> 22 <groupId>org.thingsboard</groupId>
23 - <version>3.1.2-SNAPSHOT</version> 23 + <version>3.2.0-SNAPSHOT</version>
24 <artifactId>transport</artifactId> 24 <artifactId>transport</artifactId>
25 </parent> 25 </parent>
26 <groupId>org.thingsboard.transport</groupId> 26 <groupId>org.thingsboard.transport</groupId>
@@ -70,11 +70,11 @@ queue: @@ -70,11 +70,11 @@ queue:
70 security.protocol: "${TB_QUEUE_KAFKA_CONFLUENT_SECURITY_PROTOCOL:SASL_SSL}" 70 security.protocol: "${TB_QUEUE_KAFKA_CONFLUENT_SECURITY_PROTOCOL:SASL_SSL}"
71 other: 71 other:
72 topic-properties: 72 topic-properties:
73 - rule-engine: "${TB_QUEUE_KAFKA_RE_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000}"  
74 - core: "${TB_QUEUE_KAFKA_CORE_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000}"  
75 - transport-api: "${TB_QUEUE_KAFKA_TA_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000}"  
76 - notifications: "${TB_QUEUE_KAFKA_NOTIFICATIONS_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000}"  
77 - js-executor: "${TB_QUEUE_KAFKA_JE_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:104857600}" 73 + rule-engine: "${TB_QUEUE_KAFKA_RE_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000;partitions:1}"
  74 + core: "${TB_QUEUE_KAFKA_CORE_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000;partitions:1}"
  75 + transport-api: "${TB_QUEUE_KAFKA_TA_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000;partitions:1}"
  76 + notifications: "${TB_QUEUE_KAFKA_NOTIFICATIONS_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000;partitions:1}"
  77 + js-executor: "${TB_QUEUE_KAFKA_JE_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:104857600;partitions:100}"
78 aws_sqs: 78 aws_sqs:
79 use_default_credential_provider_chain: "${TB_QUEUE_AWS_SQS_USE_DEFAULT_CREDENTIAL_PROVIDER_CHAIN:false}" 79 use_default_credential_provider_chain: "${TB_QUEUE_AWS_SQS_USE_DEFAULT_CREDENTIAL_PROVIDER_CHAIN:false}"
80 access_key_id: "${TB_QUEUE_AWS_SQS_ACCESS_KEY_ID:YOUR_KEY}" 80 access_key_id: "${TB_QUEUE_AWS_SQS_ACCESS_KEY_ID:YOUR_KEY}"
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 <modelVersion>4.0.0</modelVersion> 20 <modelVersion>4.0.0</modelVersion>
21 <parent> 21 <parent>
22 <groupId>org.thingsboard</groupId> 22 <groupId>org.thingsboard</groupId>
23 - <version>3.1.2-SNAPSHOT</version> 23 + <version>3.2.0-SNAPSHOT</version>
24 <artifactId>transport</artifactId> 24 <artifactId>transport</artifactId>
25 </parent> 25 </parent>
26 <groupId>org.thingsboard.transport</groupId> 26 <groupId>org.thingsboard.transport</groupId>
@@ -98,11 +98,11 @@ queue: @@ -98,11 +98,11 @@ queue:
98 security.protocol: "${TB_QUEUE_KAFKA_CONFLUENT_SECURITY_PROTOCOL:SASL_SSL}" 98 security.protocol: "${TB_QUEUE_KAFKA_CONFLUENT_SECURITY_PROTOCOL:SASL_SSL}"
99 other: 99 other:
100 topic-properties: 100 topic-properties:
101 - rule-engine: "${TB_QUEUE_KAFKA_RE_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000}"  
102 - core: "${TB_QUEUE_KAFKA_CORE_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000}"  
103 - transport-api: "${TB_QUEUE_KAFKA_TA_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000}"  
104 - notifications: "${TB_QUEUE_KAFKA_NOTIFICATIONS_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000}"  
105 - js-executor: "${TB_QUEUE_KAFKA_JE_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:104857600}" 101 + rule-engine: "${TB_QUEUE_KAFKA_RE_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000;partitions:1}"
  102 + core: "${TB_QUEUE_KAFKA_CORE_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000;partitions:1}"
  103 + transport-api: "${TB_QUEUE_KAFKA_TA_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000;partitions:1}"
  104 + notifications: "${TB_QUEUE_KAFKA_NOTIFICATIONS_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000;partitions:1}"
  105 + js-executor: "${TB_QUEUE_KAFKA_JE_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:104857600;partitions:100}"
106 aws_sqs: 106 aws_sqs:
107 use_default_credential_provider_chain: "${TB_QUEUE_AWS_SQS_USE_DEFAULT_CREDENTIAL_PROVIDER_CHAIN:false}" 107 use_default_credential_provider_chain: "${TB_QUEUE_AWS_SQS_USE_DEFAULT_CREDENTIAL_PROVIDER_CHAIN:false}"
108 access_key_id: "${TB_QUEUE_AWS_SQS_ACCESS_KEY_ID:YOUR_KEY}" 108 access_key_id: "${TB_QUEUE_AWS_SQS_ACCESS_KEY_ID:YOUR_KEY}"
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 <modelVersion>4.0.0</modelVersion> 20 <modelVersion>4.0.0</modelVersion>
21 <parent> 21 <parent>
22 <groupId>org.thingsboard</groupId> 22 <groupId>org.thingsboard</groupId>
23 - <version>3.1.2-SNAPSHOT</version> 23 + <version>3.2.0-SNAPSHOT</version>
24 <artifactId>thingsboard</artifactId> 24 <artifactId>thingsboard</artifactId>
25 </parent> 25 </parent>
26 <artifactId>transport</artifactId> 26 <artifactId>transport</artifactId>
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 <modelVersion>4.0.0</modelVersion> 20 <modelVersion>4.0.0</modelVersion>
21 <parent> 21 <parent>
22 <groupId>org.thingsboard</groupId> 22 <groupId>org.thingsboard</groupId>
23 - <version>3.1.2-SNAPSHOT</version> 23 + <version>3.2.0-SNAPSHOT</version>
24 <artifactId>thingsboard</artifactId> 24 <artifactId>thingsboard</artifactId>
25 </parent> 25 </parent>
26 <groupId>org.thingsboard</groupId> 26 <groupId>org.thingsboard</groupId>
@@ -123,7 +123,7 @@ export abstract class EntityComponent<T extends BaseData<HasId>, @@ -123,7 +123,7 @@ export abstract class EntityComponent<T extends BaseData<HasId>,
123 if (isString(obj[curr])) { 123 if (isString(obj[curr])) {
124 acc[curr] = obj[curr].trim(); 124 acc[curr] = obj[curr].trim();
125 } else if (isObject(obj[curr])) { 125 } else if (isObject(obj[curr])) {
126 - acc[curr] = this.deepTrim(obj[curr]) 126 + acc[curr] = this.deepTrim(obj[curr]);
127 } else { 127 } else {
128 acc[curr] = obj[curr]; 128 acc[curr] = obj[curr];
129 } 129 }
@@ -37,6 +37,7 @@ import { getCurrentAuthUser } from '@app/core/auth/auth.selectors'; @@ -37,6 +37,7 @@ import { getCurrentAuthUser } from '@app/core/auth/auth.selectors';
37 import { Authority } from '@shared/models/authority.enum'; 37 import { Authority } from '@shared/models/authority.enum';
38 import { DialogService } from '@core/services/dialog.service'; 38 import { DialogService } from '@core/services/dialog.service';
39 import { ImportExportService } from '@home/components/import-export/import-export.service'; 39 import { ImportExportService } from '@home/components/import-export/import-export.service';
  40 +import { Direction } from "@shared/models/page/sort-order";
40 41
41 @Injectable() 42 @Injectable()
42 export class WidgetsBundlesTableConfigResolver implements Resolve<EntityTableConfig<WidgetsBundle>> { 43 export class WidgetsBundlesTableConfigResolver implements Resolve<EntityTableConfig<WidgetsBundle>> {
@@ -55,6 +56,7 @@ export class WidgetsBundlesTableConfigResolver implements Resolve<EntityTableCon @@ -55,6 +56,7 @@ export class WidgetsBundlesTableConfigResolver implements Resolve<EntityTableCon
55 this.config.entityComponent = WidgetsBundleComponent; 56 this.config.entityComponent = WidgetsBundleComponent;
56 this.config.entityTranslations = entityTypeTranslations.get(EntityType.WIDGETS_BUNDLE); 57 this.config.entityTranslations = entityTypeTranslations.get(EntityType.WIDGETS_BUNDLE);
57 this.config.entityResources = entityTypeResources.get(EntityType.WIDGETS_BUNDLE); 58 this.config.entityResources = entityTypeResources.get(EntityType.WIDGETS_BUNDLE);
  59 + this.config.defaultSortOrder = {property: 'title', direction: Direction.ASC};
58 60
59 this.config.entityTitle = (widgetsBundle) => widgetsBundle ? 61 this.config.entityTitle = (widgetsBundle) => widgetsBundle ?
60 widgetsBundle.title : ''; 62 widgetsBundle.title : '';