Commit b8291be084bc2b843f61842194c82ff90d157239

Authored by Valerii Sosliuk
Committed by Andrew Shvayka
1 parent 3228312c

Update Latest TS by timestamp

There is a bug when the historic data arrives and overrides the value
with morerecent timestamp in ts_kv_latest table. This PR adds
possibility to update the ts_kv_latest table only if the value that
arrives has the newer timestamp than the one that is already in
ts_kv_latest
... ... @@ -243,6 +243,7 @@ sql:
243 243 batch_max_delay: "${SQL_TS_LATEST_BATCH_MAX_DELAY_MS:100}"
244 244 stats_print_interval_ms: "${SQL_TS_LATEST_BATCH_STATS_PRINT_MS:10000}"
245 245 batch_threads: "${SQL_TS_LATEST_BATCH_THREADS:4}"
  246 + update_by_latest_ts: "${SQL_TS_UPDATE_BY_LATEST_TIMESTAMP:true}"
246 247 # Specify whether to sort entities before batch update. Should be enabled for cluster mode to avoid deadlocks
247 248 batch_sort: "${SQL_BATCH_SORT:false}"
248 249 # Specify whether to remove null characters from strValue of attributes and timeseries before insert
... ...
... ... @@ -15,6 +15,7 @@
15 15 */
16 16 package org.thingsboard.server.dao.sqlts.insert.latest.psql;
17 17
  18 +import org.springframework.beans.factory.annotation.Value;
18 19 import org.springframework.jdbc.core.BatchPreparedStatementSetter;
19 20 import org.springframework.stereotype.Repository;
20 21 import org.springframework.transaction.TransactionStatus;
... ... @@ -37,20 +38,34 @@ import java.util.List;
37 38 @Transactional
38 39 public class PsqlLatestInsertTsRepository extends AbstractInsertRepository implements InsertLatestTsRepository {
39 40
  41 + @Value("${sql.ts_latest.update_by_latest_ts:true}")
  42 + private Boolean updateByLatestTs;
  43 +
40 44 private static final String BATCH_UPDATE =
41   - "UPDATE ts_kv_latest SET ts = ?, bool_v = ?, str_v = ?, long_v = ?, dbl_v = ?, json_v = cast(? AS json) WHERE entity_id = ? and key = ?";
  45 + "UPDATE ts_kv_latest SET ts = ?, bool_v = ?, str_v = ?, long_v = ?, dbl_v = ?, json_v = cast(? AS json) WHERE entity_id = ? AND key = ?;";
42 46
43 47
44 48 private static final String INSERT_OR_UPDATE =
45 49 "INSERT INTO ts_kv_latest (entity_id, key, ts, bool_v, str_v, long_v, dbl_v, json_v) VALUES(?, ?, ?, ?, ?, ?, ?, cast(? AS json)) " +
46 50 "ON CONFLICT (entity_id, key) DO UPDATE SET ts = ?, bool_v = ?, str_v = ?, long_v = ?, dbl_v = ?, json_v = cast(? AS json);";
47 51
  52 + private static final String BATCH_UPDATE_BY_LATEST_TS =
  53 + "UPDATE ts_kv_latest SET ts = ?, bool_v = ?, str_v = ?, long_v = ?, dbl_v = ?, json_v = cast(? AS json) WHERE entity_id = ? AND key = ? AND ts <= ?;";
  54 +
  55 +
  56 + private static final String INSERT_OR_UPDATE_BY_LATEST_TS =
  57 + "INSERT INTO ts_kv_latest (entity_id, key, ts, bool_v, str_v, long_v, dbl_v, json_v) VALUES(?, ?, ?, ?, ?, ?, ?, cast(? AS json)) " +
  58 + "ON CONFLICT (entity_id, key) DO UPDATE SET ts = ?, bool_v = ?, str_v = ?, long_v = ?, dbl_v = ?, json_v = cast(? AS json) WHERE ts_kv_latest.ts <= ?;";
  59 +
48 60 @Override
49 61 public void saveOrUpdate(List<TsKvLatestEntity> entities) {
50 62 transactionTemplate.execute(new TransactionCallbackWithoutResult() {
51 63 @Override
52 64 protected void doInTransactionWithoutResult(TransactionStatus status) {
53   - int[] result = jdbcTemplate.batchUpdate(BATCH_UPDATE, new BatchPreparedStatementSetter() {
  65 + String batchUpdateQuery = updateByLatestTs ? BATCH_UPDATE_BY_LATEST_TS : BATCH_UPDATE;
  66 + String insertOrUpdateQuery = updateByLatestTs ? INSERT_OR_UPDATE_BY_LATEST_TS : INSERT_OR_UPDATE;
  67 +
  68 + int[] result = jdbcTemplate.batchUpdate(batchUpdateQuery, new BatchPreparedStatementSetter() {
54 69 @Override
55 70 public void setValues(PreparedStatement ps, int i) throws SQLException {
56 71 TsKvLatestEntity tsKvLatestEntity = entities.get(i);
... ... @@ -80,6 +95,9 @@ public class PsqlLatestInsertTsRepository extends AbstractInsertRepository imple
80 95
81 96 ps.setObject(7, tsKvLatestEntity.getEntityId());
82 97 ps.setInt(8, tsKvLatestEntity.getKey());
  98 + if (updateByLatestTs) {
  99 + ps.setLong(9, tsKvLatestEntity.getTs());
  100 + }
83 101 }
84 102
85 103 @Override
... ... @@ -102,7 +120,7 @@ public class PsqlLatestInsertTsRepository extends AbstractInsertRepository imple
102 120 }
103 121 }
104 122
105   - jdbcTemplate.batchUpdate(INSERT_OR_UPDATE, new BatchPreparedStatementSetter() {
  123 + jdbcTemplate.batchUpdate(insertOrUpdateQuery, new BatchPreparedStatementSetter() {
106 124 @Override
107 125 public void setValues(PreparedStatement ps, int i) throws SQLException {
108 126 TsKvLatestEntity tsKvLatestEntity = insertEntities.get(i);
... ... @@ -111,6 +129,9 @@ public class PsqlLatestInsertTsRepository extends AbstractInsertRepository imple
111 129
112 130 ps.setLong(3, tsKvLatestEntity.getTs());
113 131 ps.setLong(9, tsKvLatestEntity.getTs());
  132 + if (updateByLatestTs) {
  133 + ps.setLong(15, tsKvLatestEntity.getTs());
  134 + }
114 135
115 136 if (tsKvLatestEntity.getBooleanValue() != null) {
116 137 ps.setBoolean(4, tsKvLatestEntity.getBooleanValue());
... ...