Browse Source

Notification request scheduling

pull/7511/head
ViacheslavKlimov 4 years ago
parent
commit
c4d8354fa7
  1. 8
      application/src/main/java/org/thingsboard/server/controller/NotificationController.java
  2. 8
      application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationRuleProcessingService.java
  3. 129
      application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationSchedulerService.java
  4. 37
      application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationSubscriptionService.java
  5. 27
      application/src/main/java/org/thingsboard/server/service/notification/NotificationSchedulerService.java
  6. 5
      application/src/main/java/org/thingsboard/server/service/partition/AbstractPartitionBasedService.java
  7. 28
      application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java
  8. 10
      common/cluster-api/src/main/proto/queue.proto
  9. 42
      common/dao-api/src/main/java/org/thingsboard/server/dao/notification/NotificationRequestService.java
  10. 16
      common/dao-api/src/main/java/org/thingsboard/server/dao/notification/NotificationService.java
  11. 4
      dao/src/main/java/org/thingsboard/server/dao/model/BaseSqlEntity.java
  12. 4
      dao/src/main/java/org/thingsboard/server/dao/model/sql/NotificationRequestEntity.java
  13. 87
      dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationRequestService.java
  14. 45
      dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationService.java
  15. 3
      dao/src/main/java/org/thingsboard/server/dao/notification/NotificationRequestDao.java
  16. 6
      dao/src/main/java/org/thingsboard/server/dao/sql/notification/JpaNotificationRequestDao.java
  17. 3
      dao/src/main/java/org/thingsboard/server/dao/sql/notification/NotificationRequestRepository.java

8
application/src/main/java/org/thingsboard/server/controller/NotificationController.java

