diff --git a/application/pom.xml b/application/pom.xml index 96c9ab7b39..598d58c447 100644 --- a/application/pom.xml +++ b/application/pom.xml @@ -110,7 +110,15 @@ queue - org.thingsboard.common + org.thingsboard.common.script + script-api + + + org.thingsboard.common.script + remote-js-client + + + org.thingsboard.common stats diff --git a/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java b/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java index f4e7eb2463..0ccb034017 100644 --- a/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java +++ b/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java @@ -15,9 +15,7 @@ */ package org.thingsboard.server.actors; -import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; @@ -77,7 +75,7 @@ import org.thingsboard.server.dao.timeseries.TimeseriesService; import org.thingsboard.server.dao.user.UserService; import org.thingsboard.server.queue.discovery.PartitionService; import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; -import org.thingsboard.server.queue.usagestats.TbApiUsageClient; +import org.thingsboard.server.queue.usagestats.TbApiUsageReportClient; import org.thingsboard.server.queue.util.DataDecodingEncodingService; import org.thingsboard.server.service.apiusage.TbApiUsageStateService; import org.thingsboard.server.service.component.ComponentDiscoveryService; @@ -92,7 +90,7 @@ import org.thingsboard.server.service.profile.TbDeviceProfileCache; import org.thingsboard.server.service.rpc.TbCoreDeviceRpcService; import org.thingsboard.server.service.rpc.TbRpcService; import org.thingsboard.server.service.rpc.TbRuleEngineDeviceRpcService; -import org.thingsboard.server.service.script.JsInvokeService; +import org.thingsboard.script.api.JsInvokeService; import org.thingsboard.server.service.session.DeviceSessionCacheService; import org.thingsboard.server.service.sms.SmsExecutorService; import org.thingsboard.server.service.state.DeviceStateService; @@ -105,7 +103,6 @@ import javax.annotation.PostConstruct; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; -import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ScheduledExecutorService; @@ -152,7 +149,7 @@ public class ActorSystemContext { @Autowired @Getter - private TbApiUsageClient apiUsageClient; + private TbApiUsageReportClient apiUsageClient; @Autowired @Getter diff --git a/application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleChainActorMessageProcessor.java b/application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleChainActorMessageProcessor.java index b4911650f3..f9dc760340 100644 --- a/application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleChainActorMessageProcessor.java +++ b/application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleChainActorMessageProcessor.java @@ -48,7 +48,7 @@ import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; import org.thingsboard.server.queue.TbQueueCallback; import org.thingsboard.server.queue.common.MultipleTbQueueTbMsgCallbackWrapper; import org.thingsboard.server.queue.common.TbQueueTbMsgCallbackWrapper; -import org.thingsboard.server.queue.usagestats.TbApiUsageClient; +import org.thingsboard.server.queue.usagestats.TbApiUsageReportClient; import org.thingsboard.server.cluster.TbClusterService; import java.util.ArrayList; @@ -73,7 +73,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor> nodeRoutes; private final RuleChainService service; private final TbClusterService clusterService; - private final TbApiUsageClient apiUsageClient; + private final TbApiUsageReportClient apiUsageClient; private String ruleChainName; private RuleNodeId firstId; diff --git a/application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeActorMessageProcessor.java b/application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeActorMessageProcessor.java index 0821f018e9..b9834fdc3b 100644 --- a/application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeActorMessageProcessor.java +++ b/application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeActorMessageProcessor.java @@ -31,7 +31,7 @@ import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; import org.thingsboard.server.common.msg.queue.RuleNodeException; import org.thingsboard.server.common.msg.queue.RuleNodeInfo; -import org.thingsboard.server.queue.usagestats.TbApiUsageClient; +import org.thingsboard.server.queue.usagestats.TbApiUsageReportClient; /** * @author Andrew Shvayka @@ -40,7 +40,7 @@ public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor { +public interface TbApiUsageStateService extends TbApiUsageStateClient, ApplicationListener { void process(TbProtoQueueMsg msg, TbCallback callback); - ApiUsageState getApiUsageState(TenantId tenantId); - void onTenantProfileUpdate(TenantProfileId tenantProfileId); void onTenantUpdate(TenantId tenantId); 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 f433066c06..d544cd769d 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 @@ -44,7 +44,7 @@ import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.exception.IncorrectParameterException; import org.thingsboard.server.dao.settings.AdminSettingsService; -import org.thingsboard.server.queue.usagestats.TbApiUsageClient; +import org.thingsboard.server.queue.usagestats.TbApiUsageReportClient; import org.thingsboard.server.service.apiusage.TbApiUsageStateService; import javax.annotation.PostConstruct; @@ -70,7 +70,7 @@ public class DefaultMailService implements MailService { private final MessageSource messages; private final Configuration freemarkerConfig; private final AdminSettingsService adminSettingsService; - private final TbApiUsageClient apiUsageClient; + private final TbApiUsageReportClient apiUsageClient; private static final long DEFAULT_TIMEOUT = 10_000; @@ -90,7 +90,7 @@ public class DefaultMailService implements MailService { private long timeout; - public DefaultMailService(MessageSource messages, Configuration freemarkerConfig, AdminSettingsService adminSettingsService, TbApiUsageClient apiUsageClient) { + public DefaultMailService(MessageSource messages, Configuration freemarkerConfig, AdminSettingsService adminSettingsService, TbApiUsageReportClient apiUsageClient) { this.messages = messages; this.freemarkerConfig = freemarkerConfig; this.adminSettingsService = adminSettingsService; diff --git a/application/src/main/java/org/thingsboard/server/service/sms/DefaultSmsService.java b/application/src/main/java/org/thingsboard/server/service/sms/DefaultSmsService.java index 1c85e65325..a9457d35e4 100644 --- a/application/src/main/java/org/thingsboard/server/service/sms/DefaultSmsService.java +++ b/application/src/main/java/org/thingsboard/server/service/sms/DefaultSmsService.java @@ -32,7 +32,7 @@ import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.settings.AdminSettingsService; import org.thingsboard.common.util.JacksonUtil; -import org.thingsboard.server.queue.usagestats.TbApiUsageClient; +import org.thingsboard.server.queue.usagestats.TbApiUsageReportClient; import org.thingsboard.server.service.apiusage.TbApiUsageStateService; import javax.annotation.PostConstruct; @@ -45,11 +45,11 @@ public class DefaultSmsService implements SmsService { private final SmsSenderFactory smsSenderFactory; private final AdminSettingsService adminSettingsService; private final TbApiUsageStateService apiUsageStateService; - private final TbApiUsageClient apiUsageClient; + private final TbApiUsageReportClient apiUsageClient; private SmsSender smsSender; - public DefaultSmsService(SmsSenderFactory smsSenderFactory, AdminSettingsService adminSettingsService, TbApiUsageStateService apiUsageStateService, TbApiUsageClient apiUsageClient) { + public DefaultSmsService(SmsSenderFactory smsSenderFactory, AdminSettingsService adminSettingsService, TbApiUsageStateService apiUsageStateService, TbApiUsageReportClient apiUsageClient) { this.smsSenderFactory = smsSenderFactory; this.adminSettingsService = adminSettingsService; this.apiUsageStateService = apiUsageStateService; diff --git a/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultAlarmSubscriptionService.java b/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultAlarmSubscriptionService.java index 4dc0dc238b..c2cb1b32f8 100644 --- a/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultAlarmSubscriptionService.java +++ b/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultAlarmSubscriptionService.java @@ -44,7 +44,7 @@ import org.thingsboard.server.dao.alarm.AlarmOperationResult; import org.thingsboard.server.dao.alarm.AlarmService; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.queue.discovery.PartitionService; -import org.thingsboard.server.queue.usagestats.TbApiUsageClient; +import org.thingsboard.server.queue.usagestats.TbApiUsageReportClient; import org.thingsboard.server.service.apiusage.TbApiUsageStateService; import org.thingsboard.server.cluster.TbClusterService; import org.thingsboard.server.service.subscription.SubscriptionManagerService; @@ -61,13 +61,13 @@ import java.util.Optional; public class DefaultAlarmSubscriptionService extends AbstractSubscriptionService implements AlarmSubscriptionService { private final AlarmService alarmService; - private final TbApiUsageClient apiUsageClient; + private final TbApiUsageReportClient apiUsageClient; private final TbApiUsageStateService apiUsageStateService; public DefaultAlarmSubscriptionService(TbClusterService clusterService, PartitionService partitionService, AlarmService alarmService, - TbApiUsageClient apiUsageClient, + TbApiUsageReportClient apiUsageClient, TbApiUsageStateService apiUsageStateService) { super(clusterService, partitionService); this.alarmService = alarmService; diff --git a/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultTelemetrySubscriptionService.java b/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultTelemetrySubscriptionService.java index a5f66968da..65b81c770e 100644 --- a/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultTelemetrySubscriptionService.java +++ b/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultTelemetrySubscriptionService.java @@ -47,7 +47,7 @@ import org.thingsboard.server.dao.attributes.AttributesService; import org.thingsboard.server.dao.timeseries.TimeseriesService; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.queue.discovery.PartitionService; -import org.thingsboard.server.queue.usagestats.TbApiUsageClient; +import org.thingsboard.server.queue.usagestats.TbApiUsageReportClient; import org.thingsboard.server.service.apiusage.TbApiUsageStateService; import org.thingsboard.server.service.entitiy.entityview.TbEntityViewService; import org.thingsboard.server.service.subscription.TbSubscriptionUtils; @@ -77,7 +77,7 @@ public class DefaultTelemetrySubscriptionService extends AbstractSubscriptionSer private final AttributesService attrService; private final TimeseriesService tsService; private final TbEntityViewService tbEntityViewService; - private final TbApiUsageClient apiUsageClient; + private final TbApiUsageReportClient apiUsageClient; private final TbApiUsageStateService apiUsageStateService; private ExecutorService tsCallBackExecutor; @@ -87,7 +87,7 @@ public class DefaultTelemetrySubscriptionService extends AbstractSubscriptionSer @Lazy TbEntityViewService tbEntityViewService, TbClusterService clusterService, PartitionService partitionService, - TbApiUsageClient apiUsageClient, + TbApiUsageReportClient apiUsageClient, TbApiUsageStateService apiUsageStateService) { super(clusterService, partitionService); this.attrService = attrService; diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index f5ac40afd5..3306a41558 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -599,6 +599,21 @@ state: defaultStateCheckIntervalInSec: "${DEFAULT_STATE_CHECK_INTERVAL:60}" persistToTelemetry: "${PERSIST_STATE_TO_TELEMETRY:false}" +mvel: + enabled: "${MVEL_ENABLED:true}" + max_total_args_size: "${MVEL_MAX_TOTAL_ARGS_SIZE:100000}" + max_result_size: "${MVEL_MAX_RESULT_SIZE:300000}" + max_script_body_size: "${MVEL_MAX_SCRIPT_BODY_SIZE:50000}" + # Maximum allowed MVEL script execution errors before it will be blacklisted + max_errors: "${MVEL_MAX_ERRORS:3}" + # MVEL Eval max request timeout in milliseconds. 0 - no timeout + max_requests_timeout: "${MVEL_MAX_REQUEST_TIMEOUT:500}" + # Maximum time in seconds for black listed function to stay in the list. + max_black_list_duration_sec: "${MVEL_MAX_BLACKLIST_DURATION_SEC:60}" + stats: + enabled: "${TB_MVEL_STATS_ENABLED:false}" + print_interval_ms: "${TB_MVEL_STATS_PRINT_INTERVAL_MS:10000}" + js: evaluator: "${JS_EVALUATOR:local}" # local/remote max_total_args_size: "${JS_MAX_TOTAL_ARGS_SIZE:100000}" diff --git a/application/src/test/java/org/thingsboard/server/service/script/JsInvokeServiceTest.java b/application/src/test/java/org/thingsboard/server/service/script/JsInvokeServiceTest.java index 8f0edd71c6..ae0dc9d819 100644 --- a/application/src/test/java/org/thingsboard/server/service/script/JsInvokeServiceTest.java +++ b/application/src/test/java/org/thingsboard/server/service/script/JsInvokeServiceTest.java @@ -19,6 +19,8 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.test.context.TestPropertySource; +import org.thingsboard.script.api.JsScriptType; +import org.thingsboard.script.api.NashornJsInvokeService; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.controller.AbstractControllerTest; import org.thingsboard.server.dao.service.DaoSqlTest; diff --git a/application/src/test/java/org/thingsboard/server/service/script/MockJsInvokeService.java b/application/src/test/java/org/thingsboard/server/service/script/MockJsInvokeService.java index 1d91f50131..8c705ec3a1 100644 --- a/application/src/test/java/org/thingsboard/server/service/script/MockJsInvokeService.java +++ b/application/src/test/java/org/thingsboard/server/service/script/MockJsInvokeService.java @@ -20,6 +20,8 @@ import com.google.common.util.concurrent.ListenableFuture; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; +import org.thingsboard.script.api.JsInvokeService; +import org.thingsboard.script.api.JsScriptType; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.TenantId; diff --git a/common/pom.xml b/common/pom.xml index 770cb402d2..dcf4685dea 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -47,6 +47,7 @@ coap-server edge-api version-control + script diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/usagestats/DefaultTbApiUsageClient.java b/common/queue/src/main/java/org/thingsboard/server/queue/usagestats/DefaultTbApiUsageReportClient.java similarity index 95% rename from common/queue/src/main/java/org/thingsboard/server/queue/usagestats/DefaultTbApiUsageClient.java rename to common/queue/src/main/java/org/thingsboard/server/queue/usagestats/DefaultTbApiUsageReportClient.java index 11f01cba2b..bc6d562c69 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/usagestats/DefaultTbApiUsageClient.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/usagestats/DefaultTbApiUsageReportClient.java @@ -17,9 +17,7 @@ package org.thingsboard.server.queue.usagestats; import lombok.Data; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.ApiUsageRecordKey; import org.thingsboard.server.common.data.EntityType; @@ -48,7 +46,7 @@ import java.util.concurrent.atomic.AtomicLong; @Component @Slf4j -public class DefaultTbApiUsageClient implements TbApiUsageClient { +public class DefaultTbApiUsageReportClient implements TbApiUsageReportClient { @Value("${usage.stats.report.enabled:true}") private boolean enabled; @@ -64,7 +62,7 @@ public class DefaultTbApiUsageClient implements TbApiUsageClient { private final TbQueueProducerProvider producerProvider; private TbQueueProducer> msgProducer; - public DefaultTbApiUsageClient(PartitionService partitionService, SchedulerComponent scheduler, TbQueueProducerProvider producerProvider) { + public DefaultTbApiUsageReportClient(PartitionService partitionService, SchedulerComponent scheduler, TbQueueProducerProvider producerProvider) { this.partitionService = partitionService; this.scheduler = scheduler; this.producerProvider = producerProvider; diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/usagestats/TbApiUsageClient.java b/common/queue/src/main/java/org/thingsboard/server/queue/usagestats/TbApiUsageReportClient.java similarity index 96% rename from common/queue/src/main/java/org/thingsboard/server/queue/usagestats/TbApiUsageClient.java rename to common/queue/src/main/java/org/thingsboard/server/queue/usagestats/TbApiUsageReportClient.java index 84ca085a7a..57c70ef621 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/usagestats/TbApiUsageClient.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/usagestats/TbApiUsageReportClient.java @@ -19,7 +19,7 @@ import org.thingsboard.server.common.data.ApiUsageRecordKey; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.TenantId; -public interface TbApiUsageClient { +public interface TbApiUsageReportClient { void report(TenantId tenantId, CustomerId customerId, ApiUsageRecordKey key, long value); diff --git a/common/script/pom.xml b/common/script/pom.xml new file mode 100644 index 0000000000..6f445fff76 --- /dev/null +++ b/common/script/pom.xml @@ -0,0 +1,42 @@ + + + 4.0.0 + + org.thingsboard + 3.4.2-SNAPSHOT + common + + org.thingsboard.common + script + pom + + Thingsboard Script Invoke Commons + https://thingsboard.io + + + UTF-8 + ${basedir}/../.. + + + script-api + remote-js-client + + + diff --git a/common/script/remote-js-client/pom.xml b/common/script/remote-js-client/pom.xml new file mode 100644 index 0000000000..3068901013 --- /dev/null +++ b/common/script/remote-js-client/pom.xml @@ -0,0 +1,89 @@ + + + 4.0.0 + + org.thingsboard.common + 3.4.2-SNAPSHOT + script + + org.thingsboard.common.script + remote-js-client + jar + + Thingsboard Server JS Client for remote JS execution + https://thingsboard.io + + + UTF-8 + ${basedir}/../../.. + + + + + org.thingsboard.common + queue + + + org.thingsboard.common.script + script-api + + + org.thingsboard.rule-engine + rule-engine-api + + + org.thingsboard.common + data + + + org.thingsboard.common + message + + + org.springframework.boot + spring-boot-starter-web + provided + + + org.springframework.boot + spring-boot-starter-test + test + + + org.junit.vintage + junit-vintage-engine + test + + + org.awaitility + awaitility + test + + + + + + thingsboard-repo-deploy + ThingsBoard Repo Deployment + https://repo.thingsboard.io/artifactory/libs-release-public + + + + diff --git a/application/src/main/java/org/thingsboard/server/service/script/JsExecutorService.java b/common/script/remote-js-client/src/main/java/org/thingsboard/server/service/script/JsExecutorService.java similarity index 100% rename from application/src/main/java/org/thingsboard/server/service/script/JsExecutorService.java rename to common/script/remote-js-client/src/main/java/org/thingsboard/server/service/script/JsExecutorService.java diff --git a/application/src/main/java/org/thingsboard/server/service/script/RemoteJsInvokeService.java b/common/script/remote-js-client/src/main/java/org/thingsboard/server/service/script/RemoteJsInvokeService.java similarity index 96% rename from application/src/main/java/org/thingsboard/server/service/script/RemoteJsInvokeService.java rename to common/script/remote-js-client/src/main/java/org/thingsboard/server/service/script/RemoteJsInvokeService.java index 86b364afd4..2b6e092e4b 100644 --- a/application/src/main/java/org/thingsboard/server/service/script/RemoteJsInvokeService.java +++ b/common/script/remote-js-client/src/main/java/org/thingsboard/server/service/script/RemoteJsInvokeService.java @@ -27,17 +27,19 @@ import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import org.springframework.util.StopWatch; import org.thingsboard.common.util.ThingsBoardThreadFactory; +import org.thingsboard.script.api.AbstractJsInvokeService; +import org.thingsboard.server.common.stats.TbApiUsageReportClient; +import org.thingsboard.server.common.stats.TbApiUsageStateClient; import org.thingsboard.server.gen.js.JsInvokeProtos; import org.thingsboard.server.queue.TbQueueRequestTemplate; import org.thingsboard.server.queue.common.TbProtoJsQueueMsg; import org.thingsboard.server.queue.common.TbProtoQueueMsg; -import org.thingsboard.server.queue.usagestats.TbApiUsageClient; -import org.thingsboard.server.service.apiusage.TbApiUsageStateService; import javax.annotation.Nullable; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import java.util.Map; +import java.util.Optional; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; @@ -78,8 +80,8 @@ public class RemoteJsInvokeService extends AbstractJsInvokeService { private final ExecutorService callbackExecutor = Executors.newFixedThreadPool( Runtime.getRuntime().availableProcessors(), ThingsBoardThreadFactory.forName("js-executor-remote-callback")); - public RemoteJsInvokeService(TbApiUsageStateService apiUsageStateService, TbApiUsageClient apiUsageClient) { - super(apiUsageStateService, apiUsageClient); + public RemoteJsInvokeService(Optional apiUsageStateClient, Optional apiUsageClient) { + super(apiUsageStateClient, apiUsageClient); } @Scheduled(fixedDelayString = "${js.remote.stats.print_interval_ms}") diff --git a/application/src/main/java/org/thingsboard/server/service/script/RemoteJsRequestEncoder.java b/common/script/remote-js-client/src/main/java/org/thingsboard/server/service/script/RemoteJsRequestEncoder.java similarity index 100% rename from application/src/main/java/org/thingsboard/server/service/script/RemoteJsRequestEncoder.java rename to common/script/remote-js-client/src/main/java/org/thingsboard/server/service/script/RemoteJsRequestEncoder.java diff --git a/application/src/main/java/org/thingsboard/server/service/script/RemoteJsResponseDecoder.java b/common/script/remote-js-client/src/main/java/org/thingsboard/server/service/script/RemoteJsResponseDecoder.java similarity index 100% rename from application/src/main/java/org/thingsboard/server/service/script/RemoteJsResponseDecoder.java rename to common/script/remote-js-client/src/main/java/org/thingsboard/server/service/script/RemoteJsResponseDecoder.java diff --git a/application/src/main/java/org/thingsboard/server/service/script/RuleNodeJsScriptEngine.java b/common/script/remote-js-client/src/main/java/org/thingsboard/server/service/script/RuleNodeJsScriptEngine.java similarity index 98% rename from application/src/main/java/org/thingsboard/server/service/script/RuleNodeJsScriptEngine.java rename to common/script/remote-js-client/src/main/java/org/thingsboard/server/service/script/RuleNodeJsScriptEngine.java index f1374711d5..45d51eb52f 100644 --- a/application/src/main/java/org/thingsboard/server/service/script/RuleNodeJsScriptEngine.java +++ b/common/script/remote-js-client/src/main/java/org/thingsboard/server/service/script/RuleNodeJsScriptEngine.java @@ -22,6 +22,9 @@ import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; import lombok.extern.slf4j.Slf4j; +import org.thingsboard.script.api.JsInvokeService; +import org.thingsboard.script.api.JsScriptType; +import org.thingsboard.script.api.RuleNodeScriptFactory; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.EntityId; diff --git a/common/script/script-api/pom.xml b/common/script/script-api/pom.xml new file mode 100644 index 0000000000..b982c4dfea --- /dev/null +++ b/common/script/script-api/pom.xml @@ -0,0 +1,117 @@ + + + 4.0.0 + + org.thingsboard.common + 3.4.2-SNAPSHOT + script + + org.thingsboard.common.script + script-api + jar + + Thingsboard Server Script invoke API + https://thingsboard.io + + + UTF-8 + ${basedir}/../../.. + + + + + org.thingsboard.common + data + + + org.thingsboard.common + stats + + + org.thingsboard.common + util + + + org.javadelight + delight-nashorn-sandbox + + + com.google.code.gson + gson + + + org.slf4j + slf4j-api + + + org.slf4j + log4j-over-slf4j + + + ch.qos.logback + logback-core + + + ch.qos.logback + logback-classic + + + org.springframework + spring-context + + + com.google.guava + guava + + + org.apache.commons + commons-lang3 + + + org.springframework.boot + spring-boot-starter-web + provided + + + org.springframework.boot + spring-boot-starter-test + test + + + org.junit.vintage + junit-vintage-engine + test + + + org.awaitility + awaitility + test + + + + + + thingsboard-repo-deploy + ThingsBoard Repo Deployment + https://repo.thingsboard.io/artifactory/libs-release-public + + + + diff --git a/application/src/main/java/org/thingsboard/server/service/script/AbstractJsInvokeService.java b/common/script/script-api/src/main/java/org/thingsboard/script/api/AbstractJsInvokeService.java similarity index 89% rename from application/src/main/java/org/thingsboard/server/service/script/AbstractJsInvokeService.java rename to common/script/script-api/src/main/java/org/thingsboard/script/api/AbstractJsInvokeService.java index 0af1f4846b..dfa282e031 100644 --- a/application/src/main/java/org/thingsboard/server/service/script/AbstractJsInvokeService.java +++ b/common/script/script-api/src/main/java/org/thingsboard/script/api/AbstractJsInvokeService.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.service.script; +package org.thingsboard.script.api; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; @@ -25,10 +25,11 @@ 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.queue.usagestats.TbApiUsageClient; -import org.thingsboard.server.service.apiusage.TbApiUsageStateService; +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.Executors; @@ -43,8 +44,8 @@ import static java.lang.String.format; @Slf4j public abstract class AbstractJsInvokeService implements JsInvokeService { - private final TbApiUsageStateService apiUsageStateService; - private final TbApiUsageClient apiUsageClient; + private final Optional apiUsageStateClient; + private final Optional apiUsageReportClient; protected ScheduledExecutorService timeoutExecutorService; protected Map scriptIdToNameMap = new ConcurrentHashMap<>(); protected Map disabledFunctions = new ConcurrentHashMap<>(); @@ -59,9 +60,9 @@ public abstract class AbstractJsInvokeService implements JsInvokeService { @Value("${js.max_script_body_size:50000}") private long maxScriptBodySize; - protected AbstractJsInvokeService(TbApiUsageStateService apiUsageStateService, TbApiUsageClient apiUsageClient) { - this.apiUsageStateService = apiUsageStateService; - this.apiUsageClient = apiUsageClient; + protected AbstractJsInvokeService(Optional apiUsageStateClient, Optional apiUsageReportClient) { + this.apiUsageStateClient = apiUsageStateClient; + this.apiUsageReportClient = apiUsageReportClient; } public void init(long maxRequestsTimeout) { @@ -78,7 +79,7 @@ public abstract class AbstractJsInvokeService implements JsInvokeService { @Override public ListenableFuture eval(TenantId tenantId, JsScriptType scriptType, String scriptBody, String... argNames) { - if (apiUsageStateService.getApiUsageState(tenantId).isJsExecEnabled()) { + if (!apiUsageStateClient.isPresent() || apiUsageStateClient.get().getApiUsageState(tenantId).isJsExecEnabled()) { if (scriptBodySizeExceeded(scriptBody)) { return error(format("Script body exceeds maximum allowed size of %s symbols", getMaxScriptBodySize())); } @@ -93,7 +94,7 @@ public abstract class AbstractJsInvokeService implements JsInvokeService { @Override public ListenableFuture invokeFunction(TenantId tenantId, CustomerId customerId, UUID scriptId, Object... args) { - if (apiUsageStateService.getApiUsageState(tenantId).isJsExecEnabled()) { + if (!apiUsageStateClient.isPresent() || apiUsageStateClient.get().getApiUsageState(tenantId).isJsExecEnabled()) { String functionName = scriptIdToNameMap.get(scriptId); if (functionName == null) { return error("No compiled script found for scriptId: [" + scriptId + "]!"); @@ -102,7 +103,7 @@ public abstract class AbstractJsInvokeService implements JsInvokeService { if (argsSizeExceeded(args)) { return scriptExecutionError(scriptId, format("Script input arguments exceed maximum allowed total args size of %s symbols", getMaxTotalArgsSize())); } - apiUsageClient.report(tenantId, customerId, ApiUsageRecordKey.JS_EXEC_COUNT, 1); + apiUsageReportClient.ifPresent(client -> client.report(tenantId, customerId, ApiUsageRecordKey.JS_EXEC_COUNT, 1)); return Futures.transformAsync(doInvokeFunction(scriptId, functionName, args), output -> { String result = output.toString(); if (resultSizeExceeded(result)) { diff --git a/application/src/main/java/org/thingsboard/server/service/script/AbstractNashornJsInvokeService.java b/common/script/script-api/src/main/java/org/thingsboard/script/api/AbstractNashornJsInvokeService.java similarity index 88% rename from application/src/main/java/org/thingsboard/server/service/script/AbstractNashornJsInvokeService.java rename to common/script/script-api/src/main/java/org/thingsboard/script/api/AbstractNashornJsInvokeService.java index d731ef1536..c3fc51fd79 100644 --- a/application/src/main/java/org/thingsboard/server/service/script/AbstractNashornJsInvokeService.java +++ b/common/script/script-api/src/main/java/org/thingsboard/script/api/AbstractNashornJsInvokeService.java @@ -13,11 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.service.script; +package org.thingsboard.script.api; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.MoreExecutors; import delight.nashornsandbox.NashornSandbox; import delight.nashornsandbox.NashornSandboxes; @@ -26,8 +27,8 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.annotation.Scheduled; import org.thingsboard.common.util.ThingsBoardExecutors; -import org.thingsboard.server.queue.usagestats.TbApiUsageClient; -import org.thingsboard.server.service.apiusage.TbApiUsageStateService; +import org.thingsboard.server.common.stats.TbApiUsageReportClient; +import org.thingsboard.server.common.stats.TbApiUsageStateClient; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; @@ -35,6 +36,7 @@ import javax.script.Invocable; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; +import java.util.Optional; import java.util.UUID; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; @@ -49,6 +51,7 @@ public abstract class AbstractNashornJsInvokeService extends AbstractJsInvokeSer private NashornSandbox sandbox; private ScriptEngine engine; private ExecutorService monitorExecutorService; + private ListeningExecutorService jsExecutor; private final AtomicInteger jsPushedMsgs = new AtomicInteger(0); private final AtomicInteger jsInvokeMsgs = new AtomicInteger(0); @@ -60,18 +63,17 @@ public abstract class AbstractNashornJsInvokeService extends AbstractJsInvokeSer private final ReentrantLock evalLock = new ReentrantLock(); - @Getter - private final JsExecutorService jsExecutor; - @Value("${js.local.max_requests_timeout:0}") private long maxRequestsTimeout; @Value("${js.local.stats.enabled:false}") private boolean statsEnabled; - public AbstractNashornJsInvokeService(TbApiUsageStateService apiUsageStateService, TbApiUsageClient apiUsageClient, JsExecutorService jsExecutor) { - super(apiUsageStateService, apiUsageClient); - this.jsExecutor = jsExecutor; + @Value("${js.local.js_thread_pool_size:50}") + private int jsExecutorThreadPoolSize; + + public AbstractNashornJsInvokeService(Optional apiUsageStateClient, Optional apiUsageReportClient) { + super(apiUsageStateClient, apiUsageReportClient); } @Scheduled(fixedDelayString = "${js.local.stats.print_interval_ms:10000}") @@ -92,6 +94,7 @@ public abstract class AbstractNashornJsInvokeService extends AbstractJsInvokeSer @PostConstruct public void init() { super.init(maxRequestsTimeout); + jsExecutor = MoreExecutors.listeningDecorator(Executors.newWorkStealingPool(jsExecutorThreadPoolSize)); if (useJsSandbox()) { sandbox = NashornSandboxes.create(); monitorExecutorService = ThingsBoardExecutors.newWorkStealingPool(getMonitorThreadPoolSize(), "nashorn-js-monitor"); @@ -123,7 +126,7 @@ public abstract class AbstractNashornJsInvokeService extends AbstractJsInvokeSer @Override protected ListenableFuture doEval(UUID scriptId, String functionName, String jsScript) { jsPushedMsgs.incrementAndGet(); - ListenableFuture result = jsExecutor.executeAsync(() -> { + ListenableFuture result = jsExecutor.submit(() -> { try { evalLock.lock(); try { @@ -152,7 +155,7 @@ public abstract class AbstractNashornJsInvokeService extends AbstractJsInvokeSer @Override protected ListenableFuture doInvokeFunction(UUID scriptId, String functionName, Object[] args) { jsPushedMsgs.incrementAndGet(); - ListenableFuture result = jsExecutor.executeAsync(() -> { + ListenableFuture result = jsExecutor.submit(() -> { try { if (useJsSandbox()) { return sandbox.getSandboxedInvocable().invokeFunction(functionName, args); diff --git a/application/src/main/java/org/thingsboard/server/service/script/JsInvokeService.java b/common/script/script-api/src/main/java/org/thingsboard/script/api/JsInvokeService.java similarity index 96% rename from application/src/main/java/org/thingsboard/server/service/script/JsInvokeService.java rename to common/script/script-api/src/main/java/org/thingsboard/script/api/JsInvokeService.java index f9af2f83e4..6f0d48823e 100644 --- a/application/src/main/java/org/thingsboard/server/service/script/JsInvokeService.java +++ b/common/script/script-api/src/main/java/org/thingsboard/script/api/JsInvokeService.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.service.script; +package org.thingsboard.script.api; import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.server.common.data.id.CustomerId; diff --git a/application/src/main/java/org/thingsboard/server/service/script/JsScriptType.java b/common/script/script-api/src/main/java/org/thingsboard/script/api/JsScriptType.java similarity index 93% rename from application/src/main/java/org/thingsboard/server/service/script/JsScriptType.java rename to common/script/script-api/src/main/java/org/thingsboard/script/api/JsScriptType.java index ee4b0c4c41..d202016d2a 100644 --- a/application/src/main/java/org/thingsboard/server/service/script/JsScriptType.java +++ b/common/script/script-api/src/main/java/org/thingsboard/script/api/JsScriptType.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.service.script; +package org.thingsboard.script.api; public enum JsScriptType { RULE_NODE_SCRIPT diff --git a/application/src/main/java/org/thingsboard/server/service/script/JsStatCallback.java b/common/script/script-api/src/main/java/org/thingsboard/script/api/JsStatCallback.java similarity index 96% rename from application/src/main/java/org/thingsboard/server/service/script/JsStatCallback.java rename to common/script/script-api/src/main/java/org/thingsboard/script/api/JsStatCallback.java index 75caa0511e..dffd8c0fce 100644 --- a/application/src/main/java/org/thingsboard/server/service/script/JsStatCallback.java +++ b/common/script/script-api/src/main/java/org/thingsboard/script/api/JsStatCallback.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.service.script; +package org.thingsboard.script.api; import com.google.common.util.concurrent.FutureCallback; import lombok.AllArgsConstructor; diff --git a/application/src/main/java/org/thingsboard/server/service/script/NashornJsInvokeService.java b/common/script/script-api/src/main/java/org/thingsboard/script/api/NashornJsInvokeService.java similarity index 81% rename from application/src/main/java/org/thingsboard/server/service/script/NashornJsInvokeService.java rename to common/script/script-api/src/main/java/org/thingsboard/script/api/NashornJsInvokeService.java index 4b9e5dea57..f7f91eed08 100644 --- a/application/src/main/java/org/thingsboard/server/service/script/NashornJsInvokeService.java +++ b/common/script/script-api/src/main/java/org/thingsboard/script/api/NashornJsInvokeService.java @@ -13,16 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.service.script; +package org.thingsboard.script.api; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; -import org.thingsboard.server.queue.usagestats.TbApiUsageClient; -import org.thingsboard.server.service.apiusage.TbApiUsageStateService; +import org.thingsboard.server.common.stats.TbApiUsageReportClient; +import org.thingsboard.server.common.stats.TbApiUsageStateClient; +import java.util.Optional; import java.util.concurrent.TimeUnit; @Slf4j @@ -48,8 +49,8 @@ public class NashornJsInvokeService extends AbstractNashornJsInvokeService { @Value("${js.local.max_black_list_duration_sec:60}") private int maxBlackListDurationSec; - public NashornJsInvokeService(TbApiUsageStateService apiUsageStateService, TbApiUsageClient apiUsageClient, JsExecutorService jsExecutor) { - super(apiUsageStateService, apiUsageClient, jsExecutor); + public NashornJsInvokeService(Optional apiUsageStateClient, Optional apiUsageReportClient) { + super(apiUsageStateClient, apiUsageReportClient); } @Override diff --git a/application/src/main/java/org/thingsboard/server/service/script/RuleNodeScriptFactory.java b/common/script/script-api/src/main/java/org/thingsboard/script/api/RuleNodeScriptFactory.java similarity index 97% rename from application/src/main/java/org/thingsboard/server/service/script/RuleNodeScriptFactory.java rename to common/script/script-api/src/main/java/org/thingsboard/script/api/RuleNodeScriptFactory.java index 9aab3dde63..c92ef7c16a 100644 --- a/application/src/main/java/org/thingsboard/server/service/script/RuleNodeScriptFactory.java +++ b/common/script/script-api/src/main/java/org/thingsboard/script/api/RuleNodeScriptFactory.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.service.script; +package org.thingsboard.script.api; public class RuleNodeScriptFactory { diff --git a/application/src/main/java/org/thingsboard/server/service/script/JsInvokeResponse.java b/common/stats/src/main/java/org/thingsboard/server/common/stats/TbApiUsageReportClient.java similarity index 58% rename from application/src/main/java/org/thingsboard/server/service/script/JsInvokeResponse.java rename to common/stats/src/main/java/org/thingsboard/server/common/stats/TbApiUsageReportClient.java index 020c4a3a02..60c03c0f68 100644 --- a/application/src/main/java/org/thingsboard/server/service/script/JsInvokeResponse.java +++ b/common/stats/src/main/java/org/thingsboard/server/common/stats/TbApiUsageReportClient.java @@ -13,17 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.service.script; +package org.thingsboard.server.common.stats; -import java.util.List; +import org.thingsboard.server.common.data.ApiUsageRecordKey; +import org.thingsboard.server.common.data.id.CustomerId; +import org.thingsboard.server.common.data.id.TenantId; -/** - * Created by ashvayka on 25.09.18. - */ -public class JsInvokeResponse { +public interface TbApiUsageReportClient { - private String scriptId; - private String scriptBody; - private List args; + void report(TenantId tenantId, CustomerId customerId, ApiUsageRecordKey key, long value); + + void report(TenantId tenantId, CustomerId customerId, ApiUsageRecordKey key); } diff --git a/application/src/main/java/org/thingsboard/server/service/script/JsInvokeRequest.java b/common/stats/src/main/java/org/thingsboard/server/common/stats/TbApiUsageStateClient.java similarity index 71% rename from application/src/main/java/org/thingsboard/server/service/script/JsInvokeRequest.java rename to common/stats/src/main/java/org/thingsboard/server/common/stats/TbApiUsageStateClient.java index 92166e2ac7..04e2cd277b 100644 --- a/application/src/main/java/org/thingsboard/server/service/script/JsInvokeRequest.java +++ b/common/stats/src/main/java/org/thingsboard/server/common/stats/TbApiUsageStateClient.java @@ -13,17 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.service.script; +package org.thingsboard.server.common.stats; -import java.util.List; +import org.thingsboard.server.common.data.ApiUsageState; +import org.thingsboard.server.common.data.id.TenantId; -/** - * Created by ashvayka on 25.09.18. - */ -public class JsInvokeRequest { +public interface TbApiUsageStateClient { - private String scriptId; - private String scriptBody; - private List args; + ApiUsageState getApiUsageState(TenantId tenantId); } diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java index 8b532ae92e..1d7f296444 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java @@ -94,7 +94,7 @@ import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; import org.thingsboard.server.queue.provider.TbQueueProducerProvider; import org.thingsboard.server.queue.provider.TbTransportQueueFactory; import org.thingsboard.server.queue.scheduler.SchedulerComponent; -import org.thingsboard.server.queue.usagestats.TbApiUsageClient; +import org.thingsboard.server.queue.usagestats.TbApiUsageReportClient; import org.thingsboard.server.queue.util.AfterStartUp; import org.thingsboard.server.queue.util.TbTransportComponent; @@ -157,7 +157,7 @@ public class DefaultTransportService implements TransportService { @Autowired @Lazy - private TbApiUsageClient apiUsageClient; + private TbApiUsageReportClient apiUsageClient; private final Map statsMap = new LinkedHashMap<>(); private final Gson gson = new Gson(); diff --git a/pom.xml b/pom.xml index 1c5dea9f5c..d9b97f1182 100755 --- a/pom.xml +++ b/pom.xml @@ -969,6 +969,16 @@ coap-server ${project.version} + + org.thingsboard.common.script + script-api + ${project.version} + + + org.thingsboard.common.script + remote-js-client + ${project.version} + org.thingsboard tools