diff --git a/application/src/main/data/upgrade/3.6.0/schema_update.sql b/application/src/main/data/upgrade/3.6.0/schema_update.sql index dd07a47dac..0f4302d803 100644 --- a/application/src/main/data/upgrade/3.6.0/schema_update.sql +++ b/application/src/main/data/upgrade/3.6.0/schema_update.sql @@ -15,4 +15,7 @@ -- ALTER TABLE widget_type - ADD COLUMN IF NOT EXISTS tags text[]; \ No newline at end of file + ADD COLUMN IF NOT EXISTS tags text[]; + +ALTER TABLE api_usage_state ADD COLUMN IF NOT EXISTS tbel_exec varchar(32); +UPDATE api_usage_state SET tbel_exec = js_exec WHERE tbel_exec IS NULL; diff --git a/application/src/main/java/org/thingsboard/server/controller/BaseController.java b/application/src/main/java/org/thingsboard/server/controller/BaseController.java index 0af55d7c00..365f1fc379 100644 --- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java +++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java @@ -21,7 +21,7 @@ import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; import lombok.Getter; -import lombok.extern.slf4j.Slf4j; +import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.MediaType; @@ -174,10 +174,11 @@ import static org.thingsboard.server.common.data.query.EntityKeyType.ENTITY_FIEL import static org.thingsboard.server.controller.UserController.YOU_DON_T_HAVE_PERMISSION_TO_PERFORM_THIS_OPERATION; import static org.thingsboard.server.dao.service.Validator.validateId; -@Slf4j @TbCoreComponent public abstract class BaseController { + private final Logger log = org.slf4j.LoggerFactory.getLogger(getClass()); + /*Swagger UI description*/ @Autowired diff --git a/application/src/main/java/org/thingsboard/server/service/apiusage/BaseApiUsageState.java b/application/src/main/java/org/thingsboard/server/service/apiusage/BaseApiUsageState.java index 1215bef0bf..9ae25fe2ef 100644 --- a/application/src/main/java/org/thingsboard/server/service/apiusage/BaseApiUsageState.java +++ b/application/src/main/java/org/thingsboard/server/service/apiusage/BaseApiUsageState.java @@ -145,6 +145,8 @@ public abstract class BaseApiUsageState { return apiUsageState.getDbStorageState(); case JS: return apiUsageState.getJsExecState(); + case TBEL: + return apiUsageState.getTbelExecState(); case EMAIL: return apiUsageState.getEmailExecState(); case SMS: @@ -171,6 +173,9 @@ public abstract class BaseApiUsageState { case JS: apiUsageState.setJsExecState(value); break; + case TBEL: + apiUsageState.setTbelExecState(value); + break; case EMAIL: apiUsageState.setEmailExecState(value); break; diff --git a/application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java b/application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java index 908fc75ec6..c02b7e9cc1 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java +++ b/application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java @@ -779,13 +779,15 @@ public class SqlDatabaseUpgradeService implements DatabaseEntitiesUpgradeService break; case "3.6.0": try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword)) { - log.info("Updating schema ..."); if (isOldSchema(conn, 3006000)) { + log.info("Updating schema ..."); schemaUpdateFile = Paths.get(installScripts.getDataDir(), "upgrade", "3.6.0", SCHEMA_UPDATE_SQL); loadSql(schemaUpdateFile, conn); conn.createStatement().execute("UPDATE tb_schema_settings SET schema_version = 3006001;"); + log.info("Schema updated to version 3.6.1."); + } else { + log.info("Skip schema re-update to version 3.6.1. Use env flag 'SKIP_SCHEMA_VERSION_CHECK' to force the re-update."); } - log.info("Schema updated."); } catch (Exception e) { log.error("Failed updating schema!!!", e); } diff --git a/application/src/main/java/org/thingsboard/server/service/mail/DefaultMailService.java b/application/src/main/java/org/thingsboard/server/service/mail/DefaultMailService.java index 246fa4a0fa..ba1b8cca75 100644 --- a/application/src/main/java/org/thingsboard/server/service/mail/DefaultMailService.java +++ b/application/src/main/java/org/thingsboard/server/service/mail/DefaultMailService.java @@ -362,6 +362,8 @@ public class DefaultMailService implements MailService { return valueInM + " out of " + thresholdInM + " allowed messages"; case JS_EXEC_COUNT: return valueInM + " out of " + thresholdInM + " allowed JavaScript functions"; + case TBEL_EXEC_COUNT: + return valueInM + " out of " + thresholdInM + " allowed Tbel functions"; case RE_EXEC_COUNT: return valueInM + " out of " + thresholdInM + " allowed Rule Engine messages"; case EMAIL_EXEC_COUNT: @@ -382,6 +384,8 @@ public class DefaultMailService implements MailService { return recordState.getValueAsString() + " messages"; case JS_EXEC_COUNT: return "JavaScript functions " + recordState.getValueAsString() + " times"; + case TBEL_EXEC_COUNT: + return "TBEL functions " + recordState.getValueAsString() + " times"; case RE_EXEC_COUNT: return recordState.getValueAsString() + " Rule Engine messages"; case EMAIL_EXEC_COUNT: diff --git a/application/src/test/java/org/thingsboard/server/controller/HomePageApiTest.java b/application/src/test/java/org/thingsboard/server/controller/HomePageApiTest.java index c601be7272..d020fef1cb 100644 --- a/application/src/test/java/org/thingsboard/server/controller/HomePageApiTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/HomePageApiTest.java @@ -417,6 +417,9 @@ public class HomePageApiTest extends AbstractControllerTest { Assert.assertEquals(0, usageInfo.getJsExecutions()); Assert.assertEquals(configuration.getMaxJSExecutions(), usageInfo.getMaxJsExecutions()); + Assert.assertEquals(0, usageInfo.getTbelExecutions()); + Assert.assertEquals(configuration.getMaxTbelExecutions(), usageInfo.getMaxTbelExecutions()); + Assert.assertEquals(0, usageInfo.getEmails()); Assert.assertEquals(configuration.getMaxEmails(), usageInfo.getMaxEmails()); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ApiFeature.java b/common/data/src/main/java/org/thingsboard/server/common/data/ApiFeature.java index 31d8b7aeea..84fe049ee9 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ApiFeature.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ApiFeature.java @@ -22,6 +22,7 @@ public enum ApiFeature { DB("dbApiState", "Telemetry persistence"), RE("ruleEngineApiState", "Rule Engine execution"), JS("jsExecutionApiState", "JavaScript functions execution"), + TBEL("tbelExecutionApiState", "Tbel functions execution"), EMAIL("emailApiState", "Email messages"), SMS("smsApiState", "SMS messages"), ALARM("alarmApiState", "Alarms"); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ApiUsageRecordKey.java b/common/data/src/main/java/org/thingsboard/server/common/data/ApiUsageRecordKey.java index 64eabfdd16..4554ec8f5f 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ApiUsageRecordKey.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ApiUsageRecordKey.java @@ -24,6 +24,7 @@ public enum ApiUsageRecordKey { STORAGE_DP_COUNT(ApiFeature.DB, "storageDataPointsCount", "storageDataPointsLimit", "data point"), RE_EXEC_COUNT(ApiFeature.RE, "ruleEngineExecutionCount", "ruleEngineExecutionLimit", "Rule Engine execution"), JS_EXEC_COUNT(ApiFeature.JS, "jsExecutionCount", "jsExecutionLimit", "JavaScript execution"), + TBEL_EXEC_COUNT(ApiFeature.TBEL, "tbelExecutionCount", "tbelExecutionLimit", "Tbel execution"), EMAIL_EXEC_COUNT(ApiFeature.EMAIL, "emailCount", "emailLimit", "email message"), SMS_EXEC_COUNT(ApiFeature.SMS, "smsCount", "smsLimit", "SMS message"), CREATED_ALARMS_COUNT(ApiFeature.ALARM, "createdAlarmsCount", "createdAlarmsLimit", "alarm"), @@ -31,6 +32,7 @@ public enum ApiUsageRecordKey { INACTIVE_DEVICES("inactiveDevicesCount"); private static final ApiUsageRecordKey[] JS_RECORD_KEYS = {JS_EXEC_COUNT}; + private static final ApiUsageRecordKey[] TBEL_RECORD_KEYS = {TBEL_EXEC_COUNT}; private static final ApiUsageRecordKey[] RE_RECORD_KEYS = {RE_EXEC_COUNT}; private static final ApiUsageRecordKey[] DB_RECORD_KEYS = {STORAGE_DP_COUNT}; private static final ApiUsageRecordKey[] TRANSPORT_RECORD_KEYS = {TRANSPORT_MSG_COUNT, TRANSPORT_DP_COUNT}; @@ -75,6 +77,8 @@ public enum ApiUsageRecordKey { return RE_RECORD_KEYS; case JS: return JS_RECORD_KEYS; + case TBEL: + return TBEL_RECORD_KEYS; case EMAIL: return EMAIL_RECORD_KEYS; case SMS: diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ApiUsageState.java b/common/data/src/main/java/org/thingsboard/server/common/data/ApiUsageState.java index d28a8b0908..e6f3192194 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ApiUsageState.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ApiUsageState.java @@ -37,6 +37,7 @@ public class ApiUsageState extends BaseData implements HasTenan private ApiUsageStateValue dbStorageState; private ApiUsageStateValue reExecState; private ApiUsageStateValue jsExecState; + private ApiUsageStateValue tbelExecState; private ApiUsageStateValue emailExecState; private ApiUsageStateValue smsExecState; private ApiUsageStateValue alarmExecState; @@ -57,6 +58,7 @@ public class ApiUsageState extends BaseData implements HasTenan this.dbStorageState = ur.getDbStorageState(); this.reExecState = ur.getReExecState(); this.jsExecState = ur.getJsExecState(); + this.tbelExecState = ur.getTbelExecState(); this.emailExecState = ur.getEmailExecState(); this.smsExecState = ur.getSmsExecState(); this.alarmExecState = ur.getAlarmExecState(); @@ -78,6 +80,10 @@ public class ApiUsageState extends BaseData implements HasTenan return !ApiUsageStateValue.DISABLED.equals(jsExecState); } + public boolean isTbelExecEnabled() { + return !ApiUsageStateValue.DISABLED.equals(tbelExecState); + } + public boolean isEmailSendEnabled(){ return !ApiUsageStateValue.DISABLED.equals(emailExecState); } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/UsageInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/UsageInfo.java index 9b03118bad..bdd9801b0c 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/UsageInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/UsageInfo.java @@ -33,7 +33,9 @@ public class UsageInfo { private long transportMessages; private long maxTransportMessages; private long jsExecutions; + private long tbelExecutions; private long maxJsExecutions; + private long maxTbelExecutions; private long emails; private long maxEmails; private long sms; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/DefaultTenantProfileConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/DefaultTenantProfileConfiguration.java index bd2b80f10a..2e5c78f4ba 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/DefaultTenantProfileConfiguration.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/DefaultTenantProfileConfiguration.java @@ -56,6 +56,7 @@ public class DefaultTenantProfileConfiguration implements TenantProfileConfigura private long maxTransportDataPoints; private long maxREExecutions; private long maxJSExecutions; + private long maxTbelExecutions; private long maxDPStorageDays; private int maxRuleNodeExecutionsPerMessage; private long maxEmails; @@ -94,6 +95,8 @@ public class DefaultTenantProfileConfiguration implements TenantProfileConfigura return maxTransportDataPoints; case JS_EXEC_COUNT: return maxJSExecutions; + case TBEL_EXEC_COUNT: + return maxTbelExecutions; case RE_EXEC_COUNT: return maxREExecutions; case STORAGE_DP_COUNT: diff --git a/common/script/script-api/src/main/java/org/thingsboard/script/api/AbstractScriptInvokeService.java b/common/script/script-api/src/main/java/org/thingsboard/script/api/AbstractScriptInvokeService.java index 23274e863d..ad45891cda 100644 --- a/common/script/script-api/src/main/java/org/thingsboard/script/api/AbstractScriptInvokeService.java +++ b/common/script/script-api/src/main/java/org/thingsboard/script/api/AbstractScriptInvokeService.java @@ -25,11 +25,8 @@ import org.thingsboard.common.util.ThingsBoardThreadFactory; import org.thingsboard.server.common.data.ApiUsageRecordKey; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.TenantId; -import org.thingsboard.server.common.stats.TbApiUsageReportClient; -import org.thingsboard.server.common.stats.TbApiUsageStateClient; import java.util.Map; -import java.util.Optional; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executor; @@ -45,9 +42,6 @@ import static java.lang.String.format; public abstract class AbstractScriptInvokeService implements ScriptInvokeService { protected final Map disabledScripts = new ConcurrentHashMap<>(); - - private final Optional apiUsageStateClient; - private final Optional apiUsageReportClient; private final AtomicInteger pushedMsgs = new AtomicInteger(0); private final AtomicInteger invokeMsgs = new AtomicInteger(0); private final AtomicInteger evalMsgs = new AtomicInteger(0); @@ -59,11 +53,6 @@ public abstract class AbstractScriptInvokeService implements ScriptInvokeService protected ScheduledExecutorService timeoutExecutorService; - protected AbstractScriptInvokeService(Optional apiUsageStateClient, Optional apiUsageReportClient) { - this.apiUsageStateClient = apiUsageStateClient; - this.apiUsageReportClient = apiUsageReportClient; - } - protected long getMaxEvalRequestsTimeout() { return getMaxInvokeRequestsTimeout(); } @@ -88,6 +77,9 @@ public abstract class AbstractScriptInvokeService implements ScriptInvokeService protected abstract boolean isScriptPresent(UUID scriptId); + protected abstract boolean isExecEnabled(TenantId tenantId); + protected abstract void reportExecution(TenantId tenantId, CustomerId customerId); + protected abstract ListenableFuture doEvalScript(TenantId tenantId, ScriptType scriptType, String scriptBody, UUID scriptId, String[] argNames); protected abstract TbScriptExecutionTask doInvokeFunction(UUID scriptId, Object[] args); @@ -122,7 +114,7 @@ public abstract class AbstractScriptInvokeService implements ScriptInvokeService @Override public ListenableFuture eval(TenantId tenantId, ScriptType scriptType, String scriptBody, String... argNames) { - if (!apiUsageStateClient.isPresent() || apiUsageStateClient.get().getApiUsageState(tenantId).isJsExecEnabled()) { + if (isExecEnabled(tenantId)) { if (scriptBodySizeExceeded(scriptBody)) { return error(format("Script body exceeds maximum allowed size of %s symbols", getMaxScriptBodySize())); } @@ -137,7 +129,7 @@ public abstract class AbstractScriptInvokeService implements ScriptInvokeService @Override public ListenableFuture invokeScript(TenantId tenantId, CustomerId customerId, UUID scriptId, Object... args) { - if (!apiUsageStateClient.isPresent() || apiUsageStateClient.get().getApiUsageState(tenantId).isJsExecEnabled()) { + if (isExecEnabled(tenantId)) { if (!isScriptPresent(scriptId)) { return error("No compiled script found for scriptId: [" + scriptId + "]!"); } @@ -148,7 +140,7 @@ public abstract class AbstractScriptInvokeService implements ScriptInvokeService )); return Futures.immediateFailedFuture(handleScriptException(scriptId, null, t)); } - apiUsageReportClient.ifPresent(client -> client.report(tenantId, customerId, ApiUsageRecordKey.JS_EXEC_COUNT, 1)); + reportExecution(tenantId, customerId); pushedMsgs.incrementAndGet(); log.trace("[{}] InvokeScript uuid {} with timeout {}ms", tenantId, scriptId, getMaxInvokeRequestsTimeout()); var task = doInvokeFunction(scriptId, args); diff --git a/common/script/script-api/src/main/java/org/thingsboard/script/api/js/AbstractJsInvokeService.java b/common/script/script-api/src/main/java/org/thingsboard/script/api/js/AbstractJsInvokeService.java index df84876869..192997f6a7 100644 --- a/common/script/script-api/src/main/java/org/thingsboard/script/api/js/AbstractJsInvokeService.java +++ b/common/script/script-api/src/main/java/org/thingsboard/script/api/js/AbstractJsInvokeService.java @@ -23,6 +23,8 @@ import org.springframework.beans.factory.annotation.Value; import org.thingsboard.script.api.AbstractScriptInvokeService; import org.thingsboard.script.api.RuleNodeScriptFactory; import org.thingsboard.script.api.ScriptType; +import org.thingsboard.server.common.data.ApiUsageRecordKey; +import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.stats.TbApiUsageReportClient; import org.thingsboard.server.common.stats.TbApiUsageStateClient; @@ -39,6 +41,8 @@ import java.util.concurrent.ConcurrentHashMap; public abstract class AbstractJsInvokeService extends AbstractScriptInvokeService implements JsInvokeService { protected final Map scriptInfoMap = new ConcurrentHashMap<>(); + private final Optional apiUsageStateClient; + private final Optional apiUsageReportClient; @Getter @Value("${js.max_total_args_size:100000}") @@ -51,7 +55,8 @@ public abstract class AbstractJsInvokeService extends AbstractScriptInvokeServic private long maxScriptBodySize; protected AbstractJsInvokeService(Optional apiUsageStateClient, Optional apiUsageReportClient) { - super(apiUsageStateClient, apiUsageReportClient); + this.apiUsageStateClient = apiUsageStateClient; + this.apiUsageReportClient = apiUsageReportClient; } @Override @@ -59,6 +64,16 @@ public abstract class AbstractJsInvokeService extends AbstractScriptInvokeServic return scriptInfoMap.containsKey(scriptId); } + @Override + protected boolean isExecEnabled(TenantId tenantId) { + return !apiUsageStateClient.isPresent() || apiUsageStateClient.get().getApiUsageState(tenantId).isJsExecEnabled(); + } + + @Override + protected void reportExecution(TenantId tenantId, CustomerId customerId) { + apiUsageReportClient.ifPresent(client -> client.report(tenantId, customerId, ApiUsageRecordKey.JS_EXEC_COUNT, 1)); + } + @Override protected JsScriptExecutionTask doInvokeFunction(UUID scriptId, Object[] args) { return new JsScriptExecutionTask(doInvokeFunction(scriptId, scriptInfoMap.get(scriptId), args)); diff --git a/common/script/script-api/src/main/java/org/thingsboard/script/api/tbel/DefaultTbelInvokeService.java b/common/script/script-api/src/main/java/org/thingsboard/script/api/tbel/DefaultTbelInvokeService.java index 2a60980f84..221d68c33b 100644 --- a/common/script/script-api/src/main/java/org/thingsboard/script/api/tbel/DefaultTbelInvokeService.java +++ b/common/script/script-api/src/main/java/org/thingsboard/script/api/tbel/DefaultTbelInvokeService.java @@ -40,6 +40,8 @@ import org.thingsboard.common.util.ThingsBoardExecutors; import org.thingsboard.script.api.AbstractScriptInvokeService; import org.thingsboard.script.api.ScriptType; import org.thingsboard.script.api.TbScriptException; +import org.thingsboard.server.common.data.ApiUsageRecordKey; +import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.stats.TbApiUsageReportClient; import org.thingsboard.server.common.stats.TbApiUsageStateClient; @@ -69,6 +71,8 @@ public class DefaultTbelInvokeService extends AbstractScriptInvokeService implem protected Cache compiledScriptsCache; private SandboxedParserConfiguration parserConfig; + private final Optional apiUsageStateClient; + private final Optional apiUsageReportClient; @Getter @Value("${tbel.max_total_args_size:100000}") @@ -110,7 +114,8 @@ public class DefaultTbelInvokeService extends AbstractScriptInvokeService implem private final Lock lock = new ReentrantLock(); protected DefaultTbelInvokeService(Optional apiUsageStateClient, Optional apiUsageReportClient) { - super(apiUsageStateClient, apiUsageReportClient); + this.apiUsageStateClient = apiUsageStateClient; + this.apiUsageReportClient = apiUsageReportClient; } @Scheduled(fixedDelayString = "${tbel.stats.print_interval_ms:10000}") @@ -167,6 +172,16 @@ public class DefaultTbelInvokeService extends AbstractScriptInvokeService implem return scriptIdToHash.containsKey(scriptId); } + @Override + protected boolean isExecEnabled(TenantId tenantId) { + return !apiUsageStateClient.isPresent() || apiUsageStateClient.get().getApiUsageState(tenantId).isTbelExecEnabled(); + } + + @Override + protected void reportExecution(TenantId tenantId, CustomerId customerId) { + apiUsageReportClient.ifPresent(client -> client.report(tenantId, customerId, ApiUsageRecordKey.TBEL_EXEC_COUNT, 1)); + } + @Override protected ListenableFuture doEvalScript(TenantId tenantId, ScriptType scriptType, String scriptBody, UUID scriptId, String[] argNames) { return executor.submit(() -> { diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java index d27a5365ef..527cbb8957 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java @@ -482,6 +482,7 @@ public class ModelConstants { public static final String API_USAGE_STATE_DB_STORAGE_COLUMN = "db_storage"; public static final String API_USAGE_STATE_RE_EXEC_COLUMN = "re_exec"; public static final String API_USAGE_STATE_JS_EXEC_COLUMN = "js_exec"; + public static final String API_USAGE_STATE_TBEL_EXEC_COLUMN = "tbel_exec"; public static final String API_USAGE_STATE_EMAIL_EXEC_COLUMN = "email_exec"; public static final String API_USAGE_STATE_SMS_EXEC_COLUMN = "sms_exec"; public static final String API_USAGE_STATE_ALARM_EXEC_COLUMN = "alarm_exec"; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/ApiUsageStateEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/ApiUsageStateEntity.java index b18f414c63..8b92002db5 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/ApiUsageStateEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/ApiUsageStateEntity.java @@ -64,6 +64,9 @@ public class ApiUsageStateEntity extends BaseSqlEntity implements @Column(name = ModelConstants.API_USAGE_STATE_JS_EXEC_COLUMN) private ApiUsageStateValue jsExecState = ApiUsageStateValue.ENABLED; @Enumerated(EnumType.STRING) + @Column(name = ModelConstants.API_USAGE_STATE_TBEL_EXEC_COLUMN) + private ApiUsageStateValue tbelExecState = ApiUsageStateValue.ENABLED; + @Enumerated(EnumType.STRING) @Column(name = ModelConstants.API_USAGE_STATE_EMAIL_EXEC_COLUMN) private ApiUsageStateValue emailExecState = ApiUsageStateValue.ENABLED; @Enumerated(EnumType.STRING) @@ -92,6 +95,7 @@ public class ApiUsageStateEntity extends BaseSqlEntity implements this.dbStorageState = ur.getDbStorageState(); this.reExecState = ur.getReExecState(); this.jsExecState = ur.getJsExecState(); + this.tbelExecState = ur.getTbelExecState(); this.emailExecState = ur.getEmailExecState(); this.smsExecState = ur.getSmsExecState(); this.alarmExecState = ur.getAlarmExecState(); @@ -111,6 +115,7 @@ public class ApiUsageStateEntity extends BaseSqlEntity implements ur.setDbStorageState(dbStorageState); ur.setReExecState(reExecState); ur.setJsExecState(jsExecState); + ur.setTbelExecState(tbelExecState); ur.setEmailExecState(emailExecState); ur.setSmsExecState(smsExecState); ur.setAlarmExecState(alarmExecState); diff --git a/dao/src/main/java/org/thingsboard/server/dao/usage/BasicUsageInfoService.java b/dao/src/main/java/org/thingsboard/server/dao/usage/BasicUsageInfoService.java index fcd75b25f7..7f4e065bd9 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/usage/BasicUsageInfoService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/usage/BasicUsageInfoService.java @@ -67,6 +67,7 @@ public class BasicUsageInfoService implements UsageInfoService { usageInfo.setMaxAlarms(profileConfiguration.getMaxCreatedAlarms()); usageInfo.setMaxTransportMessages(profileConfiguration.getMaxTransportMessages()); usageInfo.setMaxJsExecutions(profileConfiguration.getMaxJSExecutions()); + usageInfo.setMaxTbelExecutions(profileConfiguration.getMaxTbelExecutions()); usageInfo.setMaxEmails(profileConfiguration.getMaxEmails()); usageInfo.setMaxSms(profileConfiguration.getMaxSms()); usageInfo.setSmsEnabled(profileConfiguration.getSmsEnabled()); @@ -75,6 +76,7 @@ public class BasicUsageInfoService implements UsageInfoService { Collection keys = Arrays.asList( ApiUsageRecordKey.TRANSPORT_MSG_COUNT.getApiCountKey(), ApiUsageRecordKey.JS_EXEC_COUNT.getApiCountKey(), + ApiUsageRecordKey.TBEL_EXEC_COUNT.getApiCountKey(), ApiUsageRecordKey.EMAIL_EXEC_COUNT.getApiCountKey(), ApiUsageRecordKey.SMS_EXEC_COUNT.getApiCountKey(), ApiUsageRecordKey.CREATED_ALARMS_COUNT.getApiCountKey()); @@ -82,6 +84,7 @@ public class BasicUsageInfoService implements UsageInfoService { List entries = tsService.findLatest(tenantId, apiUsageState.getId(), keys).get(); usageInfo.setTransportMessages(getLongValueFromTsEntries(entries, ApiUsageRecordKey.TRANSPORT_MSG_COUNT.getApiCountKey())); usageInfo.setJsExecutions(getLongValueFromTsEntries(entries, ApiUsageRecordKey.JS_EXEC_COUNT.getApiCountKey())); + usageInfo.setTbelExecutions(getLongValueFromTsEntries(entries, ApiUsageRecordKey.TBEL_EXEC_COUNT.getApiCountKey())); usageInfo.setEmails(getLongValueFromTsEntries(entries, ApiUsageRecordKey.EMAIL_EXEC_COUNT.getApiCountKey())); usageInfo.setSms(getLongValueFromTsEntries(entries, ApiUsageRecordKey.SMS_EXEC_COUNT.getApiCountKey())); usageInfo.setAlarms(getLongValueFromTsEntries(entries, ApiUsageRecordKey.CREATED_ALARMS_COUNT.getApiCountKey())); diff --git a/dao/src/main/java/org/thingsboard/server/dao/usagerecord/ApiUsageStateServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/usagerecord/ApiUsageStateServiceImpl.java index ba49cc964c..25d3c97c42 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/usagerecord/ApiUsageStateServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/usagerecord/ApiUsageStateServiceImpl.java @@ -93,6 +93,7 @@ public class ApiUsageStateServiceImpl extends AbstractEntityService implements A apiUsageState.setTransportState(ApiUsageStateValue.ENABLED); apiUsageState.setReExecState(ApiUsageStateValue.ENABLED); apiUsageState.setJsExecState(ApiUsageStateValue.ENABLED); + apiUsageState.setTbelExecState(ApiUsageStateValue.ENABLED); apiUsageState.setDbStorageState(ApiUsageStateValue.ENABLED); apiUsageState.setSmsExecState(ApiUsageStateValue.ENABLED); apiUsageState.setEmailExecState(ApiUsageStateValue.ENABLED); @@ -110,6 +111,8 @@ public class ApiUsageStateServiceImpl extends AbstractEntityService implements A new StringDataEntry(ApiFeature.RE.getApiStateKey(), ApiUsageStateValue.ENABLED.name()))); apiUsageStates.add(new BasicTsKvEntry(saved.getCreatedTime(), new StringDataEntry(ApiFeature.JS.getApiStateKey(), ApiUsageStateValue.ENABLED.name()))); + apiUsageStates.add(new BasicTsKvEntry(saved.getCreatedTime(), + new StringDataEntry(ApiFeature.TBEL.getApiStateKey(), ApiUsageStateValue.ENABLED.name()))); apiUsageStates.add(new BasicTsKvEntry(saved.getCreatedTime(), new StringDataEntry(ApiFeature.EMAIL.getApiStateKey(), ApiUsageStateValue.ENABLED.name()))); apiUsageStates.add(new BasicTsKvEntry(saved.getCreatedTime(), diff --git a/dao/src/main/resources/sql/schema-entities.sql b/dao/src/main/resources/sql/schema-entities.sql index b1ae32704e..85b09e2053 100644 --- a/dao/src/main/resources/sql/schema-entities.sql +++ b/dao/src/main/resources/sql/schema-entities.sql @@ -697,6 +697,7 @@ CREATE TABLE IF NOT EXISTS api_usage_state ( db_storage varchar(32), re_exec varchar(32), js_exec varchar(32), + tbel_exec varchar(32), email_exec varchar(32), sms_exec varchar(32), alarm_exec varchar(32), diff --git a/ui-ngx/src/styles.scss b/ui-ngx/src/styles.scss index 47a7bbbac2..0ee154cf7d 100644 --- a/ui-ngx/src/styles.scss +++ b/ui-ngx/src/styles.scss @@ -738,16 +738,21 @@ mat-label { } } - .mat-mdc-row { - transition: background-color .2s; - &:hover:not(.tb-current-entity) { - background-color: #f4f4f4; - } - &.tb-current-entity { - background-color: #e9e9e9; - } - &.tb-pointer { - cursor: pointer; + .mat-mdc-table { + .mat-mdc-row { + transition: background-color .2s; + + &:hover:not(.tb-current-entity) { + background-color: #f4f4f4; + } + + &.tb-current-entity { + background-color: #e9e9e9; + } + + &.tb-pointer { + cursor: pointer; + } } }