From b9d7dcc16c64bb2d4ef3e0d15d77ab3a128a3d4f Mon Sep 17 00:00:00 2001 From: Artem Dzhereleiko Date: Wed, 20 Sep 2023 14:39:08 +0300 Subject: [PATCH 1/5] UI: Fixed table style specificity --- ui-ngx/src/styles.scss | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) 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; + } } } From 8f1c13b3354715662f7190937aae35934b1aaf77 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Thu, 21 Sep 2023 17:03:04 +0300 Subject: [PATCH 2/5] added api rate limits tbel --- .../main/data/upgrade/3.6.0/schema_update.sql | 18 +++++++++++++++++ .../service/apiusage/BaseApiUsageState.java | 5 +++++ .../install/SqlDatabaseUpgradeService.java | 15 ++++++++++++++ .../service/mail/DefaultMailService.java | 4 ++++ .../server/controller/HomePageApiTest.java | 3 +++ .../server/common/data/ApiFeature.java | 1 + .../server/common/data/ApiUsageRecordKey.java | 4 ++++ .../server/common/data/ApiUsageState.java | 6 ++++++ .../server/common/data/UsageInfo.java | 2 ++ .../DefaultTenantProfileConfiguration.java | 3 +++ .../api/AbstractScriptInvokeService.java | 20 ++++++------------- .../api/js/AbstractJsInvokeService.java | 17 +++++++++++++++- .../api/tbel/DefaultTbelInvokeService.java | 17 +++++++++++++++- .../server/dao/model/ModelConstants.java | 1 + .../dao/model/sql/ApiUsageStateEntity.java | 5 +++++ .../dao/usage/BasicUsageInfoService.java | 3 +++ .../usagerecord/ApiUsageStateServiceImpl.java | 3 +++ .../main/resources/sql/schema-entities.sql | 1 + 18 files changed, 112 insertions(+), 16 deletions(-) create mode 100644 application/src/main/data/upgrade/3.6.0/schema_update.sql 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 new file mode 100644 index 0000000000..81a0e5443f --- /dev/null +++ b/application/src/main/data/upgrade/3.6.0/schema_update.sql @@ -0,0 +1,18 @@ +-- +-- Copyright © 2016-2023 The Thingsboard Authors +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- + +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; \ No newline at end of file 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 307e2e5f3a..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 @@ -777,6 +777,21 @@ public class SqlDatabaseUpgradeService implements DatabaseEntitiesUpgradeService log.error("Failed updating schema!!!", e); } break; + case "3.6.0": + try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword)) { + 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."); + } + } catch (Exception e) { + log.error("Failed updating schema!!!", e); + } + break; default: throw new RuntimeException("Unable to upgrade SQL database, unsupported fromVersion: " + fromVersion); } 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..ff54fb6e7a 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 0e8ea2db15..278c2b094e 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 @@ -477,6 +477,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 72469e3bdd..d10be65a50 100644 --- a/dao/src/main/resources/sql/schema-entities.sql +++ b/dao/src/main/resources/sql/schema-entities.sql @@ -696,6 +696,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), From bae0ce48a85a0caaf81e7de747e0567ebd30236b Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Thu, 21 Sep 2023 17:48:53 +0200 Subject: [PATCH 3/5] BaseController: log experience improvement. use a child class logger instead of abstract class controller --- .../org/thingsboard/server/controller/BaseController.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 From 25d3b96c6c2ce1405bb40048f145b08ff4749980 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Mon, 25 Sep 2023 13:57:21 +0300 Subject: [PATCH 4/5] text refactoring --- .../org/thingsboard/server/service/mail/DefaultMailService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 ff54fb6e7a..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 @@ -385,7 +385,7 @@ public class DefaultMailService implements MailService { case JS_EXEC_COUNT: return "JavaScript functions " + recordState.getValueAsString() + " times"; case TBEL_EXEC_COUNT: - return "Tbel functions " + recordState.getValueAsString() + " times"; + return "TBEL functions " + recordState.getValueAsString() + " times"; case RE_EXEC_COUNT: return recordState.getValueAsString() + " Rule Engine messages"; case EMAIL_EXEC_COUNT: From 20ba944a3c6a82d498f5367f87225c339494d281 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Mon, 25 Sep 2023 16:30:45 +0300 Subject: [PATCH 5/5] fixed upgrade script --- .../thingsboard/server/install/ThingsboardInstallService.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java b/application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java index 208da7d36c..5ed009d4b6 100644 --- a/application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java +++ b/application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java @@ -262,6 +262,10 @@ public class ThingsboardInstallService { databaseEntitiesUpgradeService.upgradeDatabase("3.5.1"); dataUpdateService.updateData("3.5.1"); systemDataLoaderService.updateDefaultNotificationConfigs(); + break; + case "3.6.0": + log.info("Upgrading ThingsBoard from version 3.6.0 to 3.6.1 ..."); + databaseEntitiesUpgradeService.upgradeDatabase("3.6.0"); //TODO DON'T FORGET to update switch statement in the CacheCleanupService if you need to clear the cache break; default: