From 9064bfaa7663bcde45d4cb121cb2c5bf886f5ea9 Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Thu, 11 Apr 2024 17:18:47 +0300 Subject: [PATCH] Delete tenant entities in batches with id offset --- .../AlarmsDeletionTaskProcessor.java | 15 ++-- .../EntitiesDeletionTaskProcessor.java | 41 ++++++++++- .../housekeeper/HousekeeperServiceTest.java | 6 +- .../server/dao/alarm/AlarmService.java | 3 +- .../server/common/data/EntityType.java | 69 ++++++++++--------- .../AlarmsDeletionHousekeeperTask.java | 8 +-- .../EntitiesDeletionHousekeeperTask.java | 9 +++ .../server/common/data/page/PageLink.java | 14 ++-- .../java/org/thingsboard/server/dao/Dao.java | 2 + .../org/thingsboard/server/dao/DaoUtil.java | 21 ------ .../server/dao/alarm/AlarmDao.java | 2 +- .../server/dao/alarm/BaseAlarmService.java | 6 +- .../server/dao/entity/EntityDaoRegistry.java | 49 +++++++++++++ .../server/dao/sql/JpaAbstractDao.java | 19 +++++ .../server/dao/sql/alarm/JpaAlarmDao.java | 4 +- 15 files changed, 184 insertions(+), 84 deletions(-) create mode 100644 dao/src/main/java/org/thingsboard/server/dao/entity/EntityDaoRegistry.java diff --git a/application/src/main/java/org/thingsboard/server/service/housekeeper/processor/AlarmsDeletionTaskProcessor.java b/application/src/main/java/org/thingsboard/server/service/housekeeper/processor/AlarmsDeletionTaskProcessor.java index d775cdc4db..c4834df71d 100644 --- a/application/src/main/java/org/thingsboard/server/service/housekeeper/processor/AlarmsDeletionTaskProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/housekeeper/processor/AlarmsDeletionTaskProcessor.java @@ -25,9 +25,9 @@ import org.thingsboard.server.common.data.id.AlarmId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.UUIDBased; -import org.thingsboard.server.dao.DaoUtil; import org.thingsboard.server.dao.alarm.AlarmService; +import java.util.List; import java.util.UUID; import java.util.stream.Collectors; @@ -46,13 +46,18 @@ public class AlarmsDeletionTaskProcessor extends HousekeeperTaskProcessor { - return alarmService.findAlarmIdsByOriginatorId(tenantId, entityId, pageLink); - }, 128, alarms -> { + AlarmId last = null; + while (true) { + List alarms = alarmService.findAlarmIdsByOriginatorIdAndIdOffset(tenantId, entityId, last, 128); + if (alarms.isEmpty()) { + break; + } + housekeeperClient.submitTask(new AlarmsDeletionHousekeeperTask(tenantId, entityId, alarms.stream() .map(UUIDBased::getId).collect(Collectors.toList()))); + last = alarms.get(alarms.size() - 1); log.debug("[{}][{}][{}] Submitted task for deleting {} alarms", tenantId, entityType, entityId, alarms.size()); - }); + } } else { for (UUID alarmId : task.getAlarms()) { alarmService.delAlarm(tenantId, new AlarmId(alarmId)); diff --git a/application/src/main/java/org/thingsboard/server/service/housekeeper/processor/EntitiesDeletionTaskProcessor.java b/application/src/main/java/org/thingsboard/server/service/housekeeper/processor/EntitiesDeletionTaskProcessor.java index 95d45a49be..fb01fe4605 100644 --- a/application/src/main/java/org/thingsboard/server/service/housekeeper/processor/EntitiesDeletionTaskProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/housekeeper/processor/EntitiesDeletionTaskProcessor.java @@ -16,22 +16,59 @@ package org.thingsboard.server.service.housekeeper.processor; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; +import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.housekeeper.EntitiesDeletionHousekeeperTask; import org.thingsboard.server.common.data.housekeeper.HousekeeperTaskType; +import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.common.data.id.EntityIdFactory; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.dao.Dao; +import org.thingsboard.server.dao.entity.EntityDaoRegistry; import org.thingsboard.server.dao.entity.EntityDaoService; import org.thingsboard.server.dao.entity.EntityServiceRegistry; +import java.util.List; +import java.util.UUID; + @Component @RequiredArgsConstructor +@Slf4j public class EntitiesDeletionTaskProcessor extends HousekeeperTaskProcessor { + private final EntityDaoRegistry entityDaoRegistry; private final EntityServiceRegistry entityServiceRegistry; @Override public void process(EntitiesDeletionHousekeeperTask task) throws Exception { - EntityDaoService entityService = entityServiceRegistry.getServiceByEntityType(task.getEntityType()); - entityService.deleteByTenantId(task.getTenantId()); + EntityType entityType = task.getEntityType(); + TenantId tenantId = task.getTenantId(); + Dao entityDao = entityDaoRegistry.getDao(entityType); + EntityDaoService entityService = entityServiceRegistry.getServiceByEntityType(entityType); + + if (task.getEntities() == null) { + UUID last = null; + while (true) { + List entities = entityDao.findIdsByTenantIdAndIdOffset(tenantId, last, 128); + if (entities.isEmpty()) { + break; + } + + housekeeperClient.submitTask(new EntitiesDeletionHousekeeperTask(tenantId, entityType, task.getEntities())); + last = entities.get(entities.size() - 1); + log.debug("[{}] Submitted task for deleting {} {}s", tenantId, entities.size(), entityType.getNormalName().toLowerCase()); + } + } else { + for (UUID entityUuid : task.getEntities()) { + EntityId entityId = EntityIdFactory.getByTypeAndUuid(entityType, entityUuid); +// Optional> entity = entityService.findEntity(tenantId, entityId); +// if (entity.isEmpty()) { +// continue; +// } + entityService.deleteEntity(tenantId, entityId); + } + } } @Override diff --git a/application/src/test/java/org/thingsboard/server/service/housekeeper/HousekeeperServiceTest.java b/application/src/test/java/org/thingsboard/server/service/housekeeper/HousekeeperServiceTest.java index 26062810a1..efbfbffbb9 100644 --- a/application/src/test/java/org/thingsboard/server/service/housekeeper/HousekeeperServiceTest.java +++ b/application/src/test/java/org/thingsboard/server/service/housekeeper/HousekeeperServiceTest.java @@ -368,7 +368,7 @@ public class HousekeeperServiceTest extends AbstractControllerTest { } private void verifyNoAlarms(EntityId entityId) { - assertThat(alarmService.findAlarmIdsByOriginatorId(tenantId, entityId, new PageLink(1)).getData()).isEmpty(); + assertThat(alarmService.findAlarmIdsByOriginatorIdAndIdOffset(tenantId, entityId, null, 10)).isEmpty(); } private void createAttribute(EntityId entityId, AttributeScope scope, String key) throws Exception { @@ -410,7 +410,7 @@ public class HousekeeperServiceTest extends AbstractControllerTest { List entityAlarms = alarmDao.findEntityAlarmRecords(tenantId, alarm.getId()); assertThat(entityAlarms).anyMatch(entityAlarm -> entityAlarm.getEntityId().equals(deviceId) && entityAlarm.getAlarmType().equals(alarm.getType())); assertThat(entityAlarms).anyMatch(entityAlarm -> entityAlarm.getEntityId().equals(propagatedEntityId) && entityAlarm.getAlarmType().equals(alarm.getType())); - assertThat(alarmService.findAlarmIdsByOriginatorId(tenantId, deviceId, new PageLink(1)).getData()).isNotEmpty(); + assertThat(alarmService.findAlarmIdsByOriginatorIdAndIdOffset(tenantId, deviceId, null, 10)).isNotEmpty(); } private void createAlarm(DeviceId deviceId) { @@ -420,7 +420,7 @@ public class HousekeeperServiceTest extends AbstractControllerTest { .severity(AlarmSeverity.CRITICAL) .type("test alarm for " + deviceId + " " + RandomStringUtils.randomAlphabetic(10)) .build(), Alarm.class); - assertThat(alarmService.findAlarmIdsByOriginatorId(tenantId, deviceId, new PageLink(1)).getData()).isNotEmpty(); + assertThat(alarmService.findAlarmIdsByOriginatorIdAndIdOffset(tenantId, deviceId, null, 10)).isNotEmpty(); } private TsKvEntry getLatestTelemetry(EntityId entityId) throws Exception { diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmService.java index 32ce3be62c..ee584ff856 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmService.java @@ -41,6 +41,7 @@ import org.thingsboard.server.common.data.query.AlarmDataQuery; import org.thingsboard.server.dao.entity.EntityDaoService; import java.util.Collection; +import java.util.List; import java.util.Set; @@ -106,7 +107,7 @@ public interface AlarmService extends EntityDaoService { PageData findAlarmIdsByAssigneeId(TenantId tenantId, UserId userId, PageLink pageLink); - PageData findAlarmIdsByOriginatorId(TenantId tenantId, EntityId originatorId, PageLink pageLink); + List findAlarmIdsByOriginatorIdAndIdOffset(TenantId tenantId, EntityId originatorId, AlarmId idOffset, int limit); int deleteEntityAlarmRecords(TenantId tenantId, EntityId entityId); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java b/common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java index bb43bf4d11..6748aebb50 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java @@ -20,7 +20,6 @@ import org.apache.commons.lang3.StringUtils; import java.util.EnumSet; import java.util.List; -import java.util.stream.Collectors; /** * @author Andrew Shvayka @@ -28,51 +27,57 @@ import java.util.stream.Collectors; public enum EntityType { TENANT(1), CUSTOMER(2), - USER(3), + USER(3, "tb_user"), DASHBOARD(4), ASSET(5), DEVICE(6), - ALARM (7), - RULE_CHAIN (11), - RULE_NODE (12), - - ENTITY_VIEW (15) { + ALARM(7), + RULE_CHAIN(11), + RULE_NODE(12), + ENTITY_VIEW(15) { // backward compatibility for TbOriginatorTypeSwitchNode to return correct rule node connection. @Override - public String getNormalName () { + public String getNormalName() { return "Entity View"; } }, - WIDGETS_BUNDLE (16), - WIDGET_TYPE (17), - TENANT_PROFILE (20), - DEVICE_PROFILE (21), - ASSET_PROFILE (22), - API_USAGE_STATE (23), - TB_RESOURCE (24), - OTA_PACKAGE (25), - EDGE (26), - RPC (27), - QUEUE (28), - NOTIFICATION_TARGET (29), - NOTIFICATION_TEMPLATE (30), - NOTIFICATION_REQUEST (31), - NOTIFICATION (32), - NOTIFICATION_RULE (33), + WIDGETS_BUNDLE(16), + WIDGET_TYPE(17), + TENANT_PROFILE(20), + DEVICE_PROFILE(21), + ASSET_PROFILE(22), + API_USAGE_STATE(23), + TB_RESOURCE(24, "resource"), + OTA_PACKAGE(25), + EDGE(26), + RPC(27), + QUEUE(28), + NOTIFICATION_TARGET(29), + NOTIFICATION_TEMPLATE(30), + NOTIFICATION_REQUEST(31), + NOTIFICATION(32), + NOTIFICATION_RULE(33), QUEUE_STATS(34); @Getter private final int protoNumber; // Corresponds to EntityTypeProto - - private EntityType(int protoNumber) { - this.protoNumber = protoNumber; - } - - public static final List NORMAL_NAMES = EnumSet.allOf(EntityType.class).stream() - .map(EntityType::getNormalName).collect(Collectors.toUnmodifiableList()); - + @Getter + private final String tableName; @Getter private final String normalName = StringUtils.capitalize(StringUtils.removeStart(name(), "TB_") .toLowerCase().replaceAll("_", " ")); + public static final List NORMAL_NAMES = EnumSet.allOf(EntityType.class).stream() + .map(EntityType::getNormalName).toList(); + + EntityType(int protoNumber) { + this.protoNumber = protoNumber; + this.tableName = name().toLowerCase(); + } + + EntityType(int protoNumber, String tableName) { + this.protoNumber = protoNumber; + this.tableName = tableName; + } + } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/housekeeper/AlarmsDeletionHousekeeperTask.java b/common/data/src/main/java/org/thingsboard/server/common/data/housekeeper/AlarmsDeletionHousekeeperTask.java index ba9627565d..9bd8f29bb4 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/housekeeper/AlarmsDeletionHousekeeperTask.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/housekeeper/AlarmsDeletionHousekeeperTask.java @@ -34,13 +34,13 @@ public class AlarmsDeletionHousekeeperTask extends HousekeeperTask { private List alarms; + public AlarmsDeletionHousekeeperTask(TenantId tenantId, EntityId entityId) { + this(tenantId, entityId, null); + } + public AlarmsDeletionHousekeeperTask(TenantId tenantId, EntityId entityId, List alarms) { super(tenantId, entityId, HousekeeperTaskType.DELETE_ALARMS); this.alarms = alarms; } - public AlarmsDeletionHousekeeperTask(TenantId tenantId, EntityId entityId) { - super(tenantId, entityId, HousekeeperTaskType.DELETE_ALARMS); - } - } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/housekeeper/EntitiesDeletionHousekeeperTask.java b/common/data/src/main/java/org/thingsboard/server/common/data/housekeeper/EntitiesDeletionHousekeeperTask.java index 4156200758..e29c3d3c51 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/housekeeper/EntitiesDeletionHousekeeperTask.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/housekeeper/EntitiesDeletionHousekeeperTask.java @@ -24,6 +24,9 @@ import lombok.ToString; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.id.TenantId; +import java.util.List; +import java.util.UUID; + @Data @ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) @@ -31,10 +34,16 @@ import org.thingsboard.server.common.data.id.TenantId; public class EntitiesDeletionHousekeeperTask extends HousekeeperTask { private EntityType entityType; + private List entities; protected EntitiesDeletionHousekeeperTask(TenantId tenantId, EntityType entityType) { + this(tenantId, entityType, null); + } + + public EntitiesDeletionHousekeeperTask(TenantId tenantId, EntityType entityType, List entities) { super(tenantId, tenantId, HousekeeperTaskType.DELETE_ENTITIES); this.entityType = entityType; + this.entities = entities; } @JsonIgnore diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/page/PageLink.java b/common/data/src/main/java/org/thingsboard/server/common/data/page/PageLink.java index 8d806b7006..d6a3b5ad7d 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/page/PageLink.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/page/PageLink.java @@ -16,20 +16,15 @@ package org.thingsboard.server.common.data.page; import com.fasterxml.jackson.annotation.JsonIgnore; -import lombok.AllArgsConstructor; -import lombok.Builder; import lombok.Data; import org.springframework.data.domain.Sort; import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.UUID; import java.util.stream.Collectors; @Data -@AllArgsConstructor -@Builder public class PageLink { protected static final String DEFAULT_SORT_PROPERTY = "id"; @@ -39,7 +34,6 @@ public class PageLink { private final int pageSize; private final int page; private final SortOrder sortOrder; - private UUID idOffset; public PageLink(PageLink pageLink) { this.pageSize = pageLink.getPageSize(); @@ -69,10 +63,10 @@ public class PageLink { @JsonIgnore public PageLink nextPageLink() { - return new PageLink(this.pageSize, this.page+1, this.textSearch, this.sortOrder); + return new PageLink(this.pageSize, this.page + 1, this.textSearch, this.sortOrder); } - public Sort toSort(SortOrder sortOrder, Map columnMap, boolean addDefaultSorting) { + public Sort toSort(SortOrder sortOrder, Map columnMap, boolean addDefaultSorting) { if (sortOrder == null) { return DEFAULT_SORT; } else { @@ -80,7 +74,7 @@ public class PageLink { } } - public Sort toSort(List sortOrders, Map columnMap, boolean addDefaultSorting) { + public Sort toSort(List sortOrders, Map columnMap, boolean addDefaultSorting) { if (addDefaultSorting && !isDefaultSortOrderAvailable(sortOrders)) { sortOrders = new ArrayList<>(sortOrders); sortOrders.add(new SortOrder(DEFAULT_SORT_PROPERTY, SortOrder.Direction.ASC)); @@ -88,7 +82,7 @@ public class PageLink { return Sort.by(sortOrders.stream().map(s -> toSortOrder(s, columnMap)).collect(Collectors.toList())); } - private Sort.Order toSortOrder(SortOrder sortOrder, Map columnMap) { + private Sort.Order toSortOrder(SortOrder sortOrder, Map columnMap) { String property = sortOrder.getProperty(); if (columnMap.containsKey(property)) { property = columnMap.get(property); diff --git a/dao/src/main/java/org/thingsboard/server/dao/Dao.java b/dao/src/main/java/org/thingsboard/server/dao/Dao.java index 8d408945fa..e7290cdced 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/Dao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/Dao.java @@ -43,6 +43,8 @@ public interface Dao { void removeAllByIds(Collection ids); + List findIdsByTenantIdAndIdOffset(TenantId tenantId, UUID idOffset, int limit); + default EntityType getEntityType() { return null; } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/DaoUtil.java b/dao/src/main/java/org/thingsboard/server/dao/DaoUtil.java index a0941705eb..01a72ea58c 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/DaoUtil.java +++ b/dao/src/main/java/org/thingsboard/server/dao/DaoUtil.java @@ -23,7 +23,6 @@ import org.springframework.util.CollectionUtils; import org.thingsboard.server.common.data.EntityInfo; import org.thingsboard.server.common.data.EntitySubtype; import org.thingsboard.server.common.data.EntityType; -import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.UUIDBased; import org.thingsboard.server.common.data.page.PageData; @@ -169,26 +168,6 @@ public abstract class DaoUtil { } while (hasNextBatch); } - public static void iterateWithKeyOffset(Function> findFunction, int pageSize, Consumer> processor) { - List data; - UUID last = null; - while (true) { - PageLink pageLink = PageLink.builder() - .pageSize(pageSize) - .sortOrder(SortOrder.of("id", SortOrder.Direction.ASC)) - .idOffset(last) - .build(); - data = findFunction.apply(pageLink).getData(); - - if (!data.isEmpty()) { - processor.accept(data); - last = data.get(data.size() - 1).getId(); - } else { - break; - } - } - } - public static String getStringId(UUIDBased id) { if (id != null) { return id.toString(); diff --git a/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmDao.java b/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmDao.java index 365a5ac2e0..03038b3bfe 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmDao.java @@ -80,7 +80,7 @@ public interface AlarmDao extends Dao { PageData findAlarmIdsByAssigneeId(TenantId tenantId, UUID userId, PageLink pageLink); - PageData findAlarmIdsByOriginatorId(TenantId tenantId, EntityId originatorId, PageLink pageLink); + PageData findAlarmIdsByOriginatorId(TenantId tenantId, EntityId originatorId, AlarmId idOffset, PageLink pageLink); void createEntityAlarmRecord(EntityAlarm entityAlarm); diff --git a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java index 33b2d5a4c3..9d0940a605 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java @@ -313,9 +313,9 @@ public class BaseAlarmService extends AbstractCachedEntityService findAlarmIdsByOriginatorId(TenantId tenantId, EntityId originatorId, PageLink pageLink) { - log.trace("[{}] Executing findAlarmsByOriginatorId [{}]", tenantId, originatorId); - return alarmDao.findAlarmIdsByOriginatorId(tenantId, originatorId, pageLink); + public List findAlarmIdsByOriginatorIdAndIdOffset(TenantId tenantId, EntityId originatorId, AlarmId idOffset, int limit) { + log.trace("[{}] Executing findAlarmIdsByOriginatorIdAndIdOffset [{}][{}]", tenantId, originatorId, idOffset); + return alarmDao.findAlarmIdsByOriginatorId(tenantId, originatorId, idOffset, new PageLink(limit)).getData(); } @Override diff --git a/dao/src/main/java/org/thingsboard/server/dao/entity/EntityDaoRegistry.java b/dao/src/main/java/org/thingsboard/server/dao/entity/EntityDaoRegistry.java new file mode 100644 index 0000000000..261454966c --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/entity/EntityDaoRegistry.java @@ -0,0 +1,49 @@ +/** + * 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.entity; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.thingsboard.server.common.data.EntityType; +import org.thingsboard.server.dao.Dao; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Service +@RequiredArgsConstructor +@Slf4j +public class EntityDaoRegistry { + + private final Map> daos; + + private EntityDaoRegistry(List> daos) { + this.daos = daos.stream().filter(dao -> dao.getEntityType() != null) + .collect(Collectors.toMap(Dao::getEntityType, dao -> dao)); + } + + @SuppressWarnings("unchecked") + public Dao getDao(EntityType entityType) { + Dao dao = (Dao) daos.get(entityType); + if (dao == null) { + throw new IllegalArgumentException("Missing dao for entity type " + entityType); + } + return dao; + } + +} 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 fdb96195fb..6bfd74ac87 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 @@ -19,7 +19,9 @@ import com.datastax.oss.driver.api.core.uuid.Uuids; import com.google.common.collect.Lists; import com.google.common.util.concurrent.ListenableFuture; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.transaction.annotation.Transactional; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.Dao; @@ -41,6 +43,9 @@ public abstract class JpaAbstractDao, D> extends JpaAbstractDaoListeningExecutorService implements Dao { + @Autowired + protected JdbcTemplate jdbcTemplate; + protected abstract Class getEntityClass(); protected abstract JpaRepository getRepository(); @@ -117,6 +122,20 @@ public abstract class JpaAbstractDao, D> ids.forEach(repository::deleteById); } + @Override + public List findIdsByTenantIdAndIdOffset(TenantId tenantId, UUID idOffset, int limit) { + String tableName = Optional.ofNullable(getEntityType()) + .orElseThrow(() -> new IllegalArgumentException("Entity type not specified")) + .getTableName(); + if (idOffset == null) { + return jdbcTemplate.queryForList("SELECT id FROM " + tableName + " WHERE tenant_id = ? ORDER BY id LIMIT ?", + UUID.class, tenantId.getId(), limit); + } else { + return jdbcTemplate.queryForList("SELECT id FROM " + tableName + " WHERE tenant_id = ? AND id > ? ORDER BY id LIMIT ?", + UUID.class, tenantId.getId(), idOffset, limit); + } + } + @Override public List find(TenantId tenantId) { List entities = Lists.newArrayList(getRepository().findAll()); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java index 6c1118cdba..da603a6c6f 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java @@ -297,8 +297,8 @@ public class JpaAlarmDao extends JpaAbstractDao implements A } @Override - public PageData findAlarmIdsByOriginatorId(TenantId tenantId, EntityId originatorId, PageLink pageLink) { - return DaoUtil.pageToPageData(alarmRepository.findAlarmIdsByOriginatorId(tenantId.getId(), originatorId.getId(), pageLink.getIdOffset(), DaoUtil.toPageable(pageLink))) + public PageData findAlarmIdsByOriginatorId(TenantId tenantId, EntityId originatorId, AlarmId idOffset, PageLink pageLink) { + return DaoUtil.pageToPageData(alarmRepository.findAlarmIdsByOriginatorId(tenantId.getId(), originatorId.getId(), idOffset != null ? idOffset.getId() : null, DaoUtil.toPageable(pageLink))) .mapData(AlarmId::new); }