Merge pull request #10920 from dashevchenko/queueStatsFix

Added api to retrieve queue stats entities
This commit is contained in:
Viacheslav Klimov 2024-06-05 15:50:03 +03:00 committed by GitHub
commit 42679a535f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 159 additions and 14 deletions

View File

@ -107,7 +107,9 @@ 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_STATS_ID_PARAM_DESCRIPTION = "A string value representing the queue stats id. For example, '687f294c-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. ";
protected static final String OTA_PACKAGE_DESCRIPTION = "OTA Package is a heavyweight object that includes main information about the OTA Package and also data. ";

View File

@ -0,0 +1,101 @@
/**
* 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.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.QueueStatsId;
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 java.util.ArrayList;
import java.util.List;
import java.util.UUID;
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_ID_PARAM_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 Stats entities (getTenantQueueStats)",
notes = "Returns a page of queue stats objects that are designed to collect queue statistics for every service. " +
PAGE_DATA_PARAMETERS + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
@GetMapping(value = "/queueStats", params = {"pageSize", "page"})
public PageData<QueueStats> 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);
}
@ApiOperation(value = "Get Queue stats entity by id (getQueueStatsById)",
notes = "Fetch the Queue stats object based on the provided Queue stats id. " + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
@GetMapping(value = "/queueStats/{queueStatsId}")
public QueueStats getQueueStatsById(@Parameter(description = QUEUE_STATS_ID_PARAM_DESCRIPTION)
@PathVariable("queueStatsId") String queueStatsIdStr) throws ThingsboardException {
checkParameter("queueStatsId", queueStatsIdStr);
QueueStatsId queueStatsId = new QueueStatsId(UUID.fromString(queueStatsIdStr));
return checkNotNull(queueStatsService.findQueueStatsById(getTenantId(), queueStatsId));
}
@ApiOperation(value = "Get QueueStats By Ids (getQueueStatsByIds)",
notes = "Fetch the Queue stats objects based on the provided ids. ")
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
@GetMapping(value = "/queueStats", params = {"queueStatsIds"})
public List<QueueStats> getQueueStatsByIds(
@Parameter(description = "A list of queue stats ids, separated by comma ','", required = true)
@RequestParam("queueStatsIds") String[] strQueueStatsIds) throws ThingsboardException {
checkArrayParameter("queueStatsIds", strQueueStatsIds);
List<QueueStatsId> queueStatsIds = new ArrayList<>();
for (String queueStatsId : strQueueStatsIds) {
queueStatsIds.add(new QueueStatsId(toUUID(queueStatsId)));
}
return queueStatsService.findQueueStatsByIds(getTenantId(), queueStatsIds);
}
}

View File

@ -198,9 +198,9 @@ public class BaseQueueControllerTest extends AbstractControllerTest {
});
ruleEngineStatisticsService.reportQueueStats(System.currentTimeMillis(), testStats);
List<QueueStats> queueStatsList = queueStatsService.findByTenantId(tenantId);
assertThat(queueStatsList).hasSize(1);
QueueStats queueStats = queueStatsList.get(0);
PageData<QueueStats> 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<Long> ttlCaptor = ArgumentCaptor.forClass(Long.class);

View File

@ -17,6 +17,8 @@ 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;
@ -28,8 +30,10 @@ public interface QueueStatsService extends EntityDaoService {
QueueStats findQueueStatsById(TenantId tenantId, QueueStatsId queueStatsId);
List<QueueStats> findQueueStatsByIds(TenantId tenantId, List<QueueStatsId> queueStatsId);
QueueStats findByTenantIdAndNameAndServiceId(TenantId tenantId, String queueName, String serviceId);
List<QueueStats> findByTenantId(TenantId tenantId);
PageData<QueueStats> findByTenantId(TenantId tenantId, PageLink pageLink);
}

View File

@ -23,14 +23,18 @@ 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;
import static org.thingsboard.server.dao.service.Validator.validateIds;
@Service("QueueStatsDaoService")
@Slf4j
@ -57,6 +61,14 @@ public class BaseQueueStatsService extends AbstractEntityService implements Queu
return queueStatsDao.findById(tenantId, queueStatsId.getId());
}
@Override
public List<QueueStats> findQueueStatsByIds(TenantId tenantId, List<QueueStatsId> queueStatsIds) {
log.trace("Executing findQueueStatsByIds, tenantId [{}], queueStatsIds [{}]", tenantId, queueStatsIds);
validateId(tenantId, id -> INCORRECT_TENANT_ID + id);
validateIds(queueStatsIds, ids -> "Incorrect queueStatsIds " + ids);
return queueStatsDao.findByIds(tenantId, queueStatsIds);
}
@Override
public QueueStats findByTenantIdAndNameAndServiceId(TenantId tenantId, String queueName, String serviceId) {
log.trace("Executing findByTenantIdAndNameAndServiceId, tenantId: [{}], queueName: [{}], serviceId: [{}]", tenantId, queueName, serviceId);
@ -65,10 +77,10 @@ public class BaseQueueStatsService extends AbstractEntityService implements Queu
}
@Override
public List<QueueStats> findByTenantId(TenantId tenantId) {
public PageData<QueueStats> 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

View File

@ -15,7 +15,10 @@
*/
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.Dao;
@ -25,8 +28,10 @@ public interface QueueStatsDao extends Dao<QueueStats> {
QueueStats findByTenantIdQueueNameAndServiceId(TenantId tenantId, String queueName, String serviceId);
List<QueueStats> findByTenantId(TenantId tenantId);
PageData<QueueStats> findByTenantId(TenantId tenantId, PageLink pageLink);
void deleteByTenantId(TenantId tenantId);
List<QueueStats> findByIds(TenantId tenantId, List<QueueStatsId> queueStatsIds);
}

