Commit 237c2880501db168bde86588ffc12132a88dd65b

Authored by YevhenBondarenko
2 parents 9ef3445b e39ccaa2

Merge branch 'master' of https://github.com/thingsboard/thingsboard into develop/2.5-js-executor

Showing 35 changed files with 218 additions and 152 deletions
... ... @@ -21,6 +21,8 @@ CREATE OR REPLACE PROCEDURE create_partition_ts_kv_table() LANGUAGE plpgsql AS $
21 21 BEGIN
22 22 ALTER TABLE ts_kv
23 23 RENAME TO ts_kv_old;
  24 + ALTER TABLE ts_kv_old
  25 + RENAME CONSTRAINT ts_kv_pkey TO ts_kv_pkey_old;
24 26 CREATE TABLE IF NOT EXISTS ts_kv
25 27 (
26 28 LIKE ts_kv_old
... ... @@ -32,6 +34,8 @@ BEGIN
32 34 ALTER COLUMN entity_id TYPE uuid USING entity_id::uuid;
33 35 ALTER TABLE ts_kv
34 36 ALTER COLUMN key TYPE integer USING key::integer;
  37 + ALTER TABLE ts_kv
  38 + ADD CONSTRAINT ts_kv_pkey PRIMARY KEY (entity_id, key, ts);
35 39 END;
36 40 $$;
37 41
... ... @@ -59,33 +63,65 @@ BEGIN
59 63 END;
60 64 $$;
61 65
  66 +CREATE OR REPLACE FUNCTION get_partitions_data(IN partition_type varchar)
  67 + RETURNS
  68 + TABLE
  69 + (
  70 + partition_date text,
  71 + from_ts bigint,
  72 + to_ts bigint
  73 + )
  74 +AS
  75 +$$
  76 +BEGIN
  77 + CASE
  78 + WHEN partition_type = 'DAYS' THEN
  79 + RETURN QUERY SELECT day_date.day AS partition_date,
  80 + (extract(epoch from (day_date.day)::timestamp) * 1000)::bigint AS from_ts,
  81 + (extract(epoch from (day_date.day::date + INTERVAL '1 DAY')::timestamp) *
  82 + 1000)::bigint AS to_ts
  83 + FROM (SELECT DISTINCT TO_CHAR(TO_TIMESTAMP(ts / 1000), 'YYYY_MM_DD') AS day
  84 + FROM ts_kv_old) AS day_date;
  85 + WHEN partition_type = 'MONTHS' THEN
  86 + RETURN QUERY SELECT SUBSTRING(month_date.first_date, 1, 7) AS partition_date,
  87 + (extract(epoch from (month_date.first_date)::timestamp) * 1000)::bigint AS from_ts,
  88 + (extract(epoch from (month_date.first_date::date + INTERVAL '1 MONTH')::timestamp) *
  89 + 1000)::bigint AS to_ts
  90 + FROM (SELECT DISTINCT TO_CHAR(TO_TIMESTAMP(ts / 1000), 'YYYY_MM_01') AS first_date
  91 + FROM ts_kv_old) AS month_date;
  92 + WHEN partition_type = 'YEARS' THEN
  93 + RETURN QUERY SELECT SUBSTRING(year_date.year, 1, 4) AS partition_date,
  94 + (extract(epoch from (year_date.year)::timestamp) * 1000)::bigint AS from_ts,
  95 + (extract(epoch from (year_date.year::date + INTERVAL '1 YEAR')::timestamp) *
  96 + 1000)::bigint AS to_ts
  97 + FROM (SELECT DISTINCT TO_CHAR(TO_TIMESTAMP(ts / 1000), 'YYYY_01_01') AS year FROM ts_kv_old) AS year_date;
  98 + ELSE
  99 + RAISE EXCEPTION 'Failed to parse partitioning property: % !', partition_type;
  100 + END CASE;
  101 +END;
  102 +$$ LANGUAGE plpgsql;
62 103
63 104 -- call create_partitions();
64 105
65   -CREATE OR REPLACE PROCEDURE create_partitions() LANGUAGE plpgsql AS $$
  106 +CREATE OR REPLACE PROCEDURE create_partitions(IN partition_type varchar) LANGUAGE plpgsql AS $$
66 107
67 108 DECLARE
68 109 partition_date varchar;
69 110 from_ts bigint;
70 111 to_ts bigint;
71   - key_cursor CURSOR FOR select SUBSTRING(month_date.first_date, 1, 7) AS partition_date,
72   - extract(epoch from (month_date.first_date)::timestamp) * 1000 as from_ts,
73   - extract(epoch from (month_date.first_date::date + INTERVAL '1 MONTH')::timestamp) *
74   - 1000 as to_ts
75   - FROM (SELECT DISTINCT TO_CHAR(TO_TIMESTAMP(ts / 1000), 'YYYY_MM_01') AS first_date
76   - FROM ts_kv_old) AS month_date;
  112 + partitions_cursor CURSOR FOR SELECT * FROM get_partitions_data(partition_type);
77 113 BEGIN
78   - OPEN key_cursor;
  114 + OPEN partitions_cursor;
79 115 LOOP
80   - FETCH key_cursor INTO partition_date, from_ts, to_ts;
  116 + FETCH partitions_cursor INTO partition_date, from_ts, to_ts;
81 117 EXIT WHEN NOT FOUND;
82 118 EXECUTE 'CREATE TABLE IF NOT EXISTS ts_kv_' || partition_date ||
83   - ' PARTITION OF ts_kv(PRIMARY KEY (entity_id, key, ts)) FOR VALUES FROM (' || from_ts ||
  119 + ' PARTITION OF ts_kv FOR VALUES FROM (' || from_ts ||
84 120 ') TO (' || to_ts || ');';
85 121 RAISE NOTICE 'A partition % has been created!',CONCAT('ts_kv_', partition_date);
86 122 END LOOP;
87 123
88   - CLOSE key_cursor;
  124 + CLOSE partitions_cursor;
89 125 END;
90 126 $$;
91 127
... ...
... ... @@ -106,7 +106,8 @@ public abstract class AbstractSqlTsDatabaseUpgradeService {
106 106 Thread.sleep(2000);
107 107 log.info("Successfully executed query: {}", query);
108 108 } catch (InterruptedException | SQLException e) {
109   - log.info("Failed to execute query: {} due to: {}", query, e.getMessage());
  109 + log.error("Failed to execute query: {} due to: {}", query, e.getMessage());
  110 + throw new RuntimeException("Failed to execute query:" + query + " due to: ", e);
110 111 }
111 112 }
112 113
... ...
... ... @@ -15,6 +15,7 @@
15 15 */
16 16 package org.thingsboard.server.service.install;
17 17
  18 +import org.springframework.beans.factory.annotation.Value;
