From 289c5674db59e6e666a90ad4f5aaebc5d1353fcf Mon Sep 17 00:00:00 2001 From: Andrii Landiak Date: Wed, 17 Dec 2025 17:36:57 +0200 Subject: [PATCH 1/5] Fetch and drop partitioning tables --- .../server/service/ttl/EdgeEventsCleanUpService.java | 1 - .../server/dao/sql/asset/AssetRepository.java | 3 --- .../server/dao/sql/edge/JpaBaseEdgeEventDao.java | 3 --- .../dao/sql/entityview/EntityViewRepository.java | 3 --- .../server/dao/sql/entityview/JpaEntityViewDao.java | 3 --- .../server/dao/sql/relation/JpaRelationDao.java | 11 +++-------- .../server/dao/sql/tenant/TenantRepository.java | 3 --- .../dao/sql/usagerecord/ApiUsageStateRepository.java | 3 --- .../dao/sql/usagerecord/JpaApiUsageStateDao.java | 3 --- .../server/dao/sql/widget/JpaWidgetTypeDao.java | 3 --- .../server/dao/sql/widget/JpaWidgetsBundleDao.java | 3 --- .../dao/sql/widget/WidgetsBundleRepository.java | 4 ---- .../sqlts/insert/sql/SqlPartitioningRepository.java | 5 +++-- dao/src/main/resources/sql/schema-ts-psql.sql | 8 ++++---- 14 files changed, 10 insertions(+), 46 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/ttl/EdgeEventsCleanUpService.java b/application/src/main/java/org/thingsboard/server/service/ttl/EdgeEventsCleanUpService.java index 8b38ca32bb..dfa8f36a3e 100644 --- a/application/src/main/java/org/thingsboard/server/service/ttl/EdgeEventsCleanUpService.java +++ b/application/src/main/java/org/thingsboard/server/service/ttl/EdgeEventsCleanUpService.java @@ -20,7 +20,6 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; -import org.thingsboard.server.dao.edge.EdgeEventDao; import org.thingsboard.server.dao.edge.EdgeEventService; import org.thingsboard.server.dao.sqlts.insert.sql.SqlPartitioningRepository; import org.thingsboard.server.queue.discovery.PartitionService; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/asset/AssetRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/asset/AssetRepository.java index e475864684..be36ce7dd1 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/asset/AssetRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/asset/AssetRepository.java @@ -30,9 +30,6 @@ import org.thingsboard.server.dao.model.sql.AssetInfoEntity; import java.util.List; import java.util.UUID; -/** - * Created by Valerii Sosliuk on 5/21/2017. - */ public interface AssetRepository extends JpaRepository, ExportableEntityRepository { @Query("SELECT new org.thingsboard.server.dao.model.sql.AssetInfoEntity(a, c.title, c.additionalInfo, p.name) " + diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/edge/JpaBaseEdgeEventDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/edge/JpaBaseEdgeEventDao.java index ea2abbba8a..e30946f744 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/edge/JpaBaseEdgeEventDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/edge/JpaBaseEdgeEventDao.java @@ -86,9 +86,6 @@ public class JpaBaseEdgeEventDao extends JpaPartitionedAbstractDao queue; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/EntityViewRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/EntityViewRepository.java index 6094e9b171..b460699b22 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/EntityViewRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/EntityViewRepository.java @@ -29,9 +29,6 @@ import org.thingsboard.server.dao.model.sql.EntityViewInfoEntity; import java.util.List; import java.util.UUID; -/** - * Created by Victor Basanets on 8/31/2017. - */ public interface EntityViewRepository extends JpaRepository, ExportableEntityRepository { @Query("SELECT new org.thingsboard.server.dao.model.sql.EntityViewInfoEntity(e, c.title, c.additionalInfo) " + diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/JpaEntityViewDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/JpaEntityViewDao.java index 44d8a09ff4..dd9f302588 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/JpaEntityViewDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/JpaEntityViewDao.java @@ -44,9 +44,6 @@ import java.util.UUID; import static org.thingsboard.server.dao.DaoUtil.convertTenantEntityTypesToDto; -/** - * Created by Victor Basanets on 8/31/2017. - */ @Component @Slf4j @SqlDao diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/relation/JpaRelationDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/relation/JpaRelationDao.java index 7417418f54..3d9115dda0 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/relation/JpaRelationDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/relation/JpaRelationDao.java @@ -49,9 +49,6 @@ import static org.thingsboard.server.dao.model.ModelConstants.RELATION_TYPE_GROU import static org.thingsboard.server.dao.model.ModelConstants.RELATION_TYPE_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.VERSION_COLUMN; -/** - * Created by Valerii Sosliuk on 5/29/2017. - */ @Slf4j @Component @SqlDao @@ -256,9 +253,7 @@ public class JpaRelationDao extends JpaAbstractDaoListeningExecutorService imple if (!CollectionUtils.isEmpty(relationTypeGroups)) { sqlBuilder.append("AND relation_type_group IN (?"); - for (int i = 1; i < relationTypeGroups.size(); i++) { - sqlBuilder.append(", ?"); - } + sqlBuilder.append(", ?".repeat(Math.max(0, relationTypeGroups.size() - 1))); sqlBuilder.append(")"); params.addAll(relationTypeGroups); } @@ -285,12 +280,12 @@ public class JpaRelationDao extends JpaAbstractDaoListeningExecutorService imple relation.setTypeGroup(RelationTypeGroup.valueOf((String) relationTypeGroup)); relation.setVersion((Long) version); return relation; - }) - .collect(Collectors.toList()); + }).toList(); } @Override public List findRuleNodeToRuleChainRelations(RuleChainType ruleChainType, int limit) { return DaoUtil.convertDataList(relationRepository.findRuleNodeToRuleChainRelations(ruleChainType, PageRequest.of(0, limit))); } + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/TenantRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/TenantRepository.java index 08859d5f63..f424afaf39 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/TenantRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/TenantRepository.java @@ -28,9 +28,6 @@ import org.thingsboard.server.dao.model.sql.TenantInfoEntity; import java.util.List; import java.util.UUID; -/** - * Created by Valerii Sosliuk on 4/30/2017. - */ public interface TenantRepository extends JpaRepository { @Query("SELECT new org.thingsboard.server.dao.model.sql.TenantInfoEntity(t, p.name) " + diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/usagerecord/ApiUsageStateRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/usagerecord/ApiUsageStateRepository.java index 98e62fc110..b3afa997c9 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/usagerecord/ApiUsageStateRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/usagerecord/ApiUsageStateRepository.java @@ -29,9 +29,6 @@ import org.thingsboard.server.dao.model.sql.ApiUsageStateEntity; import java.util.List; import java.util.UUID; -/** - * @author Valerii Sosliuk - */ public interface ApiUsageStateRepository extends JpaRepository { @Query("SELECT ur FROM ApiUsageStateEntity ur WHERE ur.tenantId = :tenantId " + diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/usagerecord/JpaApiUsageStateDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/usagerecord/JpaApiUsageStateDao.java index ec68fa34c3..83f9c0693c 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/usagerecord/JpaApiUsageStateDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/usagerecord/JpaApiUsageStateDao.java @@ -34,9 +34,6 @@ import org.thingsboard.server.dao.util.SqlDao; import java.util.List; import java.util.UUID; -/** - * @author Andrii Shvaika - */ @Component @SqlDao public class JpaApiUsageStateDao extends JpaAbstractDao implements ApiUsageStateDao { diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDao.java index 18fb544dcb..900e508736 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDao.java @@ -53,9 +53,6 @@ import java.util.stream.Collectors; import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID; -/** - * Created by Valerii Sosliuk on 4/29/2017. - */ @Component @SqlDao public class JpaWidgetTypeDao extends JpaAbstractDao implements WidgetTypeDao, TenantEntityDao { diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDao.java index bc81be054a..d3f5e9c208 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDao.java @@ -42,9 +42,6 @@ import java.util.UUID; import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID; -/** - * Created by Valerii Sosliuk on 4/23/2017. - */ @Component @SqlDao public class JpaWidgetsBundleDao extends JpaAbstractDao implements WidgetsBundleDao, TenantEntityDao { diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetsBundleRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetsBundleRepository.java index de778588dd..3033154484 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetsBundleRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetsBundleRepository.java @@ -21,7 +21,6 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; -import org.thingsboard.server.common.data.edqs.fields.WidgetTypeFields; import org.thingsboard.server.common.data.edqs.fields.WidgetsBundleFields; import org.thingsboard.server.dao.ExportableEntityRepository; import org.thingsboard.server.dao.model.sql.WidgetsBundleEntity; @@ -29,9 +28,6 @@ import org.thingsboard.server.dao.model.sql.WidgetsBundleEntity; import java.util.List; import java.util.UUID; -/** - * Created by Valerii Sosliuk on 4/23/2017. - */ public interface WidgetsBundleRepository extends JpaRepository, ExportableEntityRepository { WidgetsBundleEntity findWidgetsBundleByTenantIdAndAlias(UUID tenantId, String alias); 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 f9b0be2395..55ecb9269d 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 @@ -41,7 +41,7 @@ public class SqlPartitioningRepository { @Autowired private JdbcTemplate jdbcTemplate; - private static final String SELECT_PARTITIONS_STMT = "SELECT tablename from pg_tables WHERE schemaname = 'public' and tablename like concat(?, '_%')"; + private static final String SELECT_PARTITIONS_STMT = "SELECT tablename from pg_tables WHERE schemaname = current_schema() and tablename like concat(?, '_%')"; private static final int PSQL_VERSION_14 = 140000; private volatile Integer currentServerVersion; @@ -54,7 +54,8 @@ public class SqlPartitioningRepository { getJdbcTemplate().execute(partition.getQuery()); } - @Transactional(propagation = Propagation.NOT_SUPPORTED) // executing non-transactionally, so that parent transaction is not aborted on partition save error + @Transactional(propagation = Propagation.NOT_SUPPORTED) + // executing non-transactionally, so that parent transaction is not aborted on partition save error public void createPartitionIfNotExists(String table, long entityTs, long partitionDurationMs) { long partitionStartTs = calculatePartitionStartTime(entityTs, partitionDurationMs); Map partitions = tablesPartitions.computeIfAbsent(table, t -> new ConcurrentHashMap<>()); diff --git a/dao/src/main/resources/sql/schema-ts-psql.sql b/dao/src/main/resources/sql/schema-ts-psql.sql index 1c88ca5604..08dfa315c9 100644 --- a/dao/src/main/resources/sql/schema-ts-psql.sql +++ b/dao/src/main/resources/sql/schema-ts-psql.sql @@ -72,7 +72,7 @@ BEGIN IF partition_type = 'YEARS' THEN FOR partition IN SELECT tablename FROM pg_tables - WHERE schemaname = 'public' + WHERE schemaname = current_schema() AND tablename like 'ts_kv_' || '%' AND tablename != 'ts_kv_latest' AND tablename != 'key_dictionary' @@ -93,7 +93,7 @@ BEGIN ELSE FOR partition IN SELECT tablename FROM pg_tables - WHERE schemaname = 'public' + WHERE schemaname = current_schema() AND tablename like 'ts_kv_' || '%' AND tablename != 'ts_kv_latest' AND tablename != 'key_dictionary' @@ -135,7 +135,7 @@ BEGIN ELSE FOR partition IN SELECT tablename FROM pg_tables - WHERE schemaname = 'public' + WHERE schemaname = current_schema() AND tablename like 'ts_kv_' || '%' AND tablename != 'ts_kv_latest' AND tablename != 'key_dictionary' @@ -205,7 +205,7 @@ BEGIN IF partition IS NOT NULL THEN IF NOT EXISTS(SELECT FROM pg_tables - WHERE schemaname = 'public' + WHERE schemaname = current_schema() AND tablename = partition) THEN partition := NULL; RAISE NOTICE 'Failed to found partition by ttl'; From 9684a1e8ad16300de6cbcf40348179cb57f139a1 Mon Sep 17 00:00:00 2001 From: Andrii Landiak Date: Wed, 17 Dec 2025 17:42:32 +0200 Subject: [PATCH 2/5] Revert --- .../server/dao/sqlts/insert/sql/SqlPartitioningRepository.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 55ecb9269d..0a7cf237c8 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 @@ -54,8 +54,7 @@ public class SqlPartitioningRepository { getJdbcTemplate().execute(partition.getQuery()); } - @Transactional(propagation = Propagation.NOT_SUPPORTED) - // executing non-transactionally, so that parent transaction is not aborted on partition save error + @Transactional(propagation = Propagation.NOT_SUPPORTED)// executing non-transactionally, so that parent transaction is not aborted on partition save error public void createPartitionIfNotExists(String table, long entityTs, long partitionDurationMs) { long partitionStartTs = calculatePartitionStartTime(entityTs, partitionDurationMs); Map partitions = tablesPartitions.computeIfAbsent(table, t -> new ConcurrentHashMap<>()); From 1baaed8279c5dcd29ceed94fe3ad262cadbfc741 Mon Sep 17 00:00:00 2001 From: Andrii Landiak Date: Wed, 17 Dec 2025 17:51:09 +0200 Subject: [PATCH 3/5] Improve EventsDeletionTaskProcessor to delete only non-debug types --- .../EventsDeletionTaskProcessor.java | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/application/src/main/java/org/thingsboard/server/service/housekeeper/processor/EventsDeletionTaskProcessor.java b/application/src/main/java/org/thingsboard/server/service/housekeeper/processor/EventsDeletionTaskProcessor.java index cd3953130f..8a0a1c882f 100644 --- a/application/src/main/java/org/thingsboard/server/service/housekeeper/processor/EventsDeletionTaskProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/housekeeper/processor/EventsDeletionTaskProcessor.java @@ -17,6 +17,11 @@ package org.thingsboard.server.service.housekeeper.processor; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; +import org.thingsboard.server.common.data.event.ErrorEventFilter; +import org.thingsboard.server.common.data.event.EventFilter; +import org.thingsboard.server.common.data.event.EventType; +import org.thingsboard.server.common.data.event.LifeCycleEventFilter; +import org.thingsboard.server.common.data.event.StatisticsEventFilter; import org.thingsboard.server.common.data.housekeeper.HousekeeperTask; import org.thingsboard.server.common.data.housekeeper.HousekeeperTaskType; import org.thingsboard.server.dao.event.EventService; @@ -29,7 +34,22 @@ public class EventsDeletionTaskProcessor extends HousekeeperTaskProcessor new ErrorEventFilter(); + case LC_EVENT -> new LifeCycleEventFilter(); + case STATS -> new StatisticsEventFilter(); + default -> throw new IllegalArgumentException("Unexpected non-debug event type: " + eventType); + }; } @Override From c4de8926e40779b6ce39413f22c53f4dc6e190ef Mon Sep 17 00:00:00 2001 From: Andrii Landiak Date: Wed, 7 Jan 2026 12:34:25 +0200 Subject: [PATCH 4/5] Refactoring after review --- .../EventsDeletionTaskProcessor.java | 23 ++----- .../server/dao/event/EventService.java | 2 + .../server/dao/event/BaseEventService.java | 12 ++-- .../server/dao/event/EventDao.java | 60 +------------------ .../server/dao/sql/event/JpaBaseEventDao.java | 8 ++- .../insert/sql/SqlPartitioningRepository.java | 2 +- 6 files changed, 22 insertions(+), 85 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/housekeeper/processor/EventsDeletionTaskProcessor.java b/application/src/main/java/org/thingsboard/server/service/housekeeper/processor/EventsDeletionTaskProcessor.java index 8a0a1c882f..738249f29c 100644 --- a/application/src/main/java/org/thingsboard/server/service/housekeeper/processor/EventsDeletionTaskProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/housekeeper/processor/EventsDeletionTaskProcessor.java @@ -17,15 +17,13 @@ package org.thingsboard.server.service.housekeeper.processor; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; -import org.thingsboard.server.common.data.event.ErrorEventFilter; -import org.thingsboard.server.common.data.event.EventFilter; import org.thingsboard.server.common.data.event.EventType; -import org.thingsboard.server.common.data.event.LifeCycleEventFilter; -import org.thingsboard.server.common.data.event.StatisticsEventFilter; import org.thingsboard.server.common.data.housekeeper.HousekeeperTask; import org.thingsboard.server.common.data.housekeeper.HousekeeperTaskType; import org.thingsboard.server.dao.event.EventService; +import java.util.Arrays; + @Component @RequiredArgsConstructor public class EventsDeletionTaskProcessor extends HousekeeperTaskProcessor { @@ -35,21 +33,8 @@ public class EventsDeletionTaskProcessor extends HousekeeperTaskProcessor new ErrorEventFilter(); - case LC_EVENT -> new LifeCycleEventFilter(); - case STATS -> new StatisticsEventFilter(); - default -> throw new IllegalArgumentException("Unexpected non-debug event type: " + eventType); - }; + EventType[] nonDebugEventTypes = Arrays.stream(EventType.values()).filter(eventType -> !eventType.isDebug()).toArray(EventType[]::new); + eventService.removeEvents(task.getTenantId(), task.getEntityId(), 0L, System.currentTimeMillis(), nonDebugEventTypes); } @Override diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/event/EventService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/event/EventService.java index 556ef0371d..26223f14e2 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/event/EventService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/event/EventService.java @@ -41,6 +41,8 @@ public interface EventService { void removeEvents(TenantId tenantId, EntityId entityId); + void removeEvents(TenantId tenantId, EntityId entityId, Long startTime, Long endTime, EventType... types); + void removeEvents(TenantId tenantId, EntityId entityId, EventFilter eventFilter, Long startTime, Long endTime); void cleanupEvents(long regularEventExpTs, long debugEventExpTs, boolean cleanupDb); diff --git a/dao/src/main/java/org/thingsboard/server/dao/event/BaseEventService.java b/dao/src/main/java/org/thingsboard/server/dao/event/BaseEventService.java index d81d8eb0f3..68ffce0acf 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/event/BaseEventService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/event/BaseEventService.java @@ -47,11 +47,6 @@ import java.util.stream.Collectors; @Slf4j public class BaseEventService implements EventService { - @Value("${sql.ttl.events.events_ttl:0}") - private long ttlInSec; - @Value("${sql.ttl.events.debug_events_ttl:604800}") - private long debugTtlInSec; - @Value("${event.debug.max-symbols:4096}") private int maxDebugEventSymbols; @@ -125,7 +120,12 @@ public class BaseEventService implements EventService { @Override public void removeEvents(TenantId tenantId, EntityId entityId) { - removeEvents(tenantId, entityId, null, null, null); + removeEvents(tenantId, entityId, null, null); + } + + @Override + public void removeEvents(TenantId tenantId, EntityId entityId, Long startTime, Long endTime, EventType... types) { + eventDao.removeEvents(tenantId.getId(), entityId.getId(), startTime, endTime, types); } @Override 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 7494ad2532..d8c7a0678a 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 @@ -25,80 +25,24 @@ import org.thingsboard.server.common.data.page.TimePageLink; import java.util.List; import java.util.UUID; -/** - * The Interface EventDao. - */ public interface EventDao { - /** - * Save or update event object async - * - * @param event the event object - * @return saved event object future - */ ListenableFuture saveAsync(Event event); - /** - * Find events by tenantId, entityId, eventType and pageLink. - * - * @param tenantId the tenantId - * @param entityId the entityId - * @param eventType the eventType - * @param pageLink the pageLink - * @return the event list - */ PageData findEvents(UUID tenantId, UUID entityId, EventType eventType, TimePageLink pageLink); PageData findEventByFilter(UUID tenantId, UUID entityId, EventFilter eventFilter, TimePageLink pageLink); - /** - * Find latest events by tenantId, entityId and eventType. - * - * @param tenantId the tenantId - * @param entityId the entityId - * @param eventType the eventType - * @param limit the limit - * @return the event list - */ List findLatestEvents(UUID tenantId, UUID entityId, EventType eventType, int limit); - /** - * Find latest debug IN event by tenantId, entityId. - * - * @param tenantId the tenantId - * @param entityId the entityId - * @return the latest debug IN event - */ Event findLatestDebugRuleNodeInEvent(UUID tenantId, UUID entityId); - /** - * Executes stored procedure to cleanup old events. Uses separate ttl for debug and other events. - * @param regularEventExpTs the expiration time of the regular events - * @param debugEventExpTs the expiration time of the debug events - * @param cleanupDb - */ void cleanupEvents(long regularEventExpTs, long debugEventExpTs, boolean cleanupDb); - /** - * Removes all events for the specified entity and time interval - * - * @param tenantId - * @param entityId - * @param startTime - * @param endTime - */ void removeEvents(UUID tenantId, UUID entityId, Long startTime, Long endTime); - /** - * - * Removes all events for the specified entity, event filter and time interval - * - * @param tenantId - * @param entityId - * @param eventFilter - * @param startTime - * @param endTime - */ + void removeEvents(UUID tenantId, UUID entityId, Long startTime, Long endTime, EventType... types); + void removeEvents(UUID tenantId, UUID entityId, EventFilter eventFilter, Long startTime, Long endTime); } 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 189e024608..5cd9012831 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 @@ -173,8 +173,14 @@ public class JpaBaseEventDao implements EventDao { @Override public void removeEvents(UUID tenantId, UUID entityId, Long startTime, Long endTime) { + removeEvents(tenantId, entityId, startTime, endTime, EventType.values()); + } + + @Override + public void removeEvents(UUID tenantId, UUID entityId, Long startTime, Long endTime, EventType... types) { log.debug("[{}][{}] Remove events [{}-{}] ", tenantId, entityId, startTime, endTime); - for (EventType eventType : EventType.values()) { + EventType[] eventTypes = (types == null || types.length == 0) ? EventType.values() : types; + for (EventType eventType : eventTypes) { getEventRepository(eventType).removeEvents(tenantId, entityId, startTime, endTime); } } 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 0a7cf237c8..550922bbc6 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 @@ -54,7 +54,7 @@ public class SqlPartitioningRepository { getJdbcTemplate().execute(partition.getQuery()); } - @Transactional(propagation = Propagation.NOT_SUPPORTED)// executing non-transactionally, so that parent transaction is not aborted on partition save error + @Transactional(propagation = Propagation.NOT_SUPPORTED) // executing non-transactionally, so that parent transaction is not aborted on partition save error public void createPartitionIfNotExists(String table, long entityTs, long partitionDurationMs) { long partitionStartTs = calculatePartitionStartTime(entityTs, partitionDurationMs); Map partitions = tablesPartitions.computeIfAbsent(table, t -> new ConcurrentHashMap<>()); From 9e748520e848daaf23254777df6e3ba70fcf418f Mon Sep 17 00:00:00 2001 From: Viacheslav Klimov Date: Fri, 9 Jan 2026 14:52:31 +0200 Subject: [PATCH 5/5] Fix invalid notification targets search by type --- .../NotificationTargetApiTest.java | 28 +++++++++++++++++++ .../JpaNotificationTargetDao.java | 2 +- .../NotificationTargetRepository.java | 15 +++++++--- 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/service/notification/NotificationTargetApiTest.java b/application/src/test/java/org/thingsboard/server/service/notification/NotificationTargetApiTest.java index adfe8a2435..2d865542a1 100644 --- a/application/src/test/java/org/thingsboard/server/service/notification/NotificationTargetApiTest.java +++ b/application/src/test/java/org/thingsboard/server/service/notification/NotificationTargetApiTest.java @@ -16,6 +16,7 @@ package org.thingsboard.server.service.notification; import com.fasterxml.jackson.core.type.TypeReference; +import org.apache.commons.lang3.RandomStringUtils; import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -30,7 +31,12 @@ import org.thingsboard.server.common.data.notification.targets.NotificationTarge import org.thingsboard.server.common.data.notification.targets.platform.AllUsersFilter; import org.thingsboard.server.common.data.notification.targets.platform.CustomerUsersFilter; import org.thingsboard.server.common.data.notification.targets.platform.PlatformUsersNotificationTargetConfig; +import org.thingsboard.server.common.data.notification.targets.platform.SystemAdministratorsFilter; import org.thingsboard.server.common.data.notification.targets.platform.UserListFilter; +import org.thingsboard.server.common.data.notification.targets.platform.UsersFilterType; +import org.thingsboard.server.common.data.notification.targets.slack.SlackConversation; +import org.thingsboard.server.common.data.notification.targets.slack.SlackConversationType; +import org.thingsboard.server.common.data.notification.targets.slack.SlackNotificationTargetConfig; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.dao.notification.NotificationTargetDao; @@ -175,6 +181,28 @@ public class NotificationTargetApiTest extends AbstractNotificationApiTest { assertThat(error).containsIgnoringCase("referenced by scheduled notification request"); } + @Test + public void findByTenantIdAndUsersFilterType() throws Exception { + loginSysAdmin(); + NotificationTarget sysAdmins = createNotificationTarget(new SystemAdministratorsFilter()); + + NotificationTarget slack = new NotificationTarget(); + slack.setName(RandomStringUtils.randomNumeric(5)); + SlackNotificationTargetConfig slackConfig = new SlackNotificationTargetConfig(); + SlackConversation slackConversation = new SlackConversation(); + slackConversation.setType(SlackConversationType.DIRECT); + slackConversation.setId("U12345678"); + slackConversation.setName("test"); + slackConfig.setConversation(slackConversation); + slack.setConfiguration(slackConfig); + slack = saveNotificationTarget(slack); + + List sysAdminTargets = notificationTargetDao.findByTenantIdAndUsersFilterType( + TenantId.SYS_TENANT_ID, UsersFilterType.SYSTEM_ADMINISTRATORS + ); + assertThat(sysAdminTargets).containsOnly(sysAdmins); + } + private String saveAndGetError(NotificationTarget notificationTarget, ResultMatcher statusMatcher) throws Exception { return getErrorMessage(save(notificationTarget, statusMatcher)); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/notification/JpaNotificationTargetDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/notification/JpaNotificationTargetDao.java index d05172e255..00dddd0114 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/notification/JpaNotificationTargetDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/notification/JpaNotificationTargetDao.java @@ -67,7 +67,7 @@ public class JpaNotificationTargetDao extends JpaAbstractDao findByTenantIdAndUsersFilterType(TenantId tenantId, UsersFilterType filterType) { - return DaoUtil.convertDataList(notificationTargetRepository.findByTenantIdAndSearchTextAndUsersFilterTypeIfPresent(tenantId.getId(), null, + return DaoUtil.convertDataList(notificationTargetRepository.findByTenantIdAndUsersFilterType(tenantId.getId(), List.of(filterType.name()), DaoUtil.toPageable(new PageLink(Integer.MAX_VALUE))).getContent()); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/notification/NotificationTargetRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/notification/NotificationTargetRepository.java index 961e734c9e..e807a6bffb 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/notification/NotificationTargetRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/notification/NotificationTargetRepository.java @@ -33,20 +33,27 @@ import java.util.UUID; public interface NotificationTargetRepository extends JpaRepository, ExportableEntityRepository { @Query("SELECT t FROM NotificationTargetEntity t WHERE t.tenantId = :tenantId " + - "AND (:searchText is NULL OR ilike(t.name, concat('%', :searchText, '%')) = true)") + "AND (:searchText is NULL OR ilike(t.name, concat('%', :searchText, '%')) = true)") Page findByTenantIdAndSearchText(@Param("tenantId") UUID tenantId, @Param("searchText") String searchText, Pageable pageable); @Query(value = "SELECT * FROM notification_target t WHERE t.tenant_id = :tenantId " + - "AND (:searchText IS NULL OR t.name ILIKE concat('%', :searchText, '%')) " + - "AND (cast(t.configuration as json) ->> 'type' <> 'PLATFORM_USERS' OR " + - "cast(t.configuration as json) -> 'usersFilter' ->> 'type' IN :usersFilterTypes)", nativeQuery = true) + "AND (:searchText IS NULL OR t.name ILIKE concat('%', :searchText, '%')) " + + "AND (cast(t.configuration as json) ->> 'type' <> 'PLATFORM_USERS' OR " + + "cast(t.configuration as json) -> 'usersFilter' ->> 'type' IN :usersFilterTypes)", nativeQuery = true) Page findByTenantIdAndSearchTextAndUsersFilterTypeIfPresent(@Param("tenantId") UUID tenantId, @Param("searchText") String searchText, @Param("usersFilterTypes") List usersFilterTypes, Pageable pageable); + @Query(value = "SELECT * FROM notification_target t WHERE t.tenant_id = :tenantId " + + "AND (cast(t.configuration as json) ->> 'type' = 'PLATFORM_USERS' AND " + + "cast(t.configuration as json) -> 'usersFilter' ->> 'type' IN :usersFilterTypes)", nativeQuery = true) + Page findByTenantIdAndUsersFilterType(@Param("tenantId") UUID tenantId, + @Param("usersFilterTypes") List usersFilterTypes, + Pageable pageable); + List findByTenantIdAndIdIn(UUID tenantId, List ids); @Transactional