View File

@ -20,7 +20,10 @@ import org.springframework.beans.factory.annotation.Autowired;
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.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.DaoUtil;
import org.thingsboard.server.dao.model.sql.QueueStatsEntity;
@ -31,6 +34,8 @@ import org.thingsboard.server.dao.util.SqlDao;
import java.util.List;
import java.util.UUID;
import static org.thingsboard.server.dao.DaoUtil.toUUIDs;
@Slf4j
@Component
@SqlDao
@ -55,8 +60,8 @@ public class JpaQueueStatsDao extends JpaAbstractDao<QueueStatsEntity, QueueStat
}
@Override
public List<QueueStats> findByTenantId(TenantId tenantId) {
return DaoUtil.convertDataList(queueStatsRepository.findByTenantId(tenantId.getId()));
public PageData<QueueStats> findByTenantId(TenantId tenantId, PageLink pageLink) {
return DaoUtil.toPageData(queueStatsRepository.findByTenantId(tenantId.getId(), pageLink.getTextSearch(), DaoUtil.toPageable(pageLink)));
}
@Override
@ -64,6 +69,11 @@ public class JpaQueueStatsDao extends JpaAbstractDao<QueueStatsEntity, QueueStat
queueStatsRepository.deleteByTenantId(tenantId.getId());
}
@Override
public List<QueueStats> findByIds(TenantId tenantId, List<QueueStatsId> queueStatsIds) {
return DaoUtil.convertDataList(queueStatsRepository.findByTenantIdAndIdIn(tenantId.getId(), toUUIDs(queueStatsIds)));
}
@Override
public EntityType getEntityType() {
return EntityType.QUEUE_STATS;

View File

@ -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;
@ -29,11 +31,18 @@ public interface QueueStatsRepository extends JpaRepository<QueueStatsEntity, UU
QueueStatsEntity findByTenantIdAndQueueNameAndServiceId(UUID tenantId, String queueName, String serviceId);
List<QueueStatsEntity> 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<QueueStatsEntity> findByTenantId(@Param("tenantId") UUID tenantId,
@Param("textSearch") String textSearch,
Pageable pageable);
@Transactional
@Modifying
@Query("DELETE FROM QueueStatsEntity t WHERE t.tenantId = :tenantId")
void deleteByTenantId(@Param("tenantId") UUID tenantId);
List<QueueStatsEntity> findByTenantIdAndIdIn(UUID tenantId, List<UUID> queueStatsIds);
}

View File

@ -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<QueueStats> queueStatsList = queueStatsService.findByTenantId(tenantId);
Assert.assertEquals(2, queueStatsList.size());
assertThat(queueStatsList).containsOnly(retrievedQueueStatsById, retrievedQueueStatsById2);
PageData<QueueStats> 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());