summaryrefslogtreecommitdiffstats
path: root/plugins/plugins-executor/plugins-executor-javascript/src/main
diff options
context:
space:
mode:
authorhuaxing <huaxing.jin@est.tech>2020-06-17 13:34:10 +0800
committerLiam Fallon <liam.fallon@est.tech>2020-06-23 13:23:02 +0000
commitdb73a6835f176150be8c770f1342d7426a6169fc (patch)
tree84ff24d91ffd2b086bfd44c5cd88e21ae9b3915b /plugins/plugins-executor/plugins-executor-javascript/src/main
parent9f9f0dd271e412779c239fc941ed2424112f3459 (diff)
Remove thread in JavascriptExecutor
This change is basically a rollback of https://gerrit.onap.org/r/c/policy/apex-pdp/+/104230, with minor refactoring. The problem that 104230 tried to address was supposed to be caused by https://jira.onap.org/browse/POLICY-2463. With this rollback, apex-pdp increases performance and reduces memory usage. Issue-ID: POLICY-2572 Signed-off-by: huaxing <huaxing.jin@est.tech> Change-Id: I3a52d0ead0c1e530d218f9e3aba8b3eb5558abaf
Diffstat (limited to 'plugins/plugins-executor/plugins-executor-javascript/src/main')
-rw-r--r--plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptExecutor.java262
-rw-r--r--plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptStateFinalizerExecutor.java23
-rw-r--r--plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskExecutor.java28
-rw-r--r--plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskSelectExecutor.java25
4 files changed, 50 insertions, 288 deletions
diff --git a/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptExecutor.java b/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptExecutor.java
index 0eecd5d4b..344f8c5ae 100644
--- a/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptExecutor.java
+++ b/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptExecutor.java
@@ -20,288 +20,88 @@
package org.onap.policy.apex.plugins.executor.javascript;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicReference;
-import lombok.AccessLevel;
-import lombok.Getter;
-import lombok.NonNull;
-import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Script;
import org.mozilla.javascript.Scriptable;
import org.onap.policy.apex.core.engine.executor.exception.StateMachineException;
import org.onap.policy.apex.model.basicmodel.concepts.AxKey;
-import org.slf4j.ext.XLogger;
-import org.slf4j.ext.XLoggerFactory;
/**
* The Class JavascriptExecutor is the executor for task logic written in Javascript.
*
* @author Liam Fallon (liam.fallon@ericsson.com)
*/
-public class JavascriptExecutor implements Runnable {
- private static final XLogger LOGGER = XLoggerFactory.getXLogger(JavascriptExecutor.class);
-
+public class JavascriptExecutor {
public static final int DEFAULT_OPTIMIZATION_LEVEL = 9;
- // Token passed to executor thread to stop execution
- private static final Object STOP_EXECUTION_TOKEN = "*** STOP EXECUTION ***";
-
// Recurring string constants
private static final String WITH_MESSAGE = " with message: ";
- private static final String JAVASCRIPT_EXECUTOR = "JavascriptExecutor ";
- private static final String EXECUTION_FAILED_EXECUTOR = "execution failed, executor ";
-
- @Setter(AccessLevel.PROTECTED)
- private static TimeUnit timeunit4Latches = TimeUnit.SECONDS;
- @Setter(AccessLevel.PROTECTED)
- private static int intializationLatchTimeout = 60;
- @Setter(AccessLevel.PROTECTED)
- private static int cleanupLatchTimeout = 60;
// The key of the subject that wants to execute Javascript code
- final AxKey subjectKey;
+ private final AxKey subjectKey;
- private String javascriptCode;
- private Context javascriptContext;
- private Script script;
-
- private final BlockingQueue<Object> executionQueue = new LinkedBlockingQueue<>();
- private final BlockingQueue<Boolean> resultQueue = new LinkedBlockingQueue<>();
-
- @Getter(AccessLevel.PROTECTED)
- private Thread executorThread;
- private CountDownLatch intializationLatch;
- private CountDownLatch cleanupLatch;
- private AtomicReference<StateMachineException> executorException = new AtomicReference<>(null);
+ private final Script script;
/**
* Initializes the Javascript executor.
*
* @param subjectKey the key of the subject that is requesting Javascript execution
- */
- public JavascriptExecutor(final AxKey subjectKey) {
- this.subjectKey = subjectKey;
- }
-
- /**
- * Prepares the executor for processing and compiles the Javascript code.
- *
* @param javascriptCode the Javascript code to execute
- * @throws StateMachineException thrown when instantiation of the executor fails
*/
- public synchronized void init(@NonNull final String javascriptCode) throws StateMachineException {
- LOGGER.debug("JavascriptExecutor {} starting ... ", subjectKey.getId());
-
- if (executorThread != null) {
- throw new StateMachineException("initiation failed, executor " + subjectKey.getId()
- + " already initialized, run cleanUp to clear executor");
- }
-
+ public JavascriptExecutor(final AxKey subjectKey, String javascriptCode) throws StateMachineException {
if (StringUtils.isBlank(javascriptCode)) {
- throw new StateMachineException("initiation failed, no logic specified for executor " + subjectKey.getId());
- }
-
- this.javascriptCode = javascriptCode;
-
- executorThread = new Thread(this);
- executorThread.setName(this.getClass().getSimpleName() + ":" + subjectKey.getId());
- intializationLatch = new CountDownLatch(1);
- cleanupLatch = new CountDownLatch(1);
-
- try {
- executorThread.start();
- } catch (IllegalThreadStateException e) {
- throw new StateMachineException("initiation failed, executor " + subjectKey.getId() + " failed to start",
- e);
- }
-
- try {
- if (!intializationLatch.await(intializationLatchTimeout, timeunit4Latches)) {
- executorThread.interrupt();
- throw new StateMachineException(JAVASCRIPT_EXECUTOR + subjectKey.getId()
- + " initiation timed out after " + intializationLatchTimeout + " " + timeunit4Latches);
- }
- } catch (InterruptedException e) {
- LOGGER.debug("JavascriptExecutor {} interrupted on execution thread startup", subjectKey.getId(), e);
- Thread.currentThread().interrupt();
- }
-
- if (executorException.get() != null) {
- executorThread.interrupt();
- checkAndThrowExecutorException();
- }
-
- checkAndThrowExecutorException();
-
- LOGGER.debug("JavascriptExecutor {} started ... ", subjectKey.getId());
- }
-
- /**
- * Execute a Javascript script.
- *
- * @param executionContext the execution context to use for script execution
- * @return true if execution was successful, false otherwise
- * @throws StateMachineException on execution errors
- */
- public synchronized boolean execute(final Object executionContext) throws StateMachineException {
- if (executorThread == null) {
- throw new StateMachineException(EXECUTION_FAILED_EXECUTOR + subjectKey.getId() + " is not initialized");
+ throw new StateMachineException("no logic specified for " + subjectKey.getId());
}
-
- if (!executorThread.isAlive() || executorThread.isInterrupted()) {
- throw new StateMachineException(EXECUTION_FAILED_EXECUTOR + subjectKey.getId()
- + " is not running, run cleanUp to clear executor and init to restart executor");
- }
-
- executionQueue.add(executionContext);
-
- boolean result = false;
-
- try {
- result = resultQueue.take();
- } catch (final InterruptedException e) {
- executorThread.interrupt();
- Thread.currentThread().interrupt();
- throw new StateMachineException(
- JAVASCRIPT_EXECUTOR + subjectKey.getId() + "interrupted on execution result wait", e);
- }
-
- checkAndThrowExecutorException();
-
- return result;
+ this.subjectKey = subjectKey;
+ this.script = compile(subjectKey.getId(), javascriptCode);
}
/**
- * Cleans up the executor after processing.
+ * Executes the Javascript code.
*
- * @throws StateMachineException thrown when cleanup of the executor fails
+ * @param executionContext the execution context of the subject to be passed to the Javascript context
+ * @return true if the Javascript executed properly
+ * @throws StateMachineException thrown when Javascript execution fails
*/
- public synchronized void cleanUp() throws StateMachineException {
- if (executorThread == null) {
- throw new StateMachineException("cleanup failed, executor " + subjectKey.getId() + " is not initialized");
- }
-
- if (executorThread.isAlive()) {
- executionQueue.add(STOP_EXECUTION_TOKEN);
-
- try {
- if (!cleanupLatch.await(cleanupLatchTimeout, timeunit4Latches)) {
- executorException.set(new StateMachineException(JAVASCRIPT_EXECUTOR + subjectKey.getId()
- + " cleanup timed out after " + cleanupLatchTimeout + " " + timeunit4Latches));
- }
- } catch (InterruptedException e) {
- LOGGER.debug("JavascriptExecutor {} interrupted on execution cleanup wait", subjectKey.getId(), e);
- Thread.currentThread().interrupt();
- }
- }
-
- executorThread = null;
- executionQueue.clear();
- resultQueue.clear();
-
- checkAndThrowExecutorException();
- }
-
- @Override
- public void run() {
- LOGGER.debug("JavascriptExecutor {} initializing ... ", subjectKey.getId());
-
- try {
- initExecutor();
- } catch (StateMachineException sme) {
- LOGGER.warn("JavascriptExecutor {} initialization failed", subjectKey.getId(), sme);
- executorException.set(sme);
- intializationLatch.countDown();
- cleanupLatch.countDown();
- return;
- }
-
- intializationLatch.countDown();
-
- LOGGER.debug("JavascriptExecutor {} executing ... ", subjectKey.getId());
-
- // Take jobs from the execution queue of the worker and execute them
- while (!Thread.currentThread().isInterrupted()) {
- try {
- Object contextObject = executionQueue.take();
- if (STOP_EXECUTION_TOKEN.equals(contextObject)) {
- LOGGER.debug("execution close was ordered for " + subjectKey.getId());
- break;
- }
- resultQueue.add(executeScript(contextObject));
- } catch (final InterruptedException e) {
- LOGGER.debug("execution was interruped for " + subjectKey.getId() + WITH_MESSAGE + e.getMessage(), e);
- executionQueue.add(STOP_EXECUTION_TOKEN);
- Thread.currentThread().interrupt();
- } catch (StateMachineException sme) {
- executorException.set(sme);
- resultQueue.add(false);
- }
- }
-
- resultQueue.add(false);
-
- try {
- Context.exit();
- } catch (final Exception e) {
- executorException.set(new StateMachineException(
- "executor close failed to close for " + subjectKey.getId() + WITH_MESSAGE + e.getMessage(), e));
- }
-
- cleanupLatch.countDown();
-
- LOGGER.debug("JavascriptExecutor {} completed processing", subjectKey.getId());
- }
-
- private void initExecutor() throws StateMachineException {
- try {
- // Create a Javascript context for this thread
- javascriptContext = Context.enter();
-
- // Set up the default values of the context
- javascriptContext.setOptimizationLevel(DEFAULT_OPTIMIZATION_LEVEL);
- javascriptContext.setLanguageVersion(Context.VERSION_1_8);
-
- script = javascriptContext.compileString(javascriptCode, subjectKey.getId(), 1, null);
- } catch (Exception e) {
- Context.exit();
- throw new StateMachineException(
- "logic failed to compile for " + subjectKey.getId() + WITH_MESSAGE + e.getMessage(), e);
- }
- }
-
- private boolean executeScript(final Object executionContext) throws StateMachineException {
+ public boolean execute(final Object executionContext) throws StateMachineException {
Object returnObject = null;
+ Context context = Context.enter();
try {
// Pass the subject context to the Javascript engine
- Scriptable javascriptScope = javascriptContext.initStandardObjects();
+ Scriptable javascriptScope = context.initStandardObjects();
javascriptScope.put("executor", javascriptScope, executionContext);
// Run the script
- returnObject = script.exec(javascriptContext, javascriptScope);
+ returnObject = script.exec(context, javascriptScope);
} catch (final Exception e) {
throw new StateMachineException(
- "logic failed to run for " + subjectKey.getId() + WITH_MESSAGE + e.getMessage(), e);
+ "logic failed to run for " + subjectKey.getId() + WITH_MESSAGE + e.getMessage(), e);
+ } finally {
+ Context.exit();
}
if (!(returnObject instanceof Boolean)) {
throw new StateMachineException(
- "execute: logic for " + subjectKey.getId() + " returned a non-boolean value " + returnObject);
+ "execute: logic for " + subjectKey.getId() + " returned a non-boolean value " + returnObject);
}
return (boolean) returnObject;
}
- private void checkAndThrowExecutorException() throws StateMachineException {
- StateMachineException exceptionToThrow = executorException.getAndSet(null);
- if (exceptionToThrow != null) {
- throw exceptionToThrow;
+ private Script compile(String id, String javascriptCode) throws StateMachineException {
+ Context context = Context.enter();
+ try {
+ // Set up the default values of the context
+ context.setOptimizationLevel(DEFAULT_OPTIMIZATION_LEVEL);
+ context.setLanguageVersion(Context.VERSION_1_8);
+ return context.compileString(javascriptCode, id, 1, null);
+ } catch (Exception e) {
+ throw new StateMachineException(
+ "logic failed to compile for " + id + WITH_MESSAGE + e.getMessage(), e);
+ } finally {
+ Context.exit();
}
}
}
diff --git a/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptStateFinalizerExecutor.java b/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptStateFinalizerExecutor.java
index ffd09259b..24c6b768a 100644
--- a/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptStateFinalizerExecutor.java
+++ b/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptStateFinalizerExecutor.java
@@ -52,12 +52,7 @@ public class JavascriptStateFinalizerExecutor extends StateFinalizerExecutor {
super.prepare();
// Create the executor
- if (javascriptExecutor == null) {
- javascriptExecutor = new JavascriptExecutor(getSubject().getKey());
- }
-
- // Initialize and cleanup the executor to check the Javascript code
- javascriptExecutor.init(getSubject().getLogic());
+ javascriptExecutor = new JavascriptExecutor(getSubject().getKey(), getSubject().getLogic());
}
/**
@@ -72,16 +67,10 @@ public class JavascriptStateFinalizerExecutor extends StateFinalizerExecutor {
*/
@Override
public String execute(final long executionId, final Properties executionProperties,
- final Map<String, Object> incomingFields) throws StateMachineException, ContextException {
- // Do execution pre work
+ final Map<String, Object> incomingFields) throws StateMachineException, ContextException {
executePre(executionId, executionProperties, incomingFields);
-
- // Execute the Javascript executor
boolean result = javascriptExecutor.execute(getExecutionContext());
-
- // Execute the Javascript
executePost(result);
-
return getOutgoing();
}
@@ -92,9 +81,9 @@ public class JavascriptStateFinalizerExecutor extends StateFinalizerExecutor {
*/
@Override
public void cleanUp() throws StateMachineException {
- LOGGER.debug("cleanUp:" + getSubject().getKey().getId() + "," + getSubject().getLogicFlavour() + ","
- + getSubject().getLogic());
-
- javascriptExecutor.cleanUp();
+ LOGGER.debug("cleanUp:{},{},{}",
+ getSubject().getKey().getId(),
+ getSubject().getLogicFlavour(),
+ getSubject().getLogic());
}
}
diff --git a/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskExecutor.java b/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskExecutor.java
index 9f30f839f..a25dca0c6 100644
--- a/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskExecutor.java
+++ b/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskExecutor.java
@@ -52,12 +52,7 @@ public class JavascriptTaskExecutor extends TaskExecutor {
super.prepare();
// Create the executor
- if (javascriptExecutor == null) {
- javascriptExecutor = new JavascriptExecutor(getSubject().getKey());
- }
-
- // Initialize and cleanup the executor to check the Javascript code
- javascriptExecutor.init(getSubject().getTaskLogic().getLogic());
+ javascriptExecutor = new JavascriptExecutor(getSubject().getKey(), getSubject().getTaskLogic().getLogic());
}
/**
@@ -72,17 +67,10 @@ public class JavascriptTaskExecutor extends TaskExecutor {
*/
@Override
public Map<String, Object> execute(final long executionId, final Properties executionProperties,
- final Map<String, Object> incomingFields) throws StateMachineException, ContextException {
-
- // Do execution pre work
+ final Map<String, Object> incomingFields) throws StateMachineException, ContextException {
executePre(executionId, executionProperties, incomingFields);
-
- // Execute the Javascript executor
boolean result = javascriptExecutor.execute(getExecutionContext());
-
- // Execute the Javascript
executePost(result);
-
return getOutgoing();
}
@@ -93,13 +81,9 @@ public class JavascriptTaskExecutor extends TaskExecutor {
*/
@Override
public void cleanUp() throws StateMachineException {
- LOGGER.debug("cleanUp:" + getSubject().getKey().getId() + "," + getSubject().getTaskLogic().getLogicFlavour()
- + "," + getSubject().getTaskLogic().getLogic());
-
- if (javascriptExecutor != null) {
- javascriptExecutor.cleanUp();
- }
-
- javascriptExecutor = null;
+ LOGGER.debug("cleanUp:{},{},{}",
+ getSubject().getKey().getId(),
+ getSubject().getTaskLogic().getLogicFlavour(),
+ getSubject().getTaskLogic().getLogic());
}
}
diff --git a/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskSelectExecutor.java b/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskSelectExecutor.java
index d7b137f2e..5c28999b5 100644
--- a/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskSelectExecutor.java
+++ b/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskSelectExecutor.java
@@ -53,12 +53,8 @@ public class JavascriptTaskSelectExecutor extends TaskSelectExecutor {
super.prepare();
// Create the executor
- if (javascriptExecutor == null) {
- javascriptExecutor = new JavascriptExecutor(getSubject().getKey());
- }
-
- // Initialize and cleanup the executor to check the Javascript code
- javascriptExecutor.init(getSubject().getTaskSelectionLogic().getLogic());
+ javascriptExecutor = new JavascriptExecutor(getSubject().getKey(),
+ getSubject().getTaskSelectionLogic().getLogic());
}
/**
@@ -73,16 +69,10 @@ public class JavascriptTaskSelectExecutor extends TaskSelectExecutor {
*/
@Override
public AxArtifactKey execute(final long executionId, final Properties executionProperties,
- final EnEvent incomingEvent) throws StateMachineException, ContextException {
- // Do execution pre work
+ final EnEvent incomingEvent) throws StateMachineException, ContextException {
executePre(executionId, executionProperties, incomingEvent);
-
- // Execute the Javascript executor
boolean result = javascriptExecutor.execute(getExecutionContext());
-
- // Execute the Javascript
executePost(result);
-
return getOutgoing();
}
@@ -93,10 +83,9 @@ public class JavascriptTaskSelectExecutor extends TaskSelectExecutor {
*/
@Override
public void cleanUp() throws StateMachineException {
- LOGGER.debug(
- "cleanUp:" + getSubject().getKey().getId() + "," + getSubject().getTaskSelectionLogic().getLogicFlavour()
- + "," + getSubject().getTaskSelectionLogic().getLogic());
-
- javascriptExecutor.cleanUp();
+ LOGGER.debug("cleanUp:{},{},{}",
+ getSubject().getKey().getId(),
+ getSubject().getTaskSelectionLogic().getLogicFlavour(),
+ getSubject().getTaskSelectionLogic().getLogic());
}
}