use of org.apache.apex.malhar.python.base.requestresponse.PythonRequestResponse in project apex-malhar by apache.
the class InterpreterThread method processCommand.
/**
* Responsible for polling the request queue and formatting the request payload to make it compatible to the
* individual processing logic of the functionalities provided by the interpreter API methods.
* @param <T> Java templating signature enforcement
* @throws ApexPythonInterpreterException if an unrecognized command is issued.
* @throws InterruptedException if interrupted while trying to wait for a request from request queue
*/
private <T> void processCommand() throws ApexPythonInterpreterException, InterruptedException {
PythonRequestResponse requestResponseHandle = requestQueue.poll(timeOutToPollFromRequestQueue, timeUnitsToPollFromRequestQueue);
if (requestResponseHandle != null) {
LOG.debug("Processing command " + requestResponseHandle.getPythonInterpreterRequest().getCommandType());
busyFlag = true;
if (errorEncountered) {
LOG.debug("Error state detected from a previous command. Resetting state to the previous" + " state of the error");
try {
JEP_INSTANCE.eval(null);
errorEncountered = false;
} catch (JepException e) {
LOG.error("Error while trying to clear the state of the interpreter due to previous command" + " " + e.getMessage(), e);
}
}
PythonInterpreterRequest<T> request = requestResponseHandle.getPythonInterpreterRequest();
PythonInterpreterResponse<T> response = requestResponseHandle.getPythonInterpreterResponse();
Map<String, Boolean> commandStatus = new HashMap<>(1);
switch(request.getCommandType()) {
case EVAL_COMMAND:
EvalCommandRequestPayload evalPayload = request.getEvalCommandRequestPayload();
T responseVal = eval(evalPayload.getEvalCommand(), evalPayload.getVariableNameToExtractInEvalCall(), evalPayload.getParamsForEvalCommand(), evalPayload.isDeleteVariableAfterEvalCall(), request.getExpectedReturnType());
response.setResponse(responseVal);
if (responseVal != null) {
commandStatus.put(evalPayload.getEvalCommand(), Boolean.TRUE);
} else {
commandStatus.put(evalPayload.getEvalCommand(), Boolean.FALSE);
}
response.setCommandStatus(commandStatus);
break;
case SCRIPT_COMMAND:
ScriptExecutionRequestPayload scriptPayload = request.getScriptExecutionRequestPayload();
if (executeScript(scriptPayload.getScriptName())) {
commandStatus.put(scriptPayload.getScriptName(), Boolean.TRUE);
} else {
commandStatus.put(scriptPayload.getScriptName(), Boolean.FALSE);
}
response.setCommandStatus(commandStatus);
break;
case METHOD_INVOCATION_COMMAND:
MethodCallRequestPayload requestpayload = request.getMethodCallRequest();
response.setResponse(executeMethodCall(requestpayload.getNameOfMethod(), requestpayload.getArgs(), request.getExpectedReturnType()));
if (response.getResponse() == null) {
commandStatus.put(requestpayload.getNameOfMethod(), Boolean.FALSE);
} else {
commandStatus.put(requestpayload.getNameOfMethod(), Boolean.TRUE);
}
response.setCommandStatus(commandStatus);
break;
case GENERIC_COMMANDS:
response.setCommandStatus(runCommands(request.getGenericCommandsRequestPayload().getGenericCommands()));
break;
default:
throw new ApexPythonInterpreterException(new Exception("Unspecified Interpreter command"));
}
requestResponseHandle.setRequestCompletionTime(System.currentTimeMillis());
responseQueue.put(requestResponseHandle);
LOG.debug("Submitted the response and executed " + response.getCommandStatus().size() + " instances of command");
}
busyFlag = false;
}
use of org.apache.apex.malhar.python.base.requestresponse.PythonRequestResponse in project apex-malhar by apache.
the class JepPythonEngine method executeMethodCall.
/**
* See {@link ApexPythonEngine#executeMethodCall(WorkerExecutionMode, long, long, PythonInterpreterRequest)} for more
* details. Note that if the worker execution mode {@link WorkerExecutionMode} is BROADCAST, then the time SLA
* set is the total time for all workers i.e. each worker is given a ( total time / N ) where N is the current
* number of worker threads
*
* @param executionMode If the method call needs to be invoked on all workers or any single worker
* @param windowId used to select the worker from the worker pool.Can be any long if an operator is not using this.
* @param requestId used to select the worker from the worker pool. Can be any long if an operator is not using this.
* @param req Represents the request to be processed.
* @param <T>
* @return
* @throws ApexPythonInterpreterException
*/
@Override
public <T> Map<String, PythonRequestResponse<T>> executeMethodCall(WorkerExecutionMode executionMode, long windowId, long requestId, PythonInterpreterRequest<T> req) throws ApexPythonInterpreterException {
checkNotNullConditions(req);
checkNotNull(req.getMethodCallRequest(), "Method call info not set");
checkNotNull(req.getMethodCallRequest().getNameOfMethod(), "Method name not set");
Map<String, PythonRequestResponse<T>> returnStatus = new HashMap<>();
req.setCommandType(PythonCommandType.METHOD_INVOCATION_COMMAND);
PythonRequestResponse lastSuccessfullySubmittedRequest = null;
try {
if (executionMode.equals(WorkerExecutionMode.BROADCAST)) {
long timeOutPerWorker = TimeUnit.NANOSECONDS.convert(req.getTimeout(), req.getTimeUnit()) / numWorkerThreads;
if (timeOutPerWorker == 0) {
timeOutPerWorker = 1;
}
req.setTimeout(timeOutPerWorker);
req.setTimeUnit(TimeUnit.NANOSECONDS);
for (InterpreterWrapper wrapper : workers) {
lastSuccessfullySubmittedRequest = wrapper.executeMethodCall(windowId, requestId, req);
if (lastSuccessfullySubmittedRequest != null) {
returnStatus.put(wrapper.getInterpreterId(), lastSuccessfullySubmittedRequest);
}
}
if (returnStatus.size() > 0) {
commandHistory.add(lastSuccessfullySubmittedRequest);
}
} else {
InterpreterWrapper currentThread = null;
if (executionMode.equals(WorkerExecutionMode.ANY)) {
currentThread = selectWorkerForCurrentCall(requestId);
}
if (executionMode.equals(WorkerExecutionMode.STICKY)) {
currentThread = workers.get(req.hashCode() % numWorkerThreads);
LOG.debug(" Choosing sticky worker " + currentThread.getInterpreterId());
}
if (currentThread != null) {
lastSuccessfullySubmittedRequest = currentThread.executeMethodCall(windowId, requestId, req);
if (lastSuccessfullySubmittedRequest != null) {
returnStatus.put(currentThread.getInterpreterId(), lastSuccessfullySubmittedRequest);
} else {
throw new ApexPythonInterpreterException("No free interpreter threads available." + " Consider increasing workers and relaunch");
}
}
}
} catch (InterruptedException e) {
throw new ApexPythonInterpreterException(e);
}
return returnStatus;
}
use of org.apache.apex.malhar.python.base.requestresponse.PythonRequestResponse in project apex-malhar by apache.
the class JepPythonEngine method executeScript.
/**
* See {@link ApexPythonEngine#executeScript(WorkerExecutionMode, long, long, PythonInterpreterRequest)} for more
* details. Note that if the worker execution mode {@link WorkerExecutionMode} is BROADCAST, then the time SLA
* set is the total time for all workers i.e. each worker is given a ( total time / N ) where N is the current
* number of worker threads
* @param executionMode If the method call needs to be invoked on all workers or any single worker
* @param windowId used to select the worker from the worker pool.Can be any long if an operator is not using this.
* @param requestId used to select the worker from the worker pool. Can be any long if an operator is not using this.
* @param req Represents the request to be processed.
* @return
* @throws ApexPythonInterpreterException
*/
@Override
public Map<String, PythonRequestResponse<Void>> executeScript(WorkerExecutionMode executionMode, long windowId, long requestId, PythonInterpreterRequest<Void> req) throws ApexPythonInterpreterException {
checkNotNullConditions(req);
checkNotNull(req.getScriptExecutionRequestPayload(), "Script execution info not set");
checkNotNull(req.getScriptExecutionRequestPayload().getScriptName(), "Script name not set");
Map<String, PythonRequestResponse<Void>> returnStatus = new HashMap<>();
PythonRequestResponse lastSuccessfullySubmittedRequest = null;
try {
if (executionMode.equals(WorkerExecutionMode.BROADCAST)) {
long timeOutPerWorker = TimeUnit.NANOSECONDS.convert(req.getTimeout(), req.getTimeUnit()) / numWorkerThreads;
if (timeOutPerWorker == 0) {
timeOutPerWorker = 1;
}
req.setTimeout(timeOutPerWorker);
req.setTimeUnit(TimeUnit.NANOSECONDS);
for (InterpreterWrapper wrapper : workers) {
lastSuccessfullySubmittedRequest = wrapper.executeScript(windowId, requestId, req);
if (lastSuccessfullySubmittedRequest != null) {
returnStatus.put(wrapper.getInterpreterId(), lastSuccessfullySubmittedRequest);
}
}
if (returnStatus.size() > 0) {
commandHistory.add(lastSuccessfullySubmittedRequest);
}
} else {
InterpreterWrapper currentThread = null;
if (executionMode.equals(WorkerExecutionMode.ANY)) {
currentThread = selectWorkerForCurrentCall(requestId);
}
if (executionMode.equals(WorkerExecutionMode.STICKY)) {
currentThread = workers.get(req.hashCode() % numWorkerThreads);
LOG.debug(" Choosing sticky worker " + currentThread.getInterpreterId());
}
if (currentThread != null) {
lastSuccessfullySubmittedRequest = currentThread.executeScript(windowId, requestId, req);
if (lastSuccessfullySubmittedRequest != null) {
returnStatus.put(currentThread.getInterpreterId(), lastSuccessfullySubmittedRequest);
}
} else {
throw new ApexPythonInterpreterException("No free interpreter threads available." + " Consider increasing workers and relaunch");
}
}
} catch (InterruptedException e) {
throw new ApexPythonInterpreterException(e);
}
return returnStatus;
}
use of org.apache.apex.malhar.python.base.requestresponse.PythonRequestResponse in project apex-malhar by apache.
the class JepPythonEngine method eval.
/**
* See {@link ApexPythonEngine#eval(WorkerExecutionMode, long, long, PythonInterpreterRequest)} for more
* details. Note that if the worker execution mode {@link WorkerExecutionMode} is BROADCAST, then the time SLA
* set is the total time for all workers i.e. each worker is given a ( total time / N ) where N is the current
* number of worker threads
* @param executionMode If the method call needs to be invoked on all workers or any single worker
* @param windowId used to select the worker from the worker pool.Can be any long if an operator is not using this.
* @param requestId used to select the worker from the worker pool. Can be any long if an operator is not using this.
* @param request
* @param <T>
* @return
* @throws ApexPythonInterpreterException
*/
@Override
public <T> Map<String, PythonRequestResponse<T>> eval(WorkerExecutionMode executionMode, long windowId, long requestId, PythonInterpreterRequest<T> request) throws ApexPythonInterpreterException {
checkNotNullConditions(request);
checkNotNull(request.getEvalCommandRequestPayload(), "Eval command info not set");
checkNotNull(request.getEvalCommandRequestPayload().getEvalCommand(), "Eval command not set");
Map<String, PythonRequestResponse<T>> statusOfEval = new HashMap<>();
PythonRequestResponse lastSuccessfullySubmittedRequest = null;
try {
if (executionMode.equals(WorkerExecutionMode.BROADCAST)) {
long timeOutPerWorker = TimeUnit.NANOSECONDS.convert(request.getTimeout(), request.getTimeUnit()) / numWorkerThreads;
if (timeOutPerWorker == 0) {
timeOutPerWorker = 1;
}
request.setTimeout(timeOutPerWorker);
request.setTimeUnit(TimeUnit.NANOSECONDS);
for (InterpreterWrapper wrapper : workers) {
lastSuccessfullySubmittedRequest = wrapper.eval(windowId, requestId, request);
if (lastSuccessfullySubmittedRequest != null) {
statusOfEval.put(wrapper.getInterpreterId(), lastSuccessfullySubmittedRequest);
}
}
commandHistory.add(lastSuccessfullySubmittedRequest);
} else {
InterpreterWrapper currentThread = null;
if (executionMode.equals(WorkerExecutionMode.ANY)) {
currentThread = selectWorkerForCurrentCall(requestId);
}
if (executionMode.equals(WorkerExecutionMode.STICKY)) {
currentThread = workers.get(request.hashCode() % numWorkerThreads);
LOG.debug(" Choosing sticky worker " + currentThread.getInterpreterId());
}
if (currentThread != null) {
lastSuccessfullySubmittedRequest = currentThread.eval(windowId, requestId, request);
if (lastSuccessfullySubmittedRequest != null) {
statusOfEval.put(currentThread.getInterpreterId(), lastSuccessfullySubmittedRequest);
}
} else {
throw new ApexPythonInterpreterException("No free interpreter threads available." + " Consider increasing workers and relaunch");
}
}
} catch (InterruptedException e) {
throw new ApexPythonInterpreterException(e);
}
return statusOfEval;
}
use of org.apache.apex.malhar.python.base.requestresponse.PythonRequestResponse in project apex-malhar by apache.
the class InterpreterWrapper method processRequest.
/**
* Handles the common logic that is common across all methods of invocation of the in-memory interpreter. Some common
* logic includes draining any stragglers, matching the request to the any of the responses that arrive in the
* response queue possibly due to previous requests
* @param requestResponse The wrapper object into which
* @param req The request that contains the timeout SLAs
* @param <T> Java templating signature
* @return A response to the original incoming request, null if the response did not arrive within given SLA.
* @throws InterruptedException if interrupted while waiting for the response queue.
*/
public <T> PythonRequestResponse<T> processRequest(PythonRequestResponse requestResponse, PythonInterpreterRequest<T> req) throws InterruptedException {
List<PythonRequestResponse> drainedResults = new ArrayList<>();
PythonRequestResponse currentRequestWithResponse = null;
boolean isCurrentRequestProcessed = false;
long timeOutInNanos = TimeUnit.NANOSECONDS.convert(req.getTimeout(), req.getTimeUnit());
// drain any previous responses that were returned while the Apex operator is processing
responseQueue.drainTo(drainedResults);
LOG.debug("Draining previous request responses if any " + drainedResults.size());
for (PythonRequestResponse oldRequestResponse : drainedResults) {
delayedResponsesQueue.put(oldRequestResponse);
}
// We first set a timer to see how long it actually it took for the response to arrive.
// It is possible that a response arrived due to a previous request and hence this need for the timer
// which tracks the time for the current request.
long currentStart = System.nanoTime();
long timeLeftToCompleteProcessing = timeOutInNanos;
while ((!isCurrentRequestProcessed) && (timeLeftToCompleteProcessing > 0)) {
LOG.debug("Submitting the interpreter Request with time out in nanos as " + timeOutInNanos);
requestQueue.put(requestResponse);
// ensures we are blocked till the time limit
currentRequestWithResponse = responseQueue.poll(timeOutInNanos, TimeUnit.NANOSECONDS);
timeLeftToCompleteProcessing = timeLeftToCompleteProcessing - (System.nanoTime() - currentStart);
currentStart = System.nanoTime();
if (currentRequestWithResponse != null) {
if ((requestResponse.getRequestId() == currentRequestWithResponse.getRequestId()) && (requestResponse.getWindowId() == currentRequestWithResponse.getWindowId())) {
isCurrentRequestProcessed = true;
break;
} else {
delayedResponsesQueue.put(currentRequestWithResponse);
}
} else {
LOG.debug(" Processing of request could not be completed on time");
}
}
if (isCurrentRequestProcessed) {
LOG.debug("Response could be processed within time SLA");
return currentRequestWithResponse;
} else {
LOG.debug("Response could not be processed within time SLA");
return null;
}
}
Aggregations