mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 05:01:07 +00:00
Move api name & version into ScriptRevision; make the records that go into record-scripts be api versions of records.
This commit is contained in:
@ -278,6 +278,7 @@ public class PollingAutomationPerTableRunner implements Runnable
|
|||||||
.withPriority(record.getValueInteger("priority"))
|
.withPriority(record.getValueInteger("priority"))
|
||||||
.withCodeReference(new QCodeReference(RunRecordScriptAutomationHandler.class))
|
.withCodeReference(new QCodeReference(RunRecordScriptAutomationHandler.class))
|
||||||
.withValues(MapBuilder.of("scriptId", record.getValue("scriptId")))
|
.withValues(MapBuilder.of("scriptId", record.getValue("scriptId")))
|
||||||
|
.withIncludeRecordAssociations(true)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -392,6 +393,8 @@ public class PollingAutomationPerTableRunner implements Runnable
|
|||||||
|
|
||||||
queryInput.setFilter(filter);
|
queryInput.setFilter(filter);
|
||||||
|
|
||||||
|
queryInput.setIncludeAssociations(action.getIncludeRecordAssociations());
|
||||||
|
|
||||||
return (new QueryAction().execute(queryInput).getRecords());
|
return (new QueryAction().execute(queryInput).getRecords());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,13 +25,21 @@ package com.kingsrook.qqq.backend.core.actions.scripts;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import com.kingsrook.qqq.backend.core.actions.scripts.logging.Log4jCodeExecutionLogger;
|
import com.kingsrook.qqq.backend.core.actions.scripts.logging.Log4jCodeExecutionLogger;
|
||||||
import com.kingsrook.qqq.backend.core.actions.scripts.logging.QCodeExecutionLoggerInterface;
|
import com.kingsrook.qqq.backend.core.actions.scripts.logging.QCodeExecutionLoggerInterface;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.scripts.logging.ScriptExecutionLoggerInterface;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.scripts.logging.StoreScriptLogAndScriptLogLineExecutionLogger;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QCodeException;
|
import com.kingsrook.qqq.backend.core.exceptions.QCodeException;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
|
import com.kingsrook.qqq.backend.core.logging.QLogger;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.scripts.AbstractRunScriptInput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.scripts.ExecuteCodeInput;
|
import com.kingsrook.qqq.backend.core.model.actions.scripts.ExecuteCodeInput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.scripts.ExecuteCodeOutput;
|
import com.kingsrook.qqq.backend.core.model.actions.scripts.ExecuteCodeOutput;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
|
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeType;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.scripts.ScriptRevision;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -49,6 +57,9 @@ import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public class ExecuteCodeAction
|
public class ExecuteCodeAction
|
||||||
{
|
{
|
||||||
|
private static final QLogger LOG = QLogger.getLogger(ExecuteCodeAction.class);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
@ -68,10 +79,10 @@ public class ExecuteCodeAction
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
String languageExecutor = switch(codeReference.getCodeType())
|
String languageExecutor = switch(codeReference.getCodeType())
|
||||||
{
|
{
|
||||||
case JAVA -> "com.kingsrook.qqq.backend.core.actions.scripts.QJavaExecutor";
|
case JAVA -> "com.kingsrook.qqq.backend.core.actions.scripts.QJavaExecutor";
|
||||||
case JAVA_SCRIPT -> "com.kingsrook.qqq.languages.javascript.QJavaScriptExecutor";
|
case JAVA_SCRIPT -> "com.kingsrook.qqq.languages.javascript.QJavaScriptExecutor";
|
||||||
};
|
};
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Class<? extends QCodeExecutor> executorClass = (Class<? extends QCodeExecutor>) Class.forName(languageExecutor);
|
Class<? extends QCodeExecutor> executorClass = (Class<? extends QCodeExecutor>) Class.forName(languageExecutor);
|
||||||
@ -108,6 +119,89 @@ public class ExecuteCodeAction
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public static ExecuteCodeInput setupExecuteCodeInput(AbstractRunScriptInput<?> input, ScriptRevision scriptRevision)
|
||||||
|
{
|
||||||
|
ExecuteCodeInput executeCodeInput = new ExecuteCodeInput();
|
||||||
|
executeCodeInput.setInput(new HashMap<>(Objects.requireNonNullElseGet(input.getInputValues(), HashMap::new)));
|
||||||
|
executeCodeInput.setContext(new HashMap<>());
|
||||||
|
if(input.getOutputObject() != null)
|
||||||
|
{
|
||||||
|
executeCodeInput.getContext().put("output", input.getOutputObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
if(input.getScriptUtils() != null)
|
||||||
|
{
|
||||||
|
executeCodeInput.getContext().put("scriptUtils", input.getScriptUtils());
|
||||||
|
}
|
||||||
|
|
||||||
|
executeCodeInput.setCodeReference(new QCodeReference().withInlineCode(scriptRevision.getContents()).withCodeType(QCodeType.JAVA_SCRIPT)); // todo - code type as attribute of script!!
|
||||||
|
|
||||||
|
ExecuteCodeAction.addApiUtilityToContext(executeCodeInput.getContext(), scriptRevision);
|
||||||
|
ExecuteCodeAction.setExecutionLoggerInExecuteCodeInput(input, scriptRevision, executeCodeInput);
|
||||||
|
|
||||||
|
return (executeCodeInput);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Try to (dynamically) load the ApiScriptUtils object from the api middleware
|
||||||
|
** module -- in case the runtime doesn't have that module deployed (e.g, not in
|
||||||
|
** the project pom).
|
||||||
|
*******************************************************************************/
|
||||||
|
private static void addApiUtilityToContext(Map<String, Serializable> context, ScriptRevision scriptRevision)
|
||||||
|
{
|
||||||
|
if(!StringUtils.hasContent(scriptRevision.getApiName()) || !StringUtils.hasContent(scriptRevision.getApiVersion()))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Class<?> apiScriptUtilsClass = Class.forName("com.kingsrook.qqq.api.utils.ApiScriptUtils");
|
||||||
|
Object apiScriptUtilsObject = apiScriptUtilsClass.getConstructor(String.class, String.class).newInstance(scriptRevision.getApiName(), scriptRevision.getApiVersion());
|
||||||
|
context.put("api", (Serializable) apiScriptUtilsObject);
|
||||||
|
}
|
||||||
|
catch(ClassNotFoundException e)
|
||||||
|
{
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// this is the only exception we're kinda expecting here - so catch for it specifically, and just log.trace - others, warn //
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
LOG.trace("Couldn't load ApiScriptUtils class - qqq-middleware-api not on the classpath?");
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
LOG.warn("Error adding api utility to script context", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private static void setExecutionLoggerInExecuteCodeInput(AbstractRunScriptInput<?> input, ScriptRevision scriptRevision, ExecuteCodeInput executeCodeInput)
|
||||||
|
{
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// let caller supply a logger, or by default use StoreScriptLogAndScriptLogLineExecutionLogger //
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
QCodeExecutionLoggerInterface executionLogger = Objects.requireNonNullElseGet(input.getLogger(), () -> new StoreScriptLogAndScriptLogLineExecutionLogger(scriptRevision.getScriptId(), scriptRevision.getId()));
|
||||||
|
executeCodeInput.setExecutionLogger(executionLogger);
|
||||||
|
if(executionLogger instanceof ScriptExecutionLoggerInterface scriptExecutionLoggerInterface)
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// if logger is aware of scripts (as opposed to a generic CodeExecution logger), give it the ids. //
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
scriptExecutionLoggerInterface.setScriptId(scriptRevision.getScriptId());
|
||||||
|
scriptExecutionLoggerInterface.setScriptRevisionId(scriptRevision.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
@ -23,15 +23,13 @@ package com.kingsrook.qqq.backend.core.actions.scripts;
|
|||||||
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import com.kingsrook.qqq.backend.core.actions.ActionHelper;
|
import com.kingsrook.qqq.backend.core.actions.ActionHelper;
|
||||||
import com.kingsrook.qqq.backend.core.actions.scripts.logging.QCodeExecutionLoggerInterface;
|
|
||||||
import com.kingsrook.qqq.backend.core.actions.scripts.logging.ScriptExecutionLoggerInterface;
|
|
||||||
import com.kingsrook.qqq.backend.core.actions.scripts.logging.StoreScriptLogAndScriptLogLineExecutionLogger;
|
|
||||||
import com.kingsrook.qqq.backend.core.actions.tables.GetAction;
|
import com.kingsrook.qqq.backend.core.actions.tables.GetAction;
|
||||||
import com.kingsrook.qqq.backend.core.actions.tables.QueryAction;
|
import com.kingsrook.qqq.backend.core.actions.tables.QueryAction;
|
||||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||||
@ -50,13 +48,10 @@ import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryInput;
|
|||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryJoin;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryJoin;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryOutput;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryOutput;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.code.AdHocScriptCodeReference;
|
import com.kingsrook.qqq.backend.core.model.metadata.code.AdHocScriptCodeReference;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeType;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.scripts.Script;
|
import com.kingsrook.qqq.backend.core.model.scripts.Script;
|
||||||
import com.kingsrook.qqq.backend.core.model.scripts.ScriptRevision;
|
import com.kingsrook.qqq.backend.core.model.scripts.ScriptRevision;
|
||||||
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
||||||
import static com.kingsrook.qqq.backend.core.logging.LogUtils.logPair;
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -98,6 +93,7 @@ public class RunAdHocRecordScriptAction
|
|||||||
QueryInput queryInput = new QueryInput();
|
QueryInput queryInput = new QueryInput();
|
||||||
queryInput.setTableName(input.getTableName());
|
queryInput.setTableName(input.getTableName());
|
||||||
queryInput.setFilter(new QQueryFilter(new QFilterCriteria(table.getPrimaryKeyField(), QCriteriaOperator.IN, input.getRecordPrimaryKeyList())));
|
queryInput.setFilter(new QQueryFilter(new QFilterCriteria(table.getPrimaryKeyField(), QCriteriaOperator.IN, input.getRecordPrimaryKeyList())));
|
||||||
|
queryInput.setIncludeAssociations(true);
|
||||||
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
||||||
input.setRecordList(queryOutput.getRecords());
|
input.setRecordList(queryOutput.getRecords());
|
||||||
}
|
}
|
||||||
@ -114,43 +110,14 @@ public class RunAdHocRecordScriptAction
|
|||||||
/////////////
|
/////////////
|
||||||
// run it! //
|
// run it! //
|
||||||
/////////////
|
/////////////
|
||||||
ExecuteCodeInput executeCodeInput = new ExecuteCodeInput();
|
ExecuteCodeInput executeCodeInput = ExecuteCodeAction.setupExecuteCodeInput(input, scriptRevision);
|
||||||
executeCodeInput.setInput(new HashMap<>(Objects.requireNonNullElseGet(input.getInputValues(), HashMap::new)));
|
executeCodeInput.getInput().put("records", getRecordsForScript(input, scriptRevision));
|
||||||
executeCodeInput.getInput().put("records", new ArrayList<>(input.getRecordList()));
|
|
||||||
executeCodeInput.setContext(new HashMap<>());
|
|
||||||
if(input.getOutputObject() != null)
|
|
||||||
{
|
|
||||||
executeCodeInput.getContext().put("output", input.getOutputObject());
|
|
||||||
}
|
|
||||||
|
|
||||||
if(input.getScriptUtils() != null)
|
|
||||||
{
|
|
||||||
executeCodeInput.getContext().put("scriptUtils", input.getScriptUtils());
|
|
||||||
}
|
|
||||||
|
|
||||||
addApiUtilityToContext(executeCodeInput.getContext(), scriptRevision);
|
|
||||||
|
|
||||||
executeCodeInput.setCodeReference(new QCodeReference().withInlineCode(scriptRevision.getContents()).withCodeType(QCodeType.JAVA_SCRIPT)); // todo - code type as attribute of script!!
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// let caller supply a logger, or by default use StoreScriptLogAndScriptLogLineExecutionLogger //
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
QCodeExecutionLoggerInterface executionLogger = Objects.requireNonNullElseGet(input.getLogger(), () -> new StoreScriptLogAndScriptLogLineExecutionLogger(scriptRevision.getScriptId(), scriptRevision.getId()));
|
|
||||||
executeCodeInput.setExecutionLogger(executionLogger);
|
|
||||||
if(executionLogger instanceof ScriptExecutionLoggerInterface scriptExecutionLoggerInterface)
|
|
||||||
{
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// if logger is aware of scripts (as opposed to a generic CodeExecution logger), give it the ids. //
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
scriptExecutionLoggerInterface.setScriptId(scriptRevision.getScriptId());
|
|
||||||
scriptExecutionLoggerInterface.setScriptRevisionId(scriptRevision.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
ExecuteCodeOutput executeCodeOutput = new ExecuteCodeOutput();
|
ExecuteCodeOutput executeCodeOutput = new ExecuteCodeOutput();
|
||||||
new ExecuteCodeAction().run(executeCodeInput, executeCodeOutput);
|
new ExecuteCodeAction().run(executeCodeInput, executeCodeOutput);
|
||||||
|
|
||||||
output.setOutput(executeCodeOutput.getOutput());
|
output.setOutput(executeCodeOutput.getOutput());
|
||||||
output.setLogger(executionLogger);
|
output.setLogger(executeCodeInput.getExecutionLogger());
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
{
|
{
|
||||||
@ -161,17 +128,18 @@ public class RunAdHocRecordScriptAction
|
|||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Try to (dynamically) load the ApiScriptUtils object from the api middleware
|
**
|
||||||
** module -- in case the runtime doesn't have that module deployed (e.g, not in
|
|
||||||
** the project pom).
|
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
private void addApiUtilityToContext(Map<String, Serializable> context, ScriptRevision scriptRevision)
|
private static ArrayList<? extends Serializable> getRecordsForScript(RunAdHocRecordScriptInput input, ScriptRevision scriptRevision)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Class<?> apiScriptUtilsClass = Class.forName("com.kingsrook.qqq.api.utils.ApiScriptUtils");
|
Class<?> apiScriptUtilsClass = Class.forName("com.kingsrook.qqq.api.utils.ApiScriptUtils");
|
||||||
Object apiScriptUtilsObject = apiScriptUtilsClass.getConstructor().newInstance();
|
Method qRecordListToApiRecordList = apiScriptUtilsClass.getMethod("qRecordListToApiRecordList", List.class, String.class, String.class, String.class);
|
||||||
context.put("api", (Serializable) apiScriptUtilsObject);
|
Object apiRecordList = qRecordListToApiRecordList.invoke(null, input.getRecordList(), input.getTableName(), scriptRevision.getApiName(), scriptRevision.getApiVersion());
|
||||||
|
|
||||||
|
// noinspection unchecked
|
||||||
|
return (ArrayList<? extends Serializable>) apiRecordList;
|
||||||
}
|
}
|
||||||
catch(ClassNotFoundException e)
|
catch(ClassNotFoundException e)
|
||||||
{
|
{
|
||||||
@ -182,8 +150,10 @@ public class RunAdHocRecordScriptAction
|
|||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
{
|
{
|
||||||
LOG.warn("Error adding api utility to script context", e, logPair("scriptRevisionId", scriptRevision.getId()));
|
LOG.warn("Error converting QRecord list to api record list", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return (new ArrayList<>(input.getRecordList()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,11 +25,7 @@ package com.kingsrook.qqq.backend.core.actions.scripts;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
|
||||||
import com.kingsrook.qqq.backend.core.actions.ActionHelper;
|
import com.kingsrook.qqq.backend.core.actions.ActionHelper;
|
||||||
import com.kingsrook.qqq.backend.core.actions.scripts.logging.QCodeExecutionLoggerInterface;
|
|
||||||
import com.kingsrook.qqq.backend.core.actions.scripts.logging.ScriptExecutionLoggerInterface;
|
|
||||||
import com.kingsrook.qqq.backend.core.actions.scripts.logging.StoreScriptLogAndScriptLogLineExecutionLogger;
|
|
||||||
import com.kingsrook.qqq.backend.core.actions.tables.GetAction;
|
import com.kingsrook.qqq.backend.core.actions.tables.GetAction;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QNotFoundException;
|
import com.kingsrook.qqq.backend.core.exceptions.QNotFoundException;
|
||||||
@ -40,8 +36,6 @@ import com.kingsrook.qqq.backend.core.model.actions.scripts.RunAssociatedScriptO
|
|||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetInput;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetInput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetOutput;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetOutput;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.code.AssociatedScriptCodeReference;
|
import com.kingsrook.qqq.backend.core.model.metadata.code.AssociatedScriptCodeReference;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeType;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.scripts.Script;
|
import com.kingsrook.qqq.backend.core.model.scripts.Script;
|
||||||
import com.kingsrook.qqq.backend.core.model.scripts.ScriptRevision;
|
import com.kingsrook.qqq.backend.core.model.scripts.ScriptRevision;
|
||||||
|
|
||||||
@ -54,6 +48,7 @@ public class RunAssociatedScriptAction
|
|||||||
private Map<AssociatedScriptCodeReference, ScriptRevision> scriptRevisionCache = new HashMap<>();
|
private Map<AssociatedScriptCodeReference, ScriptRevision> scriptRevisionCache = new HashMap<>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
@ -61,36 +56,8 @@ public class RunAssociatedScriptAction
|
|||||||
{
|
{
|
||||||
ActionHelper.validateSession(input);
|
ActionHelper.validateSession(input);
|
||||||
|
|
||||||
ScriptRevision scriptRevision = getScriptRevision(input);
|
ScriptRevision scriptRevision = getScriptRevision(input);
|
||||||
|
ExecuteCodeInput executeCodeInput = ExecuteCodeAction.setupExecuteCodeInput(input, scriptRevision);
|
||||||
ExecuteCodeInput executeCodeInput = new ExecuteCodeInput();
|
|
||||||
executeCodeInput.setInput(new HashMap<>(input.getInputValues()));
|
|
||||||
executeCodeInput.setContext(new HashMap<>());
|
|
||||||
if(input.getOutputObject() != null)
|
|
||||||
{
|
|
||||||
executeCodeInput.getContext().put("output", input.getOutputObject());
|
|
||||||
}
|
|
||||||
|
|
||||||
if(input.getScriptUtils() != null)
|
|
||||||
{
|
|
||||||
executeCodeInput.getContext().put("scriptUtils", input.getScriptUtils());
|
|
||||||
}
|
|
||||||
|
|
||||||
executeCodeInput.setCodeReference(new QCodeReference().withInlineCode(scriptRevision.getContents()).withCodeType(QCodeType.JAVA_SCRIPT)); // todo - code type as attribute of script!!
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// let caller supply a logger, or by default use StoreScriptLogAndScriptLogLineExecutionLogger //
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
QCodeExecutionLoggerInterface executionLogger = Objects.requireNonNullElseGet(input.getLogger(), () -> new StoreScriptLogAndScriptLogLineExecutionLogger(scriptRevision.getScriptId(), scriptRevision.getId()));
|
|
||||||
executeCodeInput.setExecutionLogger(executionLogger);
|
|
||||||
if(executionLogger instanceof ScriptExecutionLoggerInterface scriptExecutionLoggerInterface)
|
|
||||||
{
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// if logger is aware of scripts (as opposed to a generic CodeExecution logger), give it the ids. //
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
scriptExecutionLoggerInterface.setScriptId(scriptRevision.getScriptId());
|
|
||||||
scriptExecutionLoggerInterface.setScriptRevisionId(scriptRevision.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
ExecuteCodeOutput executeCodeOutput = new ExecuteCodeOutput();
|
ExecuteCodeOutput executeCodeOutput = new ExecuteCodeOutput();
|
||||||
new ExecuteCodeAction().run(executeCodeInput, executeCodeOutput);
|
new ExecuteCodeAction().run(executeCodeInput, executeCodeOutput);
|
||||||
|
@ -47,6 +47,11 @@ import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Object made available to scripts for access to qqq api (e.g., query, insert,
|
** Object made available to scripts for access to qqq api (e.g., query, insert,
|
||||||
** etc, plus object constructors).
|
** etc, plus object constructors).
|
||||||
|
**
|
||||||
|
** Before scripts knew about the API, this class made sense and was used.
|
||||||
|
** But, now that scripts do know about the API, it feels like this class could
|
||||||
|
** be deleted... but, what about, a QQQ deployment without the API module...
|
||||||
|
** In that case, we might still want this class... think about it.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public class ScriptApi implements Serializable
|
public class ScriptApi implements Serializable
|
||||||
{
|
{
|
||||||
|
@ -38,6 +38,12 @@ public class TableAutomationAction
|
|||||||
private Integer priority = 500;
|
private Integer priority = 500;
|
||||||
private QQueryFilter filter;
|
private QQueryFilter filter;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
// flag that will cause the records to cause their associations to be //
|
||||||
|
// fetched, when they are looked up for passing into the action //
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
private boolean includeRecordAssociations = false;
|
||||||
|
|
||||||
private Map<String, Serializable> values;
|
private Map<String, Serializable> values;
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
@ -292,4 +298,35 @@ public class TableAutomationAction
|
|||||||
return (this);
|
return (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for includeRecordAssociations
|
||||||
|
*******************************************************************************/
|
||||||
|
public boolean getIncludeRecordAssociations()
|
||||||
|
{
|
||||||
|
return (this.includeRecordAssociations);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for includeRecordAssociations
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setIncludeRecordAssociations(boolean includeRecordAssociations)
|
||||||
|
{
|
||||||
|
this.includeRecordAssociations = includeRecordAssociations;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for includeRecordAssociations
|
||||||
|
*******************************************************************************/
|
||||||
|
public TableAutomationAction withIncludeRecordAssociations(boolean includeRecordAssociations)
|
||||||
|
{
|
||||||
|
this.includeRecordAssociations = includeRecordAssociations;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ import com.kingsrook.qqq.backend.core.exceptions.QException;
|
|||||||
import com.kingsrook.qqq.backend.core.model.data.QField;
|
import com.kingsrook.qqq.backend.core.model.data.QField;
|
||||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||||
import com.kingsrook.qqq.backend.core.model.data.QRecordEntity;
|
import com.kingsrook.qqq.backend.core.model.data.QRecordEntity;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.ValueTooLongBehavior;
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -48,16 +49,22 @@ public class ScriptRevision extends QRecordEntity
|
|||||||
@QField(possibleValueSourceName = "script")
|
@QField(possibleValueSourceName = "script")
|
||||||
private Integer scriptId;
|
private Integer scriptId;
|
||||||
|
|
||||||
|
@QField(possibleValueSourceName = "apiVersion", label = "API Version")
|
||||||
|
private String apiVersion;
|
||||||
|
|
||||||
|
@QField(possibleValueSourceName = "apiName", label = "API Name")
|
||||||
|
private String apiName;
|
||||||
|
|
||||||
@QField()
|
@QField()
|
||||||
private String contents;
|
private String contents;
|
||||||
|
|
||||||
@QField()
|
@QField()
|
||||||
private Integer sequenceNo;
|
private Integer sequenceNo;
|
||||||
|
|
||||||
@QField()
|
@QField(maxLength = 250, valueTooLongBehavior = ValueTooLongBehavior.TRUNCATE_ELLIPSIS)
|
||||||
private String commitMessage;
|
private String commitMessage;
|
||||||
|
|
||||||
@QField()
|
@QField(maxLength = 100, valueTooLongBehavior = ValueTooLongBehavior.TRUNCATE_ELLIPSIS)
|
||||||
private String author;
|
private String author;
|
||||||
|
|
||||||
|
|
||||||
@ -353,4 +360,66 @@ public class ScriptRevision extends QRecordEntity
|
|||||||
return (this);
|
return (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for apiVersion
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getApiVersion()
|
||||||
|
{
|
||||||
|
return (this.apiVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for apiVersion
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setApiVersion(String apiVersion)
|
||||||
|
{
|
||||||
|
this.apiVersion = apiVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for apiVersion
|
||||||
|
*******************************************************************************/
|
||||||
|
public ScriptRevision withApiVersion(String apiVersion)
|
||||||
|
{
|
||||||
|
this.apiVersion = apiVersion;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for apiName
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getApiName()
|
||||||
|
{
|
||||||
|
return (this.apiName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for apiName
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setApiName(String apiName)
|
||||||
|
{
|
||||||
|
this.apiName = apiName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for apiName
|
||||||
|
*******************************************************************************/
|
||||||
|
public ScriptRevision withApiName(String apiName)
|
||||||
|
{
|
||||||
|
this.apiName = apiName;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -382,6 +382,7 @@ public class ScriptsMetaDataProvider
|
|||||||
.withRecordLabelFormat("%s v%s")
|
.withRecordLabelFormat("%s v%s")
|
||||||
.withRecordLabelFields(List.of("scriptId", "sequenceNo"))
|
.withRecordLabelFields(List.of("scriptId", "sequenceNo"))
|
||||||
.withSection(new QFieldSection("identity", new QIcon().withName("badge"), Tier.T1, List.of("id", "scriptId", "sequenceNo")))
|
.withSection(new QFieldSection("identity", new QIcon().withName("badge"), Tier.T1, List.of("id", "scriptId", "sequenceNo")))
|
||||||
|
.withSection(new QFieldSection("api", "API", new QIcon().withName("code"), Tier.T2, List.of("apiName", "apiVersion")))
|
||||||
.withSection(new QFieldSection("code", new QIcon().withName("data_object"), Tier.T2, List.of("contents")))
|
.withSection(new QFieldSection("code", new QIcon().withName("data_object"), Tier.T2, List.of("contents")))
|
||||||
.withSection(new QFieldSection("changeManagement", new QIcon().withName("history"), Tier.T2, List.of("commitMessage", "author")))
|
.withSection(new QFieldSection("changeManagement", new QIcon().withName("history"), Tier.T2, List.of("commitMessage", "author")))
|
||||||
.withSection(new QFieldSection("dates", new QIcon().withName("calendar_month"), Tier.T3, List.of("createDate", "modifyDate")));
|
.withSection(new QFieldSection("dates", new QIcon().withName("calendar_month"), Tier.T3, List.of("createDate", "modifyDate")));
|
||||||
|
@ -83,6 +83,9 @@ public class ExtractViaQueryStep extends AbstractExtractStep
|
|||||||
queryInput.setRecordPipe(getRecordPipe());
|
queryInput.setRecordPipe(getRecordPipe());
|
||||||
queryInput.setLimit(getLimit());
|
queryInput.setLimit(getLimit());
|
||||||
queryInput.setAsyncJobCallback(runBackendStepInput.getAsyncJobCallback());
|
queryInput.setAsyncJobCallback(runBackendStepInput.getAsyncJobCallback());
|
||||||
|
|
||||||
|
customizeInputPreQuery(queryInput);
|
||||||
|
|
||||||
new QueryAction().execute(queryInput);
|
new QueryAction().execute(queryInput);
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////
|
||||||
@ -92,6 +95,16 @@ public class ExtractViaQueryStep extends AbstractExtractStep
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** chance for sub-classes to change things about the query input, if they want.
|
||||||
|
*******************************************************************************/
|
||||||
|
protected void customizeInputPreQuery(QueryInput queryInput)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
@ -28,6 +28,7 @@ import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInpu
|
|||||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepOutput;
|
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepOutput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetInput;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetInput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetOutput;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetOutput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryInput;
|
||||||
import com.kingsrook.qqq.backend.core.model.scripts.Script;
|
import com.kingsrook.qqq.backend.core.model.scripts.Script;
|
||||||
import com.kingsrook.qqq.backend.core.processes.implementations.etl.streamedwithfrontend.ExtractViaQueryStep;
|
import com.kingsrook.qqq.backend.core.processes.implementations.etl.streamedwithfrontend.ExtractViaQueryStep;
|
||||||
import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
||||||
@ -70,4 +71,16 @@ public class RunRecordScriptExtractStep extends ExtractViaQueryStep
|
|||||||
super.preRun(runBackendStepInput, runBackendStepOutput);
|
super.preRun(runBackendStepInput, runBackendStepOutput);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Make sure associations are fetched (so api records have children!)
|
||||||
|
*******************************************************************************/
|
||||||
|
@Override
|
||||||
|
protected void customizeInputPreQuery(QueryInput queryInput)
|
||||||
|
{
|
||||||
|
super.customizeInputPreQuery(queryInput);
|
||||||
|
queryInput.setIncludeAssociations(true);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -112,6 +112,8 @@ public class StoreScriptRevisionProcessStep implements BackendStep
|
|||||||
QRecord scriptRevision = new QRecord()
|
QRecord scriptRevision = new QRecord()
|
||||||
.withValue("scriptId", script.getValue("id"))
|
.withValue("scriptId", script.getValue("id"))
|
||||||
.withValue("contents", input.getValueString("contents"))
|
.withValue("contents", input.getValueString("contents"))
|
||||||
|
.withValue("apiName", input.getValueString("apiName"))
|
||||||
|
.withValue("apiVersion", input.getValueString("apiVersion"))
|
||||||
.withValue("commitMessage", commitMessage)
|
.withValue("commitMessage", commitMessage)
|
||||||
.withValue("sequenceNo", nextSequenceNo);
|
.withValue("sequenceNo", nextSequenceNo);
|
||||||
|
|
||||||
|
@ -106,6 +106,7 @@ public class TestScriptProcessStep implements BackendStep
|
|||||||
QueryInput queryInput = new QueryInput();
|
QueryInput queryInput = new QueryInput();
|
||||||
queryInput.setTableName(tableName);
|
queryInput.setTableName(tableName);
|
||||||
queryInput.setFilter(new QQueryFilter(new QFilterCriteria(table.getPrimaryKeyField(), QCriteriaOperator.IN, recordPrimaryKeyList.split(","))));
|
queryInput.setFilter(new QQueryFilter(new QFilterCriteria(table.getPrimaryKeyField(), QCriteriaOperator.IN, recordPrimaryKeyList.split(","))));
|
||||||
|
queryInput.setIncludeAssociations(true);
|
||||||
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
||||||
if(CollectionUtils.nullSafeIsEmpty(queryOutput.getRecords()))
|
if(CollectionUtils.nullSafeIsEmpty(queryOutput.getRecords()))
|
||||||
{
|
{
|
||||||
|
@ -118,7 +118,7 @@ public class ApiInstanceMetaDataProvider
|
|||||||
ApiInstanceMetaDataContainer apiInstanceMetaDataContainer = ApiInstanceMetaDataContainer.of(instance);
|
ApiInstanceMetaDataContainer apiInstanceMetaDataContainer = ApiInstanceMetaDataContainer.of(instance);
|
||||||
for(Map.Entry<String, ApiInstanceMetaData> entry : apiInstanceMetaDataContainer.getApis().entrySet())
|
for(Map.Entry<String, ApiInstanceMetaData> entry : apiInstanceMetaDataContainer.getApis().entrySet())
|
||||||
{
|
{
|
||||||
apiNamePossibleValues.add(new QPossibleValue<>(entry.getKey()));
|
apiNamePossibleValues.add(new QPossibleValue<>(entry.getKey(), entry.getValue().getLabel()));
|
||||||
|
|
||||||
ApiInstanceMetaData apiInstanceMetaData = entry.getValue();
|
ApiInstanceMetaData apiInstanceMetaData = entry.getValue();
|
||||||
allVersions.addAll(apiInstanceMetaData.getPastVersions());
|
allVersions.addAll(apiInstanceMetaData.getPastVersions());
|
||||||
|
@ -28,11 +28,13 @@ import java.util.LinkedHashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import com.kingsrook.qqq.api.actions.ApiImplementation;
|
import com.kingsrook.qqq.api.actions.ApiImplementation;
|
||||||
|
import com.kingsrook.qqq.api.actions.QRecordApiAdapter;
|
||||||
import com.kingsrook.qqq.api.model.APIVersion;
|
import com.kingsrook.qqq.api.model.APIVersion;
|
||||||
import com.kingsrook.qqq.api.model.metadata.ApiInstanceMetaData;
|
import com.kingsrook.qqq.api.model.metadata.ApiInstanceMetaData;
|
||||||
import com.kingsrook.qqq.api.model.metadata.ApiInstanceMetaDataContainer;
|
import com.kingsrook.qqq.api.model.metadata.ApiInstanceMetaDataContainer;
|
||||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -49,20 +51,30 @@ public class ApiScriptUtils implements Serializable
|
|||||||
** Constructor
|
** Constructor
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public ApiScriptUtils()
|
public ApiScriptUtils(String apiName, String apiVersion)
|
||||||
{
|
{
|
||||||
|
setApiName(apiName);
|
||||||
|
setApiVersion(apiVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Constructor
|
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public ApiScriptUtils(String apiName, String apiVersion)
|
public static ArrayList<Map<String, Serializable>> qRecordListToApiRecordList(List<QRecord> qRecordList, String tableName, String apiName, String apiVersion) throws QException
|
||||||
{
|
{
|
||||||
setApiName(apiName);
|
if(qRecordList == null)
|
||||||
setApiVersion(apiVersion);
|
{
|
||||||
|
return (null);
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayList<Map<String, Serializable>> rs = new ArrayList<>();
|
||||||
|
for(QRecord qRecord : qRecordList)
|
||||||
|
{
|
||||||
|
rs.add(QRecordApiAdapter.qRecordToApiMap(qRecord, tableName, apiName, apiVersion));
|
||||||
|
}
|
||||||
|
return (rs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -267,10 +267,7 @@ class ApiScriptUtilsTest extends BaseTest
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
private static ApiScriptUtils newDefaultApiScriptUtils()
|
private static ApiScriptUtils newDefaultApiScriptUtils()
|
||||||
{
|
{
|
||||||
ApiScriptUtils apiScriptUtils = new ApiScriptUtils();
|
return (new ApiScriptUtils(TestUtils.API_NAME, TestUtils.CURRENT_API_VERSION));
|
||||||
apiScriptUtils.setApiName(TestUtils.API_NAME);
|
|
||||||
apiScriptUtils.setApiVersion(TestUtils.CURRENT_API_VERSION);
|
|
||||||
return apiScriptUtils;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
Reference in New Issue
Block a user