|
|
@ -17,10 +17,11 @@ package org.thingsboard.server.dao.sql.edge; |
|
|
|
|
|
|
|
|
import com.datastax.oss.driver.api.core.uuid.Uuids; |
|
|
import com.datastax.oss.driver.api.core.uuid.Uuids; |
|
|
import com.google.common.util.concurrent.ListenableFuture; |
|
|
import com.google.common.util.concurrent.ListenableFuture; |
|
|
|
|
|
import lombok.RequiredArgsConstructor; |
|
|
import lombok.extern.slf4j.Slf4j; |
|
|
import lombok.extern.slf4j.Slf4j; |
|
|
import org.springframework.beans.factory.annotation.Autowired; |
|
|
|
|
|
import org.springframework.beans.factory.annotation.Value; |
|
|
import org.springframework.beans.factory.annotation.Value; |
|
|
import org.springframework.data.jpa.repository.JpaRepository; |
|
|
import org.springframework.data.jpa.repository.JpaRepository; |
|
|
|
|
|
import org.springframework.jdbc.core.JdbcTemplate; |
|
|
import org.springframework.stereotype.Component; |
|
|
import org.springframework.stereotype.Component; |
|
|
import org.thingsboard.server.common.data.StringUtils; |
|
|
import org.thingsboard.server.common.data.StringUtils; |
|
|
import org.thingsboard.server.common.data.edge.EdgeEvent; |
|
|
import org.thingsboard.server.common.data.edge.EdgeEvent; |
|
|
@ -31,19 +32,17 @@ import org.thingsboard.server.common.data.page.TimePageLink; |
|
|
import org.thingsboard.server.common.stats.StatsFactory; |
|
|
import org.thingsboard.server.common.stats.StatsFactory; |
|
|
import org.thingsboard.server.dao.DaoUtil; |
|
|
import org.thingsboard.server.dao.DaoUtil; |
|
|
import org.thingsboard.server.dao.edge.EdgeEventDao; |
|
|
import org.thingsboard.server.dao.edge.EdgeEventDao; |
|
|
|
|
|
import org.thingsboard.server.dao.model.ModelConstants; |
|
|
import org.thingsboard.server.dao.model.sql.EdgeEventEntity; |
|
|
import org.thingsboard.server.dao.model.sql.EdgeEventEntity; |
|
|
import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao; |
|
|
import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao; |
|
|
import org.thingsboard.server.dao.sql.ScheduledLogExecutorComponent; |
|
|
import org.thingsboard.server.dao.sql.ScheduledLogExecutorComponent; |
|
|
import org.thingsboard.server.dao.sql.TbSqlBlockingQueueParams; |
|
|
import org.thingsboard.server.dao.sql.TbSqlBlockingQueueParams; |
|
|
import org.thingsboard.server.dao.sql.TbSqlBlockingQueueWrapper; |
|
|
import org.thingsboard.server.dao.sql.TbSqlBlockingQueueWrapper; |
|
|
|
|
|
import org.thingsboard.server.dao.sqlts.insert.sql.SqlPartitioningRepository; |
|
|
import org.thingsboard.server.dao.util.SqlDao; |
|
|
import org.thingsboard.server.dao.util.SqlDao; |
|
|
|
|
|
|
|
|
import javax.annotation.PostConstruct; |
|
|
import javax.annotation.PostConstruct; |
|
|
import javax.annotation.PreDestroy; |
|
|
import javax.annotation.PreDestroy; |
|
|
import java.sql.Connection; |
|
|
|
|
|
import java.sql.PreparedStatement; |
|
|
|
|
|
import java.sql.ResultSet; |
|
|
|
|
|
import java.sql.SQLException; |
|
|
|
|
|
import java.util.Comparator; |
|
|
import java.util.Comparator; |
|
|
import java.util.Objects; |
|
|
import java.util.Objects; |
|
|
import java.util.UUID; |
|
|
import java.util.UUID; |
|
|
@ -52,18 +51,25 @@ import java.util.function.Function; |
|
|
|
|
|
|
|
|
import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID; |
|
|
import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID; |
|
|
|
|
|
|
|
|
@Slf4j |
|
|
|
|
|
@Component |
|
|
@Component |
|
|
@SqlDao |
|
|
@SqlDao |
|
|
|
|
|
@RequiredArgsConstructor |
|
|
|
|
|
@Slf4j |
|
|
public class JpaBaseEdgeEventDao extends JpaAbstractSearchTextDao<EdgeEventEntity, EdgeEvent> implements EdgeEventDao { |
|
|
public class JpaBaseEdgeEventDao extends JpaAbstractSearchTextDao<EdgeEventEntity, EdgeEvent> implements EdgeEventDao { |
|
|
|
|
|
|
|
|
private final UUID systemTenantId = NULL_UUID; |
|
|
private final UUID systemTenantId = NULL_UUID; |
|
|
|
|
|
|
|
|
@Autowired |
|
|
private final ScheduledLogExecutorComponent logExecutor; |
|
|
ScheduledLogExecutorComponent logExecutor; |
|
|
|
|
|
|
|
|
private final StatsFactory statsFactory; |
|
|
|
|
|
|
|
|
|
|
|
private final EdgeEventRepository edgeEventRepository; |
|
|
|
|
|
|
|
|
|
|
|
private final EdgeEventInsertRepository edgeEventInsertRepository; |
|
|
|
|
|
|
|
|
@Autowired |
|
|
private final SqlPartitioningRepository partitioningRepository; |
|
|
private StatsFactory statsFactory; |
|
|
|
|
|
|
|
|
private final JdbcTemplate jdbcTemplate; |
|
|
|
|
|
|
|
|
@Value("${sql.edge_events.batch_size:1000}") |
|
|
@Value("${sql.edge_events.batch_size:1000}") |
|
|
private int batchSize; |
|
|
private int batchSize; |
|
|
@ -74,13 +80,15 @@ public class JpaBaseEdgeEventDao extends JpaAbstractSearchTextDao<EdgeEventEntit |
|
|
@Value("${sql.edge_events.stats_print_interval_ms:10000}") |
|
|
@Value("${sql.edge_events.stats_print_interval_ms:10000}") |
|
|
private long statsPrintIntervalMs; |
|
|
private long statsPrintIntervalMs; |
|
|
|
|
|
|
|
|
private TbSqlBlockingQueueWrapper<EdgeEventEntity> queue; |
|
|
@Value("${sql.edge_events.partitions_size:168}") |
|
|
|
|
|
private int partitionSizeInHours; |
|
|
|
|
|
|
|
|
@Autowired |
|
|
@Value("${sql.ttl.edge_events.edge_events_ttl:2628000}") |
|
|
private EdgeEventRepository edgeEventRepository; |
|
|
private long edge_events_ttl; |
|
|
|
|
|
|
|
|
@Autowired |
|
|
private static final String TABLE_NAME = ModelConstants.EDGE_EVENT_COLUMN_FAMILY_NAME; |
|
|
private EdgeEventInsertRepository edgeEventInsertRepository; |
|
|
|
|
|
|
|
|
private TbSqlBlockingQueueWrapper<EdgeEventEntity> queue; |
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
|
protected Class<EdgeEventEntity> getEntityClass() { |
|
|
protected Class<EdgeEventEntity> getEntityClass() { |
|
|
@ -140,6 +148,7 @@ public class JpaBaseEdgeEventDao extends JpaAbstractSearchTextDao<EdgeEventEntit |
|
|
if (StringUtils.isEmpty(edgeEvent.getUid())) { |
|
|
if (StringUtils.isEmpty(edgeEvent.getUid())) { |
|
|
edgeEvent.setUid(edgeEvent.getId().toString()); |
|
|
edgeEvent.setUid(edgeEvent.getId().toString()); |
|
|
} |
|
|
} |
|
|
|
|
|
partitioningRepository.createPartitionIfNotExists(TABLE_NAME, edgeEvent.getCreatedTime(), TimeUnit.HOURS.toMillis(partitionSizeInHours)); |
|
|
return save(new EdgeEventEntity(edgeEvent)); |
|
|
return save(new EdgeEventEntity(edgeEvent)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -189,20 +198,36 @@ public class JpaBaseEdgeEventDao extends JpaAbstractSearchTextDao<EdgeEventEntit |
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
|
public void cleanupEvents(long ttl) { |
|
|
public void cleanupEvents(long ttl) { |
|
|
log.info("Going to cleanup old edge events using ttl: {}s", ttl); |
|
|
partitioningRepository.dropPartitionsBefore(TABLE_NAME, ttl, TimeUnit.HOURS.toMillis(partitionSizeInHours)); |
|
|
try (Connection connection = dataSource.getConnection(); |
|
|
} |
|
|
PreparedStatement stmt = connection.prepareStatement("call cleanup_edge_events_by_ttl(?,?)")) { |
|
|
|
|
|
stmt.setLong(1, ttl); |
|
|
@Override |
|
|
stmt.setLong(2, 0); |
|
|
public void migrateEdgeEvents() { |
|
|
stmt.setQueryTimeout((int) TimeUnit.HOURS.toSeconds(1)); |
|
|
long startTime = edge_events_ttl > 0 ? System.currentTimeMillis() - TimeUnit.SECONDS.toMillis(edge_events_ttl) : 1629158400000L; |
|
|
stmt.execute(); |
|
|
|
|
|
printWarnings(stmt); |
|
|
long currentTime = System.currentTimeMillis(); |
|
|
try (ResultSet resultSet = stmt.getResultSet()) { |
|
|
var partitionStepInMs = TimeUnit.HOURS.toMillis(partitionSizeInHours); |
|
|
resultSet.next(); |
|
|
long numberOfPartitions = (currentTime - startTime) / partitionStepInMs; |
|
|
log.info("Total edge events removed by TTL: [{}]", resultSet.getLong(1)); |
|
|
|
|
|
} |
|
|
if (numberOfPartitions > 1000) { |
|
|
} catch (SQLException e) { |
|
|
String error = "Please adjust your edge event partitioning configuration. Configuration with partition size " + |
|
|
log.error("SQLException occurred during edge events TTL task execution ", e); |
|
|
"of " + partitionSizeInHours + " hours and corresponding TTL will use " + numberOfPartitions + " " + |
|
|
|
|
|
"(> 1000) partitions which is not recommended!"; |
|
|
|
|
|
log.error(error); |
|
|
|
|
|
throw new RuntimeException(error); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
while (startTime < currentTime) { |
|
|
|
|
|
var endTime = startTime + partitionStepInMs; |
|
|
|
|
|
log.info("Migrating edge event for time period: {} - {}", startTime, endTime); |
|
|
|
|
|
callMigrationFunction(startTime, endTime, partitionStepInMs); |
|
|
|
|
|
startTime = endTime; |
|
|
|
|
|
} |
|
|
|
|
|
log.info("Event edge migration finished"); |
|
|
|
|
|
jdbcTemplate.execute("DROP TABLE IF EXISTS old_edge_event"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void callMigrationFunction(long startTime, long endTime, long partitionSIzeInMs) { |
|
|
|
|
|
jdbcTemplate.update("CALL migrate_edge_event(?, ?, ?)", startTime, endTime, partitionSIzeInMs); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|