Commit 9873115d8baaae032cabe3a3fb259cc3d7501f50

Authored by Viacheslav Klimov
Committed by Andrew Shvayka
1 parent a7d1b54b

Implement created alarms limiting

@@ -130,3 +130,7 @@ DO $$ @@ -130,3 +130,7 @@ DO $$
130 END; 130 END;
131 $$; 131 $$;
132 132
  133 +
  134 +ALTER TABLE api_usage_state
  135 + ADD COLUMN IF NOT EXISTS alarm_exec VARCHAR(32);
  136 +UPDATE api_usage_state SET alarm_exec = 'ENABLED' WHERE alarm_exec IS NULL;
@@ -106,6 +106,8 @@ public abstract class BaseApiUsageState { @@ -106,6 +106,8 @@ public abstract class BaseApiUsageState {
106 return apiUsageState.getEmailExecState(); 106 return apiUsageState.getEmailExecState();
107 case SMS: 107 case SMS:
108 return apiUsageState.getSmsExecState(); 108 return apiUsageState.getSmsExecState();
  109 + case ALARM:
  110 + return apiUsageState.getAlarmExecState();
109 default: 111 default:
110 return ApiUsageStateValue.ENABLED; 112 return ApiUsageStateValue.ENABLED;
111 } 113 }
@@ -132,6 +134,9 @@ public abstract class BaseApiUsageState { @@ -132,6 +134,9 @@ public abstract class BaseApiUsageState {
132 case SMS: 134 case SMS:
133 apiUsageState.setSmsExecState(value); 135 apiUsageState.setSmsExecState(value);
134 break; 136 break;
  137 + case ALARM:
  138 + apiUsageState.setAlarmExecState(value);
  139 + break;
135 } 140 }
136 return !currentValue.equals(value); 141 return !currentValue.equals(value);
137 } 142 }
@@ -309,6 +309,8 @@ public class DefaultMailService implements MailService { @@ -309,6 +309,8 @@ public class DefaultMailService implements MailService {
309 case EMAIL: 309 case EMAIL:
310 case SMS: 310 case SMS:
311 return "send"; 311 return "send";
  312 + case ALARM:
  313 + return "create";
312 default: 314 default:
313 throw new RuntimeException("Not implemented!"); 315 throw new RuntimeException("Not implemented!");
314 } 316 }
@@ -327,6 +329,8 @@ public class DefaultMailService implements MailService { @@ -327,6 +329,8 @@ public class DefaultMailService implements MailService {
327 case EMAIL: 329 case EMAIL:
328 case SMS: 330 case SMS:
329 return "sent"; 331 return "sent";
  332 + case ALARM:
  333 + return "created";
330 default: 334 default:
331 throw new RuntimeException("Not implemented!"); 335 throw new RuntimeException("Not implemented!");
332 } 336 }
@@ -23,6 +23,7 @@ import lombok.extern.slf4j.Slf4j; @@ -23,6 +23,7 @@ import lombok.extern.slf4j.Slf4j;
23 import org.checkerframework.checker.nullness.qual.Nullable; 23 import org.checkerframework.checker.nullness.qual.Nullable;
24 import org.springframework.beans.factory.annotation.Autowired; 24 import org.springframework.beans.factory.annotation.Autowired;
25 import org.springframework.stereotype.Service; 25 import org.springframework.stereotype.Service;
  26 +import org.thingsboard.server.common.data.ApiUsageRecordKey;
26 import org.thingsboard.server.common.data.alarm.Alarm; 27 import org.thingsboard.server.common.data.alarm.Alarm;
27 import org.thingsboard.server.common.data.alarm.AlarmInfo; 28 import org.thingsboard.server.common.data.alarm.AlarmInfo;
28 import org.thingsboard.server.common.data.alarm.AlarmQuery; 29 import org.thingsboard.server.common.data.alarm.AlarmQuery;
@@ -43,6 +44,8 @@ import org.thingsboard.server.dao.alarm.AlarmOperationResult; @@ -43,6 +44,8 @@ import org.thingsboard.server.dao.alarm.AlarmOperationResult;
43 import org.thingsboard.server.dao.alarm.AlarmService; 44 import org.thingsboard.server.dao.alarm.AlarmService;
44 import org.thingsboard.server.gen.transport.TransportProtos; 45 import org.thingsboard.server.gen.transport.TransportProtos;
45 import org.thingsboard.server.queue.discovery.PartitionService; 46 import org.thingsboard.server.queue.discovery.PartitionService;
  47 +import org.thingsboard.server.queue.usagestats.TbApiUsageClient;
  48 +import org.thingsboard.server.service.apiusage.TbApiUsageStateService;
