mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 13:10:44 +00:00
add testScriptProcess
This commit is contained in:
@ -25,6 +25,7 @@ package com.kingsrook.qqq.backend.core.model.metadata.fields;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.PossibleValueEnum;
|
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.PossibleValueEnum;
|
||||||
import com.kingsrook.qqq.backend.core.utils.Pair;
|
import com.kingsrook.qqq.backend.core.utils.Pair;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.collections.MapBuilder;
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -105,14 +106,20 @@ public enum AdornmentType
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public interface SizeValues
|
public enum Size
|
||||||
{
|
{
|
||||||
String WIDTH = "width";
|
XSMALL,
|
||||||
String XSMALL = "xsmall";
|
SMALL,
|
||||||
String SMALL = "small";
|
MEDIUM,
|
||||||
String MEDIUM = "medium";
|
LARGE,
|
||||||
String LARGE = "large";
|
XLARGE;
|
||||||
String XLARGE = "xlarge";
|
|
||||||
|
|
||||||
|
|
||||||
|
public FieldAdornment toAdornment()
|
||||||
|
{
|
||||||
|
return (new FieldAdornment(AdornmentType.SIZE, MapBuilder.of("width", name().toLowerCase())));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -62,6 +62,7 @@ import com.kingsrook.qqq.backend.core.processes.implementations.etl.streamedwith
|
|||||||
import com.kingsrook.qqq.backend.core.processes.implementations.scripts.RunRecordScriptExtractStep;
|
import com.kingsrook.qqq.backend.core.processes.implementations.scripts.RunRecordScriptExtractStep;
|
||||||
import com.kingsrook.qqq.backend.core.processes.implementations.scripts.RunRecordScriptLoadStep;
|
import com.kingsrook.qqq.backend.core.processes.implementations.scripts.RunRecordScriptLoadStep;
|
||||||
import com.kingsrook.qqq.backend.core.processes.implementations.scripts.StoreScriptRevisionProcessStep;
|
import com.kingsrook.qqq.backend.core.processes.implementations.scripts.StoreScriptRevisionProcessStep;
|
||||||
|
import com.kingsrook.qqq.backend.core.processes.implementations.scripts.TestScriptProcessStep;
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -71,6 +72,7 @@ public class ScriptsMetaDataProvider
|
|||||||
{
|
{
|
||||||
public static final String RUN_RECORD_SCRIPT_PROCESS_NAME = "runRecordScript";
|
public static final String RUN_RECORD_SCRIPT_PROCESS_NAME = "runRecordScript";
|
||||||
public static final String STORE_SCRIPT_REVISION_PROCESS_NAME = "storeScriptRevision";
|
public static final String STORE_SCRIPT_REVISION_PROCESS_NAME = "storeScriptRevision";
|
||||||
|
public static final String TEST_SCRIPT_PROCESS_NAME = "testScript";
|
||||||
|
|
||||||
public static final String SCRIPT_TYPE_NAME_RECORD = "Record Script";
|
public static final String SCRIPT_TYPE_NAME_RECORD = "Record Script";
|
||||||
|
|
||||||
@ -87,6 +89,7 @@ public class ScriptsMetaDataProvider
|
|||||||
defineStandardScriptsWidgets(instance);
|
defineStandardScriptsWidgets(instance);
|
||||||
instance.addPossibleValueSource(TablesPossibleValueSourceMetaDataProvider.defineTablesPossibleValueSource(instance));
|
instance.addPossibleValueSource(TablesPossibleValueSourceMetaDataProvider.defineTablesPossibleValueSource(instance));
|
||||||
instance.addProcess(defineStoreScriptRevisionProcess());
|
instance.addProcess(defineStoreScriptRevisionProcess());
|
||||||
|
instance.addProcess(defineTestScriptProcess());
|
||||||
instance.addProcess(defineRunRecordScriptProcess());
|
instance.addProcess(defineRunRecordScriptProcess());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,6 +111,22 @@ public class ScriptsMetaDataProvider
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private QProcessMetaData defineTestScriptProcess()
|
||||||
|
{
|
||||||
|
return (new QProcessMetaData()
|
||||||
|
.withName(TEST_SCRIPT_PROCESS_NAME)
|
||||||
|
.withStepList(List.of(
|
||||||
|
new QBackendStepMetaData()
|
||||||
|
.withName("main")
|
||||||
|
.withCode(new QCodeReference(TestScriptProcessStep.class))
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
@ -303,10 +322,15 @@ public class ScriptsMetaDataProvider
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
private QTableMetaData defineScriptTable(String backendName) throws QException
|
private QTableMetaData defineScriptTable(String backendName) throws QException
|
||||||
{
|
{
|
||||||
return (defineStandardTable(backendName, Script.TABLE_NAME, Script.class)
|
QTableMetaData tableMetaData = defineStandardTable(backendName, Script.TABLE_NAME, Script.class)
|
||||||
.withSection(new QFieldSection("identity", new QIcon().withName("badge"), Tier.T1, List.of("id", "name", "scriptTypeId", "tableName", "currentScriptRevisionId")))
|
.withSection(new QFieldSection("identity", new QIcon().withName("badge"), Tier.T1, List.of("id", "name", "scriptTypeId", "tableName", "currentScriptRevisionId")))
|
||||||
.withSection(new QFieldSection("contents", new QIcon().withName("data_object"), Tier.T2).withWidgetName("scriptViewer"))
|
.withSection(new QFieldSection("contents", new QIcon().withName("data_object"), Tier.T2).withWidgetName("scriptViewer"))
|
||||||
.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")));
|
||||||
|
|
||||||
|
tableMetaData.getField("name").withFieldAdornment(AdornmentType.Size.LARGE.toAdornment());
|
||||||
|
tableMetaData.getField("currentScriptRevisionId").withFieldAdornment(AdornmentType.Size.LARGE.toAdornment());
|
||||||
|
|
||||||
|
return (tableMetaData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -342,6 +366,8 @@ public class ScriptsMetaDataProvider
|
|||||||
.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")));
|
||||||
|
|
||||||
tableMetaData.getField("contents").withFieldAdornment(new FieldAdornment(AdornmentType.CODE_EDITOR));
|
tableMetaData.getField("contents").withFieldAdornment(new FieldAdornment(AdornmentType.CODE_EDITOR));
|
||||||
|
tableMetaData.getField("scriptId").withFieldAdornment(AdornmentType.Size.LARGE.toAdornment());
|
||||||
|
|
||||||
return (tableMetaData);
|
return (tableMetaData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -352,14 +378,21 @@ public class ScriptsMetaDataProvider
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
private QTableMetaData defineScriptLogTable(String backendName) throws QException
|
private QTableMetaData defineScriptLogTable(String backendName) throws QException
|
||||||
{
|
{
|
||||||
return (defineStandardTable(backendName, ScriptLog.TABLE_NAME, ScriptLog.class)
|
QTableMetaData tableMetaData = defineStandardTable(backendName, ScriptLog.TABLE_NAME, ScriptLog.class)
|
||||||
.withRecordLabelFields(List.of("id"))
|
.withRecordLabelFields(List.of("id"))
|
||||||
.withSection(new QFieldSection("identity", new QIcon().withName("badge"), Tier.T1, List.of("id")))
|
.withSection(new QFieldSection("identity", new QIcon().withName("badge"), Tier.T1, List.of("id")))
|
||||||
.withSection(new QFieldSection("script", new QIcon().withName("data_object"), Tier.T2, List.of("scriptId", "scriptRevisionId")))
|
.withSection(new QFieldSection("script", new QIcon().withName("data_object"), Tier.T2, List.of("scriptId", "scriptRevisionId")))
|
||||||
.withSection(new QFieldSection("timing", new QIcon().withName("schedule"), Tier.T2, List.of("startTimestamp", "endTimestamp", "runTimeMillis", "createDate", "modifyDate")))
|
.withSection(new QFieldSection("timing", new QIcon().withName("schedule"), Tier.T2, List.of("startTimestamp", "endTimestamp", "runTimeMillis", "createDate", "modifyDate")))
|
||||||
.withSection(new QFieldSection("error", "Error", new QIcon().withName("error_outline"), Tier.T2, List.of("hadError", "error")))
|
.withSection(new QFieldSection("error", "Error", new QIcon().withName("error_outline"), Tier.T2, List.of("hadError", "error")))
|
||||||
.withSection(new QFieldSection("inputOutput", "Input/Output", new QIcon().withName("chat"), Tier.T2, List.of("input", "output")))
|
.withSection(new QFieldSection("inputOutput", "Input/Output", new QIcon().withName("chat"), Tier.T2, List.of("input", "output")))
|
||||||
.withSection(new QFieldSection("lines", new QIcon().withName("horizontal_rule"), Tier.T2).withWidgetName(QJoinMetaData.makeInferredJoinName(ScriptLog.TABLE_NAME, ScriptLogLine.TABLE_NAME))));
|
.withSection(new QFieldSection("lines", new QIcon().withName("horizontal_rule"), Tier.T2).withWidgetName(QJoinMetaData.makeInferredJoinName(ScriptLog.TABLE_NAME, ScriptLogLine.TABLE_NAME)));
|
||||||
|
|
||||||
|
tableMetaData.getField("scriptId").withFieldAdornment(AdornmentType.Size.LARGE.toAdornment());
|
||||||
|
tableMetaData.getField("scriptRevisionId").withFieldAdornment(AdornmentType.Size.LARGE.toAdornment());
|
||||||
|
tableMetaData.getField("input").withFieldAdornment(AdornmentType.Size.LARGE.toAdornment());
|
||||||
|
tableMetaData.getField("output").withFieldAdornment(AdornmentType.Size.LARGE.toAdornment());
|
||||||
|
|
||||||
|
return (tableMetaData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -369,8 +402,12 @@ public class ScriptsMetaDataProvider
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
private QTableMetaData defineScriptLogLineTable(String backendName) throws QException
|
private QTableMetaData defineScriptLogLineTable(String backendName) throws QException
|
||||||
{
|
{
|
||||||
return (defineStandardTable(backendName, ScriptLogLine.TABLE_NAME, ScriptLogLine.class)
|
QTableMetaData tableMetaData = defineStandardTable(backendName, ScriptLogLine.TABLE_NAME, ScriptLogLine.class)
|
||||||
.withRecordLabelFields(List.of("id")));
|
.withRecordLabelFields(List.of("id"));
|
||||||
|
|
||||||
|
tableMetaData.getField("text").withFieldAdornment(AdornmentType.Size.XLARGE.toAdornment());
|
||||||
|
|
||||||
|
return (tableMetaData);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,176 @@
|
|||||||
|
/*
|
||||||
|
* QQQ - Low-code Application Framework for Engineers.
|
||||||
|
* Copyright (C) 2021-2023. Kingsrook, LLC
|
||||||
|
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||||
|
* contact@kingsrook.com
|
||||||
|
* https://github.com/Kingsrook/
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.kingsrook.qqq.backend.core.processes.implementations.scripts;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.ActionHelper;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.processes.BackendStep;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.scripts.RunAdHocRecordScriptAction;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.scripts.logging.BuildScriptLogAndScriptLogLineExecutionLogger;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.tables.GetAction;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.tables.QueryAction;
|
||||||
|
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||||
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepOutput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.scripts.RunAdHocRecordScriptInput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.scripts.RunAdHocRecordScriptOutput;
|
||||||
|
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.query.QCriteriaOperator;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterCriteria;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryInput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryOutput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.code.AdHocScriptCodeReference;
|
||||||
|
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.ScriptRevision;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.scripts.ScriptType;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.scripts.ScriptsMetaDataProvider;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Action to test a script!
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public class TestScriptProcessStep implements BackendStep
|
||||||
|
{
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Override
|
||||||
|
public void run(RunBackendStepInput input, RunBackendStepOutput output) throws QException
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ActionHelper.validateSession(input);
|
||||||
|
|
||||||
|
////////////////
|
||||||
|
// get inputs //
|
||||||
|
////////////////
|
||||||
|
Integer scriptId = input.getValueInteger("scriptId");
|
||||||
|
String code = input.getValueString("code");
|
||||||
|
|
||||||
|
ScriptRevision scriptRevision = new ScriptRevision();
|
||||||
|
scriptRevision.setScriptId(scriptId);
|
||||||
|
scriptRevision.setContents(code);
|
||||||
|
|
||||||
|
BuildScriptLogAndScriptLogLineExecutionLogger executionLogger = new BuildScriptLogAndScriptLogLineExecutionLogger(null, null);
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// lookup the script - figure out how to proceed based on type //
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
QRecord script = getScript(scriptId);
|
||||||
|
String scriptTypeName = getScriptTypeName(script);
|
||||||
|
|
||||||
|
if(ScriptsMetaDataProvider.SCRIPT_TYPE_NAME_RECORD.equals(scriptTypeName))
|
||||||
|
{
|
||||||
|
String tableName = script.getValueString("tableName");
|
||||||
|
QTableMetaData table = QContext.getQInstance().getTable(tableName);
|
||||||
|
if(table == null)
|
||||||
|
{
|
||||||
|
throw (new QException("Could not find table [" + tableName + "] for script"));
|
||||||
|
}
|
||||||
|
|
||||||
|
String recordPrimaryKeyList = input.getValueString("recordPrimaryKeyList");
|
||||||
|
if(!StringUtils.hasContent(recordPrimaryKeyList))
|
||||||
|
{
|
||||||
|
throw (new QException("Record primary key list was not given."));
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryInput queryInput = new QueryInput();
|
||||||
|
queryInput.setTableName(tableName);
|
||||||
|
queryInput.setFilter(new QQueryFilter(new QFilterCriteria(table.getPrimaryKeyField(), QCriteriaOperator.IN, recordPrimaryKeyList.split(","))));
|
||||||
|
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
||||||
|
if(CollectionUtils.nullSafeIsEmpty(queryOutput.getRecords()))
|
||||||
|
{
|
||||||
|
throw (new QException("No records were found by the given primary keys."));
|
||||||
|
}
|
||||||
|
|
||||||
|
RunAdHocRecordScriptInput runAdHocRecordScriptInput = new RunAdHocRecordScriptInput();
|
||||||
|
runAdHocRecordScriptInput.setRecordList(queryOutput.getRecords());
|
||||||
|
runAdHocRecordScriptInput.setLogger(executionLogger);
|
||||||
|
runAdHocRecordScriptInput.setCodeReference(new AdHocScriptCodeReference().withScriptRevisionRecord(scriptRevision.toQRecord()));
|
||||||
|
RunAdHocRecordScriptOutput runAdHocRecordScriptOutput = new RunAdHocRecordScriptOutput();
|
||||||
|
new RunAdHocRecordScriptAction().run(runAdHocRecordScriptInput, runAdHocRecordScriptOutput);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new QException("This process does not know how to test a script of type: " + scriptTypeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
output.addValue("scriptLogLines", new ArrayList<>(executionLogger.getScriptLogLines()));
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// is this the kind of exception meant here? or is it more for one thrown by the script execution? or are those the same?? //
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
output.addValue("exception", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private QRecord getScript(Integer scriptId) throws QException
|
||||||
|
{
|
||||||
|
GetInput getScriptInput = new GetInput();
|
||||||
|
getScriptInput.setTableName(Script.TABLE_NAME);
|
||||||
|
getScriptInput.setPrimaryKey(scriptId);
|
||||||
|
GetOutput getScriptOutput = new GetAction().execute(getScriptInput);
|
||||||
|
if(getScriptOutput.getRecord() == null)
|
||||||
|
{
|
||||||
|
throw (new QException("Script was not found by id " + scriptId));
|
||||||
|
}
|
||||||
|
|
||||||
|
return (getScriptOutput.getRecord());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private String getScriptTypeName(QRecord script) throws QException
|
||||||
|
{
|
||||||
|
GetInput getScriptTypeInput = new GetInput();
|
||||||
|
getScriptTypeInput.setTableName(ScriptType.TABLE_NAME);
|
||||||
|
getScriptTypeInput.setPrimaryKey(script.getValueInteger("scriptTypeId"));
|
||||||
|
GetOutput getScriptTypeOutput = new GetAction().execute(getScriptTypeInput);
|
||||||
|
if(getScriptTypeOutput.getRecord() == null)
|
||||||
|
{
|
||||||
|
throw (new QException("Script Type was not found for script " + script.getValue("id")));
|
||||||
|
}
|
||||||
|
|
||||||
|
return (getScriptTypeOutput.getRecord().getValueString("name"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Reference in New Issue
Block a user