18 19 import org.springframework.context.annotation.Profile;
19 20 import org.springframework.stereotype.Service;
20 21 import org.thingsboard.server.dao.util.PsqlDao;
... ... @@ -24,9 +25,20 @@ import org.thingsboard.server.dao.util.SqlTsDao;
24 25 @SqlTsDao
25 26 @PsqlDao
26 27 @Profile("install")
27   -public class PsqlTsDatabaseSchemaService extends SqlAbstractDatabaseSchemaService
28   - implements TsDatabaseSchemaService {
  28 +public class PsqlTsDatabaseSchemaService extends SqlAbstractDatabaseSchemaService implements TsDatabaseSchemaService {
  29 +
  30 + @Value("${sql.postgres.ts_key_value_partitioning:MONTHS}")
  31 + private String partitionType;
  32 +
29 33 public PsqlTsDatabaseSchemaService() {
30 34 super("schema-ts-psql.sql", null);
31 35 }
  36 +
  37 + @Override
  38 + public void createDatabaseSchema() throws Exception {
  39 + super.createDatabaseSchema();
  40 + if (partitionType.equals("INDEFINITE")) {
  41 + executeQuery("CREATE TABLE ts_kv_indefinite PARTITION OF ts_kv DEFAULT;");
  42 + }
  43 + }
32 44 }
\ No newline at end of file
... ...
... ... @@ -16,6 +16,7 @@
16 16 package org.thingsboard.server.service.install;
17 17
18 18 import lombok.extern.slf4j.Slf4j;
  19 +import org.springframework.beans.factory.annotation.Value;
19 20 import org.springframework.context.annotation.Profile;
20 21 import org.springframework.stereotype.Service;
21 22 import org.thingsboard.server.dao.util.PsqlDao;
... ... @@ -33,6 +34,9 @@ import java.sql.DriverManager;
33 34 @PsqlDao
34 35 public class PsqlTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgradeService implements DatabaseTsUpgradeService {
35 36
  37 + @Value("${sql.postgres.ts_key_value_partitioning:MONTHS}")
  38 + private String partitionType;
  39 +
36 40 private static final String LOAD_FUNCTIONS_SQL = "schema_update_psql_ts.sql";
37 41 private static final String LOAD_TTL_FUNCTIONS_SQL = "schema_update_ttl.sql";
38 42 private static final String LOAD_DROP_PARTITIONS_FUNCTIONS_SQL = "schema_update_psql_drop_partitions.sql";
... ... @@ -50,7 +54,6 @@ public class PsqlTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgradeSe
50 54
51 55 private static final String CALL_CREATE_PARTITION_TS_KV_TABLE = CALL_REGEX + CREATE_PARTITION_TS_KV_TABLE;
52 56 private static final String CALL_CREATE_NEW_TS_KV_LATEST_TABLE = CALL_REGEX + CREATE_NEW_TS_KV_LATEST_TABLE;
53   - private static final String CALL_CREATE_PARTITIONS = CALL_REGEX + CREATE_PARTITIONS;
54 57 private static final String CALL_CREATE_TS_KV_DICTIONARY_TABLE = CALL_REGEX + CREATE_TS_KV_DICTIONARY_TABLE;
55 58 private static final String CALL_INSERT_INTO_DICTIONARY = CALL_REGEX + INSERT_INTO_DICTIONARY;
56 59 private static final String CALL_INSERT_INTO_TS_KV = CALL_REGEX + INSERT_INTO_TS_KV;
... ... @@ -66,6 +69,7 @@ public class PsqlTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgradeSe
66 69 private static final String DROP_PROCEDURE_INSERT_INTO_DICTIONARY = DROP_PROCEDURE_IF_EXISTS + INSERT_INTO_DICTIONARY;
67 70 private static final String DROP_PROCEDURE_INSERT_INTO_TS_KV = DROP_PROCEDURE_IF_EXISTS + INSERT_INTO_TS_KV;
68 71 private static final String DROP_PROCEDURE_INSERT_INTO_TS_KV_LATEST = DROP_PROCEDURE_IF_EXISTS + INSERT_INTO_TS_KV_LATEST;
  72 + private static final String DROP_FUNCTION_GET_PARTITION_DATA = "DROP FUNCTION IF EXISTS get_partitions_data;";
69 73
70 74 @Override
71 75 public void upgradeDatabase(String fromVersion) throws Exception {
... ... @@ -83,7 +87,11 @@ public class PsqlTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgradeSe
83 87 loadSql(conn, LOAD_FUNCTIONS_SQL);
84 88 log.info("Updating timeseries schema ...");
85 89 executeQuery(conn, CALL_CREATE_PARTITION_TS_KV_TABLE);
86   - executeQuery(conn, CALL_CREATE_PARTITIONS);
  90 + if (!partitionType.equals("INDEFINITE")) {
  91 + executeQuery(conn, "call create_partitions('" + partitionType + "')");
  92 + } else {
  93 + executeQuery(conn, "CREATE TABLE IF NOT EXISTS ts_kv_indefinite PARTITION OF ts_kv DEFAULT;");
  94 + }
87 95 executeQuery(conn, CALL_CREATE_TS_KV_DICTIONARY_TABLE);
88 96 executeQuery(conn, CALL_INSERT_INTO_DICTIONARY);
89 97 executeQuery(conn, CALL_INSERT_INTO_TS_KV);
... ... @@ -100,9 +108,14 @@ public class PsqlTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgradeSe
100 108 executeQuery(conn, DROP_PROCEDURE_INSERT_INTO_TS_KV);
101 109 executeQuery(conn, DROP_PROCEDURE_CREATE_NEW_TS_KV_LATEST_TABLE);
102 110 executeQuery(conn, DROP_PROCEDURE_INSERT_INTO_TS_KV_LATEST);
  111 + executeQuery(conn, DROP_PROCEDURE_INSERT_INTO_TS_KV_LATEST);
  112 + executeQuery(conn, DROP_FUNCTION_GET_PARTITION_DATA);
103 113
104 114 executeQuery(conn, "ALTER TABLE ts_kv ADD COLUMN IF NOT EXISTS json_v json;");
105 115 executeQuery(conn, "ALTER TABLE ts_kv_latest ADD COLUMN IF NOT EXISTS json_v json;");
  116 + } else {
  117 + executeQuery(conn, "ALTER TABLE ts_kv DROP CONSTRAINT IF EXISTS ts_kv_pkey;");
  118 + executeQuery(conn, "ALTER TABLE ts_kv ADD CONSTRAINT ts_kv_pkey PRIMARY KEY (entity_id, key, ts);");
106 119 }
107 120
108 121 log.info("Load TTL functions ...");
... ...
... ... @@ -25,6 +25,7 @@ import java.nio.file.Path;
25 25 import java.nio.file.Paths;
26 26 import java.sql.Connection;
27 27 import java.sql.DriverManager;
  28 +import java.sql.SQLException;
28 29
29 30 @Slf4j
30 31 public abstract class SqlAbstractDatabaseSchemaService implements DatabaseSchemaService {
... ... @@ -73,4 +74,14 @@ public abstract class SqlAbstractDatabaseSchemaService implements DatabaseSchema
73 74 }
74 75 }
75 76
  77 + protected void executeQuery(String query) {
  78 + try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword)) {
  79 + conn.createStatement().execute(query); //NOSONAR, ignoring because method used to execute thingsboard database upgrade script
  80 + log.info("Successfully executed query: {}", query);
  81 + Thread.sleep(5000);
  82 + } catch (InterruptedException | SQLException e) {
  83 + log.info("Failed to execute query: {} due to: {}", query, e.getMessage());
  84 + }
  85 + }
  86 +