46 import org.thingsboard.server.service.queue.TbClusterService; 49 import org.thingsboard.server.service.queue.TbClusterService;
47 import org.thingsboard.server.service.subscription.SubscriptionManagerService; 50 import org.thingsboard.server.service.subscription.SubscriptionManagerService;
48 import org.thingsboard.server.service.subscription.TbSubscriptionUtils; 51 import org.thingsboard.server.service.subscription.TbSubscriptionUtils;
@@ -58,12 +61,18 @@ import java.util.Optional; @@ -58,12 +61,18 @@ import java.util.Optional;
58 public class DefaultAlarmSubscriptionService extends AbstractSubscriptionService implements AlarmSubscriptionService { 61 public class DefaultAlarmSubscriptionService extends AbstractSubscriptionService implements AlarmSubscriptionService {
59 62
60 private final AlarmService alarmService; 63 private final AlarmService alarmService;
  64 + private final TbApiUsageClient apiUsageClient;
  65 + private final TbApiUsageStateService apiUsageStateService;
61 66
62 public DefaultAlarmSubscriptionService(TbClusterService clusterService, 67 public DefaultAlarmSubscriptionService(TbClusterService clusterService,
63 PartitionService partitionService, 68 PartitionService partitionService,
64 - AlarmService alarmService) { 69 + AlarmService alarmService,
  70 + TbApiUsageClient apiUsageClient,
  71 + TbApiUsageStateService apiUsageStateService) {
65 super(clusterService, partitionService); 72 super(clusterService, partitionService);
66 this.alarmService = alarmService; 73 this.alarmService = alarmService;
  74 + this.apiUsageClient = apiUsageClient;
  75 + this.apiUsageStateService = apiUsageStateService;
67 } 76 }
68 77
69 @Autowired(required = false) 78 @Autowired(required = false)
@@ -78,10 +87,19 @@ public class DefaultAlarmSubscriptionService extends AbstractSubscriptionService @@ -78,10 +87,19 @@ public class DefaultAlarmSubscriptionService extends AbstractSubscriptionService
78 87
79 @Override 88 @Override
80 public Alarm createOrUpdateAlarm(Alarm alarm) { 89 public Alarm createOrUpdateAlarm(Alarm alarm) {
81 - AlarmOperationResult result = alarmService.createOrUpdateAlarm(alarm); 90 + AlarmOperationResult result = alarmService.createOrUpdateAlarm(alarm,
  91 + () -> {
  92 + if (!apiUsageStateService.getApiUsageState(alarm.getTenantId()).isAlarmCreationEnabled()) {
  93 + throw new IllegalStateException("Alarms creation is disabled due to API limits");
  94 + }
  95 + },
  96 + () -> {});
82 if (result.isSuccessful()) { 97 if (result.isSuccessful()) {
83 onAlarmUpdated(result); 98 onAlarmUpdated(result);
84 } 99 }
  100 + if (result.isCreated()) {
  101 + apiUsageClient.report(alarm.getTenantId(), null, ApiUsageRecordKey.CREATED_ALARMS_COUNT);
  102 + }
85 return result.getAlarm(); 103 return result.getAlarm();
86 } 104 }
87 105
@@ -26,17 +26,21 @@ import java.util.List; @@ -26,17 +26,21 @@ import java.util.List;
26 public class AlarmOperationResult { 26 public class AlarmOperationResult {
27 private final Alarm alarm; 27 private final Alarm alarm;
28 private final boolean successful; 28 private final boolean successful;
  29 + private final boolean created;
29 private final List<EntityId> propagatedEntitiesList; 30 private final List<EntityId> propagatedEntitiesList;
30 31
31 public AlarmOperationResult(Alarm alarm, boolean successful) { 32 public AlarmOperationResult(Alarm alarm, boolean successful) {
32 - this.alarm = alarm;  
33 - this.successful = successful;  
34 - this.propagatedEntitiesList = Collections.emptyList(); 33 + this(alarm, successful, Collections.emptyList());
35 } 34 }
36 35
37 public AlarmOperationResult(Alarm alarm, boolean successful, List<EntityId> propagatedEntitiesList) { 36 public AlarmOperationResult(Alarm alarm, boolean successful, List<EntityId> propagatedEntitiesList) {
  37 + this(alarm, successful, false, propagatedEntitiesList);
  38 + }
  39 +
  40 + public AlarmOperationResult(Alarm alarm, boolean successful, boolean created, List<EntityId> propagatedEntitiesList) {
38 this.alarm = alarm; 41 this.alarm = alarm;
39 this.successful = successful; 42 this.successful = successful;
  43 + this.created = created;
40 this.propagatedEntitiesList = propagatedEntitiesList; 44 this.propagatedEntitiesList = propagatedEntitiesList;
41 } 45 }
42 } 46 }
@@ -31,6 +31,7 @@ import org.thingsboard.server.common.data.page.PageData; @@ -31,6 +31,7 @@ import org.thingsboard.server.common.data.page.PageData;
31 import org.thingsboard.server.common.data.query.AlarmData; 31 import org.thingsboard.server.common.data.query.AlarmData;
32 import org.thingsboard.server.common.data.query.AlarmDataPageLink; 32 import org.thingsboard.server.common.data.query.AlarmDataPageLink;
33 import org.thingsboard.server.common.data.query.AlarmDataQuery; 33 import org.thingsboard.server.common.data.query.AlarmDataQuery;
  34 +import org.thingsboard.server.common.msg.queue.TbCallback;
34 35
35 import java.util.Collection; 36 import java.util.Collection;
36 37
@@ -41,6 +42,8 @@ public interface AlarmService { @@ -41,6 +42,8 @@ public interface AlarmService {
41 42
42 AlarmOperationResult createOrUpdateAlarm(Alarm alarm); 43 AlarmOperationResult createOrUpdateAlarm(Alarm alarm);
43 44
  45 + AlarmOperationResult createOrUpdateAlarm(Alarm alarm, Runnable onAlarmCreation, Runnable onAlarmUpdate);
  46 +
44 AlarmOperationResult deleteAlarm(TenantId tenantId, AlarmId alarmId); 47 AlarmOperationResult deleteAlarm(TenantId tenantId, AlarmId alarmId);
45 48
46 ListenableFuture<AlarmOperationResult> ackAlarm(TenantId tenantId, AlarmId alarmId, long ackTs); 49 ListenableFuture<AlarmOperationResult> ackAlarm(TenantId tenantId, AlarmId alarmId, long ackTs);
@@ -23,7 +23,8 @@ public enum ApiFeature { @@ -23,7 +23,8 @@ public enum ApiFeature {
23 RE("ruleEngineApiState", "Rule Engine execution"), 23 RE("ruleEngineApiState", "Rule Engine execution"),
24 JS("jsExecutionApiState", "JavaScript functions execution"), 24 JS("jsExecutionApiState", "JavaScript functions execution"),
25 EMAIL("emailApiState", "Email messages"), 25 EMAIL("emailApiState", "Email messages"),
26 - SMS("smsApiState", "SMS messages"); 26 + SMS("smsApiState", "SMS messages"),
  27 + ALARM("alarmApiState", "Created alarms");
27 28
28 @Getter 29 @Getter
29 private final String apiStateKey; 30 private final String apiStateKey;
@@ -25,13 +25,16 @@ public enum ApiUsageRecordKey { @@ -25,13 +25,16 @@ public enum ApiUsageRecordKey {
25 RE_EXEC_COUNT(ApiFeature.RE, "ruleEngineExecutionCount", "ruleEngineExecutionLimit"), 25 RE_EXEC_COUNT(ApiFeature.RE, "ruleEngineExecutionCount", "ruleEngineExecutionLimit"),
26 JS_EXEC_COUNT(ApiFeature.JS, "jsExecutionCount", "jsExecutionLimit"), 26 JS_EXEC_COUNT(ApiFeature.JS, "jsExecutionCount", "jsExecutionLimit"),
27 EMAIL_EXEC_COUNT(ApiFeature.EMAIL, "emailCount", "emailLimit"), 27 EMAIL_EXEC_COUNT(ApiFeature.EMAIL, "emailCount", "emailLimit"),
28 - SMS_EXEC_COUNT(ApiFeature.SMS, "smsCount", "smsLimit"); 28 + SMS_EXEC_COUNT(ApiFeature.SMS, "smsCount", "smsLimit"),
  29 + CREATED_ALARMS_COUNT(ApiFeature.ALARM, "createdAlarmsCount", "createdAlarmsLimit");
  30 +
29 private static final ApiUsageRecordKey[] JS_RECORD_KEYS = {JS_EXEC_COUNT}; 31 private static final ApiUsageRecordKey[] JS_RECORD_KEYS = {JS_EXEC_COUNT};
30 private static final ApiUsageRecordKey[] RE_RECORD_KEYS = {RE_EXEC_COUNT}; 32 private static final ApiUsageRecordKey[] RE_RECORD_KEYS = {RE_EXEC_COUNT};
31 private static final ApiUsageRecordKey[] DB_RECORD_KEYS = {STORAGE_DP_COUNT}; 33 private static final ApiUsageRecordKey[] DB_RECORD_KEYS = {STORAGE_DP_COUNT};
32 private static final ApiUsageRecordKey[] TRANSPORT_RECORD_KEYS = {TRANSPORT_MSG_COUNT, TRANSPORT_DP_COUNT}; 34 private static final ApiUsageRecordKey[] TRANSPORT_RECORD_KEYS = {TRANSPORT_MSG_COUNT, TRANSPORT_DP_COUNT};
33 private static final ApiUsageRecordKey[] EMAIL_RECORD_KEYS = {EMAIL_EXEC_COUNT}; 35 private static final ApiUsageRecordKey[] EMAIL_RECORD_KEYS = {EMAIL_EXEC_COUNT};
34 private static final ApiUsageRecordKey[] SMS_RECORD_KEYS = {SMS_EXEC_COUNT}; 36 private static final ApiUsageRecordKey[] SMS_RECORD_KEYS = {SMS_EXEC_COUNT};
  37 + private static final ApiUsageRecordKey[] ALARM_RECORD_KEYS = {CREATED_ALARMS_COUNT};
35 38
36 @Getter 39 @Getter
37 private final ApiFeature apiFeature; 40 private final ApiFeature apiFeature;
@@ -60,6 +63,8 @@ public enum ApiUsageRecordKey { @@ -60,6 +63,8 @@ public enum ApiUsageRecordKey {
60 return EMAIL_RECORD_KEYS; 63 return EMAIL_RECORD_KEYS;
61 case SMS: 64 case SMS:
62 return SMS_RECORD_KEYS; 65 return SMS_RECORD_KEYS;
  66 + case ALARM:
  67 + return ALARM_RECORD_KEYS;
63 default: 68 default:
64 return new ApiUsageRecordKey[]{}; 69 return new ApiUsageRecordKey[]{};
65 } 70 }
@@ -25,34 +25,21 @@ import org.thingsboard.server.common.data.id.ApiUsageStateId; @@ -25,34 +25,21 @@ import org.thingsboard.server.common.data.id.ApiUsageStateId;
25 25
26 @ToString 26 @ToString
27 @EqualsAndHashCode(callSuper = true) 27 @EqualsAndHashCode(callSuper = true)
  28 +@Getter
  29 +@Setter
28 public class ApiUsageState extends BaseData<ApiUsageStateId> implements HasTenantId { 30 public class ApiUsageState extends BaseData<ApiUsageStateId> implements HasTenantId {
29 31
30 private static final long serialVersionUID = 8250339805336035966L; 32 private static final long serialVersionUID = 8250339805336035966L;
31 33
32 - @Getter  
33 - @Setter  
34 private TenantId tenantId; 34 private TenantId tenantId;
35 - @Getter  
36 - @Setter  
37 private EntityId entityId; 35 private EntityId entityId;
38 - @Getter  
39 - @Setter  
40 private ApiUsageStateValue transportState; 36 private ApiUsageStateValue transportState;
41 - @Getter  
42 - @Setter  
43 private ApiUsageStateValue dbStorageState; 37 private ApiUsageStateValue dbStorageState;
44 - @Getter  
45 - @Setter  
46 private ApiUsageStateValue reExecState; 38 private ApiUsageStateValue reExecState;
47 - @Getter  
48 - @Setter  
49 private ApiUsageStateValue jsExecState; 39 private ApiUsageStateValue jsExecState;
50 - @Getter  
51 - @Setter  
52 private ApiUsageStateValue emailExecState; 40 private ApiUsageStateValue emailExecState;
53 - @Getter  
54 - @Setter  
55 private ApiUsageStateValue smsExecState; 41 private ApiUsageStateValue smsExecState;
  42 + private ApiUsageStateValue alarmExecState;
56 43
57 public ApiUsageState() { 44 public ApiUsageState() {
58 super(); 45 super();
@@ -72,6 +59,7 @@ public class ApiUsageState extends BaseData<ApiUsageStateId> implements HasTenan @@ -72,6 +59,7 @@ public class ApiUsageState extends BaseData<ApiUsageStateId> implements HasTenan
72 this.jsExecState = ur.getJsExecState(); 59 this.jsExecState = ur.getJsExecState();
73 this.emailExecState = ur.getEmailExecState(); 60 this.emailExecState = ur.getEmailExecState();
74 this.smsExecState = ur.getSmsExecState(); 61 this.smsExecState = ur.getSmsExecState();
  62 + this.alarmExecState = ur.getAlarmExecState();
75 } 63 }
76 64
77 public boolean isTransportEnabled() { 65 public boolean isTransportEnabled() {
@@ -97,4 +85,8 @@ public class ApiUsageState extends BaseData<ApiUsageStateId> implements HasTenan @@ -97,4 +85,8 @@ public class ApiUsageState extends BaseData<ApiUsageStateId> implements HasTenan
97 public boolean isSmsSendEnabled(){ 85 public boolean isSmsSendEnabled(){
98 return !ApiUsageStateValue.DISABLED.equals(smsExecState); 86 return !ApiUsageStateValue.DISABLED.equals(smsExecState);
99 } 87 }
  88 +
  89 + public boolean isAlarmCreationEnabled() {
  90 + return alarmExecState != ApiUsageStateValue.DISABLED;
  91 + }
100 } 92 }
@@ -50,6 +50,7 @@ public class DefaultTenantProfileConfiguration implements TenantProfileConfigura @@ -50,6 +50,7 @@ public class DefaultTenantProfileConfiguration implements TenantProfileConfigura
50 private int maxRuleNodeExecutionsPerMessage; 50 private int maxRuleNodeExecutionsPerMessage;
51 private long maxEmails; 51 private long maxEmails;
52 private long maxSms; 52 private long maxSms;
  53 + private long maxCreatedAlarms;
53 54
54 private int defaultStorageTtlDays; 55 private int defaultStorageTtlDays;
55 56
@@ -72,6 +73,8 @@ public class DefaultTenantProfileConfiguration implements TenantProfileConfigura @@ -72,6 +73,8 @@ public class DefaultTenantProfileConfiguration implements TenantProfileConfigura
72 return maxEmails; 73 return maxEmails;
73 case SMS_EXEC_COUNT: 74 case SMS_EXEC_COUNT:
74 return maxSms; 75 return maxSms;
  76 + case CREATED_ALARMS_COUNT:
  77 + return maxCreatedAlarms;
75 } 78 }
76 return 0L; 79 return 0L;
77 } 80 }
@@ -47,6 +47,7 @@ import org.thingsboard.server.common.data.relation.EntityRelationsQuery; @@ -47,6 +47,7 @@ import org.thingsboard.server.common.data.relation.EntityRelationsQuery;
47 import org.thingsboard.server.common.data.relation.EntitySearchDirection; 47 import org.thingsboard.server.common.data.relation.EntitySearchDirection;
48 import org.thingsboard.server.common.data.relation.RelationTypeGroup; 48 import org.thingsboard.server.common.data.relation.RelationTypeGroup;
49 import org.thingsboard.server.common.data.relation.RelationsSearchParameters; 49 import org.thingsboard.server.common.data.relation.RelationsSearchParameters;
  50 +import org.thingsboard.server.common.msg.queue.TbCallback;
50 import org.thingsboard.server.dao.entity.AbstractEntityService; 51 import org.thingsboard.server.dao.entity.AbstractEntityService;
51 import org.thingsboard.server.dao.entity.EntityService; 52 import org.thingsboard.server.dao.entity.EntityService;
52 import org.thingsboard.server.dao.exception.DataValidationException; 53 import org.thingsboard.server.dao.exception.DataValidationException;
@@ -65,6 +66,7 @@ import java.util.Set; @@ -65,6 +66,7 @@ import java.util.Set;
65 import java.util.concurrent.ExecutionException; 66 import java.util.concurrent.ExecutionException;
66 import java.util.concurrent.ExecutorService; 67 import java.util.concurrent.ExecutorService;
67 import java.util.concurrent.Executors; 68 import java.util.concurrent.Executors;
  69 +import java.util.function.Consumer;
68 import java.util.stream.Collectors; 70 import java.util.stream.Collectors;
69 import java.util.stream.Stream; 71 import java.util.stream.Stream;
70 72
@@ -102,6 +104,11 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ @@ -102,6 +104,11 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
102 104
103 @Override 105 @Override
104 public AlarmOperationResult createOrUpdateAlarm(Alarm alarm) { 106 public AlarmOperationResult createOrUpdateAlarm(Alarm alarm) {
  107 + return createOrUpdateAlarm(alarm, () -> {}, () -> {});
  108 + }
  109 +
  110 + @Override
  111 + public AlarmOperationResult createOrUpdateAlarm(Alarm alarm, Runnable onAlarmCreation, Runnable onAlarmUpdate) {
105 alarmDataValidator.validate(alarm, Alarm::getTenantId); 112 alarmDataValidator.validate(alarm, Alarm::getTenantId);
106 try { 113 try {
107 if (alarm.getStartTs() == 0L) { 114 if (alarm.getStartTs() == 0L) {
@@ -114,11 +121,14 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ @@ -114,11 +121,14 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
114 if (alarm.getId() == null) { 121 if (alarm.getId() == null) {
115 Alarm existing = alarmDao.findLatestByOriginatorAndType(alarm.getTenantId(), alarm.getOriginator(), alarm.getType()).get(); 122 Alarm existing = alarmDao.findLatestByOriginatorAndType(alarm.getTenantId(), alarm.getOriginator(), alarm.getType()).get();
116 if (existing == null || existing.getStatus().isCleared()) { 123 if (existing == null || existing.getStatus().isCleared()) {
  124 + onAlarmCreation.run();
117 return createAlarm(alarm); 125 return createAlarm(alarm);
118 } else { 126 } else {
  127 + onAlarmUpdate.run();
119 return updateAlarm(existing, alarm); 128 return updateAlarm(existing, alarm);
120 } 129 }
121 } else { 130 } else {
  131 + onAlarmUpdate.run();
122 return updateAlarm(alarm).get(); 132 return updateAlarm(alarm).get();
123 } 133 }
124 } catch (ExecutionException | InterruptedException e) { 134 } catch (ExecutionException | InterruptedException e) {
@@ -159,7 +169,7 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ @@ -159,7 +169,7 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
159 log.debug("New Alarm : {}", alarm); 169 log.debug("New Alarm : {}", alarm);
160 Alarm saved = alarmDao.save(alarm.getTenantId(), alarm); 170 Alarm saved = alarmDao.save(alarm.getTenantId(), alarm);
161 List<EntityId> propagatedEntitiesList = createAlarmRelations(saved); 171 List<EntityId> propagatedEntitiesList = createAlarmRelations(saved);
162 - return new AlarmOperationResult(saved, true, propagatedEntitiesList); 172 + return new AlarmOperationResult(saved, true, true, propagatedEntitiesList);
163 } 173 }
164 174
165 private List<EntityId> createAlarmRelations(Alarm alarm) throws InterruptedException, ExecutionException { 175 private List<EntityId> createAlarmRelations(Alarm alarm) throws InterruptedException, ExecutionException {
@@ -465,6 +465,7 @@ public class ModelConstants { @@ -465,6 +465,7 @@ public class ModelConstants {
465 public static final String API_USAGE_STATE_JS_EXEC_COLUMN = "js_exec"; 465 public static final String API_USAGE_STATE_JS_EXEC_COLUMN = "js_exec";
466 public static final String API_USAGE_STATE_EMAIL_EXEC_COLUMN = "email_exec"; 466 public static final String API_USAGE_STATE_EMAIL_EXEC_COLUMN = "email_exec";
467 public static final String API_USAGE_STATE_SMS_EXEC_COLUMN = "sms_exec"; 467 public static final String API_USAGE_STATE_SMS_EXEC_COLUMN = "sms_exec";
  468 + public static final String API_USAGE_STATE_ALARM_EXEC_COLUMN = "alarm_exec";
468 469
469 /** 470 /**
470 * Resource constants. 471 * Resource constants.
@@ -69,6 +69,9 @@ public class ApiUsageStateEntity extends BaseSqlEntity<ApiUsageState> implements @@ -69,6 +69,9 @@ public class ApiUsageStateEntity extends BaseSqlEntity<ApiUsageState> implements
69 @Enumerated(EnumType.STRING) 69 @Enumerated(EnumType.STRING)
70 @Column(name = ModelConstants.API_USAGE_STATE_SMS_EXEC_COLUMN) 70 @Column(name = ModelConstants.API_USAGE_STATE_SMS_EXEC_COLUMN)
71 private ApiUsageStateValue smsExecState = ApiUsageStateValue.ENABLED; 71 private ApiUsageStateValue smsExecState = ApiUsageStateValue.ENABLED;
  72 + @Enumerated(EnumType.STRING)
  73 + @Column(name = ModelConstants.API_USAGE_STATE_ALARM_EXEC_COLUMN)
  74 + private ApiUsageStateValue alarmExecState = ApiUsageStateValue.ENABLED;
72 75
73 public ApiUsageStateEntity() { 76 public ApiUsageStateEntity() {
74 } 77 }
@@ -91,6 +94,7 @@ public class ApiUsageStateEntity extends BaseSqlEntity<ApiUsageState> implements @@ -91,6 +94,7 @@ public class ApiUsageStateEntity extends BaseSqlEntity<ApiUsageState> implements
91 this.jsExecState = ur.getJsExecState(); 94 this.jsExecState = ur.getJsExecState();
92 this.emailExecState = ur.getEmailExecState(); 95 this.emailExecState = ur.getEmailExecState();
93 this.smsExecState = ur.getSmsExecState(); 96 this.smsExecState = ur.getSmsExecState();
  97 + this.alarmExecState = ur.getAlarmExecState();
94 } 98 }
95 99
96 @Override 100 @Override
@@ -109,6 +113,7 @@ public class ApiUsageStateEntity extends BaseSqlEntity<ApiUsageState> implements @@ -109,6 +113,7 @@ public class ApiUsageStateEntity extends BaseSqlEntity<ApiUsageState> implements
109 ur.setJsExecState(jsExecState); 113 ur.setJsExecState(jsExecState);
110 ur.setEmailExecState(emailExecState); 114 ur.setEmailExecState(emailExecState);
111 ur.setSmsExecState(smsExecState); 115 ur.setSmsExecState(smsExecState);
  116 + ur.setAlarmExecState(alarmExecState);
112 return ur; 117 return ur;
113 } 118 }
114 119
@@ -90,6 +90,7 @@ public class ApiUsageStateServiceImpl extends AbstractEntityService implements A @@ -90,6 +90,7 @@ public class ApiUsageStateServiceImpl extends AbstractEntityService implements A
90 apiUsageState.setDbStorageState(ApiUsageStateValue.ENABLED); 90 apiUsageState.setDbStorageState(ApiUsageStateValue.ENABLED);
91 apiUsageState.setSmsExecState(ApiUsageStateValue.ENABLED); 91 apiUsageState.setSmsExecState(ApiUsageStateValue.ENABLED);
92 apiUsageState.setEmailExecState(ApiUsageStateValue.ENABLED); 92 apiUsageState.setEmailExecState(ApiUsageStateValue.ENABLED);
  93 + apiUsageState.setAlarmExecState(ApiUsageStateValue.ENABLED);
93 apiUsageStateValidator.validate(apiUsageState, ApiUsageState::getTenantId); 94 apiUsageStateValidator.validate(apiUsageState, ApiUsageState::getTenantId);
94 95
95 ApiUsageState saved = apiUsageStateDao.save(apiUsageState.getTenantId(), apiUsageState); 96 ApiUsageState saved = apiUsageStateDao.save(apiUsageState.getTenantId(), apiUsageState);
@@ -107,6 +108,8 @@ public class ApiUsageStateServiceImpl extends AbstractEntityService implements A @@ -107,6 +108,8 @@ public class ApiUsageStateServiceImpl extends AbstractEntityService implements A
107 new StringDataEntry(ApiFeature.EMAIL.getApiStateKey(), ApiUsageStateValue.ENABLED.name()))); 108 new StringDataEntry(ApiFeature.EMAIL.getApiStateKey(), ApiUsageStateValue.ENABLED.name())));
108 apiUsageStates.add(new BasicTsKvEntry(saved.getCreatedTime(), 109 apiUsageStates.add(new BasicTsKvEntry(saved.getCreatedTime(),
109 new StringDataEntry(ApiFeature.SMS.getApiStateKey(), ApiUsageStateValue.ENABLED.name()))); 110 new StringDataEntry(ApiFeature.SMS.getApiStateKey(), ApiUsageStateValue.ENABLED.name())));
  111 + apiUsageStates.add(new BasicTsKvEntry(saved.getCreatedTime(),
  112 + new StringDataEntry(ApiFeature.ALARM.getApiStateKey(), ApiUsageStateValue.ENABLED.name())));
110 tsService.save(tenantId, saved.getId(), apiUsageStates, 0L); 113 tsService.save(tenantId, saved.getId(), apiUsageStates, 0L);
111 114
112 if (entityId.getEntityType() == EntityType.TENANT && !entityId.equals(TenantId.SYS_TENANT_ID)) { 115 if (entityId.getEntityType() == EntityType.TENANT && !entityId.equals(TenantId.SYS_TENANT_ID)) {
@@ -454,6 +454,7 @@ CREATE TABLE IF NOT EXISTS api_usage_state ( @@ -454,6 +454,7 @@ CREATE TABLE IF NOT EXISTS api_usage_state (
454 js_exec varchar(32), 454 js_exec varchar(32),
455 email_exec varchar(32), 455 email_exec varchar(32),
456 sms_exec varchar(32), 456 sms_exec varchar(32),
  457 + alarm_exec varchar(32),
457 CONSTRAINT api_usage_state_unq_key UNIQUE (tenant_id, entity_id) 458 CONSTRAINT api_usage_state_unq_key UNIQUE (tenant_id, entity_id)
458 ); 459 );
459 460
@@ -491,6 +491,7 @@ CREATE TABLE IF NOT EXISTS api_usage_state ( @@ -491,6 +491,7 @@ CREATE TABLE IF NOT EXISTS api_usage_state (
491 js_exec varchar(32), 491 js_exec varchar(32),
492 email_exec varchar(32), 492 email_exec varchar(32),
493 sms_exec varchar(32), 493 sms_exec varchar(32),
  494 + alarm_exec varchar(32),
494 CONSTRAINT api_usage_state_unq_key UNIQUE (tenant_id, entity_id) 495 CONSTRAINT api_usage_state_unq_key UNIQUE (tenant_id, entity_id)
495 ); 496 );
496 497