diff --git a/application/src/main/java/org/thingsboard/server/controller/ControllerConstants.java b/application/src/main/java/org/thingsboard/server/controller/ControllerConstants.java index d9232cda78..5727b18011 100644 --- a/application/src/main/java/org/thingsboard/server/controller/ControllerConstants.java +++ b/application/src/main/java/org/thingsboard/server/controller/ControllerConstants.java @@ -107,6 +107,7 @@ public class ControllerConstants { protected static final String ASSET_PROFILE_INFO_DESCRIPTION = "Asset Profile Info is a lightweight object that includes main information about Asset Profile. "; protected static final String QUEUE_SERVICE_TYPE_DESCRIPTION = "Service type (implemented only for the TB-RULE-ENGINE)"; protected static final String QUEUE_QUEUE_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'substring' filter based on the queue name."; + protected static final String QUEUE_STATS_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'substring' filter based on the queue name or service id."; protected static final String QUEUE_ID_PARAM_DESCRIPTION = "A string value representing the queue id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'"; protected static final String QUEUE_NAME_PARAM_DESCRIPTION = "A string value representing the queue id. For example, 'Main'"; protected static final String OTA_PACKAGE_INFO_DESCRIPTION = "OTA Package Info is a lightweight object that includes main information about the OTA Package excluding the heavyweight data. "; diff --git a/application/src/main/java/org/thingsboard/server/controller/QueueStatsController.java b/application/src/main/java/org/thingsboard/server/controller/QueueStatsController.java new file mode 100644 index 0000000000..4e0f1ff006 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/controller/QueueStatsController.java @@ -0,0 +1,70 @@ +/** + * 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 io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.RequiredArgsConstructor; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import org.thingsboard.server.common.data.exception.ThingsboardException; +import org.thingsboard.server.common.data.page.PageData; +import org.thingsboard.server.common.data.page.PageLink; +import org.thingsboard.server.common.data.queue.QueueStats; +import org.thingsboard.server.config.annotations.ApiOperation; +import org.thingsboard.server.dao.queue.QueueStatsService; +import org.thingsboard.server.queue.util.TbCoreComponent; + +import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS; +import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION; +import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION; +import static org.thingsboard.server.controller.ControllerConstants.QUEUE_STATS_TEXT_SEARCH_DESCRIPTION; +import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION; +import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION; +import static org.thingsboard.server.controller.ControllerConstants.SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH; + +@RestController +@TbCoreComponent +@RequestMapping("/api") +@RequiredArgsConstructor +public class QueueStatsController extends BaseController { + + private final QueueStatsService queueStatsService; + + @ApiOperation(value = "Get Queue Statistics (getTenantQueueStats)", + notes = "Returns a page of queue stats objects that are used to collect queue statistics for every service. " + + PAGE_DATA_PARAMETERS + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH) + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") + @RequestMapping(value = "/queueStats", params = {"pageSize", "page"}, method = RequestMethod.GET) + @ResponseBody + public PageData getTenantQueueStats(@Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) + @RequestParam int pageSize, + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) + @RequestParam int page, + @Parameter(description = QUEUE_STATS_TEXT_SEARCH_DESCRIPTION) + @RequestParam(required = false) String textSearch, + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime"})) + @RequestParam(required = false) String sortProperty, + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) + @RequestParam(required = false) String sortOrder) throws ThingsboardException { + PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); + return queueStatsService.findByTenantId(getTenantId(), pageLink); + } +} diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseQueueControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseQueueControllerTest.java index ad52934587..6620b1a448 100644 --- a/application/src/test/java/org/thingsboard/server/controller/BaseQueueControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/BaseQueueControllerTest.java @@ -198,9 +198,9 @@ public class BaseQueueControllerTest extends AbstractControllerTest { }); ruleEngineStatisticsService.reportQueueStats(System.currentTimeMillis(), testStats); - List queueStatsList = queueStatsService.findByTenantId(tenantId); - assertThat(queueStatsList).hasSize(1); - QueueStats queueStats = queueStatsList.get(0); + PageData queueStatsList = queueStatsService.findByTenantId(tenantId, new PageLink(10)); + assertThat(queueStatsList.getData()).hasSize(1); + QueueStats queueStats = queueStatsList.getData().get(0); assertThat(queueStats.getQueueName()).isEqualTo(queue.getName()); ArgumentCaptor ttlCaptor = ArgumentCaptor.forClass(Long.class); diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/queue/QueueStatsService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/queue/QueueStatsService.java index c9e3f605c6..ec22f5d492 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/queue/QueueStatsService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/queue/QueueStatsService.java @@ -17,11 +17,11 @@ package org.thingsboard.server.dao.queue; import org.thingsboard.server.common.data.id.QueueStatsId; import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.page.PageData; +import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.queue.QueueStats; import org.thingsboard.server.dao.entity.EntityDaoService; -import java.util.List; - public interface QueueStatsService extends EntityDaoService { QueueStats save(TenantId tenantId, QueueStats queueStats); @@ -30,6 +30,6 @@ public interface QueueStatsService extends EntityDaoService { QueueStats findByTenantIdAndNameAndServiceId(TenantId tenantId, String queueName, String serviceId); - List findByTenantId(TenantId tenantId); + PageData findByTenantId(TenantId tenantId, PageLink pageLink); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/queue/BaseQueueStatsService.java b/dao/src/main/java/org/thingsboard/server/dao/queue/BaseQueueStatsService.java index 6352ac1a4c..fd5989f1cf 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/queue/BaseQueueStatsService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/queue/BaseQueueStatsService.java @@ -23,11 +23,13 @@ import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.HasId; import org.thingsboard.server.common.data.id.QueueStatsId; import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.page.PageData; +import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.queue.QueueStats; import org.thingsboard.server.dao.entity.AbstractEntityService; import org.thingsboard.server.dao.service.DataValidator; +import org.thingsboard.server.dao.service.Validator; -import java.util.List; import java.util.Optional; import static org.thingsboard.server.dao.service.Validator.validateId; @@ -65,10 +67,10 @@ public class BaseQueueStatsService extends AbstractEntityService implements Queu } @Override - public List findByTenantId(TenantId tenantId) { + public PageData findByTenantId(TenantId tenantId, PageLink pageLink) { log.trace("Executing findByTenantId, tenantId: [{}]", tenantId); - validateId(tenantId, id -> INCORRECT_TENANT_ID + id); - return queueStatsDao.findByTenantId(tenantId); + Validator.validatePageLink(pageLink); + return queueStatsDao.findByTenantId(tenantId, pageLink); } @Override diff --git a/dao/src/main/java/org/thingsboard/server/dao/queue/QueueStatsDao.java b/dao/src/main/java/org/thingsboard/server/dao/queue/QueueStatsDao.java index 1c3db8bb54..f4c20ea98e 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/queue/QueueStatsDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/queue/QueueStatsDao.java @@ -16,16 +16,16 @@ package org.thingsboard.server.dao.queue; import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.page.PageData; +import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.queue.QueueStats; import org.thingsboard.server.dao.Dao; -import java.util.List; - public interface QueueStatsDao extends Dao { QueueStats findByTenantIdQueueNameAndServiceId(TenantId tenantId, String queueName, String serviceId); - List findByTenantId(TenantId tenantId); + PageData findByTenantId(TenantId tenantId, PageLink pageLink); void deleteByTenantId(TenantId tenantId); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/queue/JpaQueueStatsDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/queue/JpaQueueStatsDao.java index 1cfdbf0b38..e49b5df77d 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/queue/JpaQueueStatsDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/queue/JpaQueueStatsDao.java @@ -21,6 +21,8 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.page.PageData; +import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.queue.QueueStats; import org.thingsboard.server.dao.DaoUtil; import org.thingsboard.server.dao.model.sql.QueueStatsEntity; @@ -28,7 +30,6 @@ import org.thingsboard.server.dao.queue.QueueStatsDao; import org.thingsboard.server.dao.sql.JpaAbstractDao; import org.thingsboard.server.dao.util.SqlDao; -import java.util.List; import java.util.UUID; @Slf4j @@ -55,8 +56,8 @@ public class JpaQueueStatsDao extends JpaAbstractDao findByTenantId(TenantId tenantId) { - return DaoUtil.convertDataList(queueStatsRepository.findByTenantId(tenantId.getId())); + public PageData findByTenantId(TenantId tenantId, PageLink pageLink) { + return DaoUtil.toPageData(queueStatsRepository.findByTenantId(tenantId.getId(), pageLink.getTextSearch(), DaoUtil.toPageable(pageLink))); } @Override diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/queue/QueueStatsRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/queue/QueueStatsRepository.java index 65df3a65fa..5e4a27f0ba 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/queue/QueueStatsRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/queue/QueueStatsRepository.java @@ -15,6 +15,8 @@ */ package org.thingsboard.server.dao.sql.queue; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; @@ -22,14 +24,18 @@ import org.springframework.data.repository.query.Param; import org.springframework.transaction.annotation.Transactional; import org.thingsboard.server.dao.model.sql.QueueStatsEntity; -import java.util.List; import java.util.UUID; public interface QueueStatsRepository extends JpaRepository { QueueStatsEntity findByTenantIdAndQueueNameAndServiceId(UUID tenantId, String queueName, String serviceId); - List findByTenantId(UUID tenantId); + @Query("SELECT q FROM QueueStatsEntity q WHERE q.tenantId = :tenantId " + + "AND (:textSearch IS NULL OR ilike(q.queueName, CONCAT('%', :textSearch, '%')) = true " + + "OR ilike(q.serviceId, CONCAT('%', :textSearch, '%')) = true)") + Page findByTenantId(@Param("tenantId") UUID tenantId, + @Param("textSearch") String textSearch, + Pageable pageable); @Transactional @Modifying diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/QueueStatsServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/QueueStatsServiceTest.java index 45a49ba5d2..7919893d00 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/QueueStatsServiceTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/QueueStatsServiceTest.java @@ -24,6 +24,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.page.PageData; +import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.queue.QueueStats; import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.queue.QueueStatsService; @@ -80,9 +82,9 @@ public class QueueStatsServiceTest extends AbstractServiceTest { QueueStats retrievedQueueStatsById2 = queueStatsService.findQueueStatsById(tenantId, savedQueueStats2.getId()); Assert.assertEquals(retrievedQueueStatsById2.getQueueName(), secondQueueName); - List queueStatsList = queueStatsService.findByTenantId(tenantId); - Assert.assertEquals(2, queueStatsList.size()); - assertThat(queueStatsList).containsOnly(retrievedQueueStatsById, retrievedQueueStatsById2); + PageData queueStatsList = queueStatsService.findByTenantId(tenantId, new PageLink(10)); + Assert.assertEquals(2, queueStatsList.getData().size()); + assertThat(queueStatsList.getData()).containsOnly(retrievedQueueStatsById, retrievedQueueStatsById2); queueStatsService.deleteByTenantId(tenantId); QueueStats retrievedQueueStatsAfterDelete = queueStatsService.findQueueStatsById(tenantId, savedQueueStats.getId());