76 87 }
... ...
... ... @@ -33,14 +33,6 @@ import java.sql.SQLException;
33 33 @Slf4j
34 34 public class TimescaleTsDatabaseSchemaService extends SqlAbstractDatabaseSchemaService implements TsDatabaseSchemaService {
35 35
36   - private static final String QUERY = "query: {}";
37   - private static final String SUCCESSFULLY_EXECUTED = "Successfully executed ";
38   - private static final String FAILED_TO_EXECUTE = "Failed to execute ";
39   - private static final String FAILED_DUE_TO = " due to: {}";
40   -
41   - private static final String SUCCESSFULLY_EXECUTED_QUERY = SUCCESSFULLY_EXECUTED + QUERY;
42   - private static final String FAILED_TO_EXECUTE_QUERY = FAILED_TO_EXECUTE + QUERY + FAILED_DUE_TO;
43   -
44 36 @Value("${sql.timescale.chunk_time_interval:86400000}")
45 37 private long chunkTimeInterval;
46 38
... ... @@ -54,15 +46,4 @@ public class TimescaleTsDatabaseSchemaService extends SqlAbstractDatabaseSchemaS
54 46 executeQuery("SELECT create_hypertable('ts_kv', 'ts', chunk_time_interval => " + chunkTimeInterval + ", if_not_exists => true);");
55 47 }
56 48
57   - private void executeQuery(String query) {
58   - try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword)) {
59   - conn.createStatement().execute(query); //NOSONAR, ignoring because method used to execute thingsboard database upgrade script
60   - log.info(SUCCESSFULLY_EXECUTED_QUERY, query);
61   - Thread.sleep(5000);
62   - } catch (InterruptedException | SQLException e) {
63   - log.info(FAILED_TO_EXECUTE_QUERY, query, e.getMessage());
64   - }
65   - }
66   -
67   -
68 49 }
\ No newline at end of file
... ...
... ... @@ -18,10 +18,13 @@ package org.thingsboard.server.service.script;
18 18 import com.google.common.util.concurrent.Futures;
19 19 import com.google.common.util.concurrent.ListenableFuture;
20 20 import lombok.extern.slf4j.Slf4j;
  21 +import org.thingsboard.common.util.ThingsBoardThreadFactory;
21 22
22 23 import java.util.Map;
23 24 import java.util.UUID;
24 25 import java.util.concurrent.ConcurrentHashMap;
  26 +import java.util.concurrent.Executors;
  27 +import java.util.concurrent.ScheduledExecutorService;