@ -37,6 +37,7 @@ import org.thingsboard.server.common.data.notification.Notification;
import org.thingsboard.server.common.data.notification.NotificationRequest; import org.thingsboard.server.common.data.notification.NotificationRequest;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.dao.notification.NotificationRequestService;
import org.thingsboard.server.dao.notification.NotificationService; import org.thingsboard.server.dao.notification.NotificationService;
import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.notification.NotificationSubscriptionService; import org.thingsboard.server.service.notification.NotificationSubscriptionService;
@ -54,6 +55,7 @@ import java.util.UUID;
public class NotificationController extends BaseController { public class NotificationController extends BaseController {
private final NotificationService notificationService; private final NotificationService notificationService;
private final NotificationRequestService notificationRequestService;
private final NotificationSubscriptionService notificationSubscriptionService; private final NotificationSubscriptionService notificationSubscriptionService;
@GetMapping("/notifications") @GetMapping("/notifications")
@ -102,7 +104,7 @@ public class NotificationController extends BaseController {
public NotificationRequest getNotificationRequestById(@PathVariable UUID id, public NotificationRequest getNotificationRequestById(@PathVariable UUID id,
@AuthenticationPrincipal SecurityUser user) { @AuthenticationPrincipal SecurityUser user) {
NotificationRequestId notificationRequestId = new NotificationRequestId(id); NotificationRequestId notificationRequestId = new NotificationRequestId(id);
return notificationService.findNotificationRequestById(user.getTenantId(), notificationRequestId); return notificationRequestService.findNotificationRequestById(user.getTenantId(), notificationRequestId);
} }
@GetMapping("/notification/requests") @GetMapping("/notification/requests")
@ -114,14 +116,14 @@ public class NotificationController extends BaseController {
@RequestParam(required = false) String sortOrder, @RequestParam(required = false) String sortOrder,
@AuthenticationPrincipal SecurityUser user) throws ThingsboardException { @AuthenticationPrincipal SecurityUser user) throws ThingsboardException {
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
return notificationService.findNotificationRequestsByTenantId(user.getTenantId(), pageLink); return notificationRequestService.findNotificationRequestsByTenantId(user.getTenantId(), pageLink);
} }
@DeleteMapping("/notification/request/{id}") @DeleteMapping("/notification/request/{id}")
public void deleteNotificationRequest(@PathVariable UUID id, public void deleteNotificationRequest(@PathVariable UUID id,
@AuthenticationPrincipal SecurityUser user) throws ThingsboardException { @AuthenticationPrincipal SecurityUser user) throws ThingsboardException {
NotificationRequestId notificationRequestId = new NotificationRequestId(id); NotificationRequestId notificationRequestId = new NotificationRequestId(id);
NotificationRequest notificationRequest = notificationService.findNotificationRequestById(user.getTenantId(), notificationRequestId); NotificationRequest notificationRequest = notificationRequestService.findNotificationRequestById(user.getTenantId(), notificationRequestId);
accessControlService.checkPermission(user, Resource.NOTIFICATION_REQUEST, Operation.DELETE, notificationRequestId, notificationRequest); accessControlService.checkPermission(user, Resource.NOTIFICATION_REQUEST, Operation.DELETE, notificationRequestId, notificationRequest);
try { try {
notificationSubscriptionService.deleteNotificationRequest(user.getTenantId(), notificationRequestId); notificationSubscriptionService.deleteNotificationRequest(user.getTenantId(), notificationRequestId);

8
application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationRuleProcessingService.java

@ -30,8 +30,8 @@ import org.thingsboard.server.common.data.notification.NotificationRequestStatus
import org.thingsboard.server.common.data.notification.NotificationSeverity; import org.thingsboard.server.common.data.notification.NotificationSeverity;
import org.thingsboard.server.common.data.notification.rule.NonConfirmedNotificationEscalation; import org.thingsboard.server.common.data.notification.rule.NonConfirmedNotificationEscalation;
import org.thingsboard.server.common.data.notification.rule.NotificationRule; import org.thingsboard.server.common.data.notification.rule.NotificationRule;
import org.thingsboard.server.dao.notification.NotificationRequestService;
import org.thingsboard.server.dao.notification.NotificationRuleService; import org.thingsboard.server.dao.notification.NotificationRuleService;
import org.thingsboard.server.dao.notification.NotificationService;
import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.executors.DbCallbackExecutorService; import org.thingsboard.server.service.executors.DbCallbackExecutorService;
@ -43,7 +43,7 @@ import java.util.List;
public class DefaultNotificationRuleProcessingService implements NotificationRuleProcessingService { public class DefaultNotificationRuleProcessingService implements NotificationRuleProcessingService {
private final NotificationRuleService notificationRuleService; private final NotificationRuleService notificationRuleService;
private final NotificationService notificationService; private final NotificationRequestService notificationRequestService;
private final NotificationSubscriptionService notificationSubscriptionService; private final NotificationSubscriptionService notificationSubscriptionService;
private final DbCallbackExecutorService dbCallbackExecutorService; private final DbCallbackExecutorService dbCallbackExecutorService;
@ -65,7 +65,7 @@ public class DefaultNotificationRuleProcessingService implements NotificationRul
} }
private void onAlarmUpdate(TenantId tenantId, NotificationRuleId notificationRuleId, Alarm alarm) { private void onAlarmUpdate(TenantId tenantId, NotificationRuleId notificationRuleId, Alarm alarm) {
List<NotificationRequest> notificationRequests = notificationService.findNotificationRequestsByRuleIdAndAlarmId(tenantId, notificationRuleId, alarm.getId()); List<NotificationRequest> notificationRequests = notificationRequestService.findNotificationRequestsByRuleIdAndAlarmId(tenantId, notificationRuleId, alarm.getId());
NotificationRule notificationRule = notificationRuleService.findNotificationRuleById(tenantId, notificationRuleId); NotificationRule notificationRule = notificationRuleService.findNotificationRuleById(tenantId, notificationRuleId);
if (notificationRequests.isEmpty()) { // in case it is first notification for alarm, or it was previously acked and now we need to send notifications again if (notificationRequests.isEmpty()) { // in case it is first notification for alarm, or it was previously acked and now we need to send notifications again
@ -80,7 +80,7 @@ public class DefaultNotificationRuleProcessingService implements NotificationRul
for (NotificationRequest notificationRequest : notificationRequests) { for (NotificationRequest notificationRequest : notificationRequests) {
if (notificationRequest.getStatus() == NotificationRequestStatus.SCHEDULED) { if (notificationRequest.getStatus() == NotificationRequestStatus.SCHEDULED) {
// using regular service due to no need to send an update to subscription manager // using regular service due to no need to send an update to subscription manager
notificationService.deleteNotificationRequestById(tenantId, notificationRequest.getId()); notificationRequestService.deleteNotificationRequestById(tenantId, notificationRequest.getId());
} else { } else {
notificationSubscriptionService.deleteNotificationRequest(tenantId, notificationRequest.getId()); notificationSubscriptionService.deleteNotificationRequest(tenantId, notificationRequest.getId());
// todo: or should we mark already sent notifications as read? // todo: or should we mark already sent notifications as read?

129
application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationSchedulerService.java

@ -0,0 +1,129 @@
/**
* Copyright © 2016-2022 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.service.notification;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListenableScheduledFuture;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.id.NotificationRequestId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.notification.NotificationRequest;
import org.thingsboard.server.common.data.notification.NotificationRequestConfig;
import org.thingsboard.server.common.data.page.PageDataIterable;
import org.thingsboard.server.common.msg.queue.ServiceType;
import org.thingsboard.server.common.msg.queue.TopicPartitionInfo;
import org.thingsboard.server.dao.notification.NotificationRequestService;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.partition.AbstractPartitionBasedService;
import javax.annotation.PostConstruct;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
@TbCoreComponent
@Service
@RequiredArgsConstructor
@Slf4j
@SuppressWarnings("UnstableApiUsage")
public class DefaultNotificationSchedulerService extends AbstractPartitionBasedService<NotificationRequestId> implements NotificationSchedulerService {
private final NotificationSubscriptionService notificationSubscriptionService;
private final NotificationRequestService notificationRequestService;
private final Map<NotificationRequestId, ScheduledFuture<?>> scheduledNotificationRequests = new ConcurrentHashMap<>();
@PostConstruct
public void init() {
super.init();
}
@Override
protected Map<TopicPartitionInfo, List<ListenableFuture<?>>> onAddedPartitions(Set<TopicPartitionInfo> addedPartitions) {
PageDataIterable<NotificationRequest> notificationRequests = new PageDataIterable<>(pageLink -> {
return notificationRequestService.findScheduledNotificationRequests(pageLink);
}, 1000);
for (NotificationRequest notificationRequest : notificationRequests) {
TopicPartitionInfo requestPartition = partitionService.resolve(ServiceType.TB_CORE, notificationRequest.getTenantId(), notificationRequest.getId());
if (addedPartitions.contains(requestPartition)) {
partitionedEntities.computeIfAbsent(requestPartition, k -> ConcurrentHashMap.newKeySet()).add(notificationRequest.getId());
if (!scheduledNotificationRequests.containsKey(notificationRequest.getId())) {
scheduleNotificationRequest(notificationRequest.getTenantId(), notificationRequest, notificationRequest.getCreatedTime());
}
}
}
return Collections.emptyMap();
}
@Override
public void scheduleNotificationRequest(TenantId tenantId, NotificationRequestId notificationRequestId, long requestTs) {
NotificationRequest notificationRequest = notificationRequestService.findNotificationRequestById(tenantId, notificationRequestId);
scheduleNotificationRequest(tenantId, notificationRequest, requestTs);
}
private void scheduleNotificationRequest(TenantId tenantId, NotificationRequest request, long requestTs) {
int delayInMinutes = Optional.ofNullable(request)
.map(NotificationRequest::getAdditionalConfig)
.map(NotificationRequestConfig::getSendingDelayInMinutes)
.orElse(0);
if (delayInMinutes <= 0) return; // todo: think about: if server was down for some time and delayMs will be negative - need to send these requests as well (but when the value is within some range)
long delayMs = TimeUnit.MINUTES.toMillis(delayInMinutes) - (System.currentTimeMillis() - requestTs);
ListenableScheduledFuture<?> scheduledTask = scheduledExecutor.schedule(() -> {
NotificationRequest notificationRequest = notificationRequestService.findNotificationRequestById(tenantId, request.getId());
if (notificationRequest == null) return;
notificationSubscriptionService.processNotificationRequest(tenantId, notificationRequest);
scheduledNotificationRequests.remove(notificationRequest.getId());
}, delayMs, TimeUnit.MILLISECONDS);
scheduledNotificationRequests.put(request.getId(), scheduledTask);
}
@Override
public void onNotificationRequestDeleted(TenantId tenantId, NotificationRequestId notificationRequestId) {
removeAndCancel(notificationRequestId);
}
@Override
protected void cleanupEntityOnPartitionRemoval(NotificationRequestId notificationRequestId) {
removeAndCancel(notificationRequestId);
}
private void removeAndCancel(NotificationRequestId notificationRequestId) {
ScheduledFuture<?> scheduledTask = scheduledNotificationRequests.remove(notificationRequestId);
if (scheduledTask != null) {
scheduledTask.cancel(false);
}
}
@Override
protected String getServiceName() {
return "Notifications scheduler";
}
@Override
protected String getSchedulerExecutorName() {
return "notifications-scheduler";
}
}

37
application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationSubscriptionService.java

@ -35,6 +35,7 @@ import org.thingsboard.server.common.msg.queue.ServiceType;
import org.thingsboard.server.common.msg.queue.TbCallback; import org.thingsboard.server.common.msg.queue.TbCallback;
import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; import org.thingsboard.server.common.msg.queue.TopicPartitionInfo;
import org.thingsboard.server.dao.DaoUtil; import org.thingsboard.server.dao.DaoUtil;
import org.thingsboard.server.dao.notification.NotificationRequestService;
import org.thingsboard.server.dao.notification.NotificationService; import org.thingsboard.server.dao.notification.NotificationService;
import org.thingsboard.server.dao.notification.NotificationTargetService; import org.thingsboard.server.dao.notification.NotificationTargetService;
import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos;
@ -56,17 +57,20 @@ import java.util.UUID;
public class DefaultNotificationSubscriptionService extends AbstractSubscriptionService implements NotificationSubscriptionService, RuleEngineNotificationService { public class DefaultNotificationSubscriptionService extends AbstractSubscriptionService implements NotificationSubscriptionService, RuleEngineNotificationService {
private final NotificationTargetService notificationTargetService; private final NotificationTargetService notificationTargetService;
private final NotificationRequestService notificationRequestService;
private final NotificationService notificationService; private final NotificationService notificationService;
private final DbCallbackExecutorService dbCallbackExecutorService; private final DbCallbackExecutorService dbCallbackExecutorService;
private final NotificationsTopicService notificationsTopicService; private final NotificationsTopicService notificationsTopicService;
public DefaultNotificationSubscriptionService(TbClusterService clusterService, PartitionService partitionService, public DefaultNotificationSubscriptionService(TbClusterService clusterService, PartitionService partitionService,
NotificationTargetService notificationTargetService, NotificationTargetService notificationTargetService,
NotificationRequestService notificationRequestService,
NotificationService notificationService, NotificationService notificationService,
DbCallbackExecutorService dbCallbackExecutorService, DbCallbackExecutorService dbCallbackExecutorService,
NotificationsTopicService notificationsTopicService) { NotificationsTopicService notificationsTopicService) {
super(clusterService, partitionService); super(clusterService, partitionService);
this.notificationTargetService = notificationTargetService; this.notificationTargetService = notificationTargetService;
this.notificationRequestService = notificationRequestService;
this.notificationService = notificationService; this.notificationService = notificationService;
this.dbCallbackExecutorService = dbCallbackExecutorService; this.dbCallbackExecutorService = dbCallbackExecutorService;
this.notificationsTopicService = notificationsTopicService; this.notificationsTopicService = notificationsTopicService;
@ -77,18 +81,18 @@ public class DefaultNotificationSubscriptionService extends AbstractSubscription
log.info("Processing notification request (tenant id: {}, notification target id: {})", tenantId, notificationRequest.getTargetId()); log.info("Processing notification request (tenant id: {}, notification target id: {})", tenantId, notificationRequest.getTargetId());
notificationRequest.setTenantId(tenantId); notificationRequest.setTenantId(tenantId);
if (notificationRequest.getAdditionalConfig() != null) { if (notificationRequest.getAdditionalConfig() != null) {
// TODO: think about notification request update
NotificationRequestConfig config = notificationRequest.getAdditionalConfig(); NotificationRequestConfig config = notificationRequest.getAdditionalConfig();
if (config.getSendingDelayInMinutes() > 0) { if (config.getSendingDelayInMinutes() > 0 && notificationRequest.getId() == null) {
notificationRequest.setStatus(NotificationRequestStatus.SCHEDULED); notificationRequest.setStatus(NotificationRequestStatus.SCHEDULED);
NotificationRequest savedNotificationRequest = notificationRequestService.saveNotificationRequest(tenantId, notificationRequest);
// todo: delayed sending; check all delayed notification requests on start up, schedule send forwardToNotificationSchedulerService(tenantId, savedNotificationRequest.getId(), false);
return savedNotificationRequest;
} }
} }
if (notificationRequest.getStatus() == null) {
notificationRequest.setStatus(NotificationRequestStatus.PROCESSED);
}
NotificationRequest savedNotificationRequest = notificationService.saveNotificationRequest(tenantId, notificationRequest); notificationRequest.setStatus(NotificationRequestStatus.PROCESSED);
NotificationRequest savedNotificationRequest = notificationRequestService.saveNotificationRequest(tenantId, notificationRequest);
DaoUtil.processBatches(pageLink -> { DaoUtil.processBatches(pageLink -> {
return notificationTargetService.findRecipientsForNotificationTarget(tenantId, notificationRequest.getTargetId(), pageLink); return notificationTargetService.findRecipientsForNotificationTarget(tenantId, notificationRequest.getTargetId(), pageLink);
@ -109,6 +113,20 @@ public class DefaultNotificationSubscriptionService extends AbstractSubscription
return savedNotificationRequest; return savedNotificationRequest;
} }
private void forwardToNotificationSchedulerService(TenantId tenantId, NotificationRequestId notificationRequestId, boolean deleted) {
TransportProtos.NotificationSchedulerServiceMsg.Builder msg = TransportProtos.NotificationSchedulerServiceMsg.newBuilder()
.setTenantIdMSB(tenantId.getId().getMostSignificantBits())
.setTenantIdLSB(tenantId.getId().getLeastSignificantBits())
.setRequestIdMSB(notificationRequestId.getId().getMostSignificantBits())
.setRequestIdLSB(notificationRequestId.getId().getLeastSignificantBits())
.setTs(System.currentTimeMillis())
.setDeleted(deleted);
TransportProtos.ToCoreMsg toCoreMsg = TransportProtos.ToCoreMsg.newBuilder()
.setNotificationSchedulerServiceMsg(msg)
.build();
clusterService.pushMsgToCore(tenantId, notificationRequestId, toCoreMsg, null);
}
@Override @Override
public void markNotificationAsRead(TenantId tenantId, UserId recipientId, NotificationId notificationId) { public void markNotificationAsRead(TenantId tenantId, UserId recipientId, NotificationId notificationId) {
boolean updated = notificationService.markNotificationAsRead(tenantId, recipientId, notificationId); boolean updated = notificationService.markNotificationAsRead(tenantId, recipientId, notificationId);
@ -122,17 +140,18 @@ public class DefaultNotificationSubscriptionService extends AbstractSubscription
@Override @Override
public void deleteNotificationRequest(TenantId tenantId, NotificationRequestId notificationRequestId) { public void deleteNotificationRequest(TenantId tenantId, NotificationRequestId notificationRequestId) {
log.debug("Deleting notification request {}", notificationRequestId); log.debug("Deleting notification request {}", notificationRequestId);
notificationService.deleteNotificationRequestById(tenantId, notificationRequestId); notificationRequestService.deleteNotificationRequestById(tenantId, notificationRequestId);
onNotificationRequestUpdate(tenantId, NotificationRequestUpdate.builder() onNotificationRequestUpdate(tenantId, NotificationRequestUpdate.builder()
.notificationRequestId(notificationRequestId) .notificationRequestId(notificationRequestId)
.deleted(true) .deleted(true)
.build()); .build());
forwardToNotificationSchedulerService(tenantId, notificationRequestId, true);
} }
@Override @Override
public void updateNotificationRequest(TenantId tenantId, NotificationRequest notificationRequest) { public void updateNotificationRequest(TenantId tenantId, NotificationRequest notificationRequest) {
log.debug("Updating notification request {}", notificationRequest.getId()); log.debug("Updating notification request {}", notificationRequest.getId());
notificationService.saveNotificationRequest(tenantId, notificationRequest); notificationRequestService.saveNotificationRequest(tenantId, notificationRequest);
notificationService.updateNotificationsInfosByRequestId(tenantId, notificationRequest.getId(), notificationRequest.getNotificationInfo()); notificationService.updateNotificationsInfosByRequestId(tenantId, notificationRequest.getId(), notificationRequest.getNotificationInfo());
onNotificationRequestUpdate(tenantId, NotificationRequestUpdate.builder() onNotificationRequestUpdate(tenantId, NotificationRequestUpdate.builder()
.notificationRequestId(notificationRequest.getId()) .notificationRequestId(notificationRequest.getId())

27
application/src/main/java/org/thingsboard/server/service/notification/NotificationSchedulerService.java

@ -0,0 +1,27 @@
/**
* Copyright © 2016-2022 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.service.notification;
import org.thingsboard.server.common.data.id.NotificationRequestId;
import org.thingsboard.server.common.data.id.TenantId;
public interface NotificationSchedulerService {
void scheduleNotificationRequest(TenantId tenantId, NotificationRequestId notificationRequestId, long requestTs);
void onNotificationRequestDeleted(TenantId tenantId, NotificationRequestId notificationRequestId);
}

5
application/src/main/java/org/thingsboard/server/service/partition/AbstractPartitionBasedService.java

@ -20,16 +20,17 @@ import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningScheduledExecutorService; import com.google.common.util.concurrent.ListeningScheduledExecutorService;
import com.google.common.util.concurrent.MoreExecutors; import com.google.common.util.concurrent.MoreExecutors;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.thingsboard.common.util.DonAsynchron; import org.thingsboard.common.util.DonAsynchron;
import org.thingsboard.common.util.ThingsBoardThreadFactory; import org.thingsboard.common.util.ThingsBoardThreadFactory;
import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.common.msg.queue.ServiceType;
import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; import org.thingsboard.server.common.msg.queue.TopicPartitionInfo;
import org.thingsboard.server.queue.discovery.PartitionService;
import org.thingsboard.server.queue.discovery.TbApplicationEventListener; import org.thingsboard.server.queue.discovery.TbApplicationEventListener;
import org.thingsboard.server.queue.discovery.event.PartitionChangeEvent; import org.thingsboard.server.queue.discovery.event.PartitionChangeEvent;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -48,6 +49,8 @@ public abstract class AbstractPartitionBasedService<T extends EntityId> extends
protected final ConcurrentMap<TopicPartitionInfo, List<ListenableFuture<?>>> partitionedFetchTasks = new ConcurrentHashMap<>(); protected final ConcurrentMap<TopicPartitionInfo, List<ListenableFuture<?>>> partitionedFetchTasks = new ConcurrentHashMap<>();
final Queue<Set<TopicPartitionInfo>> subscribeQueue = new ConcurrentLinkedQueue<>(); final Queue<Set<TopicPartitionInfo>> subscribeQueue = new ConcurrentLinkedQueue<>();
@Autowired
protected PartitionService partitionService;
protected ListeningScheduledExecutorService scheduledExecutor; protected ListeningScheduledExecutorService scheduledExecutor;
abstract protected String getServiceName(); abstract protected String getServiceName();

28
application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java

@ -31,8 +31,6 @@ import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.NotificationRequestId; import org.thingsboard.server.common.data.id.NotificationRequestId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.id.UserId;
import org.thingsboard.server.common.data.notification.Notification;
import org.thingsboard.server.common.data.notification.NotificationInfo;
import org.thingsboard.server.common.data.rpc.RpcError; import org.thingsboard.server.common.data.rpc.RpcError;
import org.thingsboard.server.common.msg.MsgType; import org.thingsboard.server.common.msg.MsgType;
import org.thingsboard.server.common.msg.TbActorMsg; import org.thingsboard.server.common.msg.TbActorMsg;
@ -69,6 +67,7 @@ import org.thingsboard.server.queue.util.AfterStartUp;
import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.apiusage.TbApiUsageStateService; import org.thingsboard.server.service.apiusage.TbApiUsageStateService;
import org.thingsboard.server.service.edge.EdgeNotificationService; import org.thingsboard.server.service.edge.EdgeNotificationService;
import org.thingsboard.server.service.notification.NotificationSchedulerService;
import org.thingsboard.server.service.ota.OtaPackageStateService; import org.thingsboard.server.service.ota.OtaPackageStateService;
import org.thingsboard.server.service.profile.TbAssetProfileCache; import org.thingsboard.server.service.profile.TbAssetProfileCache;
import org.thingsboard.server.service.profile.TbDeviceProfileCache; import org.thingsboard.server.service.profile.TbDeviceProfileCache;
@ -127,6 +126,7 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore
private final EdgeNotificationService edgeNotificationService; private final EdgeNotificationService edgeNotificationService;
private final OtaPackageStateService firmwareStateService; private final OtaPackageStateService firmwareStateService;
private final GitVersionControlQueueService vcQueueService; private final GitVersionControlQueueService vcQueueService;
private final NotificationSchedulerService notificationSchedulerService;
private final TbCoreConsumerStats stats; private final TbCoreConsumerStats stats;
protected final TbQueueConsumer<TbProtoQueueMsg<ToUsageStatsServiceMsg>> usageStatsConsumer; protected final TbQueueConsumer<TbProtoQueueMsg<ToUsageStatsServiceMsg>> usageStatsConsumer;
private final TbQueueConsumer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> firmwareStatesConsumer; private final TbQueueConsumer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> firmwareStatesConsumer;
@ -151,7 +151,8 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore
EdgeNotificationService edgeNotificationService, EdgeNotificationService edgeNotificationService,
OtaPackageStateService firmwareStateService, OtaPackageStateService firmwareStateService,
GitVersionControlQueueService vcQueueService, GitVersionControlQueueService vcQueueService,
PartitionService partitionService) { PartitionService partitionService,
NotificationSchedulerService notificationSchedulerService) {
super(actorContext, encodingService, tenantProfileCache, deviceProfileCache, assetProfileCache, apiUsageStateService, partitionService, tbCoreQueueFactory.createToCoreNotificationsMsgConsumer()); super(actorContext, encodingService, tenantProfileCache, deviceProfileCache, assetProfileCache, apiUsageStateService, partitionService, tbCoreQueueFactory.createToCoreNotificationsMsgConsumer());
this.mainConsumer = tbCoreQueueFactory.createToCoreMsgConsumer(); this.mainConsumer = tbCoreQueueFactory.createToCoreMsgConsumer();
this.usageStatsConsumer = tbCoreQueueFactory.createToUsageStatsServiceMsgConsumer(); this.usageStatsConsumer = tbCoreQueueFactory.createToUsageStatsServiceMsgConsumer();
@ -165,6 +166,7 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore
this.statsService = statsService; this.statsService = statsService;
this.firmwareStateService = firmwareStateService; this.firmwareStateService = firmwareStateService;
this.vcQueueService = vcQueueService; this.vcQueueService = vcQueueService;
this.notificationSchedulerService = notificationSchedulerService;
} }
@PostConstruct @PostConstruct
@ -259,6 +261,10 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore
} }
} }
callback.onSuccess(); callback.onSuccess();
} else if (toCoreMsg.hasNotificationSchedulerServiceMsg()) {
TransportProtos.NotificationSchedulerServiceMsg notificationSchedulerServiceMsg = toCoreMsg.getNotificationSchedulerServiceMsg();
log.trace("[{}] Forwarding message to notification scheduler service {}", id, toCoreMsg.getNotificationSchedulerServiceMsg());
forwardToNotificationSchedulerService(notificationSchedulerServiceMsg, callback);
} }
} catch (Throwable e) { } catch (Throwable e) {
log.warn("[{}] Failed to process message: {}", id, msg, e); log.warn("[{}] Failed to process message: {}", id, msg, e);
@ -571,6 +577,22 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore
} }
} }
private void forwardToNotificationSchedulerService(TransportProtos.NotificationSchedulerServiceMsg msg, TbCallback callback) {
TenantId tenantId = TenantId.fromUUID(new UUID(msg.getTenantIdMSB(), msg.getTenantIdLSB()));
NotificationRequestId notificationRequestId = new NotificationRequestId(new UUID(msg.getRequestIdMSB(), msg.getRequestIdLSB()));
boolean deleted = msg.getDeleted();
try {
if (!deleted) {
notificationSchedulerService.scheduleNotificationRequest(tenantId, notificationRequestId, msg.getTs());
} else {
notificationSchedulerService.onNotificationRequestDeleted(tenantId, notificationRequestId);
}
callback.onSuccess();
} catch (Exception e) {
callback.onFailure(new RuntimeException("Failed to scheduler notification request", e));
}
}
private void forwardToEdgeNotificationService(EdgeNotificationMsgProto edgeNotificationMsg, TbCallback callback) { private void forwardToEdgeNotificationService(EdgeNotificationMsgProto edgeNotificationMsg, TbCallback callback) {
if (statsEnabled) { if (statsEnabled) {
stats.log(edgeNotificationMsg); stats.log(edgeNotificationMsg);

10
common/cluster-api/src/main/proto/queue.proto

@ -956,6 +956,7 @@ message ToCoreMsg {
bytes toDeviceActorNotificationMsg = 4; bytes toDeviceActorNotificationMsg = 4;
EdgeNotificationMsgProto edgeNotificationMsg = 5; EdgeNotificationMsgProto edgeNotificationMsg = 5;
DeviceActivityProto deviceActivityMsg = 6; DeviceActivityProto deviceActivityMsg = 6;
NotificationSchedulerServiceMsg notificationSchedulerServiceMsg = 7;
} }
/* High priority messages with low latency are handled by ThingsBoard Core Service separately */ /* High priority messages with low latency are handled by ThingsBoard Core Service separately */
@ -1033,4 +1034,11 @@ message ToOtaPackageStateServiceMsg {
string type = 8; string type = 8;
} }
message NotificationSchedulerServiceMsg {
int64 tenantIdMSB = 1;
int64 tenantIdLSB = 2;
int64 requestIdMSB = 3;
int64 requestIdLSB = 4;
int64 ts = 5;
bool deleted = 6;
}

42
common/dao-api/src/main/java/org/thingsboard/server/dao/notification/NotificationRequestService.java

@ -0,0 +1,42 @@
/**
* Copyright © 2016-2022 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.notification;
import org.thingsboard.server.common.data.id.AlarmId;
import org.thingsboard.server.common.data.id.NotificationRequestId;
import org.thingsboard.server.common.data.id.NotificationRuleId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.notification.NotificationRequest;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import java.util.List;
public interface NotificationRequestService {
NotificationRequest saveNotificationRequest(TenantId tenantId, NotificationRequest notificationRequest);
NotificationRequest findNotificationRequestById(TenantId tenantId, NotificationRequestId id);
PageData<NotificationRequest> findNotificationRequestsByTenantId(TenantId tenantId, PageLink pageLink);
List<NotificationRequest> findNotificationRequestsByRuleIdAndAlarmId(TenantId tenantId, NotificationRuleId ruleId, AlarmId alarmId);
void deleteNotificationRequestById(TenantId tenantId, NotificationRequestId id);
PageData<NotificationRequest> findScheduledNotificationRequests(PageLink pageLink);
}

16
common/dao-api/src/main/java/org/thingsboard/server/dao/notification/NotificationService.java

@ -15,33 +15,17 @@
*/ */
package org.thingsboard.server.dao.notification; package org.thingsboard.server.dao.notification;
import org.thingsboard.server.common.data.id.AlarmId;
import org.thingsboard.server.common.data.id.NotificationId; import org.thingsboard.server.common.data.id.NotificationId;
import org.thingsboard.server.common.data.id.NotificationRequestId; import org.thingsboard.server.common.data.id.NotificationRequestId;
import org.thingsboard.server.common.data.id.NotificationRuleId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.id.UserId;
import org.thingsboard.server.common.data.notification.Notification; import org.thingsboard.server.common.data.notification.Notification;
import org.thingsboard.server.common.data.notification.NotificationInfo; import org.thingsboard.server.common.data.notification.NotificationInfo;
import org.thingsboard.server.common.data.notification.NotificationRequest;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
import java.util.List;
public interface NotificationService { public interface NotificationService {
NotificationRequest saveNotificationRequest(TenantId tenantId, NotificationRequest notificationRequest);
NotificationRequest findNotificationRequestById(TenantId tenantId, NotificationRequestId id);
PageData<NotificationRequest> findNotificationRequestsByTenantId(TenantId tenantId, PageLink pageLink);
List<NotificationRequest> findNotificationRequestsByRuleIdAndAlarmId(TenantId tenantId, NotificationRuleId ruleId, AlarmId alarmId);
void deleteNotificationRequestById(TenantId tenantId, NotificationRequestId id);
Notification saveNotification(TenantId tenantId, Notification notification); Notification saveNotification(TenantId tenantId, Notification notification);
Notification findNotificationById(TenantId tenantId, NotificationId notificationId); Notification findNotificationById(TenantId tenantId, NotificationId notificationId);

4
dao/src/main/java/org/thingsboard/server/dao/model/BaseSqlEntity.java

@ -86,8 +86,8 @@ public abstract class BaseSqlEntity<D> implements BaseEntity<D> {
} }
} }
protected <T> T fromJson(JsonNode json) { protected <T> T fromJson(JsonNode json, Class<T> type) {
return JacksonUtil.convertValue(json, new TypeReference<T>() {}); return JacksonUtil.convertValue(json, type);
} }
} }

4
dao/src/main/java/org/thingsboard/server/dao/model/sql/NotificationRequestEntity.java

@ -110,9 +110,9 @@ public class NotificationRequestEntity extends BaseSqlEntity<NotificationRequest
notificationRequest.setTargetId(createId(targetId, NotificationTargetId::new)); notificationRequest.setTargetId(createId(targetId, NotificationTargetId::new));
notificationRequest.setNotificationReason(notificationReason); notificationRequest.setNotificationReason(notificationReason);
notificationRequest.setTextTemplate(textTemplate); notificationRequest.setTextTemplate(textTemplate);
notificationRequest.setNotificationInfo(fromJson(notificationInfo)); notificationRequest.setNotificationInfo(fromJson(notificationInfo, NotificationInfo.class));
notificationRequest.setNotificationSeverity(notificationSeverity); notificationRequest.setNotificationSeverity(notificationSeverity);
notificationRequest.setAdditionalConfig(fromJson(additionalConfig)); notificationRequest.setAdditionalConfig(fromJson(additionalConfig, NotificationRequestConfig.class));
notificationRequest.setStatus(status); notificationRequest.setStatus(status);
notificationRequest.setRuleId(createId(ruleId, NotificationRuleId::new)); notificationRequest.setRuleId(createId(ruleId, NotificationRuleId::new));
notificationRequest.setAlarmId(createId(alarmId, AlarmId::new)); notificationRequest.setAlarmId(createId(alarmId, AlarmId::new));

87
dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationRequestService.java

@ -0,0 +1,87 @@
/**
* Copyright © 2016-2022 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.notification;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.id.AlarmId;
import org.thingsboard.server.common.data.id.NotificationRequestId;
import org.thingsboard.server.common.data.id.NotificationRuleId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.notification.NotificationRequest;
import org.thingsboard.server.common.data.notification.NotificationRequestStatus;
import org.thingsboard.server.common.data.notification.NotificationSeverity;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.dao.service.DataValidator;
import java.util.List;
@Service
@Slf4j
@RequiredArgsConstructor
public class DefaultNotificationRequestService implements NotificationRequestService {
private final NotificationRequestDao notificationRequestDao;
private final NotificationRequestValidator notificationRequestValidator = new NotificationRequestValidator();
@Override
public NotificationRequest saveNotificationRequest(TenantId tenantId, NotificationRequest notificationRequest) {
if (StringUtils.isBlank(notificationRequest.getNotificationReason())) {
notificationRequest.setNotificationReason(NotificationRequest.GENERAL_NOTIFICATION_REASON);
}
if (notificationRequest.getNotificationSeverity() == null) {
notificationRequest.setNotificationSeverity(NotificationSeverity.NORMAL);
}
notificationRequestValidator.validate(notificationRequest, NotificationRequest::getTenantId);
return notificationRequestDao.save(tenantId, notificationRequest);
}
@Override
public NotificationRequest findNotificationRequestById(TenantId tenantId, NotificationRequestId id) {
return notificationRequestDao.findById(tenantId, id.getId());
}
@Override
public PageData<NotificationRequest> findNotificationRequestsByTenantId(TenantId tenantId, PageLink pageLink) {
return notificationRequestDao.findByTenantIdAndPageLink(tenantId, pageLink);
}
@Override
public List<NotificationRequest> findNotificationRequestsByRuleIdAndAlarmId(TenantId tenantId, NotificationRuleId ruleId, AlarmId alarmId) {
return notificationRequestDao.findByRuleIdAndAlarmId(tenantId, ruleId, alarmId);
}
// ON DELETE CASCADE is used: notifications for request are deleted as well
@Override
public void deleteNotificationRequestById(TenantId tenantId, NotificationRequestId id) {
notificationRequestDao.removeById(tenantId, id.getId());
}
@Override
public PageData<NotificationRequest> findScheduledNotificationRequests(PageLink pageLink) {
return notificationRequestDao.findAllByStatus(NotificationRequestStatus.SCHEDULED, pageLink);
}
private static class NotificationRequestValidator extends DataValidator<NotificationRequest> {
}
}

45
dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationService.java

@ -28,6 +28,7 @@ import org.thingsboard.server.common.data.id.UserId;
import org.thingsboard.server.common.data.notification.Notification; import org.thingsboard.server.common.data.notification.Notification;
import org.thingsboard.server.common.data.notification.NotificationInfo; import org.thingsboard.server.common.data.notification.NotificationInfo;
import org.thingsboard.server.common.data.notification.NotificationRequest; import org.thingsboard.server.common.data.notification.NotificationRequest;
import org.thingsboard.server.common.data.notification.NotificationRequestStatus;
import org.thingsboard.server.common.data.notification.NotificationSeverity; import org.thingsboard.server.common.data.notification.NotificationSeverity;
import org.thingsboard.server.common.data.notification.NotificationStatus; import org.thingsboard.server.common.data.notification.NotificationStatus;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
@ -43,44 +44,8 @@ import java.util.List;
@RequiredArgsConstructor @RequiredArgsConstructor
public class DefaultNotificationService implements NotificationService { public class DefaultNotificationService implements NotificationService {
private final NotificationRequestDao notificationRequestDao;
private final NotificationDao notificationDao; private final NotificationDao notificationDao;
private final NotificationRequestValidator notificationRequestValidator = new NotificationRequestValidator();
@Override
public NotificationRequest saveNotificationRequest(TenantId tenantId, NotificationRequest notificationRequest) {
if (StringUtils.isBlank(notificationRequest.getNotificationReason())) {
notificationRequest.setNotificationReason(NotificationRequest.GENERAL_NOTIFICATION_REASON);
}
if (notificationRequest.getNotificationSeverity() == null) {
notificationRequest.setNotificationSeverity(NotificationSeverity.NORMAL);
}
notificationRequestValidator.validate(notificationRequest, NotificationRequest::getTenantId);
return notificationRequestDao.save(tenantId, notificationRequest);
}
@Override
public NotificationRequest findNotificationRequestById(TenantId tenantId, NotificationRequestId id) {
return notificationRequestDao.findById(tenantId, id.getId());
}
@Override
public PageData<NotificationRequest> findNotificationRequestsByTenantId(TenantId tenantId, PageLink pageLink) {
return notificationRequestDao.findByTenantIdAndPageLink(tenantId, pageLink);
}
@Override
public List<NotificationRequest> findNotificationRequestsByRuleIdAndAlarmId(TenantId tenantId, NotificationRuleId ruleId, AlarmId alarmId) {
return notificationRequestDao.findByRuleIdAndAlarmId(tenantId, ruleId, alarmId);
}
// ON DELETE CASCADE is used: notifications for request are deleted as well
@Override
public void deleteNotificationRequestById(TenantId tenantId, NotificationRequestId id) {
notificationRequestDao.removeById(tenantId, id.getId());
}
@Override @Override
public Notification saveNotification(TenantId tenantId, Notification notification) { public Notification saveNotification(TenantId tenantId, Notification notification) {
return notificationDao.save(tenantId, notification); return notificationDao.save(tenantId, notification);
@ -122,12 +87,4 @@ public class DefaultNotificationService implements NotificationService {
return notificationDao.updateInfosByRequestId(tenantId, notificationRequestId, notificationInfo); return notificationDao.updateInfosByRequestId(tenantId, notificationRequestId, notificationInfo);
} }
private static class NotificationRequestValidator extends DataValidator<NotificationRequest> {
@Override
protected void validateDataImpl(TenantId tenantId, NotificationRequest notificationRequest) {
}
}
} }

3
dao/src/main/java/org/thingsboard/server/dao/notification/NotificationRequestDao.java

@ -19,6 +19,7 @@ import org.thingsboard.server.common.data.id.AlarmId;
import org.thingsboard.server.common.data.id.NotificationRuleId; import org.thingsboard.server.common.data.id.NotificationRuleId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.notification.NotificationRequest; import org.thingsboard.server.common.data.notification.NotificationRequest;
import org.thingsboard.server.common.data.notification.NotificationRequestStatus;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.dao.Dao; import org.thingsboard.server.dao.Dao;
@ -31,4 +32,6 @@ public interface NotificationRequestDao extends Dao<NotificationRequest> {
List<NotificationRequest> findByRuleIdAndAlarmId(TenantId tenantId, NotificationRuleId ruleId, AlarmId alarmId); List<NotificationRequest> findByRuleIdAndAlarmId(TenantId tenantId, NotificationRuleId ruleId, AlarmId alarmId);
PageData<NotificationRequest> findAllByStatus(NotificationRequestStatus status, PageLink pageLink);
} }

6
dao/src/main/java/org/thingsboard/server/dao/sql/notification/JpaNotificationRequestDao.java

@ -23,6 +23,7 @@ import org.thingsboard.server.common.data.id.AlarmId;
import org.thingsboard.server.common.data.id.NotificationRuleId; import org.thingsboard.server.common.data.id.NotificationRuleId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.notification.NotificationRequest; import org.thingsboard.server.common.data.notification.NotificationRequest;
import org.thingsboard.server.common.data.notification.NotificationRequestStatus;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.dao.DaoUtil; import org.thingsboard.server.dao.DaoUtil;
@ -52,6 +53,11 @@ public class JpaNotificationRequestDao extends JpaAbstractDao<NotificationReques
return DaoUtil.convertDataList(notificationRequestRepository.findAllByRuleIdAndAlarmId(ruleId.getId(), alarmId.getId())); return DaoUtil.convertDataList(notificationRequestRepository.findAllByRuleIdAndAlarmId(ruleId.getId(), alarmId.getId()));
} }
@Override
public PageData<NotificationRequest> findAllByStatus(NotificationRequestStatus status, PageLink pageLink) {
return DaoUtil.toPageData(notificationRequestRepository.findAllByStatus(status, DaoUtil.toPageable(pageLink)));
}
@Override @Override
protected Class<NotificationRequestEntity> getEntityClass() { protected Class<NotificationRequestEntity> getEntityClass() {
return NotificationRequestEntity.class; return NotificationRequestEntity.class;

3
dao/src/main/java/org/thingsboard/server/dao/sql/notification/NotificationRequestRepository.java

@ -21,6 +21,7 @@ import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query; import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param; import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import org.thingsboard.server.common.data.notification.NotificationRequestStatus;
import org.thingsboard.server.dao.model.sql.NotificationRequestEntity; import org.thingsboard.server.dao.model.sql.NotificationRequestEntity;
import java.util.List; import java.util.List;
@ -37,4 +38,6 @@ public interface NotificationRequestRepository extends JpaRepository<Notificatio
List<NotificationRequestEntity> findAllByRuleIdAndAlarmId(UUID ruleId, UUID alarmId); List<NotificationRequestEntity> findAllByRuleIdAndAlarmId(UUID ruleId, UUID alarmId);
Page<NotificationRequestEntity> findAllByStatus(NotificationRequestStatus status, Pageable pageable);
} }

Loading…
Cancel
Save