@ -16,16 +16,16 @@
package org.thingsboard.server.dao.sqlts.insert.sql ;
import lombok.extern.slf4j.Slf4j ;
import org.apache.commons.lang3.StringUtils ;
import org.apache.commons.lang3.exception.ExceptionUtils ;
import org.springframework.beans.factory.annotation.Autowired ;
import org.springframework.dao.DataAccessException ;
import org.springframework.jdbc.core.JdbcTemplate ;
import org.springframework.stereotype.Repository ;
import org.springframework.transaction.annotation.Propagation ;
import org.springframework.transaction.annotation.Transactional ;
import org.thingsboard.server.dao.timeseries.SqlPartition ;
import javax.persistence.EntityManager ;
import javax.persistence.PersistenceContext ;
import java.util.ArrayList ;
import java.util.List ;
import java.util.Map ;
@ -36,9 +36,6 @@ import java.util.concurrent.locks.ReentrantLock;
@Slf4j
public class SqlPartitioningRepository {
@PersistenceContext
private EntityManager entityManager ;
@Autowired
private JdbcTemplate jdbcTemplate ;
@ -50,12 +47,12 @@ public class SqlPartitioningRepository {
private final Map < String , Map < Long , SqlPartition > > tablesPartitions = new ConcurrentHashMap < > ( ) ;
private final ReentrantLock partitionCreationLock = new ReentrantLock ( ) ;
@Transactional
@Transactional ( propagation = Propagation . NOT_SUPPORTED )
public void save ( SqlPartition partition ) {
entityManager . createNativeQuery ( partition . getQuery ( ) ) . executeUpdate ( ) ;
jdbcTemplate . execute ( partition . getQuery ( ) ) ;
}
@Transactional
@Transactional ( propagation = Propagation . NOT_SUPPORTED ) // executing non-transactionally, so that parent transaction is not aborted on partition save error
public void createPartitionIfNotExists ( String table , long entityTs , long partitionDurationMs ) {
long partitionStartTs = calculatePartitionStartTime ( entityTs , partitionDurationMs ) ;
Map < Long , SqlPartition > partitions = tablesPartitions . computeIfAbsent ( table , t - > new ConcurrentHashMap < > ( ) ) ;
@ -64,20 +61,16 @@ public class SqlPartitioningRepository {
partitionCreationLock . lock ( ) ;
try {
if ( partitions . containsKey ( partitionStartTs ) ) return ;
log . trace ( "Saving partition: {}", partition ) ;
log . info ( "Saving partition {}-{} for table {}", partition . getStart ( ) , partition . getEnd ( ) , table ) ;
save ( partition ) ;
log . trace ( "Adding partition to map: {}" , partition ) ;
partitions . put ( partition . getStart ( ) , partition ) ;
} catch ( RuntimeException e ) {
log . trace ( "Error occurred during partition save:" , e ) ;
String msg = ExceptionUtils . getRootCauseMessage ( e ) ;
if ( msg . contains ( "would overlap partition" ) ) {
log . warn ( "Couldn't save {} partition for {}, data will be saved to the default partition. SQL error: {}" ,
partition . getPartitionDate ( ) , table , msg ) ;
} catch ( Exception e ) {
String error = ExceptionUtils . getRootCauseMessage ( e ) ;
if ( StringUtils . containsAny ( error , "would overlap partition" , "already exists" ) ) {
partitions . put ( partition . getStart ( ) , partition ) ;
} else {
throw e ;
}
log . warn ( "Couldn't save partition {}-{} for table {}: {}" , partition . getStart ( ) , partition . getEnd ( ) , table , error ) ;
} finally {
partitionCreationLock . unlock ( ) ;
}