Send notifications via Slack independently of the targets
This commit is contained in:
parent
6eea14bcf7
commit
91a4de7780
@ -64,6 +64,7 @@ import org.thingsboard.server.service.ws.notification.sub.NotificationRequestUpd
|
||||
import org.thingsboard.server.service.ws.notification.sub.NotificationUpdate;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -130,27 +131,43 @@ public class DefaultNotificationCenter extends AbstractSubscriptionService imple
|
||||
.build();
|
||||
ctx.init();
|
||||
|
||||
Set<NotificationDeliveryMethod> deliveryMethods = ctx.getDeliveryMethods();
|
||||
List<ListenableFuture<Void>> results = new ArrayList<>();
|
||||
|
||||
for (NotificationTargetId targetId : notificationRequest.getTargets()) {
|
||||
DaoUtil.processBatches(pageLink -> {
|
||||
return notificationTargetService.findRecipientsForNotificationTarget(tenantId, ctx.getCustomerId(), targetId, pageLink);
|
||||
}, 200, recipientsBatch -> {
|
||||
for (NotificationDeliveryMethod deliveryMethod : ctx.getDeliveryMethods()) {
|
||||
for (NotificationDeliveryMethod deliveryMethod : deliveryMethods) {
|
||||
if (deliveryMethod.isIndependent()) continue;
|
||||
|
||||
List<User> recipients = recipientsBatch.getData();
|
||||
log.debug("Sending {} notifications for request {} to recipients batch ({})", deliveryMethod, savedNotificationRequest.getId(), recipients.size());
|
||||
NotificationChannel notificationChannel = channels.get(deliveryMethod);
|
||||
for (User recipient : recipients) {
|
||||
ListenableFuture<Void> resultFuture = processForRecipient(notificationChannel, recipient, ctx);
|
||||
ListenableFuture<Void> resultFuture = process(notificationChannel, recipient, ctx);
|
||||
DonAsynchron.withCallback(resultFuture, result -> {
|
||||
ctx.getStats().reportSent(deliveryMethod, recipient);
|
||||
}, error -> {
|
||||
ctx.getStats().reportError(deliveryMethod, recipient, error);
|
||||
ctx.getStats().reportError(deliveryMethod, error, recipient);
|
||||
});
|
||||
results.add(resultFuture);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
for (NotificationDeliveryMethod deliveryMethod : deliveryMethods) {
|
||||
if (deliveryMethod.isIndependent()) {
|
||||
NotificationChannel notificationChannel = channels.get(deliveryMethod);
|
||||
ListenableFuture<Void> resultFuture = process(notificationChannel, null, ctx);
|
||||
DonAsynchron.withCallback(resultFuture, result -> {
|
||||
ctx.getStats().reportSent(deliveryMethod, null);
|
||||
}, error -> {
|
||||
ctx.getStats().reportError(deliveryMethod, error, null);
|
||||
});
|
||||
results.add(resultFuture);
|
||||
}
|
||||
}
|
||||
|
||||
Futures.whenAllComplete(results).run(() -> {
|
||||
NotificationRequestStats stats = ctx.getStats();
|
||||
@ -177,33 +194,21 @@ public class DefaultNotificationCenter extends AbstractSubscriptionService imple
|
||||
return savedNotificationRequest;
|
||||
}
|
||||
|
||||
private ListenableFuture<Void> processForRecipient(NotificationChannel notificationChannel, User recipient, NotificationProcessingContext ctx) {
|
||||
private ListenableFuture<Void> process(NotificationChannel notificationChannel, User recipient, NotificationProcessingContext ctx) {
|
||||
NotificationDeliveryMethod deliveryMethod = notificationChannel.getDeliveryMethod();
|
||||
if (ctx.getStats().contains(deliveryMethod, recipient.getId())) {
|
||||
if (recipient != null && ctx.getStats().contains(deliveryMethod, recipient.getId())) {
|
||||
return Futures.immediateFailedFuture(new AlreadySentException());
|
||||
}
|
||||
DeliveryMethodNotificationTemplate processedTemplate;
|
||||
try {
|
||||
processedTemplate = ctx.getProcessedTemplate(deliveryMethod, recipient);
|
||||
Map<String, String> templateContext = recipient != null ? ctx.createTemplateContext(recipient) : Collections.emptyMap();
|
||||
processedTemplate = ctx.getProcessedTemplate(deliveryMethod, templateContext);
|
||||
} catch (Exception e) {
|
||||
return Futures.immediateFailedFuture(e);
|
||||
}
|
||||
return notificationChannel.sendNotification(recipient, processedTemplate, ctx);
|
||||
}
|
||||
|
||||
private void forwardToNotificationSchedulerService(TenantId tenantId, NotificationRequestId notificationRequestId) {
|
||||
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());
|
||||
TransportProtos.ToCoreMsg toCoreMsg = TransportProtos.ToCoreMsg.newBuilder()
|
||||
.setNotificationSchedulerServiceMsg(msg)
|
||||
.build();
|
||||
clusterService.pushMsgToCore(tenantId, notificationRequestId, toCoreMsg, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Void> sendNotification(User recipient, PushDeliveryMethodNotificationTemplate processedTemplate, NotificationProcessingContext ctx) {
|
||||
NotificationRequest request = ctx.getRequest();
|
||||
@ -302,6 +307,19 @@ public class DefaultNotificationCenter extends AbstractSubscriptionService imple
|
||||
return notificationRequest;
|
||||
}
|
||||
|
||||
private void forwardToNotificationSchedulerService(TenantId tenantId, NotificationRequestId notificationRequestId) {
|
||||
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());
|
||||
TransportProtos.ToCoreMsg toCoreMsg = TransportProtos.ToCoreMsg.newBuilder()
|
||||
.setNotificationSchedulerServiceMsg(msg)
|
||||
.build();
|
||||
clusterService.pushMsgToCore(tenantId, notificationRequestId, toCoreMsg, null);
|
||||
}
|
||||
|
||||
private ListenableFuture<Void> onNotificationUpdate(TenantId tenantId, UserId recipientId, NotificationUpdate update) {
|
||||
log.trace("Submitting notification update for recipient {}: {}", recipientId, update);
|
||||
return Futures.submit(() -> {
|
||||
|
||||
@ -90,8 +90,11 @@ public class NotificationProcessingContext {
|
||||
return (C) settings.getDeliveryMethodsConfigs().get(deliveryMethod);
|
||||
}
|
||||
|
||||
protected <T extends DeliveryMethodNotificationTemplate> T getProcessedTemplate(NotificationDeliveryMethod deliveryMethod, User recipient) {
|
||||
Map<String, String> templateContext = createTemplateContext(recipient);
|
||||
protected <T extends DeliveryMethodNotificationTemplate> T getProcessedTemplate(NotificationDeliveryMethod deliveryMethod, Map<String, String> templateContext) {
|
||||
if (request.getInfo() != null) {
|
||||
templateContext = new HashMap<>(templateContext);
|
||||
templateContext.putAll(request.getInfo().getTemplateData());
|
||||
}
|
||||
|
||||
T template = (T) templates.get(deliveryMethod).copy();
|
||||
template.setBody(processTemplate(template.getBody(), templateContext));
|
||||
@ -106,14 +109,11 @@ public class NotificationProcessingContext {
|
||||
return TbNodeUtils.processTemplate(template, context);
|
||||
}
|
||||
|
||||
private Map<String, String> createTemplateContext(User recipient) {
|
||||
public Map<String, String> createTemplateContext(User recipient) {
|
||||
Map<String, String> templateContext = new HashMap<>();
|
||||
templateContext.put("email", recipient.getEmail());
|
||||
templateContext.put("firstName", Strings.nullToEmpty(recipient.getFirstName()));
|
||||
templateContext.put("lastName", Strings.nullToEmpty(recipient.getLastName()));
|
||||
if (request.getInfo() != null) {
|
||||
templateContext.putAll(request.getInfo().getTemplateData());
|
||||
}
|
||||
return templateContext;
|
||||
}
|
||||
|
||||
|
||||
@ -25,13 +25,16 @@ import org.thingsboard.rule.engine.api.slack.SlackService;
|
||||
import org.thingsboard.server.common.data.User;
|
||||
import org.thingsboard.server.common.data.id.NotificationRequestId;
|
||||
import org.thingsboard.server.common.data.id.NotificationTargetId;
|
||||
import org.thingsboard.server.common.data.id.NotificationTemplateId;
|
||||
import org.thingsboard.server.common.data.id.UserId;
|
||||
import org.thingsboard.server.common.data.notification.Notification;
|
||||
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
|
||||
import org.thingsboard.server.common.data.notification.NotificationRequest;
|
||||
import org.thingsboard.server.common.data.notification.NotificationRequestConfig;
|
||||
import org.thingsboard.server.common.data.notification.NotificationRequestStats;
|
||||
import org.thingsboard.server.common.data.notification.NotificationType;
|
||||
import org.thingsboard.server.common.data.notification.info.UserOriginatedNotificationInfo;
|
||||
import org.thingsboard.server.common.data.notification.settings.NotificationSettings;
|
||||
import org.thingsboard.server.common.data.notification.targets.NotificationTarget;
|
||||
import org.thingsboard.server.common.data.notification.targets.UserListNotificationTargetConfig;
|
||||
import org.thingsboard.server.common.data.notification.template.DeliveryMethodNotificationTemplate;
|
||||
@ -52,6 +55,7 @@ import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
public abstract class AbstractNotificationApiTest extends AbstractControllerTest {
|
||||
|
||||
@ -94,20 +98,28 @@ public abstract class AbstractNotificationApiTest extends AbstractControllerTest
|
||||
deliveryMethods = new NotificationDeliveryMethod[]{NotificationDeliveryMethod.PUSH};
|
||||
}
|
||||
NotificationTemplate notificationTemplate = createNotificationTemplate(DEFAULT_NOTIFICATION_TYPE, DEFAULT_NOTIFICATION_SUBJECT, text, deliveryMethods);
|
||||
return submitNotificationRequest(targets, notificationTemplate.getId(), delayInSec);
|
||||
}
|
||||
|
||||
protected NotificationRequest submitNotificationRequest(List<NotificationTargetId> targets, NotificationTemplateId notificationTemplateId, int delayInSec) {
|
||||
NotificationRequestConfig config = new NotificationRequestConfig();
|
||||
config.setSendingDelayInSec(delayInSec);
|
||||
UserOriginatedNotificationInfo notificationInfo = new UserOriginatedNotificationInfo();
|
||||
notificationInfo.setDescription("The text: " + text);
|
||||
notificationInfo.setDescription("My description");
|
||||
NotificationRequest notificationRequest = NotificationRequest.builder()
|
||||
.tenantId(tenantId)
|
||||
.targets(targets)
|
||||
.templateId(notificationTemplate.getId())
|
||||
.templateId(notificationTemplateId)
|
||||
.info(notificationInfo)
|
||||
.additionalConfig(config)
|
||||
.build();
|
||||
return doPost("/api/notification/request", notificationRequest, NotificationRequest.class);
|
||||
}
|
||||
|
||||
protected NotificationRequestStats getStats(NotificationRequestId notificationRequestId) throws Exception {
|
||||
return findNotificationRequest(notificationRequestId).getStats();
|
||||
}
|
||||
|
||||
protected NotificationTemplate createNotificationTemplate(NotificationType notificationType, String subject,
|
||||
String text, NotificationDeliveryMethod... deliveryMethods) {
|
||||
NotificationTemplate notificationTemplate = new NotificationTemplate();
|
||||
@ -143,9 +155,17 @@ public abstract class AbstractNotificationApiTest extends AbstractControllerTest
|
||||
config.getDeliveryMethodsTemplates().put(deliveryMethod, deliveryMethodNotificationTemplate);
|
||||
}
|
||||
notificationTemplate.setConfiguration(config);
|
||||
return saveNotificationTemplate(notificationTemplate);
|
||||
}
|
||||
|
||||
protected NotificationTemplate saveNotificationTemplate(NotificationTemplate notificationTemplate) {
|
||||
return doPost("/api/notification/template", notificationTemplate, NotificationTemplate.class);
|
||||
}
|
||||
|
||||
protected void saveNotificationSettings(NotificationSettings notificationSettings) throws Exception {
|
||||
doPost("/api/notification/settings", notificationSettings).andExpect(status().isOk());
|
||||
}
|
||||
|
||||
protected Pair<User, NotificationApiWsClient> createUserAndConnectWsClient(Authority authority) throws Exception {
|
||||
User user = new User();
|
||||
user.setTenantId(tenantId);
|
||||
|
||||
@ -30,9 +30,16 @@ import org.thingsboard.server.common.data.notification.NotificationDeliveryMetho
|
||||
import org.thingsboard.server.common.data.notification.NotificationRequest;
|
||||
import org.thingsboard.server.common.data.notification.NotificationRequestStats;
|
||||
import org.thingsboard.server.common.data.notification.NotificationRequestStatus;
|
||||
import org.thingsboard.server.common.data.notification.NotificationType;
|
||||
import org.thingsboard.server.common.data.notification.info.UserOriginatedNotificationInfo;
|
||||
import org.thingsboard.server.common.data.notification.settings.NotificationSettings;
|
||||
import org.thingsboard.server.common.data.notification.settings.SlackNotificationDeliveryMethodConfig;
|
||||
import org.thingsboard.server.common.data.notification.targets.AllUsersNotificationTargetConfig;
|
||||
import org.thingsboard.server.common.data.notification.targets.NotificationTarget;
|
||||
import org.thingsboard.server.common.data.notification.template.NotificationTemplate;
|
||||
import org.thingsboard.server.common.data.notification.template.NotificationTemplateConfig;
|
||||
import org.thingsboard.server.common.data.notification.template.SlackConversation;
|
||||
import org.thingsboard.server.common.data.notification.template.SlackDeliveryMethodNotificationTemplate;
|
||||
import org.thingsboard.server.common.data.page.PageData;
|
||||
import org.thingsboard.server.common.data.page.PageLink;
|
||||
import org.thingsboard.server.common.data.security.Authority;
|
||||
@ -43,6 +50,7 @@ import org.thingsboard.server.service.ws.notification.cmd.UnreadNotificationsCou
|
||||
import org.thingsboard.server.service.ws.notification.cmd.UnreadNotificationsUpdate;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -55,6 +63,7 @@ import static org.awaitility.Awaitility.await;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.startsWith;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.timeout;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
@ -312,8 +321,8 @@ public class NotificationApiTest extends AbstractNotificationApiTest {
|
||||
});
|
||||
|
||||
await().atMost(2, TimeUnit.SECONDS)
|
||||
.until(() -> findNotificationRequest(notificationRequest.getId()).getStats() != null);
|
||||
NotificationRequestStats stats = findNotificationRequest(notificationRequest.getId()).getStats();
|
||||
.until(() -> getStats(notificationRequest.getId()) != null);
|
||||
NotificationRequestStats stats = getStats(notificationRequest.getId());
|
||||
assertThat(stats.getSent().get(NotificationDeliveryMethod.PUSH)).hasValue(usersCount);
|
||||
assertThat(stats.getSent().get(NotificationDeliveryMethod.EMAIL)).hasValue(usersCount);
|
||||
|
||||
@ -341,8 +350,8 @@ public class NotificationApiTest extends AbstractNotificationApiTest {
|
||||
wsClient.waitForUpdate();
|
||||
|
||||
await().atMost(2, TimeUnit.SECONDS)
|
||||
.until(() -> findNotificationRequest(notificationRequest.getId()).getStats() != null);
|
||||
NotificationRequestStats stats = findNotificationRequest(notificationRequest.getId()).getStats();
|
||||
.until(() -> getStats(notificationRequest.getId()) != null);
|
||||
NotificationRequestStats stats = getStats(notificationRequest.getId());
|
||||
|
||||
assertThat(stats.getSent().get(NotificationDeliveryMethod.PUSH)).hasValue(1);
|
||||
assertThat(stats.getSent().get(NotificationDeliveryMethod.EMAIL)).hasValue(1);
|
||||
@ -360,7 +369,6 @@ public class NotificationApiTest extends AbstractNotificationApiTest {
|
||||
user.setAuthority(Authority.TENANT_ADMIN);
|
||||
user.setEmail("test-user-" + i + "@thingsboard.org");
|
||||
user = doPost("/api/user", user, User.class);
|
||||
System.err.println(i);
|
||||
users.add(user);
|
||||
}
|
||||
|
||||
@ -389,10 +397,57 @@ public class NotificationApiTest extends AbstractNotificationApiTest {
|
||||
assertThat(sentNotifications.getData()).extracting(Notification::getRecipientId)
|
||||
.containsAll(users.stream().map(User::getId).collect(Collectors.toSet()));
|
||||
|
||||
NotificationRequestStats stats = findNotificationRequest(notificationRequest.getId()).getStats();
|
||||
NotificationRequestStats stats = getStats(notificationRequest.getId());
|
||||
assertThat(stats.getSent().values().stream().mapToInt(AtomicInteger::get).sum()).isGreaterThanOrEqualTo(usersCount);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSlackNotifications() throws Exception {
|
||||
NotificationSettings settings = new NotificationSettings();
|
||||
SlackNotificationDeliveryMethodConfig slackConfig = new SlackNotificationDeliveryMethodConfig();
|
||||
slackConfig.setMethod(NotificationDeliveryMethod.SLACK);
|
||||
slackConfig.setEnabled(true);
|
||||
String slackToken = "xoxb-123123123";
|
||||
slackConfig.setBotToken(slackToken);
|
||||
settings.setDeliveryMethodsConfigs(Map.of(
|
||||
NotificationDeliveryMethod.SLACK, slackConfig
|
||||
));
|
||||
saveNotificationSettings(settings);
|
||||
|
||||
NotificationTemplate notificationTemplate = new NotificationTemplate();
|
||||
notificationTemplate.setName("Slack notification template");
|
||||
notificationTemplate.setNotificationType(NotificationType.GENERAL);
|
||||
NotificationTemplateConfig config = new NotificationTemplateConfig();
|
||||
config.setDefaultTextTemplate("To Slack :)");
|
||||
|
||||
SlackDeliveryMethodNotificationTemplate slackNotificationTemplate = new SlackDeliveryMethodNotificationTemplate();
|
||||
slackNotificationTemplate.setEnabled(true);
|
||||
slackNotificationTemplate.setConversationType(SlackConversation.Type.PUBLIC_CHANNEL);
|
||||
String conversationId = "U154475415";
|
||||
slackNotificationTemplate.setConversationId(conversationId);
|
||||
|
||||
config.setDeliveryMethodsTemplates(Map.of(
|
||||
NotificationDeliveryMethod.SLACK, slackNotificationTemplate
|
||||
));
|
||||
notificationTemplate.setConfiguration(config);
|
||||
notificationTemplate = saveNotificationTemplate(notificationTemplate);
|
||||
|
||||
NotificationRequest successfulNotificationRequest = submitNotificationRequest(Collections.emptyList(), notificationTemplate.getId(), 0);
|
||||
await().atMost(2, TimeUnit.SECONDS)
|
||||
.until(() -> getStats(successfulNotificationRequest.getId()) != null);
|
||||
verify(slackService).sendMessage(eq(tenantId), eq(slackToken), eq(conversationId), eq(config.getDefaultTextTemplate()));
|
||||
NotificationRequestStats stats = getStats(successfulNotificationRequest.getId());
|
||||
assertThat(stats.getSent().get(NotificationDeliveryMethod.SLACK)).hasValue(1);
|
||||
|
||||
String errorMessage = "Error!!!";
|
||||
doThrow(new RuntimeException(errorMessage)).when(slackService).sendMessage(any(), any(), any(), any());
|
||||
NotificationRequest failedNotificationRequest = submitNotificationRequest(Collections.emptyList(), notificationTemplate.getId(), 0);
|
||||
await().atMost(2, TimeUnit.SECONDS)
|
||||
.until(() -> getStats(failedNotificationRequest.getId()) != null);
|
||||
stats = getStats(failedNotificationRequest.getId());
|
||||
assertThat(stats.getErrors().get(NotificationDeliveryMethod.SLACK).values()).containsExactly(errorMessage);
|
||||
}
|
||||
|
||||
private void checkFullNotificationsUpdate(UnreadNotificationsUpdate notificationsUpdate, String... expectedNotifications) {
|
||||
assertThat(notificationsUpdate.getNotifications()).extracting(Notification::getText).containsOnly(expectedNotifications);
|
||||
assertThat(notificationsUpdate.getNotifications()).extracting(Notification::getType).containsOnly(DEFAULT_NOTIFICATION_TYPE);
|
||||
|
||||
@ -15,6 +15,24 @@
|
||||
*/
|
||||
package org.thingsboard.server.common.data.notification;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
public enum NotificationDeliveryMethod {
|
||||
PUSH, EMAIL, SMS, SLACK
|
||||
|
||||
PUSH,
|
||||
EMAIL,
|
||||
SMS,
|
||||
SLACK(true);
|
||||
|
||||
@Getter
|
||||
private final boolean independent; // TODO: think of a better name
|
||||
|
||||
NotificationDeliveryMethod() {
|
||||
this(false);
|
||||
}
|
||||
|
||||
NotificationDeliveryMethod(boolean independent) {
|
||||
this.independent = independent;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -46,7 +46,7 @@ import java.util.List;
|
||||
public class NotificationRequest extends BaseData<NotificationRequestId> implements HasTenantId, HasName {
|
||||
|
||||
private TenantId tenantId;
|
||||
@NotEmpty
|
||||
@NotNull
|
||||
private List<NotificationTargetId> targets;
|
||||
|
||||
@NotNull
|
||||
|
||||
@ -24,6 +24,7 @@ import org.thingsboard.server.common.data.id.UserId;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
@ -52,15 +53,18 @@ public class NotificationRequestStats {
|
||||
|
||||
public void reportSent(NotificationDeliveryMethod deliveryMethod, User recipient) {
|
||||
sent.computeIfAbsent(deliveryMethod, k -> new AtomicInteger()).incrementAndGet();
|
||||
processedRecipients.computeIfAbsent(deliveryMethod, k -> ConcurrentHashMap.newKeySet()).add(recipient.getId());
|
||||
if (recipient != null) {
|
||||
processedRecipients.computeIfAbsent(deliveryMethod, k -> ConcurrentHashMap.newKeySet()).add(recipient.getId());
|
||||
}
|
||||
}
|
||||
|
||||
public void reportError(NotificationDeliveryMethod deliveryMethod, User recipient, Throwable error) {
|
||||
public void reportError(NotificationDeliveryMethod deliveryMethod, Throwable error, User recipient) {
|
||||
if (error instanceof AlreadySentException) {
|
||||
return;
|
||||
}
|
||||
String errorMessage = error.getMessage();
|
||||
errors.computeIfAbsent(deliveryMethod, k -> new ConcurrentHashMap<>()).put(recipient.getEmail(), errorMessage);
|
||||
String key = Optional.ofNullable(recipient).map(User::getEmail).orElse("");
|
||||
errors.computeIfAbsent(deliveryMethod, k -> new ConcurrentHashMap<>()).put(key, errorMessage);
|
||||
}
|
||||
|
||||
public boolean contains(NotificationDeliveryMethod deliveryMethod) {
|
||||
|
||||
@ -18,6 +18,7 @@ package org.thingsboard.server.common.data.notification.settings;
|
||||
import lombok.Data;
|
||||
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Map;
|
||||
|
||||
@ -25,6 +26,7 @@ import java.util.Map;
|
||||
public class NotificationSettings {
|
||||
|
||||
@NotNull
|
||||
@Valid
|
||||
// location on the screen, shown notifications count, timings of displaying
|
||||
private Map<NotificationDeliveryMethod, NotificationDeliveryMethodConfig> deliveryMethodsConfigs;
|
||||
|
||||
|
||||
@ -37,6 +37,7 @@ public class NotificationTemplateConfig {
|
||||
@JsonIgnore
|
||||
@AssertTrue(message = "defaultTextTemplate and notificationSubject must be specified if one absent for delivery method")
|
||||
public boolean isValid() {
|
||||
if (deliveryMethodsTemplates == null) return true;
|
||||
for (DeliveryMethodNotificationTemplate template : deliveryMethodsTemplates.values()) {
|
||||
if (StringUtils.isEmpty(template.getBody()) && StringUtils.isEmpty(defaultTextTemplate)) {
|
||||
return false;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user