Browse Source

Improve entities count limit notification rule

pull/8405/head
ViacheslavKlimov 3 years ago
parent
commit
97cc1ab0da
  1. 2
      application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java
  2. 6
      application/src/main/java/org/thingsboard/server/controller/BaseController.java
  3. 11
      application/src/main/java/org/thingsboard/server/service/action/EntityActionService.java
  4. 2
      application/src/main/java/org/thingsboard/server/service/apiusage/DefaultTbApiUsageStateService.java
  5. 2
      application/src/main/java/org/thingsboard/server/service/notification/rule/DefaultNotificationRuleProcessor.java
  6. 15
      application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/EntitiesLimitTriggerProcessor.java
  7. 2
      application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java
  8. 2
      application/src/main/java/org/thingsboard/server/service/telemetry/DefaultAlarmSubscriptionService.java
  9. 3
      application/src/main/java/org/thingsboard/server/service/update/DefaultUpdateService.java
  10. 7
      application/src/test/java/org/thingsboard/server/service/notification/MockNotificationSettingsService.java
  11. 177
      application/src/test/java/org/thingsboard/server/service/notification/NotificationRuleApiTest.java
  12. 5
      common/message/src/main/java/org/thingsboard/server/common/msg/notification/trigger/EntitiesLimitTrigger.java
  13. 2
      common/queue/src/main/java/org/thingsboard/server/queue/notification/NotificationRuleProcessor.java
  14. 1
      common/queue/src/main/java/org/thingsboard/server/queue/notification/RemoteNotificationRuleProcessor.java
  15. 13
      dao/src/main/java/org/thingsboard/server/dao/usagerecord/DefaultApiLimitService.java

2
application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java

@ -89,7 +89,7 @@ import org.thingsboard.server.dao.widget.WidgetTypeService;
import org.thingsboard.server.dao.widget.WidgetsBundleService;
import org.thingsboard.server.queue.discovery.PartitionService;
import org.thingsboard.server.queue.discovery.TbServiceInfoProvider;
import org.thingsboard.server.common.msg.notification.NotificationRuleProcessor;
import org.thingsboard.server.queue.notification.NotificationRuleProcessor;
import org.thingsboard.server.queue.util.DataDecodingEncodingService;
import org.thingsboard.server.service.apiusage.TbApiUsageStateService;
import org.thingsboard.server.service.component.ComponentDiscoveryService;

6
application/src/main/java/org/thingsboard/server/controller/BaseController.java

