From 248c268d6ab0aa41268e478831a3b5888f58bf7c Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Thu, 25 Jul 2024 13:53:14 +0300 Subject: [PATCH 01/10] Dedicated datasource for events --- .../src/main/resources/thingsboard.yml | 16 +++ .../server/dao/DedicatedJpaDaoConfig.java | 111 ++++++++++++++++++ .../thingsboard/server/dao/JpaDaoConfig.java | 93 +++++++++++++-- .../server/dao/SqlTimeseriesDaoConfig.java | 34 ------ .../server/dao/SqlTsDaoConfig.java | 2 - .../server/dao/SqlTsLatestDaoConfig.java | 2 - .../dao/sql/event/EventInsertRepository.java | 5 + .../server/dao/sql/event/JpaBaseEventDao.java | 2 +- .../insert/sql/SqlPartitioningRepository.java | 12 +- .../server/dao/AbstractDaoServiceTest.java | 2 +- .../server/dao/AbstractJpaDaoTest.java | 2 +- 11 files changed, 230 insertions(+), 51 deletions(-) create mode 100644 dao/src/main/java/org/thingsboard/server/dao/DedicatedJpaDaoConfig.java delete mode 100644 dao/src/main/java/org/thingsboard/server/dao/SqlTimeseriesDaoConfig.java diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index 03a0a4f849..391e3d590e 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -762,6 +762,22 @@ spring: # This property increases the number of connections in the pool as demand increases. At the same time, the property ensures that the pool doesn't grow to the point of exhausting a system's resources, which ultimately affects an application's performance and availability maximumPoolSize: "${SPRING_DATASOURCE_MAXIMUM_POOL_SIZE:16}" registerMbeans: "${SPRING_DATASOURCE_HIKARI_REGISTER_MBEANS:false}" # true - enable MBean to diagnose pools state via JMX + dedicated: + enabled: "${SPRING_DEDICATED_DATASOURCE_ENABLED:true}" + # Database driver for Spring JPA - org.postgresql.Driver + driverClassName: "${SPRING_DEDICATED_DATASOURCE_DRIVER_CLASS_NAME:org.postgresql.Driver}" + # Database connection URL + url: "${SPRING_DEDICATED_DATASOURCE_URL:jdbc:postgresql://localhost:5432/thingsboard_ce_events}" + # Database user name + username: "${SPRING_DEDICATED_DATASOURCE_USERNAME:postgres}" + # Database user password + password: "${SPRING_DEDICATED_DATASOURCE_PASSWORD:postgres}" + hikari: + # This property controls the amount of time that a connection can be out of the pool before a message is logged indicating a possible connection leak. A value of 0 means leak detection is disabled + leakDetectionThreshold: "${SPRING_DEDICATED_DATASOURCE_HIKARI_LEAK_DETECTION_THRESHOLD:0}" + # This property increases the number of connections in the pool as demand increases. At the same time, the property ensures that the pool doesn't grow to the point of exhausting a system's resources, which ultimately affects an application's performance and availability + maximumPoolSize: "${SPRING_DEDICATED_DATASOURCE_MAXIMUM_POOL_SIZE:16}" + registerMbeans: "${SPRING_DEDICATED_DATASOURCE_HIKARI_REGISTER_MBEANS:false}" # true - enable MBean to diagnose pools state via JMX # Audit log parameters audit-log: diff --git a/dao/src/main/java/org/thingsboard/server/dao/DedicatedJpaDaoConfig.java b/dao/src/main/java/org/thingsboard/server/dao/DedicatedJpaDaoConfig.java new file mode 100644 index 0000000000..259e61c808 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/DedicatedJpaDaoConfig.java @@ -0,0 +1,111 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.dao; + +import com.zaxxer.hikari.HikariDataSource; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.data.repository.config.BootstrapMode; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.transaction.support.TransactionTemplate; +import org.thingsboard.server.dao.model.sql.ErrorEventEntity; +import org.thingsboard.server.dao.model.sql.LifecycleEventEntity; +import org.thingsboard.server.dao.model.sql.RuleChainDebugEventEntity; +import org.thingsboard.server.dao.model.sql.RuleNodeDebugEventEntity; +import org.thingsboard.server.dao.model.sql.StatisticsEventEntity; + +import javax.sql.DataSource; +import java.util.Objects; + +@Configuration +@EnableJpaRepositories(value = "org.thingsboard.server.dao.sql.event", bootstrapMode = BootstrapMode.LAZY, + entityManagerFactoryRef = "dedicatedEntityManagerFactory", transactionManagerRef = "dedicatedTransactionManager") +public class DedicatedJpaDaoConfig { + + @Value("${spring.datasource.dedicated.enabled:false}") + private boolean dedicatedDataSourceEnabled; + + @Bean + @ConfigurationProperties("spring.datasource.dedicated") + public DataSourceProperties dedicatedDataSourceProperties() { + if (dedicatedDataSourceEnabled) { + return new DataSourceProperties(); + } else { + return null; + } + } + + @ConfigurationProperties(prefix = "spring.datasource.dedicated.hikari") + @Bean + public DataSource dedicatedDataSource(@Qualifier("dedicatedDataSourceProperties") DataSourceProperties dedicatedDataSourceProperties) { + if (dedicatedDataSourceEnabled) { + return dedicatedDataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build(); + } else { + return null; + } + } + + @Bean + public LocalContainerEntityManagerFactoryBean dedicatedEntityManagerFactory(@Qualifier("dedicatedDataSource") DataSource dedicatedDataSource, + @Qualifier("dataSource") DataSource defaultDataSource, + EntityManagerFactoryBuilder builder) { + if (dedicatedDataSourceEnabled) { + return builder + .dataSource(dedicatedDataSource) + .packages(LifecycleEventEntity.class, StatisticsEventEntity.class, ErrorEventEntity.class, RuleNodeDebugEventEntity.class, RuleChainDebugEventEntity.class) + .persistenceUnit("dedicated") + .build(); + } else { + return null; + } + } + + @Bean + public JpaTransactionManager dedicatedTransactionManager(@Qualifier("dedicatedEntityManagerFactory") LocalContainerEntityManagerFactoryBean dedicatedEntityManagerFactory) { + if (dedicatedDataSourceEnabled) { + return new JpaTransactionManager(Objects.requireNonNull(dedicatedEntityManagerFactory.getObject())); + } else { + return null; + } + } + + @Bean + public TransactionTemplate dedicatedTransactionTemplate(@Qualifier("dedicatedTransactionManager") JpaTransactionManager dedicatedTransactionManager) { + if (dedicatedDataSourceEnabled) { + return new TransactionTemplate(dedicatedTransactionManager); + } else { + return null; + } + } + + @Bean + public JdbcTemplate dedicatedJdbcTemplate(@Qualifier("dedicatedDataSource") DataSource dedicatedDataSource) { + if (dedicatedDataSourceEnabled) { + return new JdbcTemplate(dedicatedDataSource); + } else { + return null; + } + } + +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/JpaDaoConfig.java b/dao/src/main/java/org/thingsboard/server/dao/JpaDaoConfig.java index 4dd0633420..b4565498ab 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/JpaDaoConfig.java +++ b/dao/src/main/java/org/thingsboard/server/dao/JpaDaoConfig.java @@ -15,23 +15,98 @@ */ package org.thingsboard.server.dao; -import org.springframework.boot.autoconfigure.domain.EntityScan; +import com.zaxxer.hikari.HikariDataSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; +import org.springframework.context.annotation.Primary; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.data.repository.config.BootstrapMode; -import org.springframework.transaction.annotation.EnableTransactionManagement; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.transaction.support.TransactionTemplate; +import org.thingsboard.server.dao.sql.event.EventRepository; import org.thingsboard.server.dao.util.TbAutoConfiguration; -/** - * @author Valerii Sosliuk - */ +import javax.sql.DataSource; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + @Configuration @TbAutoConfiguration -@ComponentScan({"org.thingsboard.server.dao.sql", "org.thingsboard.server.dao.attributes", "org.thingsboard.server.dao.cache", "org.thingsboard.server.cache"}) -@EnableJpaRepositories(value = "org.thingsboard.server.dao.sql", bootstrapMode = BootstrapMode.LAZY) -@EntityScan("org.thingsboard.server.dao.model.sql") -@EnableTransactionManagement +@ComponentScan({"org.thingsboard.server.dao.sql", "org.thingsboard.server.dao.attributes", "org.thingsboard.server.dao.sqlts.dictionary", "org.thingsboard.server.dao.cache", "org.thingsboard.server.cache"}) +@EnableJpaRepositories(value = {"org.thingsboard.server.dao.sql", "org.thingsboard.server.dao.sqlts.dictionary"}, + excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = { + EventRepository.class + }), bootstrapMode = BootstrapMode.LAZY) public class JpaDaoConfig { + @Bean + @ConfigurationProperties("spring.datasource") + public DataSourceProperties dataSourceProperties() { + return new DataSourceProperties(); + } + + @Primary + @ConfigurationProperties(prefix = "spring.datasource.hikari") + @Bean + public DataSource dataSource(@Qualifier("dataSourceProperties") DataSourceProperties dataSourceProperties) { + return dataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build(); + } + + @Primary + @Bean + public LocalContainerEntityManagerFactoryBean entityManagerFactory(@Qualifier("dataSource") DataSource dataSource, + EntityManagerFactoryBuilder builder, + @Autowired(required = false) SqlTsLatestDaoConfig tsLatestDaoConfig, + @Autowired(required = false) SqlTsDaoConfig tsDaoConfig) { + List packages = new ArrayList<>(); + packages.add("org.thingsboard.server.dao.model.sql"); + packages.add("org.thingsboard.server.dao.model.sqlts.dictionary"); + if (tsLatestDaoConfig != null) { + packages.add("org.thingsboard.server.dao.model.sqlts.latest"); + } + if (tsDaoConfig != null) { + packages.add("org.thingsboard.server.dao.model.sqlts.ts"); + } + return builder + .dataSource(dataSource) + .packages(packages.toArray(String[]::new)) + .persistenceUnit("default") + .build(); + } + + @Primary + @Bean + public JpaTransactionManager transactionManager(@Qualifier("entityManagerFactory") LocalContainerEntityManagerFactoryBean entityManagerFactory) { + return new JpaTransactionManager(Objects.requireNonNull(entityManagerFactory.getObject())); + } + + @Primary + @Bean + public TransactionTemplate transactionTemplate(@Qualifier("transactionManager") JpaTransactionManager transactionManager) { + return new TransactionTemplate(transactionManager); + } + + @Primary + @Bean + public JdbcTemplate jdbcTemplate(@Qualifier("dataSource") DataSource dataSource) { + return new JdbcTemplate(dataSource); + } + + @Primary + @Bean + public NamedParameterJdbcTemplate namedParameterJdbcTemplate(@Qualifier("dataSource") DataSource dataSource) { + return new NamedParameterJdbcTemplate(dataSource); + } + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/SqlTimeseriesDaoConfig.java b/dao/src/main/java/org/thingsboard/server/dao/SqlTimeseriesDaoConfig.java deleted file mode 100644 index 09553fb973..0000000000 --- a/dao/src/main/java/org/thingsboard/server/dao/SqlTimeseriesDaoConfig.java +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Copyright © 2016-2024 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.dao; - -import org.springframework.boot.autoconfigure.domain.EntityScan; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.data.jpa.repository.config.EnableJpaRepositories; -import org.springframework.data.repository.config.BootstrapMode; -import org.springframework.transaction.annotation.EnableTransactionManagement; -import org.thingsboard.server.dao.util.TbAutoConfiguration; - -@Configuration -@TbAutoConfiguration -@ComponentScan({"org.thingsboard.server.dao.sqlts.dictionary"}) -@EnableJpaRepositories(value = {"org.thingsboard.server.dao.sqlts.dictionary"}, bootstrapMode = BootstrapMode.LAZY) -@EntityScan({"org.thingsboard.server.dao.model.sqlts.dictionary"}) -@EnableTransactionManagement -public class SqlTimeseriesDaoConfig { - -} diff --git a/dao/src/main/java/org/thingsboard/server/dao/SqlTsDaoConfig.java b/dao/src/main/java/org/thingsboard/server/dao/SqlTsDaoConfig.java index bbd31846db..f073cb8523 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/SqlTsDaoConfig.java +++ b/dao/src/main/java/org/thingsboard/server/dao/SqlTsDaoConfig.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.dao; -import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; @@ -28,7 +27,6 @@ import org.thingsboard.server.dao.util.TbAutoConfiguration; @TbAutoConfiguration @ComponentScan({"org.thingsboard.server.dao.sqlts.sql", "org.thingsboard.server.dao.sqlts.insert.sql"}) @EnableJpaRepositories(value = {"org.thingsboard.server.dao.sqlts.ts", "org.thingsboard.server.dao.sqlts.insert.sql"}, bootstrapMode = BootstrapMode.LAZY) -@EntityScan({"org.thingsboard.server.dao.model.sqlts.ts"}) @EnableTransactionManagement @SqlTsDao public class SqlTsDaoConfig { diff --git a/dao/src/main/java/org/thingsboard/server/dao/SqlTsLatestDaoConfig.java b/dao/src/main/java/org/thingsboard/server/dao/SqlTsLatestDaoConfig.java index 6fcf21a0a8..e54fea48f1 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/SqlTsLatestDaoConfig.java +++ b/dao/src/main/java/org/thingsboard/server/dao/SqlTsLatestDaoConfig.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.dao; -import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; @@ -28,7 +27,6 @@ import org.thingsboard.server.dao.util.TbAutoConfiguration; @TbAutoConfiguration @ComponentScan({"org.thingsboard.server.dao.sqlts.sql"}) @EnableJpaRepositories(value = {"org.thingsboard.server.dao.sqlts.insert.latest.sql", "org.thingsboard.server.dao.sqlts.latest"}, bootstrapMode = BootstrapMode.LAZY) -@EntityScan({"org.thingsboard.server.dao.model.sqlts.latest"}) @EnableTransactionManagement @SqlTsLatestDao public class SqlTsLatestDaoConfig { diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/event/EventInsertRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/event/EventInsertRepository.java index 5c6969fce9..76431d1858 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/event/EventInsertRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/event/EventInsertRepository.java @@ -15,7 +15,9 @@ */ package org.thingsboard.server.dao.sql.event; +import lombok.Getter; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.jdbc.core.BatchPreparedStatementSetter; import org.springframework.jdbc.core.JdbcTemplate; @@ -55,10 +57,13 @@ public class EventInsertRepository { private final Map insertStmtMap = new ConcurrentHashMap<>(); + @Getter @Autowired + @Qualifier("dedicatedJdbcTemplate") protected JdbcTemplate jdbcTemplate; @Autowired + @Qualifier("dedicatedTransactionTemplate") private TransactionTemplate transactionTemplate; @Value("${sql.remove_null_chars:true}") diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDao.java index afd6608774..eac0350143 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDao.java @@ -157,7 +157,7 @@ public class JpaBaseEventDao implements EventDao { } } partitioningRepository.createPartitionIfNotExists(event.getType().getTable(), event.getCreatedTime(), - partitionConfiguration.getPartitionSizeInMs(event.getType())); + partitionConfiguration.getPartitionSizeInMs(event.getType()), eventInsertRepository.getJdbcTemplate()); return queue.add(event); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sqlts/insert/sql/SqlPartitioningRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sqlts/insert/sql/SqlPartitioningRepository.java index 83a7415780..22c6fae7b8 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sqlts/insert/sql/SqlPartitioningRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sqlts/insert/sql/SqlPartitioningRepository.java @@ -49,11 +49,21 @@ public class SqlPartitioningRepository { @Transactional(propagation = Propagation.NOT_SUPPORTED) public void save(SqlPartition partition) { + save(partition, jdbcTemplate); + } + + @Transactional(propagation = Propagation.NOT_SUPPORTED) + public void save(SqlPartition partition, JdbcTemplate jdbcTemplate) { jdbcTemplate.execute(partition.getQuery()); } @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) { + createPartitionIfNotExists(table, entityTs, partitionDurationMs, jdbcTemplate); + } + + @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, JdbcTemplate jdbcTemplate) { long partitionStartTs = calculatePartitionStartTime(entityTs, partitionDurationMs); Map partitions = tablesPartitions.computeIfAbsent(table, t -> new ConcurrentHashMap<>()); if (!partitions.containsKey(partitionStartTs)) { @@ -62,7 +72,7 @@ public class SqlPartitioningRepository { try { if (partitions.containsKey(partitionStartTs)) return; log.info("Saving partition {}-{} for table {}", partition.getStart(), partition.getEnd(), table); - save(partition); + save(partition, jdbcTemplate); log.trace("Adding partition to map: {}", partition); partitions.put(partition.getStart(), partition); } catch (Exception e) { diff --git a/dao/src/test/java/org/thingsboard/server/dao/AbstractDaoServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/AbstractDaoServiceTest.java index efa529cb5e..82790a61b9 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/AbstractDaoServiceTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/AbstractDaoServiceTest.java @@ -28,7 +28,7 @@ import org.thingsboard.server.common.stats.StatsFactory; import org.thingsboard.server.dao.service.DaoSqlTest; @RunWith(SpringRunner.class) -@ContextConfiguration(classes = {JpaDaoConfig.class, SqlTsDaoConfig.class, SqlTsLatestDaoConfig.class, SqlTimeseriesDaoConfig.class}) +@ContextConfiguration(classes = {JpaDaoConfig.class, SqlTsDaoConfig.class, SqlTsLatestDaoConfig.class, DedicatedJpaDaoConfig.class}) @DaoSqlTest @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) @TestExecutionListeners({ diff --git a/dao/src/test/java/org/thingsboard/server/dao/AbstractJpaDaoTest.java b/dao/src/test/java/org/thingsboard/server/dao/AbstractJpaDaoTest.java index 8682aa5968..59a5af044a 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/AbstractJpaDaoTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/AbstractJpaDaoTest.java @@ -30,7 +30,7 @@ import org.thingsboard.server.dao.service.DaoSqlTest; * Created by Valerii Sosliuk on 4/22/2017. */ @RunWith(SpringRunner.class) -@ContextConfiguration(classes = {JpaDaoConfig.class, SqlTsDaoConfig.class, SqlTsLatestDaoConfig.class, SqlTimeseriesDaoConfig.class}) +@ContextConfiguration(classes = {JpaDaoConfig.class, SqlTsDaoConfig.class, SqlTsLatestDaoConfig.class, DedicatedJpaDaoConfig.class}) @DaoSqlTest @TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, From a98ae2c5199be6be26ef2607c975cf3991db5004 Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Wed, 31 Jul 2024 11:56:50 +0300 Subject: [PATCH 02/10] JPA config refactoring --- .../{ => config}/DedicatedJpaDaoConfig.java | 64 +++++++------------ .../config/DefaultDedicatedJpaDaoConfig.java | 27 ++++++++ .../server/dao/{ => config}/JpaDaoConfig.java | 9 +-- .../dao/{ => config}/SqlTsDaoConfig.java | 2 +- .../{ => config}/SqlTsLatestDaoConfig.java | 2 +- .../dao/{ => config}/TimescaleDaoConfig.java | 2 +- .../TimescaleTsLatestDaoConfig.java | 2 +- .../server/dao/sql/audit/JpaAuditLogDao.java | 2 - .../server/dao/AbstractDaoServiceTest.java | 4 ++ .../server/dao/AbstractJpaDaoTest.java | 4 ++ 10 files changed, 67 insertions(+), 51 deletions(-) rename dao/src/main/java/org/thingsboard/server/dao/{ => config}/DedicatedJpaDaoConfig.java (64%) create mode 100644 dao/src/main/java/org/thingsboard/server/dao/config/DefaultDedicatedJpaDaoConfig.java rename dao/src/main/java/org/thingsboard/server/dao/{ => config}/JpaDaoConfig.java (93%) rename dao/src/main/java/org/thingsboard/server/dao/{ => config}/SqlTsDaoConfig.java (97%) rename dao/src/main/java/org/thingsboard/server/dao/{ => config}/SqlTsLatestDaoConfig.java (97%) rename dao/src/main/java/org/thingsboard/server/dao/{ => config}/TimescaleDaoConfig.java (97%) rename dao/src/main/java/org/thingsboard/server/dao/{ => config}/TimescaleTsLatestDaoConfig.java (97%) diff --git a/dao/src/main/java/org/thingsboard/server/dao/DedicatedJpaDaoConfig.java b/dao/src/main/java/org/thingsboard/server/dao/config/DedicatedJpaDaoConfig.java similarity index 64% rename from dao/src/main/java/org/thingsboard/server/dao/DedicatedJpaDaoConfig.java rename to dao/src/main/java/org/thingsboard/server/dao/config/DedicatedJpaDaoConfig.java index 259e61c808..0311066ff6 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/DedicatedJpaDaoConfig.java +++ b/dao/src/main/java/org/thingsboard/server/dao/config/DedicatedJpaDaoConfig.java @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.dao; +package org.thingsboard.server.dao.config; import com.zaxxer.hikari.HikariDataSource; import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder; @@ -29,6 +29,7 @@ import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.transaction.support.TransactionTemplate; +import org.thingsboard.server.dao.model.sql.AuditLogEntity; import org.thingsboard.server.dao.model.sql.ErrorEventEntity; import org.thingsboard.server.dao.model.sql.LifecycleEventEntity; import org.thingsboard.server.dao.model.sql.RuleChainDebugEventEntity; @@ -38,74 +39,55 @@ import org.thingsboard.server.dao.model.sql.StatisticsEventEntity; import javax.sql.DataSource; import java.util.Objects; +/* + * To make entity use a dedicated datasource: + * - add its JpaRepository to exclusions list in @EnableJpaRepositories in JpaDaoConfig + * - add the package of this JpaRepository to @EnableJpaRepositories in DefaultDedicatedJpaDaoConfig + * - add the package of this JpaRepository to @EnableJpaRepositories in DedicatedJpaDaoConfig + * - add the entity class to packages list in dedicatedEntityManagerFactory in DedicatedJpaDaoConfig + * */ +@ConditionalOnProperty(value = "spring.datasource.dedicated.enabled", havingValue = "true") @Configuration -@EnableJpaRepositories(value = "org.thingsboard.server.dao.sql.event", bootstrapMode = BootstrapMode.LAZY, +@EnableJpaRepositories(value = {"org.thingsboard.server.dao.sql.event", "org.thingsboard.server.dao.sql.audit"}, + bootstrapMode = BootstrapMode.LAZY, entityManagerFactoryRef = "dedicatedEntityManagerFactory", transactionManagerRef = "dedicatedTransactionManager") public class DedicatedJpaDaoConfig { - @Value("${spring.datasource.dedicated.enabled:false}") - private boolean dedicatedDataSourceEnabled; - @Bean @ConfigurationProperties("spring.datasource.dedicated") public DataSourceProperties dedicatedDataSourceProperties() { - if (dedicatedDataSourceEnabled) { - return new DataSourceProperties(); - } else { - return null; - } + return new DataSourceProperties(); } @ConfigurationProperties(prefix = "spring.datasource.dedicated.hikari") @Bean public DataSource dedicatedDataSource(@Qualifier("dedicatedDataSourceProperties") DataSourceProperties dedicatedDataSourceProperties) { - if (dedicatedDataSourceEnabled) { - return dedicatedDataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build(); - } else { - return null; - } + return dedicatedDataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build(); } @Bean public LocalContainerEntityManagerFactoryBean dedicatedEntityManagerFactory(@Qualifier("dedicatedDataSource") DataSource dedicatedDataSource, - @Qualifier("dataSource") DataSource defaultDataSource, EntityManagerFactoryBuilder builder) { - if (dedicatedDataSourceEnabled) { - return builder - .dataSource(dedicatedDataSource) - .packages(LifecycleEventEntity.class, StatisticsEventEntity.class, ErrorEventEntity.class, RuleNodeDebugEventEntity.class, RuleChainDebugEventEntity.class) - .persistenceUnit("dedicated") - .build(); - } else { - return null; - } + return builder + .dataSource(dedicatedDataSource) + .packages(LifecycleEventEntity.class, StatisticsEventEntity.class, ErrorEventEntity.class, RuleNodeDebugEventEntity.class, RuleChainDebugEventEntity.class, AuditLogEntity.class) + .persistenceUnit("dedicated") + .build(); } @Bean public JpaTransactionManager dedicatedTransactionManager(@Qualifier("dedicatedEntityManagerFactory") LocalContainerEntityManagerFactoryBean dedicatedEntityManagerFactory) { - if (dedicatedDataSourceEnabled) { - return new JpaTransactionManager(Objects.requireNonNull(dedicatedEntityManagerFactory.getObject())); - } else { - return null; - } + return new JpaTransactionManager(Objects.requireNonNull(dedicatedEntityManagerFactory.getObject())); } @Bean public TransactionTemplate dedicatedTransactionTemplate(@Qualifier("dedicatedTransactionManager") JpaTransactionManager dedicatedTransactionManager) { - if (dedicatedDataSourceEnabled) { - return new TransactionTemplate(dedicatedTransactionManager); - } else { - return null; - } + return new TransactionTemplate(dedicatedTransactionManager); } @Bean public JdbcTemplate dedicatedJdbcTemplate(@Qualifier("dedicatedDataSource") DataSource dedicatedDataSource) { - if (dedicatedDataSourceEnabled) { - return new JdbcTemplate(dedicatedDataSource); - } else { - return null; - } + return new JdbcTemplate(dedicatedDataSource); } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/config/DefaultDedicatedJpaDaoConfig.java b/dao/src/main/java/org/thingsboard/server/dao/config/DefaultDedicatedJpaDaoConfig.java new file mode 100644 index 0000000000..ee159ac53a --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/config/DefaultDedicatedJpaDaoConfig.java @@ -0,0 +1,27 @@ +package org.thingsboard.server.dao.config; + +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.data.repository.config.BootstrapMode; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.transaction.support.TransactionTemplate; + +@ConditionalOnProperty(value = "spring.datasource.dedicated.enabled", havingValue = "false", matchIfMissing = true) +@Configuration +@EnableJpaRepositories(value = {"org.thingsboard.server.dao.sql.event", "org.thingsboard.server.dao.sql.audit"}, bootstrapMode = BootstrapMode.LAZY) +public class DefaultDedicatedJpaDaoConfig { + + @Bean + public JdbcTemplate dedicatedJdbcTemplate(@Qualifier("jdbcTemplate") JdbcTemplate defaultJdbcTemplate) { + return defaultJdbcTemplate; + } + + @Bean + public TransactionTemplate dedicatedTransactionTemplate(@Qualifier("transactionTemplate") TransactionTemplate defaultTransactionTemplate) { + return defaultTransactionTemplate; + } + +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/JpaDaoConfig.java b/dao/src/main/java/org/thingsboard/server/dao/config/JpaDaoConfig.java similarity index 93% rename from dao/src/main/java/org/thingsboard/server/dao/JpaDaoConfig.java rename to dao/src/main/java/org/thingsboard/server/dao/config/JpaDaoConfig.java index b4565498ab..75bd14eaa1 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/JpaDaoConfig.java +++ b/dao/src/main/java/org/thingsboard/server/dao/config/JpaDaoConfig.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.dao; +package org.thingsboard.server.dao.config; import com.zaxxer.hikari.HikariDataSource; import org.springframework.beans.factory.annotation.Autowired; @@ -23,6 +23,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; import org.springframework.context.annotation.Primary; @@ -33,6 +34,7 @@ import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.transaction.support.TransactionTemplate; +import org.thingsboard.server.dao.sql.audit.AuditLogRepository; import org.thingsboard.server.dao.sql.event.EventRepository; import org.thingsboard.server.dao.util.TbAutoConfiguration; @@ -45,9 +47,8 @@ import java.util.Objects; @TbAutoConfiguration @ComponentScan({"org.thingsboard.server.dao.sql", "org.thingsboard.server.dao.attributes", "org.thingsboard.server.dao.sqlts.dictionary", "org.thingsboard.server.dao.cache", "org.thingsboard.server.cache"}) @EnableJpaRepositories(value = {"org.thingsboard.server.dao.sql", "org.thingsboard.server.dao.sqlts.dictionary"}, - excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = { - EventRepository.class - }), bootstrapMode = BootstrapMode.LAZY) + excludeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {EventRepository.class, AuditLogRepository.class}), + bootstrapMode = BootstrapMode.LAZY) public class JpaDaoConfig { @Bean diff --git a/dao/src/main/java/org/thingsboard/server/dao/SqlTsDaoConfig.java b/dao/src/main/java/org/thingsboard/server/dao/config/SqlTsDaoConfig.java similarity index 97% rename from dao/src/main/java/org/thingsboard/server/dao/SqlTsDaoConfig.java rename to dao/src/main/java/org/thingsboard/server/dao/config/SqlTsDaoConfig.java index f073cb8523..478dbde5d1 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/SqlTsDaoConfig.java +++ b/dao/src/main/java/org/thingsboard/server/dao/config/SqlTsDaoConfig.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.dao; +package org.thingsboard.server.dao.config; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; diff --git a/dao/src/main/java/org/thingsboard/server/dao/SqlTsLatestDaoConfig.java b/dao/src/main/java/org/thingsboard/server/dao/config/SqlTsLatestDaoConfig.java similarity index 97% rename from dao/src/main/java/org/thingsboard/server/dao/SqlTsLatestDaoConfig.java rename to dao/src/main/java/org/thingsboard/server/dao/config/SqlTsLatestDaoConfig.java index e54fea48f1..49ff2afdb4 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/SqlTsLatestDaoConfig.java +++ b/dao/src/main/java/org/thingsboard/server/dao/config/SqlTsLatestDaoConfig.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.dao; +package org.thingsboard.server.dao.config; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; diff --git a/dao/src/main/java/org/thingsboard/server/dao/TimescaleDaoConfig.java b/dao/src/main/java/org/thingsboard/server/dao/config/TimescaleDaoConfig.java similarity index 97% rename from dao/src/main/java/org/thingsboard/server/dao/TimescaleDaoConfig.java rename to dao/src/main/java/org/thingsboard/server/dao/config/TimescaleDaoConfig.java index c134b88897..05a84ca1cc 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/TimescaleDaoConfig.java +++ b/dao/src/main/java/org/thingsboard/server/dao/config/TimescaleDaoConfig.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.dao; +package org.thingsboard.server.dao.config; import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.context.annotation.ComponentScan; diff --git a/dao/src/main/java/org/thingsboard/server/dao/TimescaleTsLatestDaoConfig.java b/dao/src/main/java/org/thingsboard/server/dao/config/TimescaleTsLatestDaoConfig.java similarity index 97% rename from dao/src/main/java/org/thingsboard/server/dao/TimescaleTsLatestDaoConfig.java rename to dao/src/main/java/org/thingsboard/server/dao/config/TimescaleTsLatestDaoConfig.java index f0e74f1c3d..74d0cc7ae3 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/TimescaleTsLatestDaoConfig.java +++ b/dao/src/main/java/org/thingsboard/server/dao/config/TimescaleTsLatestDaoConfig.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.dao; +package org.thingsboard.server.dao.config; import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.context.annotation.ComponentScan; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/audit/JpaAuditLogDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/audit/JpaAuditLogDao.java index f73cb95c27..0c152cbc27 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/audit/JpaAuditLogDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/audit/JpaAuditLogDao.java @@ -19,7 +19,6 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.audit.AuditLog; @@ -48,7 +47,6 @@ public class JpaAuditLogDao extends JpaPartitionedAbstractDao Date: Tue, 6 Aug 2024 13:12:51 +0300 Subject: [PATCH 03/10] Dedicated datasource: improvements and refactoring --- .../src/main/resources/thingsboard.yml | 4 +- .../controller/AuditLogControllerTest.java | 6 +- ...LogControllerTest_DedicatedDataSource.java | 28 +++++++ .../server/dao/audit/AuditLogDao.java | 1 - .../server/dao/audit/AuditLogServiceImpl.java | 8 +- .../dao/config/DedicatedJpaDaoConfig.java | 15 ++-- .../config/DefaultDedicatedJpaDaoConfig.java | 29 +++++++- .../server/dao/event/EventDao.java | 1 - .../server/dao/model/sql/AuditLogEntity.java | 1 + .../server/dao/sql/JpaAbstractDao.java | 14 ++-- .../dao/sql/JpaPartitionedAbstractDao.java | 8 +- .../server/dao/sql/audit/JpaAuditLogDao.java | 74 ++++++++++++++++--- .../dao/sql/event/EventCleanupRepository.java | 1 - .../dao/sql/event/EventInsertRepository.java | 9 ++- .../server/dao/sql/event/JpaBaseEventDao.java | 55 ++++---------- .../sql/event/SqlEventCleanupRepository.java | 64 ++-------------- .../DedicatedSqlPartitioningRepository.java | 53 +++++++++++++ .../insert/sql/SqlPartitioningRepository.java | 28 +++---- .../server/dao/PostgreSqlInitializer.java | 11 +++ ...entServiceSqlTest_DedicatedDataSource.java | 28 +++++++ 20 files changed, 284 insertions(+), 154 deletions(-) create mode 100644 application/src/test/java/org/thingsboard/server/controller/AuditLogControllerTest_DedicatedDataSource.java create mode 100644 dao/src/main/java/org/thingsboard/server/dao/sqlts/insert/sql/DedicatedSqlPartitioningRepository.java create mode 100644 dao/src/test/java/org/thingsboard/server/dao/service/event/sql/EventServiceSqlTest_DedicatedDataSource.java diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index 391e3d590e..0e094d0299 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -763,11 +763,11 @@ spring: maximumPoolSize: "${SPRING_DATASOURCE_MAXIMUM_POOL_SIZE:16}" registerMbeans: "${SPRING_DATASOURCE_HIKARI_REGISTER_MBEANS:false}" # true - enable MBean to diagnose pools state via JMX dedicated: - enabled: "${SPRING_DEDICATED_DATASOURCE_ENABLED:true}" + enabled: "${SPRING_DEDICATED_DATASOURCE_ENABLED:false}" # Database driver for Spring JPA - org.postgresql.Driver driverClassName: "${SPRING_DEDICATED_DATASOURCE_DRIVER_CLASS_NAME:org.postgresql.Driver}" # Database connection URL - url: "${SPRING_DEDICATED_DATASOURCE_URL:jdbc:postgresql://localhost:5432/thingsboard_ce_events}" + url: "${SPRING_DEDICATED_DATASOURCE_URL:jdbc:postgresql://localhost:5432/thingsboard_dedicated}" # Database user name username: "${SPRING_DEDICATED_DATASOURCE_USERNAME:postgres}" # Database user password diff --git a/application/src/test/java/org/thingsboard/server/controller/AuditLogControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/AuditLogControllerTest.java index 5005e6ad34..998d4587a4 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AuditLogControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AuditLogControllerTest.java @@ -38,7 +38,7 @@ import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.dao.audit.AuditLogDao; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.service.DaoSqlTest; -import org.thingsboard.server.dao.sqlts.insert.sql.SqlPartitioningRepository; +import org.thingsboard.server.dao.sqlts.insert.sql.DedicatedSqlPartitioningRepository; import org.thingsboard.server.service.ttl.AuditLogsCleanUpService; import java.text.ParseException; @@ -65,7 +65,7 @@ public class AuditLogControllerTest extends AbstractControllerTest { @Autowired private AuditLogDao auditLogDao; @SpyBean - private SqlPartitioningRepository partitioningRepository; + private DedicatedSqlPartitioningRepository partitioningRepository; @SpyBean private AuditLogsCleanUpService auditLogsCleanUpService; @@ -229,7 +229,7 @@ public class AuditLogControllerTest extends AbstractControllerTest { createAuditLog(ActionType.LOGIN, tenantAdminUserId, entityTs); }); assertThat(partitioningRepository.fetchPartitions("audit_log")) - .contains(ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-04-28T00:00:00Z").getTime());; + .contains(ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-04-28T00:00:00Z").getTime()); } private AuditLog createAuditLog(ActionType actionType, EntityId entityId, long entityTs) { diff --git a/application/src/test/java/org/thingsboard/server/controller/AuditLogControllerTest_DedicatedDataSource.java b/application/src/test/java/org/thingsboard/server/controller/AuditLogControllerTest_DedicatedDataSource.java new file mode 100644 index 0000000000..b642322ea4 --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/controller/AuditLogControllerTest_DedicatedDataSource.java @@ -0,0 +1,28 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.controller; + +import org.springframework.test.context.TestPropertySource; +import org.thingsboard.server.dao.service.DaoSqlTest; + +@DaoSqlTest +@TestPropertySource(properties = { + "spring.datasource.dedicated.enabled=true", + "spring.datasource.dedicated.url=${spring.datasource.url}", + "spring.datasource.dedicated.driverClassName=${spring.datasource.driverClassName}", +}) +public class AuditLogControllerTest_DedicatedDataSource extends AuditLogControllerTest { +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogDao.java b/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogDao.java index ad5a4ba686..82712c8a2c 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogDao.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.dao.audit; -import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.audit.AuditLog; import org.thingsboard.server.common.data.id.CustomerId; diff --git a/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java index 29b097bfab..c5ff7132cb 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java @@ -408,8 +408,12 @@ public class AuditLogServiceImpl implements AuditLogService { } return executor.submit(() -> { - AuditLog auditLog = auditLogDao.save(tenantId, auditLogEntry); - auditLogSink.logAction(auditLog); + try { + AuditLog auditLog = auditLogDao.save(tenantId, auditLogEntry); + auditLogSink.logAction(auditLog); + } catch (Throwable e) { + log.error("[{}] Failed to save audit log: {}", tenantId, auditLogEntry, e); + } return null; }); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/config/DedicatedJpaDaoConfig.java b/dao/src/main/java/org/thingsboard/server/dao/config/DedicatedJpaDaoConfig.java index 0311066ff6..2c47cfbc5b 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/config/DedicatedJpaDaoConfig.java +++ b/dao/src/main/java/org/thingsboard/server/dao/config/DedicatedJpaDaoConfig.java @@ -53,6 +53,11 @@ import java.util.Objects; entityManagerFactoryRef = "dedicatedEntityManagerFactory", transactionManagerRef = "dedicatedTransactionManager") public class DedicatedJpaDaoConfig { + public static final String DEDICATED_PERSISTENCE_UNIT = "dedicated"; + public static final String DEDICATED_TRANSACTION_MANAGER = DEDICATED_PERSISTENCE_UNIT + "TransactionManager"; + public static final String DEDICATED_TRANSACTION_TEMPLATE = DEDICATED_PERSISTENCE_UNIT + "TransactionTemplate"; + public static final String DEDICATED_JDBC_TEMPLATE = DEDICATED_PERSISTENCE_UNIT + "JdbcTemplate"; + @Bean @ConfigurationProperties("spring.datasource.dedicated") public DataSourceProperties dedicatedDataSourceProperties() { @@ -71,21 +76,21 @@ public class DedicatedJpaDaoConfig { return builder .dataSource(dedicatedDataSource) .packages(LifecycleEventEntity.class, StatisticsEventEntity.class, ErrorEventEntity.class, RuleNodeDebugEventEntity.class, RuleChainDebugEventEntity.class, AuditLogEntity.class) - .persistenceUnit("dedicated") + .persistenceUnit(DEDICATED_PERSISTENCE_UNIT) .build(); } - @Bean + @Bean(DEDICATED_TRANSACTION_MANAGER) public JpaTransactionManager dedicatedTransactionManager(@Qualifier("dedicatedEntityManagerFactory") LocalContainerEntityManagerFactoryBean dedicatedEntityManagerFactory) { return new JpaTransactionManager(Objects.requireNonNull(dedicatedEntityManagerFactory.getObject())); } - @Bean - public TransactionTemplate dedicatedTransactionTemplate(@Qualifier("dedicatedTransactionManager") JpaTransactionManager dedicatedTransactionManager) { + @Bean(DEDICATED_TRANSACTION_TEMPLATE) + public TransactionTemplate dedicatedTransactionTemplate(@Qualifier(DEDICATED_TRANSACTION_MANAGER) JpaTransactionManager dedicatedTransactionManager) { return new TransactionTemplate(dedicatedTransactionManager); } - @Bean + @Bean(DEDICATED_JDBC_TEMPLATE) public JdbcTemplate dedicatedJdbcTemplate(@Qualifier("dedicatedDataSource") DataSource dedicatedDataSource) { return new JdbcTemplate(dedicatedDataSource); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/config/DefaultDedicatedJpaDaoConfig.java b/dao/src/main/java/org/thingsboard/server/dao/config/DefaultDedicatedJpaDaoConfig.java index ee159ac53a..2cd68f34b5 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/config/DefaultDedicatedJpaDaoConfig.java +++ b/dao/src/main/java/org/thingsboard/server/dao/config/DefaultDedicatedJpaDaoConfig.java @@ -1,3 +1,18 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.thingsboard.server.dao.config; import org.springframework.beans.factory.annotation.Qualifier; @@ -7,19 +22,29 @@ import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.data.repository.config.BootstrapMode; import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.transaction.support.TransactionTemplate; +import static org.thingsboard.server.dao.config.DedicatedJpaDaoConfig.DEDICATED_JDBC_TEMPLATE; +import static org.thingsboard.server.dao.config.DedicatedJpaDaoConfig.DEDICATED_TRANSACTION_MANAGER; +import static org.thingsboard.server.dao.config.DedicatedJpaDaoConfig.DEDICATED_TRANSACTION_TEMPLATE; + @ConditionalOnProperty(value = "spring.datasource.dedicated.enabled", havingValue = "false", matchIfMissing = true) @Configuration @EnableJpaRepositories(value = {"org.thingsboard.server.dao.sql.event", "org.thingsboard.server.dao.sql.audit"}, bootstrapMode = BootstrapMode.LAZY) public class DefaultDedicatedJpaDaoConfig { - @Bean + @Bean(DEDICATED_JDBC_TEMPLATE) public JdbcTemplate dedicatedJdbcTemplate(@Qualifier("jdbcTemplate") JdbcTemplate defaultJdbcTemplate) { return defaultJdbcTemplate; } - @Bean + @Bean(DEDICATED_TRANSACTION_MANAGER) + public JpaTransactionManager dedicatedTransactionManager(@Qualifier("transactionManager") JpaTransactionManager defaultTransactionManager) { + return defaultTransactionManager; + } + + @Bean(DEDICATED_TRANSACTION_TEMPLATE) public TransactionTemplate dedicatedTransactionTemplate(@Qualifier("transactionTemplate") TransactionTemplate defaultTransactionTemplate) { return defaultTransactionTemplate; } diff --git a/dao/src/main/java/org/thingsboard/server/dao/event/EventDao.java b/dao/src/main/java/org/thingsboard/server/dao/event/EventDao.java index 6b3febf502..52335d87ec 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/event/EventDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/event/EventDao.java @@ -101,5 +101,4 @@ public interface EventDao { */ void removeEvents(UUID tenantId, UUID entityId, EventFilter eventFilter, Long startTime, Long endTime); - void migrateEvents(long regularEventTs, long debugEventTs); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AuditLogEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AuditLogEntity.java index 1e878e9dc5..85e697bb2b 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AuditLogEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AuditLogEntity.java @@ -149,4 +149,5 @@ public class AuditLogEntity extends BaseSqlEntity implements BaseEntit auditLog.setActionFailureDetails(this.actionFailureDetails); return auditLog; } + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractDao.java index 973cb4b5b2..cfd5415bca 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractDao.java @@ -47,10 +47,6 @@ public abstract class JpaAbstractDao, D> @Autowired protected JdbcTemplate jdbcTemplate; - protected abstract Class getEntityClass(); - - protected abstract JpaRepository getRepository(); - @Override @Transactional public D save(TenantId tenantId, D domain) { @@ -141,11 +137,19 @@ public abstract class JpaAbstractDao, D> } query += " ORDER BY id LIMIT ?"; - return jdbcTemplate.queryForList(query, UUID.class, params); + return getJdbcTemplate().queryForList(query, UUID.class, params); } protected String getTenantIdColumn() { return ModelConstants.TENANT_ID_COLUMN; } + protected JdbcTemplate getJdbcTemplate() { + return jdbcTemplate; + } + + protected abstract Class getEntityClass(); + + protected abstract JpaRepository getRepository(); + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/JpaPartitionedAbstractDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/JpaPartitionedAbstractDao.java index 45438a9b51..d80e2ecee4 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/JpaPartitionedAbstractDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/JpaPartitionedAbstractDao.java @@ -31,13 +31,17 @@ public abstract class JpaPartitionedAbstractDao, D> exte protected E doSave(E entity, boolean isNew) { createPartition(entity); if (isNew) { - entityManager.persist(entity); + getEntityManager().persist(entity); } else { - entity = entityManager.merge(entity); + entity = getEntityManager().merge(entity); } return entity; } public abstract void createPartition(E entity); + protected EntityManager getEntityManager() { + return entityManager; + } + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/audit/JpaAuditLogDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/audit/JpaAuditLogDao.java index 0c152cbc27..a7eaebf50c 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/audit/JpaAuditLogDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/audit/JpaAuditLogDao.java @@ -15,30 +15,42 @@ */ package org.thingsboard.server.dao.sql.audit; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.audit.AuditLog; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.TimePageLink; import org.thingsboard.server.dao.DaoUtil; import org.thingsboard.server.dao.audit.AuditLogDao; -import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.model.sql.AuditLogEntity; import org.thingsboard.server.dao.sql.JpaPartitionedAbstractDao; -import org.thingsboard.server.dao.sqlts.insert.sql.SqlPartitioningRepository; +import org.thingsboard.server.dao.sqlts.insert.sql.DedicatedSqlPartitioningRepository; import org.thingsboard.server.dao.util.SqlDao; +import java.util.Collection; import java.util.List; import java.util.UUID; import java.util.concurrent.TimeUnit; +import static org.thingsboard.server.dao.config.DedicatedJpaDaoConfig.DEDICATED_JDBC_TEMPLATE; +import static org.thingsboard.server.dao.config.DedicatedJpaDaoConfig.DEDICATED_PERSISTENCE_UNIT; +import static org.thingsboard.server.dao.config.DedicatedJpaDaoConfig.DEDICATED_TRANSACTION_MANAGER; +import static org.thingsboard.server.dao.model.ModelConstants.AUDIT_LOG_TABLE_NAME; + @Component @SqlDao @RequiredArgsConstructor @@ -46,23 +58,38 @@ import java.util.concurrent.TimeUnit; public class JpaAuditLogDao extends JpaPartitionedAbstractDao implements AuditLogDao { private final AuditLogRepository auditLogRepository; - private final SqlPartitioningRepository partitioningRepository; + private final DedicatedSqlPartitioningRepository partitioningRepository; + @Autowired + @Qualifier(DEDICATED_JDBC_TEMPLATE) + private JdbcTemplate jdbcTemplate; + @PersistenceContext(unitName = DEDICATED_PERSISTENCE_UNIT) + private EntityManager entityManager; @Value("${sql.audit_logs.partition_size:168}") private int partitionSizeInHours; - @Value("${sql.ttl.audit_logs.ttl:0}") - private long ttlInSec; - private static final String TABLE_NAME = ModelConstants.AUDIT_LOG_TABLE_NAME; + @Transactional(transactionManager = DEDICATED_TRANSACTION_MANAGER) + @Override + public AuditLog save(TenantId tenantId, AuditLog domain) { + return super.save(tenantId, domain); + } + @Transactional(transactionManager = DEDICATED_TRANSACTION_MANAGER) @Override - protected Class getEntityClass() { - return AuditLogEntity.class; + public AuditLog saveAndFlush(TenantId tenantId, AuditLog domain) { + return super.saveAndFlush(tenantId, domain); } + @Transactional(transactionManager = DEDICATED_TRANSACTION_MANAGER) @Override - protected JpaRepository getRepository() { - return auditLogRepository; + public boolean removeById(TenantId tenantId, UUID id) { + return super.removeById(tenantId, id); + } + + @Transactional(transactionManager = DEDICATED_TRANSACTION_MANAGER) + @Override + public void removeAllByIds(Collection ids) { + super.removeAllByIds(ids); } @Override @@ -122,12 +149,35 @@ public class JpaAuditLogDao extends JpaPartitionedAbstractDao getEntityClass() { + return AuditLogEntity.class; + } + + @Override + protected JpaRepository getRepository() { + return auditLogRepository; } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/event/EventCleanupRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/event/EventCleanupRepository.java index 3b9aa3d5c1..0282e8ea3b 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/event/EventCleanupRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/event/EventCleanupRepository.java @@ -19,5 +19,4 @@ public interface EventCleanupRepository { void cleanupEvents(long eventExpTime, boolean debug); - void migrateEvents(long regularEventTs, long debugEventTs); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/event/EventInsertRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/event/EventInsertRepository.java index 76431d1858..f97ac99198 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/event/EventInsertRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/event/EventInsertRepository.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.dao.sql.event; +import jakarta.annotation.PostConstruct; import lombok.Getter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @@ -35,7 +36,6 @@ import org.thingsboard.server.common.data.event.RuleNodeDebugEvent; import org.thingsboard.server.common.data.event.StatisticsEvent; import org.thingsboard.server.dao.util.SqlDao; -import jakarta.annotation.PostConstruct; import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.Types; @@ -46,6 +46,9 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Pattern; import java.util.stream.Collectors; +import static org.thingsboard.server.dao.config.DedicatedJpaDaoConfig.DEDICATED_JDBC_TEMPLATE; +import static org.thingsboard.server.dao.config.DedicatedJpaDaoConfig.DEDICATED_TRANSACTION_TEMPLATE; + @Repository @Transactional @SqlDao @@ -59,11 +62,11 @@ public class EventInsertRepository { @Getter @Autowired - @Qualifier("dedicatedJdbcTemplate") + @Qualifier(DEDICATED_JDBC_TEMPLATE) protected JdbcTemplate jdbcTemplate; @Autowired - @Qualifier("dedicatedTransactionTemplate") + @Qualifier(DEDICATED_TRANSACTION_TEMPLATE) private TransactionTemplate transactionTemplate; @Value("${sql.remove_null_chars:true}") diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDao.java index eac0350143..85898acd18 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDao.java @@ -19,8 +19,8 @@ import com.datastax.oss.driver.api.core.uuid.Uuids; import com.google.common.util.concurrent.ListenableFuture; import jakarta.annotation.PostConstruct; import jakarta.annotation.PreDestroy; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.StringUtils; @@ -43,7 +43,7 @@ import org.thingsboard.server.dao.model.sql.EventEntity; import org.thingsboard.server.dao.sql.ScheduledLogExecutorComponent; import org.thingsboard.server.dao.sql.TbSqlBlockingQueueParams; import org.thingsboard.server.dao.sql.TbSqlBlockingQueueWrapper; -import org.thingsboard.server.dao.sqlts.insert.sql.SqlPartitioningRepository; +import org.thingsboard.server.dao.sqlts.insert.sql.DedicatedSqlPartitioningRepository; import org.thingsboard.server.dao.util.SqlDao; import java.util.Comparator; @@ -60,40 +60,20 @@ import java.util.function.Function; @Slf4j @Component @SqlDao +@RequiredArgsConstructor public class JpaBaseEventDao implements EventDao { - @Autowired - private EventPartitionConfiguration partitionConfiguration; - - @Autowired - private SqlPartitioningRepository partitioningRepository; - - @Autowired - private LifecycleEventRepository lcEventRepository; - - @Autowired - private StatisticsEventRepository statsEventRepository; - - @Autowired - private ErrorEventRepository errorEventRepository; - - @Autowired - private EventInsertRepository eventInsertRepository; - - @Autowired - private EventCleanupRepository eventCleanupRepository; - - @Autowired - private RuleNodeDebugEventRepository ruleNodeDebugEventRepository; - - @Autowired - private RuleChainDebugEventRepository ruleChainDebugEventRepository; - - @Autowired - ScheduledLogExecutorComponent logExecutor; - - @Autowired - private StatsFactory statsFactory; + private final EventPartitionConfiguration partitionConfiguration; + private final DedicatedSqlPartitioningRepository partitioningRepository; + private final LifecycleEventRepository lcEventRepository; + private final StatisticsEventRepository statsEventRepository; + private final ErrorEventRepository errorEventRepository; + private final EventInsertRepository eventInsertRepository; + private final EventCleanupRepository eventCleanupRepository; + private final RuleNodeDebugEventRepository ruleNodeDebugEventRepository; + private final RuleChainDebugEventRepository ruleChainDebugEventRepository; + private final ScheduledLogExecutorComponent logExecutor; + private final StatsFactory statsFactory; @Value("${sql.events.batch_size:10000}") private int batchSize; @@ -157,7 +137,7 @@ public class JpaBaseEventDao implements EventDao { } } partitioningRepository.createPartitionIfNotExists(event.getType().getTable(), event.getCreatedTime(), - partitionConfiguration.getPartitionSizeInMs(event.getType()), eventInsertRepository.getJdbcTemplate()); + partitionConfiguration.getPartitionSizeInMs(event.getType())); return queue.add(event); } @@ -223,11 +203,6 @@ public class JpaBaseEventDao implements EventDao { } } - @Override - public void migrateEvents(long regularEventTs, long debugEventTs) { - eventCleanupRepository.migrateEvents(regularEventTs, debugEventTs); - } - private PageData findEventByFilter(UUID tenantId, UUID entityId, RuleChainDebugEventFilter eventFilter, TimePageLink pageLink) { return DaoUtil.toPageData( ruleChainDebugEventRepository.findEvents( diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/event/SqlEventCleanupRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/event/SqlEventCleanupRepository.java index d1e8aa380f..36efd9ddb9 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/event/SqlEventCleanupRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/event/SqlEventCleanupRepository.java @@ -15,25 +15,21 @@ */ package org.thingsboard.server.dao.sql.event; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.dao.DataAccessException; import org.springframework.stereotype.Repository; import org.thingsboard.server.common.data.event.EventType; import org.thingsboard.server.dao.sql.JpaAbstractDaoListeningExecutorService; -import org.thingsboard.server.dao.sqlts.insert.sql.SqlPartitioningRepository; - -import java.util.concurrent.TimeUnit; +import org.thingsboard.server.dao.sqlts.insert.sql.DedicatedSqlPartitioningRepository; @Slf4j @Repository +@RequiredArgsConstructor public class SqlEventCleanupRepository extends JpaAbstractDaoListeningExecutorService implements EventCleanupRepository { - @Autowired - private EventPartitionConfiguration partitionConfiguration; - @Autowired - private SqlPartitioningRepository partitioningRepository; + private final EventPartitionConfiguration partitionConfiguration; + private final DedicatedSqlPartitioningRepository partitioningRepository; @Override public void cleanupEvents(long eventExpTime, boolean debug) { @@ -44,56 +40,6 @@ public class SqlEventCleanupRepository extends JpaAbstractDaoListeningExecutorSe } } - @Override - public void migrateEvents(long regularEventTs, long debugEventTs) { - regularEventTs = Math.max(regularEventTs, 1480982400000L); - debugEventTs = Math.max(debugEventTs, 1480982400000L); - - callMigrateFunctionByPartitions("regular", "migrate_regular_events", regularEventTs, partitionConfiguration.getRegularPartitionSizeInHours()); - callMigrateFunctionByPartitions("debug", "migrate_debug_events", debugEventTs, partitionConfiguration.getDebugPartitionSizeInHours()); - - try { - jdbcTemplate.execute("DROP PROCEDURE IF EXISTS migrate_regular_events(bigint, bigint, int)"); - jdbcTemplate.execute("DROP PROCEDURE IF EXISTS migrate_debug_events(bigint, bigint, int)"); - jdbcTemplate.execute("DROP TABLE IF EXISTS event"); - } catch (DataAccessException e) { - log.error("Error occurred during drop of the `events` table", e); - throw e; - } - } - - private void callMigrateFunctionByPartitions(String logTag, String functionName, long startTs, int partitionSizeInHours) { - long currentTs = System.currentTimeMillis(); - var regularPartitionStepInMs = TimeUnit.HOURS.toMillis(partitionSizeInHours); - long numberOfPartitions = (currentTs - startTs) / regularPartitionStepInMs; - if (numberOfPartitions > 1000) { - log.error("Please adjust your {} events partitioning configuration. " + - "Configuration with partition size of {} hours and corresponding TTL will use {} (>1000) partitions which is not recommended!", - logTag, partitionSizeInHours, numberOfPartitions); - throw new RuntimeException("Please adjust your " + logTag + " events partitioning configuration. " + - "Configuration with partition size of " + partitionSizeInHours + " hours and corresponding TTL will use " + - +numberOfPartitions + " (>1000) partitions which is not recommended!"); - } - while (startTs < currentTs) { - var endTs = startTs + regularPartitionStepInMs; - log.info("Migrate {} events for time period: [{},{}]", logTag, startTs, endTs); - callMigrateFunction(functionName, startTs, startTs + regularPartitionStepInMs, partitionSizeInHours); - startTs = endTs; - } - log.info("Migrate {} events done.", logTag); - } - - private void callMigrateFunction(String functionName, long startTs, long endTs, int partitionSizeInHours) { - try { - jdbcTemplate.update("CALL " + functionName + "(?, ?, ?)", startTs, endTs, partitionSizeInHours); - } catch (DataAccessException e) { - if (e.getMessage() == null || !e.getMessage().contains("relation \"event\" does not exist")) { - log.error("[{}] SQLException occurred during execution of {} with parameters {} and {}", functionName, startTs, partitionSizeInHours, e); - throw new RuntimeException(e); - } - } - } - private void cleanupEvents(EventType eventType, long eventExpTime) { partitioningRepository.dropPartitionsBefore(eventType.getTable(), eventExpTime, partitionConfiguration.getPartitionSizeInMs(eventType)); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sqlts/insert/sql/DedicatedSqlPartitioningRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sqlts/insert/sql/DedicatedSqlPartitioningRepository.java new file mode 100644 index 0000000000..efcec2e2e4 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/sqlts/insert/sql/DedicatedSqlPartitioningRepository.java @@ -0,0 +1,53 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.dao.sqlts.insert.sql; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +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 static org.thingsboard.server.dao.config.DedicatedJpaDaoConfig.DEDICATED_JDBC_TEMPLATE; +import static org.thingsboard.server.dao.config.DedicatedJpaDaoConfig.DEDICATED_TRANSACTION_MANAGER; + +@Repository +public class DedicatedSqlPartitioningRepository extends SqlPartitioningRepository { + + @Autowired + @Qualifier(DEDICATED_JDBC_TEMPLATE) + private JdbcTemplate jdbcTemplate; + + @Transactional(propagation = Propagation.NOT_SUPPORTED, transactionManager = DEDICATED_TRANSACTION_MANAGER) + @Override + public void save(SqlPartition partition) { + super.save(partition); + } + + @Transactional(propagation = Propagation.NOT_SUPPORTED, transactionManager = DEDICATED_TRANSACTION_MANAGER) + @Override + public void createPartitionIfNotExists(String table, long entityTs, long partitionDurationMs) { + super.createPartitionIfNotExists(table, entityTs, partitionDurationMs); + } + + @Override + protected JdbcTemplate getJdbcTemplate() { + return jdbcTemplate; + } + +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/sqlts/insert/sql/SqlPartitioningRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sqlts/insert/sql/SqlPartitioningRepository.java index 22c6fae7b8..0f3922e070 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sqlts/insert/sql/SqlPartitioningRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sqlts/insert/sql/SqlPartitioningRepository.java @@ -19,6 +19,7 @@ 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.context.annotation.Primary; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; @@ -32,6 +33,7 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.ReentrantLock; +@Primary @Repository @Slf4j public class SqlPartitioningRepository { @@ -49,21 +51,11 @@ public class SqlPartitioningRepository { @Transactional(propagation = Propagation.NOT_SUPPORTED) public void save(SqlPartition partition) { - save(partition, jdbcTemplate); - } - - @Transactional(propagation = Propagation.NOT_SUPPORTED) - public void save(SqlPartition partition, JdbcTemplate jdbcTemplate) { - jdbcTemplate.execute(partition.getQuery()); + getJdbcTemplate().execute(partition.getQuery()); } @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) { - createPartitionIfNotExists(table, entityTs, partitionDurationMs, jdbcTemplate); - } - - @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, JdbcTemplate jdbcTemplate) { long partitionStartTs = calculatePartitionStartTime(entityTs, partitionDurationMs); Map partitions = tablesPartitions.computeIfAbsent(table, t -> new ConcurrentHashMap<>()); if (!partitions.containsKey(partitionStartTs)) { @@ -72,7 +64,7 @@ public class SqlPartitioningRepository { try { if (partitions.containsKey(partitionStartTs)) return; log.info("Saving partition {}-{} for table {}", partition.getStart(), partition.getEnd(), table); - save(partition, jdbcTemplate); + save(partition); log.trace("Adding partition to map: {}", partition); partitions.put(partition.getStart(), partition); } catch (Exception e) { @@ -129,8 +121,8 @@ public class SqlPartitioningRepository { String dropStmtStr = "DROP TABLE " + tablePartition; try { - jdbcTemplate.execute(detachPsqlStmtStr); - jdbcTemplate.execute(dropStmtStr); + getJdbcTemplate().execute(detachPsqlStmtStr); + getJdbcTemplate().execute(dropStmtStr); return true; } catch (DataAccessException e) { log.error("[{}] Error occurred trying to detach and drop the partition {} ", table, partitionTs, e); @@ -144,7 +136,7 @@ public class SqlPartitioningRepository { public List fetchPartitions(String table) { List partitions = new ArrayList<>(); - List partitionsTables = jdbcTemplate.queryForList(SELECT_PARTITIONS_STMT, String.class, table); + List partitionsTables = getJdbcTemplate().queryForList(SELECT_PARTITIONS_STMT, String.class, table); for (String partitionTableName : partitionsTables) { String partitionTsStr = partitionTableName.substring(table.length() + 1); try { @@ -163,7 +155,7 @@ public class SqlPartitioningRepository { private synchronized int getCurrentServerVersion() { if (currentServerVersion == null) { try { - currentServerVersion = jdbcTemplate.queryForObject("SELECT current_setting('server_version_num')", Integer.class); + currentServerVersion = getJdbcTemplate().queryForObject("SELECT current_setting('server_version_num')", Integer.class); } catch (Exception e) { log.warn("Error occurred during fetch of the server version", e); } @@ -174,4 +166,8 @@ public class SqlPartitioningRepository { return currentServerVersion; } + protected JdbcTemplate getJdbcTemplate() { + return jdbcTemplate; + } + } diff --git a/dao/src/test/java/org/thingsboard/server/dao/PostgreSqlInitializer.java b/dao/src/test/java/org/thingsboard/server/dao/PostgreSqlInitializer.java index 4feef028d4..82e8249286 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/PostgreSqlInitializer.java +++ b/dao/src/test/java/org/thingsboard/server/dao/PostgreSqlInitializer.java @@ -52,6 +52,17 @@ public class PostgreSqlInitializer { } log.info("Postgres DB is initialized!"); } + public static void initDedicatedDb(Connection conn) { + log.info("initialize Postgres DB..."); + try { + URL sqlFileUrl = Resources.getResource("sql/dedicated.sql"); + String sql = Resources.toString(sqlFileUrl, Charsets.UTF_8); + conn.createStatement().execute(sql); + } catch (IOException | SQLException e) { + throw new RuntimeException("Unable to init the Postgres database. Reason: " + e.getMessage(), e); + } + log.info("Postgres DB is initialized!"); + } private static void cleanUpDb(Connection conn) { log.info("clean up Postgres DB..."); diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/event/sql/EventServiceSqlTest_DedicatedDataSource.java b/dao/src/test/java/org/thingsboard/server/dao/service/event/sql/EventServiceSqlTest_DedicatedDataSource.java new file mode 100644 index 0000000000..e7319f3128 --- /dev/null +++ b/dao/src/test/java/org/thingsboard/server/dao/service/event/sql/EventServiceSqlTest_DedicatedDataSource.java @@ -0,0 +1,28 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.dao.service.event.sql; + +import org.springframework.test.context.TestPropertySource; +import org.thingsboard.server.dao.service.DaoSqlTest; + +@DaoSqlTest +@TestPropertySource(properties = { + "spring.datasource.dedicated.enabled=true", + "spring.datasource.dedicated.url=${spring.datasource.url}", + "spring.datasource.dedicated.driverClassName=${spring.datasource.driverClassName}" +}) +public class EventServiceSqlTest_DedicatedDataSource extends EventServiceSqlTest { +} From f53f5e4fbbbab3e759f88f15ade166e3c4b15204 Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Tue, 6 Aug 2024 13:43:29 +0300 Subject: [PATCH 04/10] Separate dao implementations for dedicated datasource --- .../controller/AuditLogControllerTest.java | 30 ++++--- ...LogControllerTest_DedicatedDataSource.java | 8 ++ .../DedicatedDataSource.java} | 10 ++- .../dao/config/DedicatedJpaDaoConfig.java | 3 +- .../server/dao/config/DefaultDataSource.java | 26 ++++++ .../config/DefaultDedicatedJpaDaoConfig.java | 27 +----- .../sql/audit/DedicatedJpaAuditLogDao.java | 87 +++++++++++++++++++ .../server/dao/sql/audit/JpaAuditLogDao.java | 59 +------------ .../event/DedicatedEventInsertRepository.java | 36 ++++++++ .../dao/sql/event/DedicatedJpaEventDao.java | 45 ++++++++++ .../dao/sql/event/EventInsertRepository.java | 21 ++--- .../server/dao/sql/event/JpaBaseEventDao.java | 28 ++++-- .../sql/event/SqlEventCleanupRepository.java | 47 ---------- .../DedicatedSqlPartitioningRepository.java | 2 + 14 files changed, 259 insertions(+), 170 deletions(-) rename dao/src/main/java/org/thingsboard/server/dao/{sql/event/EventCleanupRepository.java => config/DedicatedDataSource.java} (62%) create mode 100644 dao/src/main/java/org/thingsboard/server/dao/config/DefaultDataSource.java create mode 100644 dao/src/main/java/org/thingsboard/server/dao/sql/audit/DedicatedJpaAuditLogDao.java create mode 100644 dao/src/main/java/org/thingsboard/server/dao/sql/event/DedicatedEventInsertRepository.java create mode 100644 dao/src/main/java/org/thingsboard/server/dao/sql/event/DedicatedJpaEventDao.java delete mode 100644 dao/src/main/java/org/thingsboard/server/dao/sql/event/SqlEventCleanupRepository.java diff --git a/application/src/test/java/org/thingsboard/server/controller/AuditLogControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/AuditLogControllerTest.java index 998d4587a4..6aede51c2f 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AuditLogControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AuditLogControllerTest.java @@ -17,6 +17,7 @@ package org.thingsboard.server.controller; import com.datastax.oss.driver.api.core.uuid.Uuids; import com.fasterxml.jackson.core.type.TypeReference; +import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.junit.After; import org.junit.Assert; @@ -38,7 +39,7 @@ import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.dao.audit.AuditLogDao; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.service.DaoSqlTest; -import org.thingsboard.server.dao.sqlts.insert.sql.DedicatedSqlPartitioningRepository; +import org.thingsboard.server.dao.sqlts.insert.sql.SqlPartitioningRepository; import org.thingsboard.server.service.ttl.AuditLogsCleanUpService; import java.text.ParseException; @@ -64,8 +65,9 @@ public class AuditLogControllerTest extends AbstractControllerTest { @Autowired private AuditLogDao auditLogDao; + @Getter @SpyBean - private DedicatedSqlPartitioningRepository partitioningRepository; + private SqlPartitioningRepository partitioningRepository; @SpyBean private AuditLogsCleanUpService auditLogsCleanUpService; @@ -183,12 +185,12 @@ public class AuditLogControllerTest extends AbstractControllerTest { @Test public void whenSavingNewAuditLog_thenCheckAndCreatePartitionIfNotExists() throws ParseException { long entityTs = ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2024-01-01T01:43:11Z").getTime(); - reset(partitioningRepository); + reset(getPartitioningRepository()); AuditLog auditLog = createAuditLog(ActionType.LOGIN, tenantAdminUserId, entityTs); - verify(partitioningRepository).createPartitionIfNotExists(eq("audit_log"), eq(auditLog.getCreatedTime()), eq(partitionDurationInMs)); + verify(getPartitioningRepository()).createPartitionIfNotExists(eq("audit_log"), eq(auditLog.getCreatedTime()), eq(partitionDurationInMs)); - List partitions = partitioningRepository.fetchPartitions("audit_log"); - assertThat(partitions).contains(partitioningRepository.calculatePartitionStartTime(auditLog.getCreatedTime(), partitionDurationInMs)); + List partitions = getPartitioningRepository().fetchPartitions("audit_log"); + assertThat(partitions).contains(getPartitioningRepository().calculatePartitionStartTime(auditLog.getCreatedTime(), partitionDurationInMs)); } @Test @@ -197,15 +199,15 @@ public class AuditLogControllerTest extends AbstractControllerTest { final long oldAuditLogTs = ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2020-10-01T00:00:00Z").getTime(); final long currentTimeMillis = oldAuditLogTs + TimeUnit.SECONDS.toMillis(auditLogsTtlInSec) * 2; - final long partitionStartTs = partitioningRepository.calculatePartitionStartTime(oldAuditLogTs, partitionDurationInMs); - partitioningRepository.createPartitionIfNotExists("audit_log", oldAuditLogTs, partitionDurationInMs); - List partitions = partitioningRepository.fetchPartitions("audit_log"); + final long partitionStartTs = getPartitioningRepository().calculatePartitionStartTime(oldAuditLogTs, partitionDurationInMs); + getPartitioningRepository().createPartitionIfNotExists("audit_log", oldAuditLogTs, partitionDurationInMs); + List partitions = getPartitioningRepository().fetchPartitions("audit_log"); assertThat(partitions).contains(partitionStartTs); willReturn(currentTimeMillis).given(auditLogsCleanUpService).getCurrentTimeMillis(); auditLogsCleanUpService.cleanUp(); - partitions = partitioningRepository.fetchPartitions("audit_log"); + partitions = getPartitioningRepository().fetchPartitions("audit_log"); assertThat(partitions).as("partitions cleared").doesNotContain(partitionStartTs); assertThat(partitions).as("only newer partitions left").allSatisfy(partitionsStart -> { long partitionEndTs = partitionsStart + partitionDurationInMs; @@ -218,17 +220,17 @@ public class AuditLogControllerTest extends AbstractControllerTest { // creating partition bigger than sql.audit_logs.partition_size long entityTs = ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-04-29T07:43:11Z").getTime(); //the partition 7 days is overlapping default partition size 1 day, use in the far past to not affect other tests - partitioningRepository.createPartitionIfNotExists("audit_log", entityTs, TimeUnit.DAYS.toMillis(7)); - List partitions = partitioningRepository.fetchPartitions("audit_log"); + getPartitioningRepository().createPartitionIfNotExists("audit_log", entityTs, TimeUnit.DAYS.toMillis(7)); + List partitions = getPartitioningRepository().fetchPartitions("audit_log"); log.warn("entityTs [{}], fetched partitions {}", entityTs, partitions); assertThat(partitions).contains(ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-04-28T00:00:00Z").getTime()); - partitioningRepository.cleanupPartitionsCache("audit_log", entityTs, 0); + getPartitioningRepository().cleanupPartitionsCache("audit_log", entityTs, 0); assertDoesNotThrow(() -> { // expecting partition overlap error on partition save createAuditLog(ActionType.LOGIN, tenantAdminUserId, entityTs); }); - assertThat(partitioningRepository.fetchPartitions("audit_log")) + assertThat(getPartitioningRepository().fetchPartitions("audit_log")) .contains(ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-04-28T00:00:00Z").getTime()); } diff --git a/application/src/test/java/org/thingsboard/server/controller/AuditLogControllerTest_DedicatedDataSource.java b/application/src/test/java/org/thingsboard/server/controller/AuditLogControllerTest_DedicatedDataSource.java index b642322ea4..bda7eab5a2 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AuditLogControllerTest_DedicatedDataSource.java +++ b/application/src/test/java/org/thingsboard/server/controller/AuditLogControllerTest_DedicatedDataSource.java @@ -15,8 +15,11 @@ */ package org.thingsboard.server.controller; +import lombok.Getter; +import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.test.context.TestPropertySource; import org.thingsboard.server.dao.service.DaoSqlTest; +import org.thingsboard.server.dao.sqlts.insert.sql.DedicatedSqlPartitioningRepository; @DaoSqlTest @TestPropertySource(properties = { @@ -25,4 +28,9 @@ import org.thingsboard.server.dao.service.DaoSqlTest; "spring.datasource.dedicated.driverClassName=${spring.datasource.driverClassName}", }) public class AuditLogControllerTest_DedicatedDataSource extends AuditLogControllerTest { + + @Getter + @SpyBean + private DedicatedSqlPartitioningRepository partitioningRepository; + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/event/EventCleanupRepository.java b/dao/src/main/java/org/thingsboard/server/dao/config/DedicatedDataSource.java similarity index 62% rename from dao/src/main/java/org/thingsboard/server/dao/sql/event/EventCleanupRepository.java rename to dao/src/main/java/org/thingsboard/server/dao/config/DedicatedDataSource.java index 0282e8ea3b..74884e1032 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/event/EventCleanupRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/config/DedicatedDataSource.java @@ -13,10 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.dao.sql.event; +package org.thingsboard.server.dao.config; -public interface EventCleanupRepository { +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; - void cleanupEvents(long eventExpTime, boolean debug); +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +@Retention(RetentionPolicy.RUNTIME) +@ConditionalOnProperty(value = "spring.datasource.dedicated.enabled", havingValue = "true") +public @interface DedicatedDataSource { } diff --git a/dao/src/main/java/org/thingsboard/server/dao/config/DedicatedJpaDaoConfig.java b/dao/src/main/java/org/thingsboard/server/dao/config/DedicatedJpaDaoConfig.java index 2c47cfbc5b..0f0554230d 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/config/DedicatedJpaDaoConfig.java +++ b/dao/src/main/java/org/thingsboard/server/dao/config/DedicatedJpaDaoConfig.java @@ -17,7 +17,6 @@ package org.thingsboard.server.dao.config; import com.zaxxer.hikari.HikariDataSource; import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder; @@ -46,7 +45,7 @@ import java.util.Objects; * - add the package of this JpaRepository to @EnableJpaRepositories in DedicatedJpaDaoConfig * - add the entity class to packages list in dedicatedEntityManagerFactory in DedicatedJpaDaoConfig * */ -@ConditionalOnProperty(value = "spring.datasource.dedicated.enabled", havingValue = "true") +@DedicatedDataSource @Configuration @EnableJpaRepositories(value = {"org.thingsboard.server.dao.sql.event", "org.thingsboard.server.dao.sql.audit"}, bootstrapMode = BootstrapMode.LAZY, diff --git a/dao/src/main/java/org/thingsboard/server/dao/config/DefaultDataSource.java b/dao/src/main/java/org/thingsboard/server/dao/config/DefaultDataSource.java new file mode 100644 index 0000000000..298ed12005 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/config/DefaultDataSource.java @@ -0,0 +1,26 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.dao.config; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +@ConditionalOnProperty(value = "spring.datasource.dedicated.enabled", havingValue = "false", matchIfMissing = true) +public @interface DefaultDataSource { +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/config/DefaultDedicatedJpaDaoConfig.java b/dao/src/main/java/org/thingsboard/server/dao/config/DefaultDedicatedJpaDaoConfig.java index 2cd68f34b5..fd28735b79 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/config/DefaultDedicatedJpaDaoConfig.java +++ b/dao/src/main/java/org/thingsboard/server/dao/config/DefaultDedicatedJpaDaoConfig.java @@ -15,38 +15,13 @@ */ package org.thingsboard.server.dao.config; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.data.repository.config.BootstrapMode; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.orm.jpa.JpaTransactionManager; -import org.springframework.transaction.support.TransactionTemplate; -import static org.thingsboard.server.dao.config.DedicatedJpaDaoConfig.DEDICATED_JDBC_TEMPLATE; -import static org.thingsboard.server.dao.config.DedicatedJpaDaoConfig.DEDICATED_TRANSACTION_MANAGER; -import static org.thingsboard.server.dao.config.DedicatedJpaDaoConfig.DEDICATED_TRANSACTION_TEMPLATE; - -@ConditionalOnProperty(value = "spring.datasource.dedicated.enabled", havingValue = "false", matchIfMissing = true) +@DefaultDataSource @Configuration @EnableJpaRepositories(value = {"org.thingsboard.server.dao.sql.event", "org.thingsboard.server.dao.sql.audit"}, bootstrapMode = BootstrapMode.LAZY) public class DefaultDedicatedJpaDaoConfig { - @Bean(DEDICATED_JDBC_TEMPLATE) - public JdbcTemplate dedicatedJdbcTemplate(@Qualifier("jdbcTemplate") JdbcTemplate defaultJdbcTemplate) { - return defaultJdbcTemplate; - } - - @Bean(DEDICATED_TRANSACTION_MANAGER) - public JpaTransactionManager dedicatedTransactionManager(@Qualifier("transactionManager") JpaTransactionManager defaultTransactionManager) { - return defaultTransactionManager; - } - - @Bean(DEDICATED_TRANSACTION_TEMPLATE) - public TransactionTemplate dedicatedTransactionTemplate(@Qualifier("transactionTemplate") TransactionTemplate defaultTransactionTemplate) { - return defaultTransactionTemplate; - } - } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/audit/DedicatedJpaAuditLogDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/audit/DedicatedJpaAuditLogDao.java new file mode 100644 index 0000000000..2d60c3adc7 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/audit/DedicatedJpaAuditLogDao.java @@ -0,0 +1,87 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.dao.sql.audit; + +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; +import org.thingsboard.server.common.data.audit.AuditLog; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.dao.config.DedicatedDataSource; +import org.thingsboard.server.dao.sqlts.insert.sql.DedicatedSqlPartitioningRepository; +import org.thingsboard.server.dao.util.SqlDao; + +import java.util.Collection; +import java.util.UUID; + +import static org.thingsboard.server.dao.config.DedicatedJpaDaoConfig.DEDICATED_JDBC_TEMPLATE; +import static org.thingsboard.server.dao.config.DedicatedJpaDaoConfig.DEDICATED_PERSISTENCE_UNIT; +import static org.thingsboard.server.dao.config.DedicatedJpaDaoConfig.DEDICATED_TRANSACTION_MANAGER; + +@DedicatedDataSource +@Component +@SqlDao +public class DedicatedJpaAuditLogDao extends JpaAuditLogDao { + + @Autowired + @Qualifier(DEDICATED_JDBC_TEMPLATE) + private JdbcTemplate jdbcTemplate; + @PersistenceContext(unitName = DEDICATED_PERSISTENCE_UNIT) + private EntityManager entityManager; + + public DedicatedJpaAuditLogDao(AuditLogRepository auditLogRepository, DedicatedSqlPartitioningRepository partitioningRepository) { + super(auditLogRepository, partitioningRepository); + } + + @Transactional(transactionManager = DEDICATED_TRANSACTION_MANAGER) + @Override + public AuditLog save(TenantId tenantId, AuditLog domain) { + return super.save(tenantId, domain); + } + + @Transactional(transactionManager = DEDICATED_TRANSACTION_MANAGER) + @Override + public AuditLog saveAndFlush(TenantId tenantId, AuditLog domain) { + return super.saveAndFlush(tenantId, domain); + } + + @Transactional(transactionManager = DEDICATED_TRANSACTION_MANAGER) + @Override + public boolean removeById(TenantId tenantId, UUID id) { + return super.removeById(tenantId, id); + } + + @Transactional(transactionManager = DEDICATED_TRANSACTION_MANAGER) + @Override + public void removeAllByIds(Collection ids) { + super.removeAllByIds(ids); + } + + @Override + protected EntityManager getEntityManager() { + return entityManager; + } + + @Override + protected JdbcTemplate getJdbcTemplate() { + return jdbcTemplate; + } + +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/audit/JpaAuditLogDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/audit/JpaAuditLogDao.java index a7eaebf50c..7e859d1e8c 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/audit/JpaAuditLogDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/audit/JpaAuditLogDao.java @@ -15,42 +15,33 @@ */ package org.thingsboard.server.dao.sql.audit; -import jakarta.persistence.EntityManager; -import jakarta.persistence.PersistenceContext; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Component; -import org.springframework.transaction.annotation.Transactional; import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.audit.AuditLog; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.EntityId; -import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.TimePageLink; import org.thingsboard.server.dao.DaoUtil; import org.thingsboard.server.dao.audit.AuditLogDao; +import org.thingsboard.server.dao.config.DefaultDataSource; import org.thingsboard.server.dao.model.sql.AuditLogEntity; import org.thingsboard.server.dao.sql.JpaPartitionedAbstractDao; -import org.thingsboard.server.dao.sqlts.insert.sql.DedicatedSqlPartitioningRepository; +import org.thingsboard.server.dao.sqlts.insert.sql.SqlPartitioningRepository; import org.thingsboard.server.dao.util.SqlDao; -import java.util.Collection; import java.util.List; import java.util.UUID; import java.util.concurrent.TimeUnit; -import static org.thingsboard.server.dao.config.DedicatedJpaDaoConfig.DEDICATED_JDBC_TEMPLATE; -import static org.thingsboard.server.dao.config.DedicatedJpaDaoConfig.DEDICATED_PERSISTENCE_UNIT; -import static org.thingsboard.server.dao.config.DedicatedJpaDaoConfig.DEDICATED_TRANSACTION_MANAGER; import static org.thingsboard.server.dao.model.ModelConstants.AUDIT_LOG_TABLE_NAME; +@DefaultDataSource @Component @SqlDao @RequiredArgsConstructor @@ -58,40 +49,11 @@ import static org.thingsboard.server.dao.model.ModelConstants.AUDIT_LOG_TABLE_NA public class JpaAuditLogDao extends JpaPartitionedAbstractDao implements AuditLogDao { private final AuditLogRepository auditLogRepository; - private final DedicatedSqlPartitioningRepository partitioningRepository; - @Autowired - @Qualifier(DEDICATED_JDBC_TEMPLATE) - private JdbcTemplate jdbcTemplate; - @PersistenceContext(unitName = DEDICATED_PERSISTENCE_UNIT) - private EntityManager entityManager; + private final SqlPartitioningRepository partitioningRepository; @Value("${sql.audit_logs.partition_size:168}") private int partitionSizeInHours; - @Transactional(transactionManager = DEDICATED_TRANSACTION_MANAGER) - @Override - public AuditLog save(TenantId tenantId, AuditLog domain) { - return super.save(tenantId, domain); - } - - @Transactional(transactionManager = DEDICATED_TRANSACTION_MANAGER) - @Override - public AuditLog saveAndFlush(TenantId tenantId, AuditLog domain) { - return super.saveAndFlush(tenantId, domain); - } - - @Transactional(transactionManager = DEDICATED_TRANSACTION_MANAGER) - @Override - public boolean removeById(TenantId tenantId, UUID id) { - return super.removeById(tenantId, id); - } - - @Transactional(transactionManager = DEDICATED_TRANSACTION_MANAGER) - @Override - public void removeAllByIds(Collection ids) { - super.removeAllByIds(ids); - } - @Override public PageData findAuditLogsByTenantIdAndEntityId(UUID tenantId, EntityId entityId, List actionTypes, TimePageLink pageLink) { return DaoUtil.toPageData( @@ -157,19 +119,6 @@ public class JpaAuditLogDao extends JpaPartitionedAbstractDao getEntityClass() { return AuditLogEntity.class; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/event/DedicatedEventInsertRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/event/DedicatedEventInsertRepository.java new file mode 100644 index 0000000000..78462e3819 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/event/DedicatedEventInsertRepository.java @@ -0,0 +1,36 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.dao.sql.event; + +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.support.TransactionTemplate; +import org.thingsboard.server.dao.config.DedicatedDataSource; + +import static org.thingsboard.server.dao.config.DedicatedJpaDaoConfig.DEDICATED_JDBC_TEMPLATE; +import static org.thingsboard.server.dao.config.DedicatedJpaDaoConfig.DEDICATED_TRANSACTION_TEMPLATE; + +@DedicatedDataSource +@Repository +public class DedicatedEventInsertRepository extends EventInsertRepository { + + public DedicatedEventInsertRepository(@Qualifier(DEDICATED_JDBC_TEMPLATE) JdbcTemplate jdbcTemplate, + @Qualifier(DEDICATED_TRANSACTION_TEMPLATE) TransactionTemplate transactionTemplate) { + super(jdbcTemplate, transactionTemplate); + } + +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/event/DedicatedJpaEventDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/event/DedicatedJpaEventDao.java new file mode 100644 index 0000000000..bfaaeadfe3 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/event/DedicatedJpaEventDao.java @@ -0,0 +1,45 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.dao.sql.event; + +import org.springframework.stereotype.Component; +import org.thingsboard.server.common.stats.StatsFactory; +import org.thingsboard.server.dao.config.DedicatedDataSource; +import org.thingsboard.server.dao.sql.ScheduledLogExecutorComponent; +import org.thingsboard.server.dao.sqlts.insert.sql.DedicatedSqlPartitioningRepository; +import org.thingsboard.server.dao.util.SqlDao; + +@DedicatedDataSource +@Component +@SqlDao +public class DedicatedJpaEventDao extends JpaBaseEventDao { + + public DedicatedJpaEventDao(EventPartitionConfiguration partitionConfiguration, + DedicatedSqlPartitioningRepository partitioningRepository, + LifecycleEventRepository lcEventRepository, + StatisticsEventRepository statsEventRepository, + ErrorEventRepository errorEventRepository, + DedicatedEventInsertRepository eventInsertRepository, + RuleNodeDebugEventRepository ruleNodeDebugEventRepository, + RuleChainDebugEventRepository ruleChainDebugEventRepository, + ScheduledLogExecutorComponent logExecutor, + StatsFactory statsFactory) { + super(partitionConfiguration, partitioningRepository, lcEventRepository, statsEventRepository, + errorEventRepository, eventInsertRepository, ruleNodeDebugEventRepository, + ruleChainDebugEventRepository, logExecutor, statsFactory); + } + +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/event/EventInsertRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/event/EventInsertRepository.java index f97ac99198..962be57892 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/event/EventInsertRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/event/EventInsertRepository.java @@ -16,9 +16,7 @@ package org.thingsboard.server.dao.sql.event; import jakarta.annotation.PostConstruct; -import lombok.Getter; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; +import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.jdbc.core.BatchPreparedStatementSetter; import org.springframework.jdbc.core.JdbcTemplate; @@ -34,6 +32,7 @@ import org.thingsboard.server.common.data.event.LifecycleEvent; import org.thingsboard.server.common.data.event.RuleChainDebugEvent; import org.thingsboard.server.common.data.event.RuleNodeDebugEvent; import org.thingsboard.server.common.data.event.StatisticsEvent; +import org.thingsboard.server.dao.config.DefaultDataSource; import org.thingsboard.server.dao.util.SqlDao; import java.sql.PreparedStatement; @@ -46,12 +45,11 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Pattern; import java.util.stream.Collectors; -import static org.thingsboard.server.dao.config.DedicatedJpaDaoConfig.DEDICATED_JDBC_TEMPLATE; -import static org.thingsboard.server.dao.config.DedicatedJpaDaoConfig.DEDICATED_TRANSACTION_TEMPLATE; - +@DefaultDataSource @Repository @Transactional @SqlDao +@RequiredArgsConstructor public class EventInsertRepository { private static final ThreadLocal PATTERN_THREAD_LOCAL = ThreadLocal.withInitial(() -> Pattern.compile(String.valueOf(Character.MIN_VALUE))); @@ -60,14 +58,8 @@ public class EventInsertRepository { private final Map insertStmtMap = new ConcurrentHashMap<>(); - @Getter - @Autowired - @Qualifier(DEDICATED_JDBC_TEMPLATE) - protected JdbcTemplate jdbcTemplate; - - @Autowired - @Qualifier(DEDICATED_TRANSACTION_TEMPLATE) - private TransactionTemplate transactionTemplate; + private final JdbcTemplate jdbcTemplate; + private final TransactionTemplate transactionTemplate; @Value("${sql.remove_null_chars:true}") private boolean removeNullChars; @@ -244,4 +236,5 @@ public class EventInsertRepository { } return strValue; } + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDao.java index 85898acd18..b7d824ce00 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDao.java @@ -38,12 +38,13 @@ import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.TimePageLink; import org.thingsboard.server.common.stats.StatsFactory; import org.thingsboard.server.dao.DaoUtil; +import org.thingsboard.server.dao.config.DefaultDataSource; import org.thingsboard.server.dao.event.EventDao; import org.thingsboard.server.dao.model.sql.EventEntity; import org.thingsboard.server.dao.sql.ScheduledLogExecutorComponent; import org.thingsboard.server.dao.sql.TbSqlBlockingQueueParams; import org.thingsboard.server.dao.sql.TbSqlBlockingQueueWrapper; -import org.thingsboard.server.dao.sqlts.insert.sql.DedicatedSqlPartitioningRepository; +import org.thingsboard.server.dao.sqlts.insert.sql.SqlPartitioningRepository; import org.thingsboard.server.dao.util.SqlDao; import java.util.Comparator; @@ -54,22 +55,19 @@ import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; -/** - * Created by Valerii Sosliuk on 5/3/2017. - */ -@Slf4j +@DefaultDataSource @Component @SqlDao @RequiredArgsConstructor +@Slf4j public class JpaBaseEventDao implements EventDao { private final EventPartitionConfiguration partitionConfiguration; - private final DedicatedSqlPartitioningRepository partitioningRepository; + private final SqlPartitioningRepository partitioningRepository; private final LifecycleEventRepository lcEventRepository; private final StatisticsEventRepository statsEventRepository; private final ErrorEventRepository errorEventRepository; private final EventInsertRepository eventInsertRepository; - private final EventCleanupRepository eventCleanupRepository; private final RuleNodeDebugEventRepository ruleNodeDebugEventRepository; private final RuleChainDebugEventRepository ruleChainDebugEventRepository; private final ScheduledLogExecutorComponent logExecutor; @@ -377,7 +375,7 @@ public class JpaBaseEventDao implements EventDao { if (regularEventExpTs > 0) { log.info("Going to cleanup regular events with exp time: {}", regularEventExpTs); if (cleanupDb) { - eventCleanupRepository.cleanupEvents(regularEventExpTs, false); + cleanupEvents(regularEventExpTs, false); } else { cleanupPartitionsCache(regularEventExpTs, false); } @@ -385,13 +383,25 @@ public class JpaBaseEventDao implements EventDao { if (debugEventExpTs > 0) { log.info("Going to cleanup debug events with exp time: {}", debugEventExpTs); if (cleanupDb) { - eventCleanupRepository.cleanupEvents(debugEventExpTs, true); + cleanupEvents(debugEventExpTs, true); } else { cleanupPartitionsCache(debugEventExpTs, true); } } } + private void cleanupEvents(long eventExpTime, boolean debug) { + for (EventType eventType : EventType.values()) { + if (eventType.isDebug() == debug) { + cleanupPartitions(eventType, eventExpTime); + } + } + } + + private void cleanupPartitions(EventType eventType, long eventExpTime) { + partitioningRepository.dropPartitionsBefore(eventType.getTable(), eventExpTime, partitionConfiguration.getPartitionSizeInMs(eventType)); + } + private void cleanupPartitionsCache(long expTime, boolean isDebug) { for (EventType eventType : EventType.values()) { if (eventType.isDebug() == isDebug) { diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/event/SqlEventCleanupRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/event/SqlEventCleanupRepository.java deleted file mode 100644 index 36efd9ddb9..0000000000 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/event/SqlEventCleanupRepository.java +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Copyright © 2016-2024 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.dao.sql.event; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Repository; -import org.thingsboard.server.common.data.event.EventType; -import org.thingsboard.server.dao.sql.JpaAbstractDaoListeningExecutorService; -import org.thingsboard.server.dao.sqlts.insert.sql.DedicatedSqlPartitioningRepository; - - -@Slf4j -@Repository -@RequiredArgsConstructor -public class SqlEventCleanupRepository extends JpaAbstractDaoListeningExecutorService implements EventCleanupRepository { - - private final EventPartitionConfiguration partitionConfiguration; - private final DedicatedSqlPartitioningRepository partitioningRepository; - - @Override - public void cleanupEvents(long eventExpTime, boolean debug) { - for (EventType eventType : EventType.values()) { - if (eventType.isDebug() == debug) { - cleanupEvents(eventType, eventExpTime); - } - } - } - - private void cleanupEvents(EventType eventType, long eventExpTime) { - partitioningRepository.dropPartitionsBefore(eventType.getTable(), eventExpTime, partitionConfiguration.getPartitionSizeInMs(eventType)); - } - -} diff --git a/dao/src/main/java/org/thingsboard/server/dao/sqlts/insert/sql/DedicatedSqlPartitioningRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sqlts/insert/sql/DedicatedSqlPartitioningRepository.java index efcec2e2e4..78b477778d 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sqlts/insert/sql/DedicatedSqlPartitioningRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sqlts/insert/sql/DedicatedSqlPartitioningRepository.java @@ -21,11 +21,13 @@ 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.config.DedicatedDataSource; import org.thingsboard.server.dao.timeseries.SqlPartition; import static org.thingsboard.server.dao.config.DedicatedJpaDaoConfig.DEDICATED_JDBC_TEMPLATE; import static org.thingsboard.server.dao.config.DedicatedJpaDaoConfig.DEDICATED_TRANSACTION_MANAGER; +@DedicatedDataSource @Repository public class DedicatedSqlPartitioningRepository extends SqlPartitioningRepository { From e69470aee192d6641f6084ae30df64e59b44aa66 Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Tue, 6 Aug 2024 16:56:21 +0300 Subject: [PATCH 05/10] Fix dao tests ContextConfiguration --- .../java/org/thingsboard/server/dao/AbstractJpaDaoTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dao/src/test/java/org/thingsboard/server/dao/AbstractJpaDaoTest.java b/dao/src/test/java/org/thingsboard/server/dao/AbstractJpaDaoTest.java index 99cb6e6c48..c52b09ff3a 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/AbstractJpaDaoTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/AbstractJpaDaoTest.java @@ -25,6 +25,7 @@ import org.springframework.test.context.support.DependencyInjectionTestExecution import org.springframework.test.context.support.DirtiesContextTestExecutionListener; import org.thingsboard.server.common.stats.StatsFactory; import org.thingsboard.server.dao.config.DedicatedJpaDaoConfig; +import org.thingsboard.server.dao.config.DefaultDedicatedJpaDaoConfig; import org.thingsboard.server.dao.config.JpaDaoConfig; import org.thingsboard.server.dao.config.SqlTsDaoConfig; import org.thingsboard.server.dao.config.SqlTsLatestDaoConfig; @@ -34,7 +35,7 @@ import org.thingsboard.server.dao.service.DaoSqlTest; * Created by Valerii Sosliuk on 4/22/2017. */ @RunWith(SpringRunner.class) -@ContextConfiguration(classes = {JpaDaoConfig.class, SqlTsDaoConfig.class, SqlTsLatestDaoConfig.class, DedicatedJpaDaoConfig.class}) +@ContextConfiguration(classes = {JpaDaoConfig.class, SqlTsDaoConfig.class, SqlTsLatestDaoConfig.class, DedicatedJpaDaoConfig.class, DefaultDedicatedJpaDaoConfig.class}) @DaoSqlTest @TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, From 49707f9cfc704a454dc9585fb55dbb0dd6b187b2 Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Tue, 6 Aug 2024 17:12:50 +0300 Subject: [PATCH 06/10] Fix Timescale dao configuration --- .../thingsboard/server/dao/config/JpaDaoConfig.java | 10 +++++++++- .../server/dao/config/TimescaleDaoConfig.java | 2 -- .../server/dao/config/TimescaleTsLatestDaoConfig.java | 2 -- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/dao/src/main/java/org/thingsboard/server/dao/config/JpaDaoConfig.java b/dao/src/main/java/org/thingsboard/server/dao/config/JpaDaoConfig.java index 75bd14eaa1..86c0ed4ea3 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/config/JpaDaoConfig.java +++ b/dao/src/main/java/org/thingsboard/server/dao/config/JpaDaoConfig.java @@ -69,7 +69,9 @@ public class JpaDaoConfig { public LocalContainerEntityManagerFactoryBean entityManagerFactory(@Qualifier("dataSource") DataSource dataSource, EntityManagerFactoryBuilder builder, @Autowired(required = false) SqlTsLatestDaoConfig tsLatestDaoConfig, - @Autowired(required = false) SqlTsDaoConfig tsDaoConfig) { + @Autowired(required = false) SqlTsDaoConfig tsDaoConfig, + @Autowired(required = false) TimescaleDaoConfig timescaleDaoConfig, + @Autowired(required = false) TimescaleTsLatestDaoConfig timescaleTsLatestDaoConfig) { List packages = new ArrayList<>(); packages.add("org.thingsboard.server.dao.model.sql"); packages.add("org.thingsboard.server.dao.model.sqlts.dictionary"); @@ -79,6 +81,12 @@ public class JpaDaoConfig { if (tsDaoConfig != null) { packages.add("org.thingsboard.server.dao.model.sqlts.ts"); } + if (timescaleDaoConfig != null) { + packages.add("org.thingsboard.server.dao.model.sqlts.timescale"); + } + if (timescaleTsLatestDaoConfig != null) { + packages.add("org.thingsboard.server.dao.model.sqlts.latest"); + } return builder .dataSource(dataSource) .packages(packages.toArray(String[]::new)) diff --git a/dao/src/main/java/org/thingsboard/server/dao/config/TimescaleDaoConfig.java b/dao/src/main/java/org/thingsboard/server/dao/config/TimescaleDaoConfig.java index 05a84ca1cc..3c910778a2 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/config/TimescaleDaoConfig.java +++ b/dao/src/main/java/org/thingsboard/server/dao/config/TimescaleDaoConfig.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.dao.config; -import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; @@ -28,7 +27,6 @@ import org.thingsboard.server.dao.util.TimescaleDBTsDao; @TbAutoConfiguration @ComponentScan({"org.thingsboard.server.dao.sqlts.timescale"}) @EnableJpaRepositories(value = {"org.thingsboard.server.dao.sqlts.timescale", "org.thingsboard.server.dao.sqlts.insert.timescale"}, bootstrapMode = BootstrapMode.LAZY) -@EntityScan({"org.thingsboard.server.dao.model.sqlts.timescale"}) @EnableTransactionManagement @TimescaleDBTsDao public class TimescaleDaoConfig { diff --git a/dao/src/main/java/org/thingsboard/server/dao/config/TimescaleTsLatestDaoConfig.java b/dao/src/main/java/org/thingsboard/server/dao/config/TimescaleTsLatestDaoConfig.java index 74d0cc7ae3..f6d1e49a6e 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/config/TimescaleTsLatestDaoConfig.java +++ b/dao/src/main/java/org/thingsboard/server/dao/config/TimescaleTsLatestDaoConfig.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.dao.config; -import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; @@ -28,7 +27,6 @@ import org.thingsboard.server.dao.util.TimescaleDBTsLatestDao; @TbAutoConfiguration @ComponentScan({"org.thingsboard.server.dao.sqlts.timescale"}) @EnableJpaRepositories(value = {"org.thingsboard.server.dao.sqlts.insert.latest.sql", "org.thingsboard.server.dao.sqlts.latest"}, bootstrapMode = BootstrapMode.LAZY) -@EntityScan({"org.thingsboard.server.dao.model.sqlts.latest"}) @EnableTransactionManagement @TimescaleDBTsLatestDao public class TimescaleTsLatestDaoConfig { From 7b9f936d2e35aa32642cbf96e1b60c9e7e9804ab Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Wed, 7 Aug 2024 13:59:00 +0300 Subject: [PATCH 07/10] Add configs description for dedicated datasource --- .../src/main/resources/thingsboard.yml | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index 44c65c05cb..2e0ee612eb 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -768,23 +768,28 @@ spring: leakDetectionThreshold: "${SPRING_DATASOURCE_HIKARI_LEAK_DETECTION_THRESHOLD:0}" # This property increases the number of connections in the pool as demand increases. At the same time, the property ensures that the pool doesn't grow to the point of exhausting a system's resources, which ultimately affects an application's performance and availability maximumPoolSize: "${SPRING_DATASOURCE_MAXIMUM_POOL_SIZE:16}" - registerMbeans: "${SPRING_DATASOURCE_HIKARI_REGISTER_MBEANS:false}" # true - enable MBean to diagnose pools state via JMX + # Enable MBean to diagnose pools state via JMX + registerMbeans: "${SPRING_DATASOURCE_HIKARI_REGISTER_MBEANS:false}" dedicated: + # Enable dedicated datasource (a separate database) for events and audit logs. + # Before enabling this, make sure you have set up the following tables in the new DB: + # error_event, lc_event, rule_chain_debug_event, rule_node_debug_event, stats_event, audit_log enabled: "${SPRING_DEDICATED_DATASOURCE_ENABLED:false}" - # Database driver for Spring JPA - org.postgresql.Driver + # Database driver for Spring JPA for dedicated datasource driverClassName: "${SPRING_DEDICATED_DATASOURCE_DRIVER_CLASS_NAME:org.postgresql.Driver}" - # Database connection URL + # Database connection URL for dedicated datasource url: "${SPRING_DEDICATED_DATASOURCE_URL:jdbc:postgresql://localhost:5432/thingsboard_dedicated}" - # Database user name + # Database user name for dedicated datasource username: "${SPRING_DEDICATED_DATASOURCE_USERNAME:postgres}" - # Database user password + # Database user password for dedicated datasource password: "${SPRING_DEDICATED_DATASOURCE_PASSWORD:postgres}" hikari: - # This property controls the amount of time that a connection can be out of the pool before a message is logged indicating a possible connection leak. A value of 0 means leak detection is disabled + # This property controls the amount of time that a connection can be out of the pool before a message is logged indicating a possible connection leak for dedicated datasource. A value of 0 means leak detection is disabled leakDetectionThreshold: "${SPRING_DEDICATED_DATASOURCE_HIKARI_LEAK_DETECTION_THRESHOLD:0}" - # This property increases the number of connections in the pool as demand increases. At the same time, the property ensures that the pool doesn't grow to the point of exhausting a system's resources, which ultimately affects an application's performance and availability + # This property increases the number of connections in the pool as demand increases for dedicated datasource. At the same time, the property ensures that the pool doesn't grow to the point of exhausting a system's resources, which ultimately affects an application's performance and availability maximumPoolSize: "${SPRING_DEDICATED_DATASOURCE_MAXIMUM_POOL_SIZE:16}" - registerMbeans: "${SPRING_DEDICATED_DATASOURCE_HIKARI_REGISTER_MBEANS:false}" # true - enable MBean to diagnose pools state via JMX + # Enable MBean to diagnose pools state via JMX for dedicated datasource + registerMbeans: "${SPRING_DEDICATED_DATASOURCE_HIKARI_REGISTER_MBEANS:false}" # Audit log parameters audit-log: From 0418e93bd1d2925ac7b21ae3e3133b97424b87bd Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Fri, 9 Aug 2024 14:38:37 +0300 Subject: [PATCH 08/10] Rename dedicated datasource to events datasource --- .../src/main/resources/thingsboard.yml | 32 +++++------ ...rollerTest_DedicatedEventsDataSource.java} | 12 ++-- ...ce.java => DedicatedEventsDataSource.java} | 4 +- ....java => DedicatedEventsJpaDaoConfig.java} | 55 ++++++++----------- .../server/dao/config/DefaultDataSource.java | 2 +- .../sql/audit/DedicatedJpaAuditLogDao.java | 26 ++++----- .../event/DedicatedEventInsertRepository.java | 12 ++-- .../dao/sql/event/DedicatedJpaEventDao.java | 8 +-- ...catedEventsSqlPartitioningRepository.java} | 16 +++--- .../server/dao/AbstractDaoServiceTest.java | 4 +- .../server/dao/AbstractJpaDaoTest.java | 4 +- .../server/dao/PostgreSqlInitializer.java | 12 +--- ...iceSqlTest_DedicatedEventsDataSource.java} | 8 +-- 13 files changed, 89 insertions(+), 106 deletions(-) rename application/src/test/java/org/thingsboard/server/controller/{AuditLogControllerTest_DedicatedDataSource.java => AuditLogControllerTest_DedicatedEventsDataSource.java} (66%) rename dao/src/main/java/org/thingsboard/server/dao/config/{DedicatedDataSource.java => DedicatedEventsDataSource.java} (86%) rename dao/src/main/java/org/thingsboard/server/dao/config/{DedicatedJpaDaoConfig.java => DedicatedEventsJpaDaoConfig.java} (51%) rename dao/src/main/java/org/thingsboard/server/dao/sqlts/insert/sql/{DedicatedSqlPartitioningRepository.java => DedicatedEventsSqlPartitioningRepository.java} (76%) rename dao/src/test/java/org/thingsboard/server/dao/service/event/sql/{EventServiceSqlTest_DedicatedDataSource.java => EventServiceSqlTest_DedicatedEventsDataSource.java} (74%) diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index 5c645b1473..be897b4c08 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -775,26 +775,26 @@ spring: maximumPoolSize: "${SPRING_DATASOURCE_MAXIMUM_POOL_SIZE:16}" # Enable MBean to diagnose pools state via JMX registerMbeans: "${SPRING_DATASOURCE_HIKARI_REGISTER_MBEANS:false}" - dedicated: + events: # Enable dedicated datasource (a separate database) for events and audit logs. # Before enabling this, make sure you have set up the following tables in the new DB: # error_event, lc_event, rule_chain_debug_event, rule_node_debug_event, stats_event, audit_log - enabled: "${SPRING_DEDICATED_DATASOURCE_ENABLED:false}" - # Database driver for Spring JPA for dedicated datasource - driverClassName: "${SPRING_DEDICATED_DATASOURCE_DRIVER_CLASS_NAME:org.postgresql.Driver}" - # Database connection URL for dedicated datasource - url: "${SPRING_DEDICATED_DATASOURCE_URL:jdbc:postgresql://localhost:5432/thingsboard_dedicated}" - # Database user name for dedicated datasource - username: "${SPRING_DEDICATED_DATASOURCE_USERNAME:postgres}" - # Database user password for dedicated datasource - password: "${SPRING_DEDICATED_DATASOURCE_PASSWORD:postgres}" + enabled: "${SPRING_DEDICATED_EVENTS_DATASOURCE_ENABLED:false}" + # Database driver for Spring JPA for events datasource + driverClassName: "${SPRING_EVENTS_DATASOURCE_DRIVER_CLASS_NAME:org.postgresql.Driver}" + # Database connection URL for events datasource + url: "${SPRING_EVENTS_DATASOURCE_URL:jdbc:postgresql://localhost:5432/thingsboard_events}" + # Database username for events datasource + username: "${SPRING_EVENTS_DATASOURCE_USERNAME:postgres}" + # Database user password for events datasource + password: "${SPRING_EVENTS_DATASOURCE_PASSWORD:postgres}" hikari: - # This property controls the amount of time that a connection can be out of the pool before a message is logged indicating a possible connection leak for dedicated datasource. A value of 0 means leak detection is disabled - leakDetectionThreshold: "${SPRING_DEDICATED_DATASOURCE_HIKARI_LEAK_DETECTION_THRESHOLD:0}" - # This property increases the number of connections in the pool as demand increases for dedicated datasource. At the same time, the property ensures that the pool doesn't grow to the point of exhausting a system's resources, which ultimately affects an application's performance and availability - maximumPoolSize: "${SPRING_DEDICATED_DATASOURCE_MAXIMUM_POOL_SIZE:16}" - # Enable MBean to diagnose pools state via JMX for dedicated datasource - registerMbeans: "${SPRING_DEDICATED_DATASOURCE_HIKARI_REGISTER_MBEANS:false}" + # This property controls the amount of time that a connection can be out of the pool before a message is logged indicating a possible connection leak for events datasource. A value of 0 means leak detection is disabled + leakDetectionThreshold: "${SPRING_EVENTS_DATASOURCE_HIKARI_LEAK_DETECTION_THRESHOLD:0}" + # This property increases the number of connections in the pool as demand increases for events datasource. At the same time, the property ensures that the pool doesn't grow to the point of exhausting a system's resources, which ultimately affects an application's performance and availability + maximumPoolSize: "${SPRING_EVENTS_DATASOURCE_MAXIMUM_POOL_SIZE:16}" + # Enable MBean to diagnose pools state via JMX for events datasource + registerMbeans: "${SPRING_EVENTS_DATASOURCE_HIKARI_REGISTER_MBEANS:false}" # Audit log parameters audit-log: diff --git a/application/src/test/java/org/thingsboard/server/controller/AuditLogControllerTest_DedicatedDataSource.java b/application/src/test/java/org/thingsboard/server/controller/AuditLogControllerTest_DedicatedEventsDataSource.java similarity index 66% rename from application/src/test/java/org/thingsboard/server/controller/AuditLogControllerTest_DedicatedDataSource.java rename to application/src/test/java/org/thingsboard/server/controller/AuditLogControllerTest_DedicatedEventsDataSource.java index bda7eab5a2..7678b2a91f 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AuditLogControllerTest_DedicatedDataSource.java +++ b/application/src/test/java/org/thingsboard/server/controller/AuditLogControllerTest_DedicatedEventsDataSource.java @@ -19,18 +19,18 @@ import lombok.Getter; import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.test.context.TestPropertySource; import org.thingsboard.server.dao.service.DaoSqlTest; -import org.thingsboard.server.dao.sqlts.insert.sql.DedicatedSqlPartitioningRepository; +import org.thingsboard.server.dao.sqlts.insert.sql.DedicatedEventsSqlPartitioningRepository; @DaoSqlTest @TestPropertySource(properties = { - "spring.datasource.dedicated.enabled=true", - "spring.datasource.dedicated.url=${spring.datasource.url}", - "spring.datasource.dedicated.driverClassName=${spring.datasource.driverClassName}", + "spring.datasource.events.enabled=true", + "spring.datasource.events.url=${spring.datasource.url}", + "spring.datasource.events.driverClassName=${spring.datasource.driverClassName}", }) -public class AuditLogControllerTest_DedicatedDataSource extends AuditLogControllerTest { +public class AuditLogControllerTest_DedicatedEventsDataSource extends AuditLogControllerTest { @Getter @SpyBean - private DedicatedSqlPartitioningRepository partitioningRepository; + private DedicatedEventsSqlPartitioningRepository partitioningRepository; } diff --git a/dao/src/main/java/org/thingsboard/server/dao/config/DedicatedDataSource.java b/dao/src/main/java/org/thingsboard/server/dao/config/DedicatedEventsDataSource.java similarity index 86% rename from dao/src/main/java/org/thingsboard/server/dao/config/DedicatedDataSource.java rename to dao/src/main/java/org/thingsboard/server/dao/config/DedicatedEventsDataSource.java index 74884e1032..3ca6a20d44 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/config/DedicatedDataSource.java +++ b/dao/src/main/java/org/thingsboard/server/dao/config/DedicatedEventsDataSource.java @@ -21,6 +21,6 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @Retention(RetentionPolicy.RUNTIME) -@ConditionalOnProperty(value = "spring.datasource.dedicated.enabled", havingValue = "true") -public @interface DedicatedDataSource { +@ConditionalOnProperty(value = "spring.datasource.events.enabled", havingValue = "true") +public @interface DedicatedEventsDataSource { } diff --git a/dao/src/main/java/org/thingsboard/server/dao/config/DedicatedJpaDaoConfig.java b/dao/src/main/java/org/thingsboard/server/dao/config/DedicatedEventsJpaDaoConfig.java similarity index 51% rename from dao/src/main/java/org/thingsboard/server/dao/config/DedicatedJpaDaoConfig.java rename to dao/src/main/java/org/thingsboard/server/dao/config/DedicatedEventsJpaDaoConfig.java index 0f0554230d..03c0d76bbe 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/config/DedicatedJpaDaoConfig.java +++ b/dao/src/main/java/org/thingsboard/server/dao/config/DedicatedEventsJpaDaoConfig.java @@ -38,60 +38,53 @@ import org.thingsboard.server.dao.model.sql.StatisticsEventEntity; import javax.sql.DataSource; import java.util.Objects; -/* - * To make entity use a dedicated datasource: - * - add its JpaRepository to exclusions list in @EnableJpaRepositories in JpaDaoConfig - * - add the package of this JpaRepository to @EnableJpaRepositories in DefaultDedicatedJpaDaoConfig - * - add the package of this JpaRepository to @EnableJpaRepositories in DedicatedJpaDaoConfig - * - add the entity class to packages list in dedicatedEntityManagerFactory in DedicatedJpaDaoConfig - * */ -@DedicatedDataSource +@DedicatedEventsDataSource @Configuration @EnableJpaRepositories(value = {"org.thingsboard.server.dao.sql.event", "org.thingsboard.server.dao.sql.audit"}, bootstrapMode = BootstrapMode.LAZY, - entityManagerFactoryRef = "dedicatedEntityManagerFactory", transactionManagerRef = "dedicatedTransactionManager") -public class DedicatedJpaDaoConfig { + entityManagerFactoryRef = "eventsEntityManagerFactory", transactionManagerRef = "eventsTransactionManager") +public class DedicatedEventsJpaDaoConfig { - public static final String DEDICATED_PERSISTENCE_UNIT = "dedicated"; - public static final String DEDICATED_TRANSACTION_MANAGER = DEDICATED_PERSISTENCE_UNIT + "TransactionManager"; - public static final String DEDICATED_TRANSACTION_TEMPLATE = DEDICATED_PERSISTENCE_UNIT + "TransactionTemplate"; - public static final String DEDICATED_JDBC_TEMPLATE = DEDICATED_PERSISTENCE_UNIT + "JdbcTemplate"; + public static final String EVENTS_PERSISTENCE_UNIT = "events"; + public static final String EVENTS_TRANSACTION_MANAGER = EVENTS_PERSISTENCE_UNIT + "TransactionManager"; + public static final String EVENTS_TRANSACTION_TEMPLATE = EVENTS_PERSISTENCE_UNIT + "TransactionTemplate"; + public static final String EVENTS_JDBC_TEMPLATE = EVENTS_PERSISTENCE_UNIT + "JdbcTemplate"; @Bean - @ConfigurationProperties("spring.datasource.dedicated") - public DataSourceProperties dedicatedDataSourceProperties() { + @ConfigurationProperties("spring.datasource.events") + public DataSourceProperties eventsDataSourceProperties() { return new DataSourceProperties(); } - @ConfigurationProperties(prefix = "spring.datasource.dedicated.hikari") + @ConfigurationProperties(prefix = "spring.datasource.events.hikari") @Bean - public DataSource dedicatedDataSource(@Qualifier("dedicatedDataSourceProperties") DataSourceProperties dedicatedDataSourceProperties) { - return dedicatedDataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build(); + public DataSource eventsDataSource(@Qualifier("eventsDataSourceProperties") DataSourceProperties eventsDataSourceProperties) { + return eventsDataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build(); } @Bean - public LocalContainerEntityManagerFactoryBean dedicatedEntityManagerFactory(@Qualifier("dedicatedDataSource") DataSource dedicatedDataSource, + public LocalContainerEntityManagerFactoryBean eventsEntityManagerFactory(@Qualifier("eventsDataSource") DataSource eventsDataSource, EntityManagerFactoryBuilder builder) { return builder - .dataSource(dedicatedDataSource) + .dataSource(eventsDataSource) .packages(LifecycleEventEntity.class, StatisticsEventEntity.class, ErrorEventEntity.class, RuleNodeDebugEventEntity.class, RuleChainDebugEventEntity.class, AuditLogEntity.class) - .persistenceUnit(DEDICATED_PERSISTENCE_UNIT) + .persistenceUnit(EVENTS_PERSISTENCE_UNIT) .build(); } - @Bean(DEDICATED_TRANSACTION_MANAGER) - public JpaTransactionManager dedicatedTransactionManager(@Qualifier("dedicatedEntityManagerFactory") LocalContainerEntityManagerFactoryBean dedicatedEntityManagerFactory) { - return new JpaTransactionManager(Objects.requireNonNull(dedicatedEntityManagerFactory.getObject())); + @Bean(EVENTS_TRANSACTION_MANAGER) + public JpaTransactionManager eventsTransactionManager(@Qualifier("eventsEntityManagerFactory") LocalContainerEntityManagerFactoryBean eventsEntityManagerFactory) { + return new JpaTransactionManager(Objects.requireNonNull(eventsEntityManagerFactory.getObject())); } - @Bean(DEDICATED_TRANSACTION_TEMPLATE) - public TransactionTemplate dedicatedTransactionTemplate(@Qualifier(DEDICATED_TRANSACTION_MANAGER) JpaTransactionManager dedicatedTransactionManager) { - return new TransactionTemplate(dedicatedTransactionManager); + @Bean(EVENTS_TRANSACTION_TEMPLATE) + public TransactionTemplate eventsTransactionTemplate(@Qualifier(EVENTS_TRANSACTION_MANAGER) JpaTransactionManager eventsTransactionManager) { + return new TransactionTemplate(eventsTransactionManager); } - @Bean(DEDICATED_JDBC_TEMPLATE) - public JdbcTemplate dedicatedJdbcTemplate(@Qualifier("dedicatedDataSource") DataSource dedicatedDataSource) { - return new JdbcTemplate(dedicatedDataSource); + @Bean(EVENTS_JDBC_TEMPLATE) + public JdbcTemplate eventsJdbcTemplate(@Qualifier("eventsDataSource") DataSource eventsDataSource) { + return new JdbcTemplate(eventsDataSource); } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/config/DefaultDataSource.java b/dao/src/main/java/org/thingsboard/server/dao/config/DefaultDataSource.java index 298ed12005..ad6c398ea6 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/config/DefaultDataSource.java +++ b/dao/src/main/java/org/thingsboard/server/dao/config/DefaultDataSource.java @@ -21,6 +21,6 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @Retention(RetentionPolicy.RUNTIME) -@ConditionalOnProperty(value = "spring.datasource.dedicated.enabled", havingValue = "false", matchIfMissing = true) +@ConditionalOnProperty(value = "spring.datasource.events.enabled", havingValue = "false", matchIfMissing = true) public @interface DefaultDataSource { } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/audit/DedicatedJpaAuditLogDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/audit/DedicatedJpaAuditLogDao.java index 2d60c3adc7..12069f87be 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/audit/DedicatedJpaAuditLogDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/audit/DedicatedJpaAuditLogDao.java @@ -24,51 +24,51 @@ import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import org.thingsboard.server.common.data.audit.AuditLog; import org.thingsboard.server.common.data.id.TenantId; -import org.thingsboard.server.dao.config.DedicatedDataSource; -import org.thingsboard.server.dao.sqlts.insert.sql.DedicatedSqlPartitioningRepository; +import org.thingsboard.server.dao.config.DedicatedEventsDataSource; +import org.thingsboard.server.dao.sqlts.insert.sql.DedicatedEventsSqlPartitioningRepository; import org.thingsboard.server.dao.util.SqlDao; import java.util.Collection; import java.util.UUID; -import static org.thingsboard.server.dao.config.DedicatedJpaDaoConfig.DEDICATED_JDBC_TEMPLATE; -import static org.thingsboard.server.dao.config.DedicatedJpaDaoConfig.DEDICATED_PERSISTENCE_UNIT; -import static org.thingsboard.server.dao.config.DedicatedJpaDaoConfig.DEDICATED_TRANSACTION_MANAGER; +import static org.thingsboard.server.dao.config.DedicatedEventsJpaDaoConfig.EVENTS_JDBC_TEMPLATE; +import static org.thingsboard.server.dao.config.DedicatedEventsJpaDaoConfig.EVENTS_PERSISTENCE_UNIT; +import static org.thingsboard.server.dao.config.DedicatedEventsJpaDaoConfig.EVENTS_TRANSACTION_MANAGER; -@DedicatedDataSource +@DedicatedEventsDataSource @Component @SqlDao public class DedicatedJpaAuditLogDao extends JpaAuditLogDao { @Autowired - @Qualifier(DEDICATED_JDBC_TEMPLATE) + @Qualifier(EVENTS_JDBC_TEMPLATE) private JdbcTemplate jdbcTemplate; - @PersistenceContext(unitName = DEDICATED_PERSISTENCE_UNIT) + @PersistenceContext(unitName = EVENTS_PERSISTENCE_UNIT) private EntityManager entityManager; - public DedicatedJpaAuditLogDao(AuditLogRepository auditLogRepository, DedicatedSqlPartitioningRepository partitioningRepository) { + public DedicatedJpaAuditLogDao(AuditLogRepository auditLogRepository, DedicatedEventsSqlPartitioningRepository partitioningRepository) { super(auditLogRepository, partitioningRepository); } - @Transactional(transactionManager = DEDICATED_TRANSACTION_MANAGER) + @Transactional(transactionManager = EVENTS_TRANSACTION_MANAGER) @Override public AuditLog save(TenantId tenantId, AuditLog domain) { return super.save(tenantId, domain); } - @Transactional(transactionManager = DEDICATED_TRANSACTION_MANAGER) + @Transactional(transactionManager = EVENTS_TRANSACTION_MANAGER) @Override public AuditLog saveAndFlush(TenantId tenantId, AuditLog domain) { return super.saveAndFlush(tenantId, domain); } - @Transactional(transactionManager = DEDICATED_TRANSACTION_MANAGER) + @Transactional(transactionManager = EVENTS_TRANSACTION_MANAGER) @Override public boolean removeById(TenantId tenantId, UUID id) { return super.removeById(tenantId, id); } - @Transactional(transactionManager = DEDICATED_TRANSACTION_MANAGER) + @Transactional(transactionManager = EVENTS_TRANSACTION_MANAGER) @Override public void removeAllByIds(Collection ids) { super.removeAllByIds(ids); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/event/DedicatedEventInsertRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/event/DedicatedEventInsertRepository.java index 78462e3819..65169dcbc7 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/event/DedicatedEventInsertRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/event/DedicatedEventInsertRepository.java @@ -19,17 +19,17 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; import org.springframework.transaction.support.TransactionTemplate; -import org.thingsboard.server.dao.config.DedicatedDataSource; +import org.thingsboard.server.dao.config.DedicatedEventsDataSource; -import static org.thingsboard.server.dao.config.DedicatedJpaDaoConfig.DEDICATED_JDBC_TEMPLATE; -import static org.thingsboard.server.dao.config.DedicatedJpaDaoConfig.DEDICATED_TRANSACTION_TEMPLATE; +import static org.thingsboard.server.dao.config.DedicatedEventsJpaDaoConfig.EVENTS_JDBC_TEMPLATE; +import static org.thingsboard.server.dao.config.DedicatedEventsJpaDaoConfig.EVENTS_TRANSACTION_TEMPLATE; -@DedicatedDataSource +@DedicatedEventsDataSource @Repository public class DedicatedEventInsertRepository extends EventInsertRepository { - public DedicatedEventInsertRepository(@Qualifier(DEDICATED_JDBC_TEMPLATE) JdbcTemplate jdbcTemplate, - @Qualifier(DEDICATED_TRANSACTION_TEMPLATE) TransactionTemplate transactionTemplate) { + public DedicatedEventInsertRepository(@Qualifier(EVENTS_JDBC_TEMPLATE) JdbcTemplate jdbcTemplate, + @Qualifier(EVENTS_TRANSACTION_TEMPLATE) TransactionTemplate transactionTemplate) { super(jdbcTemplate, transactionTemplate); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/event/DedicatedJpaEventDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/event/DedicatedJpaEventDao.java index bfaaeadfe3..9b7af5e7f7 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/event/DedicatedJpaEventDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/event/DedicatedJpaEventDao.java @@ -17,18 +17,18 @@ package org.thingsboard.server.dao.sql.event; import org.springframework.stereotype.Component; import org.thingsboard.server.common.stats.StatsFactory; -import org.thingsboard.server.dao.config.DedicatedDataSource; +import org.thingsboard.server.dao.config.DedicatedEventsDataSource; import org.thingsboard.server.dao.sql.ScheduledLogExecutorComponent; -import org.thingsboard.server.dao.sqlts.insert.sql.DedicatedSqlPartitioningRepository; +import org.thingsboard.server.dao.sqlts.insert.sql.DedicatedEventsSqlPartitioningRepository; import org.thingsboard.server.dao.util.SqlDao; -@DedicatedDataSource +@DedicatedEventsDataSource @Component @SqlDao public class DedicatedJpaEventDao extends JpaBaseEventDao { public DedicatedJpaEventDao(EventPartitionConfiguration partitionConfiguration, - DedicatedSqlPartitioningRepository partitioningRepository, + DedicatedEventsSqlPartitioningRepository partitioningRepository, LifecycleEventRepository lcEventRepository, StatisticsEventRepository statsEventRepository, ErrorEventRepository errorEventRepository, diff --git a/dao/src/main/java/org/thingsboard/server/dao/sqlts/insert/sql/DedicatedSqlPartitioningRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sqlts/insert/sql/DedicatedEventsSqlPartitioningRepository.java similarity index 76% rename from dao/src/main/java/org/thingsboard/server/dao/sqlts/insert/sql/DedicatedSqlPartitioningRepository.java rename to dao/src/main/java/org/thingsboard/server/dao/sqlts/insert/sql/DedicatedEventsSqlPartitioningRepository.java index 78b477778d..7e1be6bbd9 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sqlts/insert/sql/DedicatedSqlPartitioningRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sqlts/insert/sql/DedicatedEventsSqlPartitioningRepository.java @@ -21,27 +21,27 @@ 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.config.DedicatedDataSource; +import org.thingsboard.server.dao.config.DedicatedEventsDataSource; import org.thingsboard.server.dao.timeseries.SqlPartition; -import static org.thingsboard.server.dao.config.DedicatedJpaDaoConfig.DEDICATED_JDBC_TEMPLATE; -import static org.thingsboard.server.dao.config.DedicatedJpaDaoConfig.DEDICATED_TRANSACTION_MANAGER; +import static org.thingsboard.server.dao.config.DedicatedEventsJpaDaoConfig.EVENTS_JDBC_TEMPLATE; +import static org.thingsboard.server.dao.config.DedicatedEventsJpaDaoConfig.EVENTS_TRANSACTION_MANAGER; -@DedicatedDataSource +@DedicatedEventsDataSource @Repository -public class DedicatedSqlPartitioningRepository extends SqlPartitioningRepository { +public class DedicatedEventsSqlPartitioningRepository extends SqlPartitioningRepository { @Autowired - @Qualifier(DEDICATED_JDBC_TEMPLATE) + @Qualifier(EVENTS_JDBC_TEMPLATE) private JdbcTemplate jdbcTemplate; - @Transactional(propagation = Propagation.NOT_SUPPORTED, transactionManager = DEDICATED_TRANSACTION_MANAGER) + @Transactional(propagation = Propagation.NOT_SUPPORTED, transactionManager = EVENTS_TRANSACTION_MANAGER) @Override public void save(SqlPartition partition) { super.save(partition); } - @Transactional(propagation = Propagation.NOT_SUPPORTED, transactionManager = DEDICATED_TRANSACTION_MANAGER) + @Transactional(propagation = Propagation.NOT_SUPPORTED, transactionManager = EVENTS_TRANSACTION_MANAGER) @Override public void createPartitionIfNotExists(String table, long entityTs, long partitionDurationMs) { super.createPartitionIfNotExists(table, entityTs, partitionDurationMs); diff --git a/dao/src/test/java/org/thingsboard/server/dao/AbstractDaoServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/AbstractDaoServiceTest.java index 81c443cc33..c4bb8fb336 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/AbstractDaoServiceTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/AbstractDaoServiceTest.java @@ -25,14 +25,14 @@ import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; import org.springframework.test.context.support.DirtiesContextTestExecutionListener; import org.thingsboard.server.common.stats.StatsFactory; -import org.thingsboard.server.dao.config.DedicatedJpaDaoConfig; +import org.thingsboard.server.dao.config.DedicatedEventsJpaDaoConfig; import org.thingsboard.server.dao.config.JpaDaoConfig; import org.thingsboard.server.dao.config.SqlTsDaoConfig; import org.thingsboard.server.dao.config.SqlTsLatestDaoConfig; import org.thingsboard.server.dao.service.DaoSqlTest; @RunWith(SpringRunner.class) -@ContextConfiguration(classes = {JpaDaoConfig.class, SqlTsDaoConfig.class, SqlTsLatestDaoConfig.class, DedicatedJpaDaoConfig.class}) +@ContextConfiguration(classes = {JpaDaoConfig.class, SqlTsDaoConfig.class, SqlTsLatestDaoConfig.class, DedicatedEventsJpaDaoConfig.class}) @DaoSqlTest @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) @TestExecutionListeners({ diff --git a/dao/src/test/java/org/thingsboard/server/dao/AbstractJpaDaoTest.java b/dao/src/test/java/org/thingsboard/server/dao/AbstractJpaDaoTest.java index c52b09ff3a..f3ddda769d 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/AbstractJpaDaoTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/AbstractJpaDaoTest.java @@ -24,7 +24,7 @@ import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; import org.springframework.test.context.support.DirtiesContextTestExecutionListener; import org.thingsboard.server.common.stats.StatsFactory; -import org.thingsboard.server.dao.config.DedicatedJpaDaoConfig; +import org.thingsboard.server.dao.config.DedicatedEventsJpaDaoConfig; import org.thingsboard.server.dao.config.DefaultDedicatedJpaDaoConfig; import org.thingsboard.server.dao.config.JpaDaoConfig; import org.thingsboard.server.dao.config.SqlTsDaoConfig; @@ -35,7 +35,7 @@ import org.thingsboard.server.dao.service.DaoSqlTest; * Created by Valerii Sosliuk on 4/22/2017. */ @RunWith(SpringRunner.class) -@ContextConfiguration(classes = {JpaDaoConfig.class, SqlTsDaoConfig.class, SqlTsLatestDaoConfig.class, DedicatedJpaDaoConfig.class, DefaultDedicatedJpaDaoConfig.class}) +@ContextConfiguration(classes = {JpaDaoConfig.class, SqlTsDaoConfig.class, SqlTsLatestDaoConfig.class, DedicatedEventsJpaDaoConfig.class, DefaultDedicatedJpaDaoConfig.class}) @DaoSqlTest @TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, diff --git a/dao/src/test/java/org/thingsboard/server/dao/PostgreSqlInitializer.java b/dao/src/test/java/org/thingsboard/server/dao/PostgreSqlInitializer.java index 82e8249286..80938b5724 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/PostgreSqlInitializer.java +++ b/dao/src/test/java/org/thingsboard/server/dao/PostgreSqlInitializer.java @@ -52,17 +52,6 @@ public class PostgreSqlInitializer { } log.info("Postgres DB is initialized!"); } - public static void initDedicatedDb(Connection conn) { - log.info("initialize Postgres DB..."); - try { - URL sqlFileUrl = Resources.getResource("sql/dedicated.sql"); - String sql = Resources.toString(sqlFileUrl, Charsets.UTF_8); - conn.createStatement().execute(sql); - } catch (IOException | SQLException e) { - throw new RuntimeException("Unable to init the Postgres database. Reason: " + e.getMessage(), e); - } - log.info("Postgres DB is initialized!"); - } private static void cleanUpDb(Connection conn) { log.info("clean up Postgres DB..."); @@ -74,4 +63,5 @@ public class PostgreSqlInitializer { throw new RuntimeException("Unable to clean up the Postgres database. Reason: " + e.getMessage(), e); } } + } diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/event/sql/EventServiceSqlTest_DedicatedDataSource.java b/dao/src/test/java/org/thingsboard/server/dao/service/event/sql/EventServiceSqlTest_DedicatedEventsDataSource.java similarity index 74% rename from dao/src/test/java/org/thingsboard/server/dao/service/event/sql/EventServiceSqlTest_DedicatedDataSource.java rename to dao/src/test/java/org/thingsboard/server/dao/service/event/sql/EventServiceSqlTest_DedicatedEventsDataSource.java index e7319f3128..cb765c29d0 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/event/sql/EventServiceSqlTest_DedicatedDataSource.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/event/sql/EventServiceSqlTest_DedicatedEventsDataSource.java @@ -20,9 +20,9 @@ import org.thingsboard.server.dao.service.DaoSqlTest; @DaoSqlTest @TestPropertySource(properties = { - "spring.datasource.dedicated.enabled=true", - "spring.datasource.dedicated.url=${spring.datasource.url}", - "spring.datasource.dedicated.driverClassName=${spring.datasource.driverClassName}" + "spring.datasource.events.enabled=true", + "spring.datasource.events.url=${spring.datasource.url}", + "spring.datasource.events.driverClassName=${spring.datasource.driverClassName}" }) -public class EventServiceSqlTest_DedicatedDataSource extends EventServiceSqlTest { +public class EventServiceSqlTest_DedicatedEventsDataSource extends EventServiceSqlTest { } From 9569812b5fac78e04102cb0193ac73f01e006f69 Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Fri, 9 Aug 2024 14:47:42 +0300 Subject: [PATCH 09/10] Minor refactoring for DedicatedEventsJpaDaoConfig --- .../server/dao/config/DedicatedEventsJpaDaoConfig.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/dao/src/main/java/org/thingsboard/server/dao/config/DedicatedEventsJpaDaoConfig.java b/dao/src/main/java/org/thingsboard/server/dao/config/DedicatedEventsJpaDaoConfig.java index 03c0d76bbe..e4a0b36100 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/config/DedicatedEventsJpaDaoConfig.java +++ b/dao/src/main/java/org/thingsboard/server/dao/config/DedicatedEventsJpaDaoConfig.java @@ -46,6 +46,7 @@ import java.util.Objects; public class DedicatedEventsJpaDaoConfig { public static final String EVENTS_PERSISTENCE_UNIT = "events"; + public static final String EVENTS_DATA_SOURCE = EVENTS_PERSISTENCE_UNIT + "DataSource"; public static final String EVENTS_TRANSACTION_MANAGER = EVENTS_PERSISTENCE_UNIT + "TransactionManager"; public static final String EVENTS_TRANSACTION_TEMPLATE = EVENTS_PERSISTENCE_UNIT + "TransactionTemplate"; public static final String EVENTS_JDBC_TEMPLATE = EVENTS_PERSISTENCE_UNIT + "JdbcTemplate"; @@ -57,14 +58,14 @@ public class DedicatedEventsJpaDaoConfig { } @ConfigurationProperties(prefix = "spring.datasource.events.hikari") - @Bean + @Bean(EVENTS_DATA_SOURCE) public DataSource eventsDataSource(@Qualifier("eventsDataSourceProperties") DataSourceProperties eventsDataSourceProperties) { return eventsDataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build(); } @Bean - public LocalContainerEntityManagerFactoryBean eventsEntityManagerFactory(@Qualifier("eventsDataSource") DataSource eventsDataSource, - EntityManagerFactoryBuilder builder) { + public LocalContainerEntityManagerFactoryBean eventsEntityManagerFactory(@Qualifier(EVENTS_DATA_SOURCE) DataSource eventsDataSource, + EntityManagerFactoryBuilder builder) { return builder .dataSource(eventsDataSource) .packages(LifecycleEventEntity.class, StatisticsEventEntity.class, ErrorEventEntity.class, RuleNodeDebugEventEntity.class, RuleChainDebugEventEntity.class, AuditLogEntity.class) @@ -83,7 +84,7 @@ public class DedicatedEventsJpaDaoConfig { } @Bean(EVENTS_JDBC_TEMPLATE) - public JdbcTemplate eventsJdbcTemplate(@Qualifier("eventsDataSource") DataSource eventsDataSource) { + public JdbcTemplate eventsJdbcTemplate(@Qualifier(EVENTS_DATA_SOURCE) DataSource eventsDataSource) { return new JdbcTemplate(eventsDataSource); } From 003a917d4da353e5573001bf928723e9c3918a15 Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Thu, 15 Aug 2024 12:47:34 +0300 Subject: [PATCH 10/10] Refactor JpaAbstractDao --- .../java/org/thingsboard/server/dao/sql/JpaAbstractDao.java | 5 +++++ .../server/dao/sql/JpaPartitionedAbstractDao.java | 4 ---- .../server/dao/sql/audit/DedicatedJpaAuditLogDao.java | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractDao.java index 988a79bb85..8002730686 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractDao.java @@ -81,6 +81,7 @@ public abstract class JpaAbstractDao, D> } protected E doSave(E entity, boolean isNew) { + EntityManager entityManager = getEntityManager(); if (isNew) { if (entity instanceof HasVersion versionedEntity) { versionedEntity.setVersion(1L); @@ -179,6 +180,10 @@ public abstract class JpaAbstractDao, D> return ModelConstants.TENANT_ID_COLUMN; } + protected EntityManager getEntityManager() { + return entityManager; + } + protected JdbcTemplate getJdbcTemplate() { return jdbcTemplate; } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/JpaPartitionedAbstractDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/JpaPartitionedAbstractDao.java index dad6fbf4f7..6afb8b4ede 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/JpaPartitionedAbstractDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/JpaPartitionedAbstractDao.java @@ -29,8 +29,4 @@ public abstract class JpaPartitionedAbstractDao, D> exte public abstract void createPartition(E entity); - protected EntityManager getEntityManager() { - return entityManager; - } - } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/audit/DedicatedJpaAuditLogDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/audit/DedicatedJpaAuditLogDao.java index 12069f87be..d40e1e5474 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/audit/DedicatedJpaAuditLogDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/audit/DedicatedJpaAuditLogDao.java @@ -64,8 +64,8 @@ public class DedicatedJpaAuditLogDao extends JpaAuditLogDao { @Transactional(transactionManager = EVENTS_TRANSACTION_MANAGER) @Override - public boolean removeById(TenantId tenantId, UUID id) { - return super.removeById(tenantId, id); + public void removeById(TenantId tenantId, UUID id) { + super.removeById(tenantId, id); } @Transactional(transactionManager = EVENTS_TRANSACTION_MANAGER)