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
+
+ org.thingsboard.common.script
+ script-api
+ ${project.version}
+
+
+ org.thingsboard.common.script
+ remote-js-client
+ ${project.version}
+
org.thingsboard
tools