25 28 import java.util.concurrent.atomic.AtomicInteger;
26 29
27 30 /**
... ... @@ -30,9 +33,22 @@ import java.util.concurrent.atomic.AtomicInteger;
30 33 @Slf4j
31 34 public abstract class AbstractJsInvokeService implements JsInvokeService {
32 35
  36 + protected ScheduledExecutorService timeoutExecutorService;
33 37 protected Map<UUID, String> scriptIdToNameMap = new ConcurrentHashMap<>();
34 38 protected Map<UUID, BlackListInfo> blackListedFunctions = new ConcurrentHashMap<>();
35 39
  40 + public void init(long maxRequestsTimeout) {
  41 + if (maxRequestsTimeout > 0) {
  42 + timeoutExecutorService = Executors.newSingleThreadScheduledExecutor(ThingsBoardThreadFactory.forName("nashorn-js-timeout"));
  43 + }
  44 + }
  45 +
  46 + public void stop() {
  47 + if (timeoutExecutorService != null) {
  48 + timeoutExecutorService.shutdownNow();
  49 + }
  50 + }
  51 +
36 52 @Override
37 53 public ListenableFuture<UUID> eval(JsScriptType scriptType, String scriptBody, String... argNames) {
38 54 UUID scriptId = UUID.randomUUID();
... ...
... ... @@ -48,7 +48,6 @@ public abstract class AbstractNashornJsInvokeService extends AbstractJsInvokeSer
48 48 private NashornSandbox sandbox;
49 49 private ScriptEngine engine;
50 50 private ExecutorService monitorExecutorService;
51   - private ScheduledExecutorService timeoutExecutorService;
52 51
53 52 private final AtomicInteger jsPushedMsgs = new AtomicInteger(0);
54 53 private final AtomicInteger jsInvokeMsgs = new AtomicInteger(0);
... ... @@ -85,9 +84,7 @@ public abstract class AbstractNashornJsInvokeService extends AbstractJsInvokeSer
85 84
86 85 @PostConstruct
87 86 public void init() {
88   - if (maxRequestsTimeout > 0) {
89   - timeoutExecutorService = Executors.newSingleThreadScheduledExecutor(ThingsBoardThreadFactory.forName("nashorn-js-timeout"));
90   - }
  87 + super.init(maxRequestsTimeout);
91 88 if (useJsSandbox()) {
92 89 sandbox = NashornSandboxes.create();
93 90 monitorExecutorService = Executors.newWorkStealingPool(getMonitorThreadPoolSize());
... ... @@ -104,12 +101,10 @@ public abstract class AbstractNashornJsInvokeService extends AbstractJsInvokeSer
104 101
105 102 @PreDestroy
106 103 public void stop() {
  104 + super.stop();
107 105 if (monitorExecutorService != null) {
108 106 monitorExecutorService.shutdownNow();
109 107 }
110   - if (timeoutExecutorService != null) {
111   - timeoutExecutorService.shutdownNow();
112   - }
113 108 }
114 109
115 110 protected abstract boolean useJsSandbox();
... ...
... ... @@ -87,11 +87,13 @@ public class RemoteJsInvokeService extends AbstractJsInvokeService {
87 87
88 88 @PostConstruct
89 89 public void init() {
  90 + super.init(maxRequestsTimeout);
90 91 requestTemplate.init();
91 92 }
92 93
93 94 @PreDestroy
94 95 public void destroy() {
  96 + super.stop();
95 97 if (requestTemplate != null) {
96 98 requestTemplate.stop();
97 99 }
... ... @@ -111,7 +113,9 @@ public class RemoteJsInvokeService extends AbstractJsInvokeService {
111 113
112 114 log.trace("Post compile request for scriptId [{}]", scriptId);
113 115 ListenableFuture<TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> future = requestTemplate.send(new TbProtoJsQueueMsg<>(UUID.randomUUID(), jsRequestWrapper));
114   -
  116 + if (maxRequestsTimeout > 0) {
  117 + future = Futures.withTimeout(future, maxRequestsTimeout, TimeUnit.MILLISECONDS, timeoutExecutorService);
  118 + }
115 119 kafkaPushedMsgs.incrementAndGet();
116 120 Futures.addCallback(future, new FutureCallback<TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>>() {
117 121 @Override
... ... @@ -154,8 +158,8 @@ public class RemoteJsInvokeService extends AbstractJsInvokeService {
154 158 .setTimeout((int) maxRequestsTimeout)
155 159 .setScriptBody(scriptIdToBodysMap.get(scriptId));
156 160
157   - for (int i = 0; i < args.length; i++) {
158   - jsRequestBuilder.addArgs(args[i].toString());
  161 + for (Object arg : args) {
  162 + jsRequestBuilder.addArgs(arg.toString());
159 163 }
160 164
161 165 JsInvokeProtos.RemoteJsRequest jsRequestWrapper = JsInvokeProtos.RemoteJsRequest.newBuilder()
... ... @@ -163,6 +167,9 @@ public class RemoteJsInvokeService extends AbstractJsInvokeService {
163 167 .build();
164 168
165 169 ListenableFuture<TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> future = requestTemplate.send(new TbProtoJsQueueMsg<>(UUID.randomUUID(), jsRequestWrapper));
  170 + if (maxRequestsTimeout > 0) {
  171 + future = Futures.withTimeout(future, maxRequestsTimeout, TimeUnit.MILLISECONDS, timeoutExecutorService);
  172 + }
166 173 kafkaPushedMsgs.incrementAndGet();
167 174 Futures.addCallback(future, new FutureCallback<TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>>() {
168 175 @Override
... ... @@ -203,6 +210,9 @@ public class RemoteJsInvokeService extends AbstractJsInvokeService {
203 210 .build();
204 211
205 212 ListenableFuture<TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> future = requestTemplate.send(new TbProtoJsQueueMsg<>(UUID.randomUUID(), jsRequestWrapper));
  213 + if (maxRequestsTimeout > 0) {
  214 + future = Futures.withTimeout(future, maxRequestsTimeout, TimeUnit.MILLISECONDS, timeoutExecutorService);
  215 + }
206 216 JsInvokeProtos.RemoteJsResponse response = future.get().getValue();
207 217
208 218 JsInvokeProtos.JsReleaseResponse compilationResult = response.getReleaseResponse();
... ...
... ... @@ -33,7 +33,7 @@ public class ControllerSqlTestSuite {
33 33 @ClassRule
34 34 public static CustomSqlUnit sqlUnit = new CustomSqlUnit(
35 35 Arrays.asList("sql/schema-ts-hsql.sql", "sql/schema-entities-hsql.sql", "sql/schema-entities-idx.sql", "sql/system-data.sql"),
36   - "sql/drop-all-tables.sql",
  36 + "sql/hsql/drop-all-tables.sql",
37 37 "sql-test.properties");
38 38
39 39 @BeforeClass
... ...
... ... @@ -32,7 +32,7 @@ public class MqttSqlTestSuite {
32 32 @ClassRule
33 33 public static CustomSqlUnit sqlUnit = new CustomSqlUnit(
34 34 Arrays.asList("sql/schema-ts-hsql.sql", "sql/schema-entities-hsql.sql", "sql/system-data.sql"),
35   - "sql/drop-all-tables.sql",
  35 + "sql/hsql/drop-all-tables.sql",
36 36 "sql-test.properties");
37 37
38 38 @BeforeClass
... ...
... ... @@ -33,7 +33,7 @@ public class RuleEngineSqlTestSuite {
33 33 @ClassRule
34 34 public static CustomSqlUnit sqlUnit = new CustomSqlUnit(
35 35 Arrays.asList("sql/schema-ts-hsql.sql", "sql/schema-entities-hsql.sql", "sql/system-data.sql"),
36   - "sql/drop-all-tables.sql",
  36 + "sql/hsql/drop-all-tables.sql",
37 37 "sql-test.properties");
38 38
39 39 @BeforeClass
... ...
... ... @@ -34,7 +34,7 @@ public class SystemSqlTestSuite {
34 34 @ClassRule
35 35 public static CustomSqlUnit sqlUnit = new CustomSqlUnit(
36 36 Arrays.asList("sql/schema-ts-hsql.sql", "sql/schema-entities-hsql.sql", "sql/system-data.sql"),
37   - "sql/drop-all-tables.sql",
  37 + "sql/hsql/drop-all-tables.sql",
38 38 "sql-test.properties");
39 39
40 40 @BeforeClass
... ...
... ... @@ -54,7 +54,7 @@ public abstract class AbstractChunkedAggregationTimeseriesDao extends AbstractSq
54 54 @Autowired
55 55 protected InsertTsRepository<TsKvEntity> insertRepository;
56 56
57   - protected TbSqlBlockingQueue<EntityContainer<TsKvEntity>> tsQueue;
  57 + protected TbSqlBlockingQueue<TsKvEntity> tsQueue;
58 58
59 59 @PostConstruct
60 60 protected void init() {
... ...
... ... @@ -23,7 +23,6 @@ import org.thingsboard.server.common.data.id.TenantId;
23 23 import org.thingsboard.server.common.data.kv.TsKvEntry;
24 24 import org.thingsboard.server.dao.model.sqlts.ts.TsKvEntity;
25 25 import org.thingsboard.server.dao.sqlts.AbstractChunkedAggregationTimeseriesDao;
26   -import org.thingsboard.server.dao.sqlts.EntityContainer;
27 26 import org.thingsboard.server.dao.timeseries.TimeseriesDao;
28 27 import org.thingsboard.server.dao.util.HsqlDao;
29 28 import org.thingsboard.server.dao.util.SqlTsDao;
... ... @@ -48,7 +47,7 @@ public class JpaHsqlTimeseriesDao extends AbstractChunkedAggregationTimeseriesDa
48 47 entity.setLongValue(tsKvEntry.getLongValue().orElse(null));
49 48 entity.setBooleanValue(tsKvEntry.getBooleanValue().orElse(null));
50 49 log.trace("Saving entity: {}", entity);
51   - return tsQueue.add(new EntityContainer(entity, null));
  50 + return tsQueue.add(entity);
52 51 }
53 52
54 53 }
... ...
... ... @@ -16,12 +16,11 @@
16 16 package org.thingsboard.server.dao.sqlts.insert;
17 17
18 18 import org.thingsboard.server.dao.model.sql.AbstractTsKvEntity;
19   -import org.thingsboard.server.dao.sqlts.EntityContainer;
20 19
21 20 import java.util.List;
22 21
23 22 public interface InsertTsRepository<T extends AbstractTsKvEntity> {
24 23
25   - void saveOrUpdate(List<EntityContainer<T>> entities);
  24 + void saveOrUpdate(List<T> entities);
26 25
27 26 }
... ...
... ... @@ -19,7 +19,6 @@ import org.springframework.jdbc.core.BatchPreparedStatementSetter;
19 19 import org.springframework.stereotype.Repository;
20 20 import org.springframework.transaction.annotation.Transactional;
21 21 import org.thingsboard.server.dao.model.sqlts.ts.TsKvEntity;
22   -import org.thingsboard.server.dao.sqlts.EntityContainer;
23 22 import org.thingsboard.server.dao.sqlts.insert.AbstractInsertRepository;
24 23 import org.thingsboard.server.dao.sqlts.insert.InsertTsRepository;
25 24 import org.thingsboard.server.dao.util.HsqlDao;
... ... @@ -47,12 +46,11 @@ public class HsqlInsertTsRepository extends AbstractInsertRepository implements
47 46 "VALUES (T.entity_id, T.key, T.ts, T.bool_v, T.str_v, T.long_v, T.dbl_v, T.json_v);";
48 47
49 48 @Override
50   - public void saveOrUpdate(List<EntityContainer<TsKvEntity>> entities) {
  49 + public void saveOrUpdate(List<TsKvEntity> entities) {
51 50 jdbcTemplate.batchUpdate(INSERT_OR_UPDATE, new BatchPreparedStatementSetter() {
52 51 @Override
53 52 public void setValues(PreparedStatement ps, int i) throws SQLException {
54   - EntityContainer<TsKvEntity> tsKvEntityEntityContainer = entities.get(i);
55   - TsKvEntity tsKvEntity = tsKvEntityEntityContainer.getEntity();
  53 + TsKvEntity tsKvEntity = entities.get(i);
56 54 ps.setObject(1, tsKvEntity.getEntityId());
57 55 ps.setInt(2, tsKvEntity.getKey());
58 56 ps.setLong(3, tsKvEntity.getTs());
... ...
... ... @@ -20,7 +20,6 @@ import org.springframework.stereotype.Repository;
20 20 import org.springframework.transaction.annotation.Transactional;
21 21 import org.thingsboard.server.dao.model.sqlts.ts.TsKvEntity;
22 22 import org.thingsboard.server.dao.sqlts.insert.AbstractInsertRepository;
23   -import org.thingsboard.server.dao.sqlts.EntityContainer;
24 23 import org.thingsboard.server.dao.sqlts.insert.InsertTsRepository;
25 24 import org.thingsboard.server.dao.util.PsqlDao;
26 25 import org.thingsboard.server.dao.util.SqlTsDao;
... ... @@ -28,10 +27,7 @@ import org.thingsboard.server.dao.util.SqlTsDao;
28 27 import java.sql.PreparedStatement;
29 28 import java.sql.SQLException;
30 29 import java.sql.Types;
31   -import java.util.ArrayList;
32   -import java.util.HashMap;
33 30 import java.util.List;
34   -import java.util.Map;
35 31
36 32 @SqlTsDao
37 33 @PsqlDao
... ... @@ -39,22 +35,15 @@ import java.util.Map;
39 35 @Transactional
40 36 public class PsqlInsertTsRepository extends AbstractInsertRepository implements InsertTsRepository<TsKvEntity> {
41 37
42   - private static final String INSERT_INTO_TS_KV = "INSERT INTO ts_kv_";
43   -
44   - private static final String VALUES_ON_CONFLICT_DO_UPDATE = " (entity_id, key, ts, bool_v, str_v, long_v, dbl_v, json_v) VALUES (?, ?, ?, ?, ?, ?, ?, cast(? AS json)) " +
  38 + private static final String INSERT_ON_CONFLICT_DO_UPDATE = "INSERT INTO ts_kv (entity_id, key, ts, bool_v, str_v, long_v, dbl_v, json_v) VALUES (?, ?, ?, ?, ?, ?, ?, cast(? AS json)) " +
45 39 "ON CONFLICT (entity_id, key, ts) DO UPDATE SET bool_v = ?, str_v = ?, long_v = ?, dbl_v = ?, json_v = cast(? AS json);";
46 40
47 41 @Override
48   - public void saveOrUpdate(List<EntityContainer<TsKvEntity>> entities) {
49   - Map<String, List<TsKvEntity>> partitionMap = new HashMap<>();
50   - for (EntityContainer<TsKvEntity> entityContainer : entities) {
51   - List<TsKvEntity> tsKvEntities = partitionMap.computeIfAbsent(entityContainer.getPartitionDate(), k -> new ArrayList<>());
52   - tsKvEntities.add(entityContainer.getEntity());
53   - }
54   - partitionMap.forEach((partition, entries) -> jdbcTemplate.batchUpdate(getInsertOrUpdateQuery(partition), new BatchPreparedStatementSetter() {
  42 + public void saveOrUpdate(List<TsKvEntity> entities) {
  43 + jdbcTemplate.batchUpdate(INSERT_ON_CONFLICT_DO_UPDATE, new BatchPreparedStatementSetter() {
55 44 @Override
56 45 public void setValues(PreparedStatement ps, int i) throws SQLException {
57   - TsKvEntity tsKvEntity = entries.get(i);
  46 + TsKvEntity tsKvEntity = entities.get(i);
58 47 ps.setObject(1, tsKvEntity.getEntityId());
59 48 ps.setInt(2, tsKvEntity.getKey());
60 49 ps.setLong(3, tsKvEntity.getTs());
... ... @@ -93,12 +82,9 @@ public class PsqlInsertTsRepository extends AbstractInsertRepository implements
93 82
94 83 @Override
95 84 public int getBatchSize() {
96   - return entries.size();
  85 + return entities.size();
97 86 }
98   - }));
  87 + });
99 88 }
100 89
101   - private String getInsertOrUpdateQuery(String partitionDate) {
102   - return INSERT_INTO_TS_KV + partitionDate + VALUES_ON_CONFLICT_DO_UPDATE;
103   - }
104 90 }
... ...
... ... @@ -20,7 +20,6 @@ import org.springframework.stereotype.Repository;
20 20 import org.springframework.transaction.annotation.Transactional;
21 21 import org.thingsboard.server.dao.model.sqlts.timescale.ts.TimescaleTsKvEntity;
22 22 import org.thingsboard.server.dao.sqlts.insert.AbstractInsertRepository;
23   -import org.thingsboard.server.dao.sqlts.EntityContainer;
24 23 import org.thingsboard.server.dao.sqlts.insert.InsertTsRepository;
25 24 import org.thingsboard.server.dao.util.PsqlDao;
26 25 import org.thingsboard.server.dao.util.TimescaleDBTsDao;
... ... @@ -41,11 +40,11 @@ public class TimescaleInsertTsRepository extends AbstractInsertRepository implem
41 40 "ON CONFLICT (entity_id, key, ts) DO UPDATE SET bool_v = ?, str_v = ?, long_v = ?, dbl_v = ?, json_v = cast(? AS json);";
42 41
43 42 @Override
44   - public void saveOrUpdate(List<EntityContainer<TimescaleTsKvEntity>> entities) {
  43 + public void saveOrUpdate(List<TimescaleTsKvEntity> entities) {
45 44 jdbcTemplate.batchUpdate(INSERT_OR_UPDATE, new BatchPreparedStatementSetter() {
46 45 @Override
47 46 public void setValues(PreparedStatement ps, int i) throws SQLException {
48   - TimescaleTsKvEntity tsKvEntity = entities.get(i).getEntity();
  47 + TimescaleTsKvEntity tsKvEntity = entities.get(i);
49 48 ps.setObject(1, tsKvEntity.getEntityId());
50 49 ps.setInt(2, tsKvEntity.getKey());
51 50 ps.setLong(3, tsKvEntity.getTs());
... ...
... ... @@ -25,7 +25,6 @@ import org.thingsboard.server.common.data.id.TenantId;
25 25 import org.thingsboard.server.common.data.kv.TsKvEntry;
26 26 import org.thingsboard.server.dao.model.sqlts.ts.TsKvEntity;
27 27 import org.thingsboard.server.dao.sqlts.AbstractChunkedAggregationTimeseriesDao;
28   -import org.thingsboard.server.dao.sqlts.EntityContainer;
29 28 import org.thingsboard.server.dao.sqlts.insert.psql.PsqlPartitioningRepository;
30 29 import org.thingsboard.server.dao.timeseries.PsqlPartition;
31 30 import org.thingsboard.server.dao.timeseries.SqlTsPartitionDate;
... ... @@ -42,8 +41,6 @@ import java.util.Optional;
42 41 import java.util.concurrent.ConcurrentHashMap;
43 42 import java.util.concurrent.locks.ReentrantLock;
44 43
45   -import static org.thingsboard.server.dao.timeseries.SqlTsPartitionDate.EPOCH_START;
46   -
47 44
48 45 @Component
49 46 @Slf4j
... ... @@ -58,7 +55,6 @@ public class JpaPsqlTimeseriesDao extends AbstractChunkedAggregationTimeseriesDa
58 55 private PsqlPartitioningRepository partitioningRepository;
59 56
60 57 private SqlTsPartitionDate tsFormat;
61   - private PsqlPartition indefinitePartition;
62 58
63 59 @Value("${sql.postgres.ts_key_value_partitioning:MONTHS}")
64 60 private String partitioning;
... ... @@ -69,10 +65,6 @@ public class JpaPsqlTimeseriesDao extends AbstractChunkedAggregationTimeseriesDa
69 65 Optional<SqlTsPartitionDate> partition = SqlTsPartitionDate.parse(partitioning);
70 66 if (partition.isPresent()) {
71 67 tsFormat = partition.get();
72   - if (tsFormat.equals(SqlTsPartitionDate.INDEFINITE)) {
73   - indefinitePartition = new PsqlPartition(toMills(EPOCH_START), Long.MAX_VALUE, tsFormat.getPattern());
74   - savePartition(indefinitePartition);
75   - }
76 68 } else {
77 69 log.warn("Incorrect configuration of partitioning {}", partitioning);
78 70 throw new RuntimeException("Failed to parse partitioning property: " + partitioning + "!");
... ... @@ -81,6 +73,7 @@ public class JpaPsqlTimeseriesDao extends AbstractChunkedAggregationTimeseriesDa
81 73
82 74 @Override
83 75 public ListenableFuture<Void> save(TenantId tenantId, EntityId entityId, TsKvEntry tsKvEntry, long ttl) {
  76 + savePartitionIfNotExist(tsKvEntry.getTs());
84 77 String strKey = tsKvEntry.getKey();
85 78 Integer keyId = getOrSaveKeyId(strKey);
86 79 TsKvEntity entity = new TsKvEntity();
... ... @@ -92,9 +85,23 @@ public class JpaPsqlTimeseriesDao extends AbstractChunkedAggregationTimeseriesDa
92 85 entity.setLongValue(tsKvEntry.getLongValue().orElse(null));
93 86 entity.setBooleanValue(tsKvEntry.getBooleanValue().orElse(null));
94 87 entity.setJsonValue(tsKvEntry.getJsonValue().orElse(null));
95   - PsqlPartition psqlPartition = toPartition(tsKvEntry.getTs());
96 88 log.trace("Saving entity: {}", entity);
97   - return tsQueue.add(new EntityContainer(entity, psqlPartition.getPartitionDate()));
  89 + return tsQueue.add(entity);
  90 + }
  91 +
  92 + private void savePartitionIfNotExist(long ts) {
  93 + if (!tsFormat.equals(SqlTsPartitionDate.INDEFINITE)) {
  94 + LocalDateTime time = LocalDateTime.ofInstant(Instant.ofEpochMilli(ts), ZoneOffset.UTC);
  95 + LocalDateTime localDateTimeStart = tsFormat.trancateTo(time);
  96 + long partitionStartTs = toMills(localDateTimeStart);
  97 + if (partitions.get(partitionStartTs) == null) {
  98 + LocalDateTime localDateTimeEnd = tsFormat.plusTo(localDateTimeStart);
  99 + long partitionEndTs = toMills(localDateTimeEnd);
  100 + ZonedDateTime zonedDateTime = localDateTimeStart.atZone(ZoneOffset.UTC);
  101 + String partitionDate = zonedDateTime.format(DateTimeFormatter.ofPattern(tsFormat.getPattern()));
  102 + savePartition(new PsqlPartition(partitionStartTs, partitionEndTs, partitionDate));
  103 + }
  104 + }
98 105 }
99 106
100 107 private void savePartition(PsqlPartition psqlPartition) {
... ... @@ -111,28 +118,6 @@ public class JpaPsqlTimeseriesDao extends AbstractChunkedAggregationTimeseriesDa
111 118 }
112 119 }
113 120
114   - private PsqlPartition toPartition(long ts) {
115   - if (tsFormat.equals(SqlTsPartitionDate.INDEFINITE)) {
116   - return indefinitePartition;
117   - } else {
118   - LocalDateTime time = LocalDateTime.ofInstant(Instant.ofEpochMilli(ts), ZoneOffset.UTC);
119   - LocalDateTime localDateTimeStart = tsFormat.trancateTo(time);
120   - long partitionStartTs = toMills(localDateTimeStart);
121   - PsqlPartition partition = partitions.get(partitionStartTs);
122   - if (partition != null) {
123   - return partition;
124   - } else {
125   - LocalDateTime localDateTimeEnd = tsFormat.plusTo(localDateTimeStart);
126   - long partitionEndTs = toMills(localDateTimeEnd);
127   - ZonedDateTime zonedDateTime = localDateTimeStart.atZone(ZoneOffset.UTC);
128   - String partitionDate = zonedDateTime.format(DateTimeFormatter.ofPattern(tsFormat.getPattern()));
129   - partition = new PsqlPartition(partitionStartTs, partitionEndTs, partitionDate);
130   - savePartition(partition);
131   - return partition;
132   - }
133   - }
134   - }
135   -
136 121 private static long toMills(LocalDateTime time) {
137 122 return time.toInstant(ZoneOffset.UTC).toEpochMilli();
138 123 }
... ...
... ... @@ -36,7 +36,6 @@ import org.thingsboard.server.dao.model.sqlts.timescale.ts.TimescaleTsKvEntity;
36 36 import org.thingsboard.server.dao.sql.TbSqlBlockingQueue;
37 37 import org.thingsboard.server.dao.sql.TbSqlBlockingQueueParams;
38 38 import org.thingsboard.server.dao.sqlts.AbstractSqlTimeseriesDao;
39   -import org.thingsboard.server.dao.sqlts.EntityContainer;
40 39 import org.thingsboard.server.dao.sqlts.insert.InsertTsRepository;
41 40 import org.thingsboard.server.dao.timeseries.TimeseriesDao;
42 41 import org.thingsboard.server.dao.util.TimescaleDBTsDao;
... ... @@ -64,7 +63,7 @@ public class TimescaleTimeseriesDao extends AbstractSqlTimeseriesDao implements
64 63 @Autowired
65 64 protected InsertTsRepository<TimescaleTsKvEntity> insertRepository;
66 65
67   - protected TbSqlBlockingQueue<EntityContainer<TimescaleTsKvEntity>> tsQueue;
  66 + protected TbSqlBlockingQueue<TimescaleTsKvEntity> tsQueue;
68 67
69 68 @PostConstruct
70 69 protected void init() {
... ... @@ -175,7 +174,7 @@ public class TimescaleTimeseriesDao extends AbstractSqlTimeseriesDao implements
175 174 entity.setJsonValue(tsKvEntry.getJsonValue().orElse(null));
176 175
177 176 log.trace("Saving entity to timescale db: {}", entity);
178   - return tsQueue.add(new EntityContainer(entity, null));
  177 + return tsQueue.add(entity);
179 178 }
180 179
181 180 @Override
... ...
... ... @@ -35,6 +35,6 @@ public class PsqlPartition {
35 35 }
36 36
37 37 private String createStatement(long start, long end, String partitionDate) {
38   - return "CREATE TABLE IF NOT EXISTS " + TABLE_REGEX + partitionDate + " PARTITION OF ts_kv(PRIMARY KEY (entity_id, key, ts)) FOR VALUES FROM (" + start + ") TO (" + end + ")";
  38 + return "CREATE TABLE IF NOT EXISTS " + TABLE_REGEX + partitionDate + " PARTITION OF ts_kv FOR VALUES FROM (" + start + ") TO (" + end + ")";
39 39 }
40 40 }
\ No newline at end of file
... ...
... ... @@ -23,7 +23,7 @@ import java.util.Optional;
23 23
24 24 public enum SqlTsPartitionDate {
25 25
26   - MINUTES("yyyy_MM_dd_HH_mm", ChronoUnit.MINUTES), HOURS("yyyy_MM_dd_HH", ChronoUnit.HOURS), DAYS("yyyy_MM_dd", ChronoUnit.DAYS), MONTHS("yyyy_MM", ChronoUnit.MONTHS), YEARS("yyyy", ChronoUnit.YEARS), INDEFINITE("indefinite", ChronoUnit.FOREVER);
  26 + DAYS("yyyy_MM_dd", ChronoUnit.DAYS), MONTHS("yyyy_MM", ChronoUnit.MONTHS), YEARS("yyyy", ChronoUnit.YEARS), INDEFINITE("indefinite", ChronoUnit.FOREVER);
27 27
28 28 private final String pattern;
29 29 private final transient TemporalUnit truncateUnit;
... ... @@ -44,10 +44,6 @@ public enum SqlTsPartitionDate {
44 44
45 45 public LocalDateTime trancateTo(LocalDateTime time) {
46 46 switch (this) {
47   - case MINUTES:
48   - return time.truncatedTo(ChronoUnit.MINUTES);
49   - case HOURS:
50   - return time.truncatedTo(ChronoUnit.HOURS);
51 47 case DAYS:
52 48 return time.truncatedTo(ChronoUnit.DAYS);
53 49 case MONTHS:
... ... @@ -63,10 +59,6 @@ public enum SqlTsPartitionDate {
63 59
64 60 public LocalDateTime plusTo(LocalDateTime time) {
65 61 switch (this) {
66   - case MINUTES:
67   - return time.plusMinutes(1);
68   - case HOURS:
69   - return time.plusHours(1);
70 62 case DAYS:
71 63 return time.plusDays(1);
72 64 case MONTHS:
... ...
... ... @@ -23,7 +23,8 @@ CREATE TABLE IF NOT EXISTS ts_kv
23 23 str_v varchar(10000000),
24 24 long_v bigint,
25 25 dbl_v double precision,
26   - json_v json
  26 + json_v json,
  27 + CONSTRAINT ts_kv_pkey PRIMARY KEY (entity_id, key, ts)
27 28 ) PARTITION BY RANGE (ts);
28 29
29 30 CREATE TABLE IF NOT EXISTS ts_kv_latest
... ...
... ... @@ -31,14 +31,14 @@ public class JpaDaoTestSuite {
31 31 @ClassRule
32 32 public static CustomSqlUnit sqlUnit = new CustomSqlUnit(
33 33 Arrays.asList("sql/schema-ts-hsql.sql", "sql/schema-entities-hsql.sql", "sql/system-data.sql"),
34   - "sql/drop-all-tables.sql",
  34 + "sql/hsql/drop-all-tables.sql",
35 35 "sql-test.properties"
36 36 );
37 37
38 38 // @ClassRule
39 39 // public static CustomSqlUnit sqlUnit = new CustomSqlUnit(
40 40 // Arrays.asList("sql/schema-ts-psql.sql", "sql/schema-entities.sql", "sql/system-data.sql"),
41   -// "sql/drop-all-tables.sql",
  41 +// "sql/psql/drop-all-tables.sql",
42 42 // "sql-test.properties"
43 43 // );
44 44
... ...
... ... @@ -31,14 +31,14 @@ public class SqlDaoServiceTestSuite {
31 31 @ClassRule
32 32 public static CustomSqlUnit sqlUnit = new CustomSqlUnit(
33 33 Arrays.asList("sql/schema-ts-hsql.sql", "sql/schema-entities-hsql.sql", "sql/schema-entities-idx.sql", "sql/system-data.sql", "sql/system-test.sql"),
34   - "sql/drop-all-tables.sql",
  34 + "sql/hsql/drop-all-tables.sql",
35 35 "sql-test.properties"
36 36 );
37 37
38 38 // @ClassRule
39 39 // public static CustomSqlUnit sqlUnit = new CustomSqlUnit(
40 40 // Arrays.asList("sql/schema-ts-psql.sql", "sql/schema-entities.sql", "sql/schema-entities-idx.sql", "sql/system-data.sql", "sql/system-test.sql"),
41   -// "sql/drop-all-tables.sql",
  41 +// "sql/psql/drop-all-tables.sql",
42 42 // "sql-test.properties"
43 43 // );
44 44
... ...
dao/src/test/resources/sql/hsql/drop-all-tables.sql renamed from dao/src/test/resources/sql/drop-all-tables.sql
  1 +DROP TABLE IF EXISTS admin_settings;
  2 +DROP TABLE IF EXISTS alarm;
  3 +DROP TABLE IF EXISTS asset;
  4 +DROP TABLE IF EXISTS audit_log;
  5 +DROP TABLE IF EXISTS attribute_kv;
  6 +DROP TABLE IF EXISTS component_descriptor;
  7 +DROP TABLE IF EXISTS customer;
  8 +DROP TABLE IF EXISTS dashboard;
  9 +DROP TABLE IF EXISTS device;
  10 +DROP TABLE IF EXISTS device_credentials;
  11 +DROP TABLE IF EXISTS event;
  12 +DROP TABLE IF EXISTS relation;
  13 +DROP TABLE IF EXISTS tb_user;
  14 +DROP TABLE IF EXISTS tenant;
  15 +DROP TABLE IF EXISTS ts_kv;
  16 +DROP TABLE IF EXISTS ts_kv_latest;
  17 +DROP TABLE IF EXISTS ts_kv_dictionary;
  18 +DROP TABLE IF EXISTS user_credentials;
  19 +DROP TABLE IF EXISTS widget_type;
  20 +DROP TABLE IF EXISTS widgets_bundle;
  21 +DROP TABLE IF EXISTS rule_node;
  22 +DROP TABLE IF EXISTS rule_chain;
  23 +DROP TABLE IF EXISTS entity_view;
  24 +DROP TABLE IF EXISTS tb_schema_settings;
\ No newline at end of file
... ...
... ... @@ -14,9 +14,11 @@ DROP TABLE IF EXISTS tb_user;
14 14 DROP TABLE IF EXISTS tenant;
15 15 DROP TABLE IF EXISTS ts_kv;
16 16 DROP TABLE IF EXISTS ts_kv_latest;
  17 +DROP TABLE IF EXISTS ts_kv_dictionary;
17 18 DROP TABLE IF EXISTS user_credentials;
18 19 DROP TABLE IF EXISTS widget_type;
19 20 DROP TABLE IF EXISTS widgets_bundle;
20 21 DROP TABLE IF EXISTS rule_node;
21 22 DROP TABLE IF EXISTS rule_chain;
22   -DROP TABLE IF EXISTS entity_view;
\ No newline at end of file
  23 +DROP TABLE IF EXISTS entity_view;
  24 +DROP TABLE IF EXISTS tb_schema_settings;
\ No newline at end of file
... ...
... ... @@ -59,7 +59,7 @@ JsInvokeMessageProcessor.prototype.onJsInvokeMessage = function(message) {
59 59 } else if (request.releaseRequest) {
60 60 this.processReleaseRequest(requestId, responseTopic, headers, request.releaseRequest);
61 61 } else {
62   - logger.error('[%s] Unknown request recevied!', requestId);
  62 + logger.error('[%s] Unknown request received!', requestId);
63 63 }
64 64
65 65 } catch (err) {
... ...
... ... @@ -41,8 +41,6 @@ function KafkaProducer() {
41 41 }
42 42 }
43 43
44   - let headersData = headers.data;
45   - headersData = Object.fromEntries(Object.entries(headersData).map(([key, value]) => [key, Buffer.from(value)]));
46 44 return producer.send(
47 45 {
48 46 topic: responseTopic,
... ... @@ -50,7 +48,7 @@ function KafkaProducer() {
50 48 {
51 49 key: scriptId,
52 50 value: rawResponse,
53   - headers: headersData
  51 + headers: headers.data
54 52 }
55 53 ]
56 54 });
... ... @@ -96,15 +94,10 @@ function KafkaProducer() {
96 94 eachMessage: async ({topic, partition, message}) => {
97 95 let headers = message.headers;
98 96 let key = message.key;
99   - let data = message.value;
100 97 let msg = {};
101   -
102   - headers = Object.fromEntries(
103   - Object.entries(headers).map(([key, value]) => [key, [...value]]));
104   -
105 98 msg.key = key.toString('utf8');
106   - msg.data = [...data];
107   - msg.headers = {data: headers}
  99 + msg.data = message.value;
  100 + msg.headers = {data: headers};
108 101 messageProcessor.onJsInvokeMessage(msg);
109 102 },
110 103 });
... ...
... ... @@ -38,7 +38,7 @@ import java.io.IOException;
38 38 @Slf4j
39 39 @RuleNode(
40 40 type = ComponentType.FILTER,
41   - name = "checks alarm status",
  41 + name = "check alarm status",
42 42 configClazz = TbCheckAlarmStatusNodeConfig.class,
43 43 relationTypes = {"True", "False"},
44 44 nodeDescription = "Checks alarm status.",
... ...
... ... @@ -386,6 +386,26 @@ function UserService($http, $q, $rootScope, adminService, dashboardService, time
386 386 deferred.reject();
387 387 }
388 388 procceedJwtTokenValidate();
  389 + } else if (locationSearch.username && locationSearch.password) {
  390 + var user = {};
  391 + user.name = locationSearch.username;
  392 + user.password = locationSearch.password;
  393 + $location.search('username', null);
  394 + $location.search('password', null);
  395 +
  396 + loginService.login(user).then(function success(response) {
  397 + var token = response.data.token;
  398 + var refreshToken = response.data.refreshToken;
  399 + try {
  400 + updateAndValidateToken(token, 'jwt_token', false);
  401 + updateAndValidateToken(refreshToken, 'refresh_token', false);
  402 + } catch (e) {
  403 + deferred.reject();
  404 + }
  405 + procceedJwtTokenValidate();
  406 + }, function fail() {
  407 + deferred.reject();
  408 + });
389 409 } else {
390 410 procceedJwtTokenValidate();
391 411 }
... ...
... ... @@ -20,7 +20,7 @@ import logoSvg from '../../svg/logo_title_white.svg';
20 20 /* eslint-enable import/no-unresolved, import/default */
21 21
22 22 /*@ngInject*/
23   -export default function LoginController(toast, loginService, userService, types, $state, $stateParams/*, $rootScope, $log, $translate*/) {
  23 +export default function LoginController(toast, loginService, userService, types, $state/*, $rootScope, $log, $translate*/) {
24 24 var vm = this;
25 25
26 26 vm.logoSvg = logoSvg;
... ... @@ -32,12 +32,6 @@ export default function LoginController(toast, loginService, userService, types,
32 32
33 33 vm.login = login;
34 34
35   - if ($stateParams.username && $stateParams.password) {
36   - vm.user.name = $stateParams.username;
37   - vm.user.password = $stateParams.password;
38   - doLogin();
39   - }
40   -
41 35 function doLogin() {
42 36 loginService.login(vm.user).then(function success(response) {
43 37 var token = response.data.token;
... ...
... ... @@ -25,7 +25,7 @@ import createPasswordTemplate from './create-password.tpl.html';
25 25 /*@ngInject*/
26 26 export default function LoginRoutes($stateProvider) {
27 27 $stateProvider.state('login', {
28   - url: '/login?username&password',
  28 + url: '/login',
29 29 module: 'public',
30 30 views: {
31 31 "@": {
... ...