Commit 237c2880501db168bde86588ffc12132a88dd65b
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 | } | ... | ... |
dao/src/main/java/org/thingsboard/server/dao/sqlts/insert/timescale/TimescaleInsertTsRepository.java
... | ... | @@ -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 | "@": { | ... | ... |