@ -797,8 +797,10 @@ public abstract class BaseController {
protected <E extends HasName & HasId<? extends EntityId>> void logEntityAction(SecurityUser user, EntityType entityType, E entity, E savedEntity, ActionType actionType, Exception e) {
EntityId entityId = savedEntity != null ? savedEntity.getId() : emptyId(entityType);
entityActionService.logEntityAction(user, entityId, savedEntity != null ? savedEntity : entity,
user.getCustomerId(), actionType, e);
if (!user.isSystemAdmin()) {
entityActionService.logEntityAction(user, entityId, savedEntity != null ? savedEntity : entity,
user.getCustomerId(), actionType, e);
}
}
protected <E extends HasName & HasId<? extends EntityId>> E doSaveAndLog(EntityType entityType, E entity, BiFunction<TenantId, E, E> savingFunction) throws Exception {

11
application/src/main/java/org/thingsboard/server/service/action/EntityActionService.java

@ -41,7 +41,9 @@ import org.thingsboard.server.common.data.relation.EntityRelation;
import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.TbMsgDataType;
import org.thingsboard.server.common.msg.TbMsgMetaData;
import org.thingsboard.server.common.msg.notification.trigger.EntitiesLimitTrigger;
import org.thingsboard.server.dao.audit.AuditLogService;
import org.thingsboard.server.queue.notification.NotificationRuleProcessor;
import java.util.List;
import java.util.Map;
@ -53,6 +55,7 @@ import java.util.stream.Collectors;
public class EntityActionService {
private final TbClusterService tbClusterService;
private final AuditLogService auditLogService;
private final NotificationRuleProcessor notificationRuleProcessor;
private static final ObjectMapper json = new ObjectMapper();
@ -187,6 +190,12 @@ public class EntityActionService {
AlarmComment comment = extractParameter(AlarmComment.class, 0, additionalInfo);
metaData.putValue("comment", json.writeValueAsString(comment));
}
if (actionType == ActionType.ADDED) {
notificationRuleProcessor.process(EntitiesLimitTrigger.builder()
.tenantId(tenantId)
.entityType(entityId.getEntityType())
.build());
}
ObjectNode entityNode;
if (entity != null) {
entityNode = json.valueToTree(entity);
@ -247,7 +256,7 @@ public class EntityActionService {
}
public <E extends HasName, I extends EntityId> void logEntityAction(User user, I entityId, E entity, CustomerId customerId,
ActionType actionType, Exception e, Object... additionalInfo) {
ActionType actionType, Exception e, Object... additionalInfo) {
if (customerId == null || customerId.isNullUid()) {
customerId = user.getCustomerId();
}

2
application/src/main/java/org/thingsboard/server/service/apiusage/DefaultTbApiUsageStateService.java

@ -48,7 +48,7 @@ import org.thingsboard.server.common.data.kv.TsKvEntry;
import org.thingsboard.server.common.data.page.PageDataIterable;
import org.thingsboard.server.common.data.tenant.profile.TenantProfileConfiguration;
import org.thingsboard.server.common.data.tenant.profile.TenantProfileData;
import org.thingsboard.server.common.msg.notification.NotificationRuleProcessor;
import org.thingsboard.server.queue.notification.NotificationRuleProcessor;
import org.thingsboard.server.common.msg.notification.trigger.ApiUsageLimitTrigger;
import org.thingsboard.server.common.msg.queue.ServiceType;
import org.thingsboard.server.common.msg.queue.TbCallback;

2
application/src/main/java/org/thingsboard/server/service/notification/rule/DefaultNotificationRuleProcessor.java

@ -35,7 +35,7 @@ import org.thingsboard.server.common.data.notification.rule.NotificationRule;
import org.thingsboard.server.common.data.notification.rule.trigger.NotificationRuleTriggerConfig;
import org.thingsboard.server.common.data.notification.rule.trigger.NotificationRuleTriggerType;
import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;
import org.thingsboard.server.common.msg.notification.NotificationRuleProcessor;
import org.thingsboard.server.queue.notification.NotificationRuleProcessor;
import org.thingsboard.server.common.msg.notification.trigger.NotificationRuleTrigger;
import org.thingsboard.server.common.msg.notification.trigger.RuleEngineMsgTrigger;
import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg;

15
application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/EntitiesLimitTriggerProcessor.java

@ -21,7 +21,10 @@ import org.thingsboard.server.common.data.notification.info.EntitiesLimitNotific
import org.thingsboard.server.common.data.notification.info.RuleOriginatedNotificationInfo;
import org.thingsboard.server.common.data.notification.rule.trigger.EntitiesLimitNotificationRuleTriggerConfig;
import org.thingsboard.server.common.data.notification.rule.trigger.NotificationRuleTriggerType;
import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration;
import org.thingsboard.server.common.msg.notification.trigger.EntitiesLimitTrigger;
import org.thingsboard.server.dao.entity.EntityCountService;
import org.thingsboard.server.dao.tenant.TbTenantProfileCache;
import org.thingsboard.server.dao.tenant.TenantService;
import static org.apache.commons.collections.CollectionUtils.isNotEmpty;
@ -30,6 +33,8 @@ import static org.apache.commons.collections.CollectionUtils.isNotEmpty;
@RequiredArgsConstructor
public class EntitiesLimitTriggerProcessor implements NotificationRuleTriggerProcessor<EntitiesLimitTrigger, EntitiesLimitNotificationRuleTriggerConfig> {
private final EntityCountService entityCountService;
private final TbTenantProfileCache tenantProfileCache;
private final TenantService tenantService;
@Override
@ -37,7 +42,15 @@ public class EntitiesLimitTriggerProcessor implements NotificationRuleTriggerPro
if (isNotEmpty(triggerConfig.getEntityTypes()) && !triggerConfig.getEntityTypes().contains(trigger.getEntityType())) {
return false;
}
return (int) (trigger.getLimit() * triggerConfig.getThreshold()) == trigger.getCurrentCount(); // strict comparing not to send notification on each new entity
DefaultTenantProfileConfiguration profileConfiguration = tenantProfileCache.get(trigger.getTenantId()).getDefaultProfileConfiguration();
long limit = profileConfiguration.getEntitiesLimit(trigger.getEntityType());
if (limit <= 0) {
return false;
}
long currentCount = entityCountService.countByTenantIdAndEntityType(trigger.getTenantId(), trigger.getEntityType());
trigger.setLimit(limit);
trigger.setCurrentCount(currentCount);
return (int) (limit * triggerConfig.getThreshold()) == currentCount; // strict comparing not to send notification on each new entity
}
@Override

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

@ -35,7 +35,7 @@ import org.thingsboard.server.common.data.id.UserId;
import org.thingsboard.server.common.data.rpc.RpcError;
import org.thingsboard.server.common.msg.MsgType;
import org.thingsboard.server.common.msg.TbActorMsg;
import org.thingsboard.server.common.msg.notification.NotificationRuleProcessor;
import org.thingsboard.server.queue.notification.NotificationRuleProcessor;
import org.thingsboard.server.common.msg.notification.trigger.NotificationRuleTrigger;
import org.thingsboard.server.common.msg.queue.ServiceType;
import org.thingsboard.server.common.msg.queue.TbCallback;

2
application/src/main/java/org/thingsboard/server/service/telemetry/DefaultAlarmSubscriptionService.java

@ -51,7 +51,7 @@ import org.thingsboard.server.common.msg.queue.TbCallback;
import org.thingsboard.server.common.stats.TbApiUsageReportClient;
import org.thingsboard.server.dao.alarm.AlarmOperationResult;
import org.thingsboard.server.dao.alarm.AlarmService;
import org.thingsboard.server.common.msg.notification.NotificationRuleProcessor;
import org.thingsboard.server.queue.notification.NotificationRuleProcessor;
import org.thingsboard.server.service.apiusage.TbApiUsageStateService;
import org.thingsboard.server.service.entitiy.alarm.TbAlarmCommentService;
import org.thingsboard.server.service.subscription.TbSubscriptionUtils;

3
application/src/main/java/org/thingsboard/server/service/update/DefaultUpdateService.java

@ -29,11 +29,10 @@ import org.springframework.web.client.RestTemplate;
import org.thingsboard.common.util.ThingsBoardThreadFactory;
import org.thingsboard.server.common.data.UpdateMessage;
import org.thingsboard.server.common.msg.notification.trigger.NewPlatformVersionTrigger;
import org.thingsboard.server.common.msg.notification.NotificationRuleProcessor;
import org.thingsboard.server.queue.notification.NotificationRuleProcessor;
import org.thingsboard.server.queue.util.AfterStartUp;
import org.thingsboard.server.queue.util.TbCoreComponent;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.IOException;
import java.nio.file.Files;

7
application/src/test/java/org/thingsboard/server/service/notification/MockNotificationSettingsService.java

@ -19,17 +19,14 @@ import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.notification.DefaultNotificationSettingsService;
import org.thingsboard.server.dao.notification.NotificationRuleService;
import org.thingsboard.server.dao.notification.NotificationTargetService;
import org.thingsboard.server.dao.notification.NotificationTemplateService;
import org.thingsboard.server.dao.settings.AdminSettingsService;
@Service
@Primary
public class MockNotificationSettingsService extends DefaultNotificationSettingsService {
public MockNotificationSettingsService(AdminSettingsService adminSettingsService, NotificationTargetService notificationTargetService, NotificationTemplateService notificationTemplateService, NotificationRuleService notificationRuleService) {
super(adminSettingsService, notificationTargetService, notificationTemplateService, notificationRuleService);
public MockNotificationSettingsService(AdminSettingsService adminSettingsService) {
super(adminSettingsService, null, null);
}
@Override

177
application/src/test/java/org/thingsboard/server/service/notification/NotificationRuleApiTest.java

@ -20,6 +20,7 @@ import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.BooleanNode;
import org.junit.Before;
import org.junit.Test;
import org.junit.function.ThrowingRunnable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.data.util.Pair;
@ -34,6 +35,7 @@ import org.thingsboard.server.common.data.alarm.Alarm;
import org.thingsboard.server.common.data.alarm.AlarmSearchStatus;
import org.thingsboard.server.common.data.alarm.AlarmSeverity;
import org.thingsboard.server.common.data.alarm.AlarmStatus;
import org.thingsboard.server.common.data.asset.Asset;
import org.thingsboard.server.common.data.device.profile.AlarmCondition;
import org.thingsboard.server.common.data.device.profile.AlarmConditionFilter;
import org.thingsboard.server.common.data.device.profile.AlarmConditionFilterKey;
@ -41,6 +43,7 @@ import org.thingsboard.server.common.data.device.profile.AlarmConditionKeyType;
import org.thingsboard.server.common.data.device.profile.AlarmRule;
import org.thingsboard.server.common.data.device.profile.DeviceProfileAlarm;
import org.thingsboard.server.common.data.device.profile.SimpleAlarmConditionSpec;
import org.thingsboard.server.common.data.id.NotificationTargetId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.notification.Notification;
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
@ -54,7 +57,9 @@ import org.thingsboard.server.common.data.notification.rule.NotificationRule;
import org.thingsboard.server.common.data.notification.rule.NotificationRuleInfo;
import org.thingsboard.server.common.data.notification.rule.trigger.AlarmNotificationRuleTriggerConfig;
import org.thingsboard.server.common.data.notification.rule.trigger.AlarmNotificationRuleTriggerConfig.AlarmAction;
import org.thingsboard.server.common.data.notification.rule.trigger.EntitiesLimitNotificationRuleTriggerConfig;
import org.thingsboard.server.common.data.notification.rule.trigger.EntityActionNotificationRuleTriggerConfig;
import org.thingsboard.server.common.data.notification.rule.trigger.NotificationRuleTriggerConfig;
import org.thingsboard.server.common.data.notification.rule.trigger.NotificationRuleTriggerType;
import org.thingsboard.server.common.data.notification.targets.NotificationTarget;
import org.thingsboard.server.common.data.notification.template.NotificationTemplate;
@ -66,21 +71,27 @@ import org.thingsboard.server.common.data.query.FilterPredicateValue;
import org.thingsboard.server.common.data.security.Authority;
import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration;
import org.thingsboard.server.common.data.tenant.profile.TenantProfileData;
import org.thingsboard.server.dao.DaoUtil;
import org.thingsboard.server.dao.notification.NotificationRequestService;
import org.thingsboard.server.dao.service.DaoSqlTest;
import org.thingsboard.server.dao.tenant.TenantProfileService;
import org.thingsboard.server.service.apiusage.limits.LimitedApi;
import org.thingsboard.server.service.apiusage.limits.RateLimitService;
import org.thingsboard.server.service.entitiy.tenant.profile.TbTenantProfileService;
import org.thingsboard.server.service.telemetry.AlarmSubscriptionService;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.offset;
@ -98,6 +109,8 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest {
@Autowired
private TenantProfileService tenantProfileService;
@Autowired
private TbTenantProfileService tbTenantProfileService;
@Autowired
private RateLimitService rateLimitService;
@Before
@ -107,56 +120,33 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest {
@Test
public void testNotificationRuleProcessing_entityActionTrigger() throws Exception {
String notificationSubject = "${actionType}: ${entityType} [${entityId}]";
String notificationText = "User: ${userEmail}";
NotificationTemplate notificationTemplate = createNotificationTemplate(NotificationType.GENERAL, notificationSubject, notificationText, NotificationDeliveryMethod.WEB);
NotificationRule notificationRule = new NotificationRule();
notificationRule.setName("Web notification when any device is created, updated or deleted");
notificationRule.setTemplateId(notificationTemplate.getId());
notificationRule.setTriggerType(NotificationRuleTriggerType.ENTITY_ACTION);
EntityActionNotificationRuleTriggerConfig triggerConfig = new EntityActionNotificationRuleTriggerConfig();
triggerConfig.setEntityTypes(Set.of(EntityType.DEVICE));
triggerConfig.setCreated(true);
triggerConfig.setUpdated(true);
triggerConfig.setDeleted(true);
createNotificationRule(triggerConfig, "${actionType}: ${entityType} [${entityId}]",
"User: ${userEmail}", createNotificationTarget(tenantAdminUserId).getId());
Device device = checkNotificationAfter(() -> {
return createDevice("DEVICE!!!", "default", "12345");
}, (notification, newDevice) -> {
assertThat(notification.getSubject()).isEqualTo("added: Device [" + newDevice.getId() + "]");
assertThat(notification.getText()).isEqualTo("User: " + TENANT_ADMIN_EMAIL);
});
DefaultNotificationRuleRecipientsConfig recipientsConfig = new DefaultNotificationRuleRecipientsConfig();
recipientsConfig.setTriggerType(NotificationRuleTriggerType.ENTITY_ACTION);
recipientsConfig.setTargets(List.of(createNotificationTarget(tenantAdminUserId).getUuidId()));
notificationRule.setTriggerConfig(triggerConfig);
notificationRule.setRecipientsConfig(recipientsConfig);
notificationRule = saveNotificationRule(notificationRule);
getWsClient().subscribeForUnreadNotifications(10).waitForReply(true);
getWsClient().registerWaitForUpdate();
Device device = createDevice("DEVICE!!!", "default", "12345");
getWsClient().waitForUpdate(true);
Notification notification = getWsClient().getLastDataUpdate().getUpdate();
assertThat(notification.getSubject()).isEqualTo("added: Device [" + device.getId() + "]");
assertThat(notification.getText()).isEqualTo("User: " + TENANT_ADMIN_EMAIL);
getWsClient().registerWaitForUpdate();
device.setName("Updated name");
device = doPost("/api/device", device, Device.class);
getWsClient().waitForUpdate(true);
notification = getWsClient().getLastDataUpdate().getUpdate();
assertThat(notification.getSubject()).isEqualTo("updated: Device [" + device.getId() + "]");
getWsClient().registerWaitForUpdate();
doDelete("/api/device/" + device.getId()).andExpect(status().isOk());
getWsClient().waitForUpdate(true);
checkNotificationAfter(() -> {
device.setName("Updated name");
doPost("/api/device", device, Device.class);
}, notification -> {
assertThat(notification.getSubject()).isEqualTo("updated: Device [" + device.getId() + "]");
});
notification = getWsClient().getLastDataUpdate().getUpdate();
assertThat(notification.getSubject()).isEqualTo("deleted: Device [" + device.getId() + "]");
checkNotificationAfter(() -> {
doDelete("/api/device/" + device.getId()).andExpect(status().isOk());
}, notification -> {
assertThat(notification.getSubject()).isEqualTo("deleted: Device [" + device.getId() + "]");
});
}
@Test
@ -215,7 +205,7 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest {
clients.forEach((expectedDelay, wsClient) -> {
Notification notification = wsClient.getLastDataUpdate().getUpdate();
double actualDelay = (double) (notification.getCreatedTime() - ts) / 1000;
assertThat(actualDelay).isCloseTo(expectedDelay, offset(0.5));
assertThat(actualDelay).isCloseTo(expectedDelay, offset(2.0));
assertThat(notification.getSubject()).isEqualTo("Alarm type: " + alarmType + ", status: " + AlarmStatus.ACTIVE_UNACK + ", " +
"severity: " + AlarmSeverity.CRITICAL.toString().toLowerCase() + ", deviceId: " + device.getId());
@ -312,6 +302,62 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest {
assertThat(findNotificationRequests(EntityType.ALARM).getData()).filteredOn(NotificationRequest::isScheduled).isEmpty();
}
@Test
public void testNotificationRuleProcessing_entitiesLimit() throws Exception {
TenantProfile tenantProfile = tenantProfileService.findDefaultTenantProfile(TenantId.SYS_TENANT_ID);
TenantProfileData profileData = tenantProfile.getProfileData();
DefaultTenantProfileConfiguration profileConfiguration = (DefaultTenantProfileConfiguration) profileData.getConfiguration();
int limit = 5;
profileConfiguration.setMaxDevices(limit);
profileConfiguration.setMaxAssets(limit);
profileConfiguration.setMaxCustomers(limit);
profileConfiguration.setMaxUsers(limit);
profileConfiguration.setMaxDashboards(limit);
profileConfiguration.setMaxRuleChains(limit);
tenantProfile.setProfileData(profileData);
tbTenantProfileService.save(TenantId.SYS_TENANT_ID, tenantProfile, null);
EntitiesLimitNotificationRuleTriggerConfig triggerConfig = EntitiesLimitNotificationRuleTriggerConfig.builder()
.entityTypes(null).threshold(0.8f)
.build();
loginSysAdmin();
NotificationRule rule = createNotificationRule(triggerConfig, "${entityType}s limit will be reached soon",
"${entityType}s usage: ${currentCount}/${limit} (${percents}%)", createNotificationTarget(tenantAdminUserId).getId());
int threshold = (int) (limit * 0.8);
loginTenantAdmin();
checkNotificationAfter(() -> {
for (int i = 1; i <= threshold; i++) {
createDevice(i + "", i + "");
}
}, notification -> {
assertThat(notification.getText()).isEqualTo("Devices usage: " + threshold + "/" + limit + " (80%)");
});
checkNotificationAfter(() -> {
for (int i = 1; i <= threshold; i++) {
Asset asset = new Asset();
asset.setType("Test");
asset.setName(i + "");
doPost("/api/asset", asset);
}
}, notification -> {
assertThat(notification.getText()).isEqualTo("Assets usage: " + threshold + "/" + limit + " (80%)");
});
triggerConfig.setThreshold(1.0f);
rule.setTriggerConfig(triggerConfig);
loginSysAdmin();
saveNotificationRule(rule);
loginTenantAdmin();
checkNotificationAfter(() -> {
createDevice(limit + "", limit + "");
}, notification -> {
assertThat(notification.getText()).isEqualTo("Devices usage: " + limit + "/" + limit + " (100%)");
});
}
@Test
public void testNotificationRuleInfo() throws Exception {
NotificationDeliveryMethod[] deliveryMethods = {NotificationDeliveryMethod.WEB, NotificationDeliveryMethod.EMAIL};
@ -345,9 +391,7 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest {
DefaultTenantProfileConfiguration profileConfiguration = (DefaultTenantProfileConfiguration) profileData.getConfiguration();
profileConfiguration.setTenantNotificationRequestsPerRuleRateLimit(notificationRequestsLimit + ":300");
tenantProfile.setProfileData(profileData);
loginSysAdmin();
doPost("/api/tenantProfile", tenantProfile).andExpect(status().isOk());
loginTenantAdmin();
tbTenantProfileService.save(TenantId.SYS_TENANT_ID, tenantProfile, null);
NotificationRule rule = new NotificationRule();
rule.setName("Device created");
@ -386,6 +430,45 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest {
assertThat(getMyNotifications(false, 100)).size().isEqualTo(notificationRequestsLimit);
}
private <R> R checkNotificationAfter(Callable<R> action, BiConsumer<Notification, R> check) throws Exception {
if (getWsClient().getLastDataUpdate() == null) {
getWsClient().subscribeForUnreadNotifications(10).waitForReply(true);
}
getWsClient().registerWaitForUpdate();
R result = action.call();
getWsClient().waitForUpdate(true);
check.accept(getWsClient().getLastDataUpdate().getUpdate(), result);
return result;
}
private void checkNotificationAfter(ThrowingRunnable action, Consumer<Notification> check) throws Exception {
checkNotificationAfter(() -> {
try {
action.run();
return null;
} catch (Throwable e) {
throw new Exception(e);
}
}, (notification, r) -> check.accept(notification));
}
private NotificationRule createNotificationRule(NotificationRuleTriggerConfig triggerConfig, String subject, String text, NotificationTargetId... targets) {
NotificationTemplate template = createNotificationTemplate(NotificationType.valueOf(triggerConfig.getTriggerType().toString()), subject, text, NotificationDeliveryMethod.WEB);
NotificationRule rule = new NotificationRule();
rule.setName(triggerConfig.getTriggerType() + " [" + Arrays.toString(targets) + "]");
rule.setTemplateId(template.getId());
rule.setTriggerType(triggerConfig.getTriggerType());
rule.setTriggerConfig(triggerConfig);
DefaultNotificationRuleRecipientsConfig recipientsConfig = new DefaultNotificationRuleRecipientsConfig();
recipientsConfig.setTriggerType(triggerConfig.getTriggerType());
recipientsConfig.setTargets(DaoUtil.toUUIDs(List.of(targets)));
rule.setRecipientsConfig(recipientsConfig);
return saveNotificationRule(rule);
}
private DeviceProfile createDeviceProfileWithAlarmRules(String alarmType) {
DeviceProfile deviceProfile = createDeviceProfile("For notification rule test");
deviceProfile.setTenantId(tenantId);

5
common/message/src/main/java/org/thingsboard/server/common/msg/notification/trigger/EntitiesLimitTrigger.java

@ -28,8 +28,9 @@ public class EntitiesLimitTrigger implements NotificationRuleTrigger {
private final TenantId tenantId;
private final EntityType entityType;
private final long currentCount;
private final long limit;
private long limit;
private long currentCount;
@Override
public NotificationRuleTriggerType getType() {

2
common/message/src/main/java/org/thingsboard/server/common/msg/notification/NotificationRuleProcessor.java → common/queue/src/main/java/org/thingsboard/server/queue/notification/NotificationRuleProcessor.java

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.msg.notification;
package org.thingsboard.server.queue.notification;
import org.thingsboard.server.common.msg.notification.trigger.NotificationRuleTrigger;

1
common/queue/src/main/java/org/thingsboard/server/queue/notification/RemoteNotificationRuleProcessor.java

@ -20,7 +20,6 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.stereotype.Service;
import org.thingsboard.server.common.msg.notification.NotificationRuleProcessor;
import org.thingsboard.server.common.msg.notification.trigger.NotificationRuleTrigger;
import org.thingsboard.server.common.msg.queue.ServiceType;
import org.thingsboard.server.common.msg.queue.TopicPartitionInfo;

13
dao/src/main/java/org/thingsboard/server/dao/usagerecord/DefaultApiLimitService.java

@ -16,7 +16,6 @@
package org.thingsboard.server.dao.usagerecord;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.id.CustomerId;
@ -25,8 +24,6 @@ import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.query.EntityCountQuery;
import org.thingsboard.server.common.data.query.EntityTypeFilter;
import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration;
import org.thingsboard.server.common.msg.notification.NotificationRuleProcessor;
import org.thingsboard.server.common.msg.notification.trigger.EntitiesLimitTrigger;
import org.thingsboard.server.dao.entity.EntityService;
import org.thingsboard.server.dao.tenant.TbTenantProfileCache;
@ -36,8 +33,6 @@ public class DefaultApiLimitService implements ApiLimitService {
private final EntityService entityService;
private final TbTenantProfileCache tenantProfileCache;
@Autowired(required = false)
private NotificationRuleProcessor notificationRuleProcessor;
@Override
public boolean checkEntitiesLimit(TenantId tenantId, EntityType entityType) {
@ -47,14 +42,6 @@ public class DefaultApiLimitService implements ApiLimitService {
EntityTypeFilter filter = new EntityTypeFilter();
filter.setEntityType(entityType);
long currentCount = entityService.countEntitiesByQuery(tenantId, new CustomerId(EntityId.NULL_UUID), new EntityCountQuery(filter));
if (notificationRuleProcessor != null) {
notificationRuleProcessor.process(EntitiesLimitTrigger.builder()
.tenantId(tenantId)
.entityType(entityType)
.currentCount(currentCount)
.limit(limit)
.build());
}
return currentCount < limit;
} else {
return true;

Loading…
Cancel
Save