mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 05:01:07 +00:00
QQQ-37 adding pre & post run to ETL transform & load; minor QOL
This commit is contained in:
@ -41,6 +41,9 @@ public class RecordPipe
|
|||||||
{
|
{
|
||||||
private static final Logger LOG = LogManager.getLogger(RecordPipe.class);
|
private static final Logger LOG = LogManager.getLogger(RecordPipe.class);
|
||||||
|
|
||||||
|
private static final long BLOCKING_SLEEP_MILLIS = 100;
|
||||||
|
private static final long MAX_SLEEP_LOOP_MILLIS = 300_000; // 5 minutes
|
||||||
|
|
||||||
private ArrayBlockingQueue<QRecord> queue = new ArrayBlockingQueue<>(1_000);
|
private ArrayBlockingQueue<QRecord> queue = new ArrayBlockingQueue<>(1_000);
|
||||||
|
|
||||||
private boolean isTerminated = false;
|
private boolean isTerminated = false;
|
||||||
@ -53,6 +56,7 @@ public class RecordPipe
|
|||||||
private List<QRecord> singleRecordListForPostRecordActions = new ArrayList<>();
|
private List<QRecord> singleRecordListForPostRecordActions = new ArrayList<>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Turn off the pipe. Stop accepting new records (just ignore them in the add
|
** Turn off the pipe. Stop accepting new records (just ignore them in the add
|
||||||
** method). Clear the existing queue. Don't return any more records. Note that
|
** method). Clear the existing queue. Don't return any more records. Note that
|
||||||
@ -103,11 +107,22 @@ public class RecordPipe
|
|||||||
{
|
{
|
||||||
boolean offerResult = queue.offer(record);
|
boolean offerResult = queue.offer(record);
|
||||||
|
|
||||||
while(!offerResult && !isTerminated)
|
if(!offerResult && !isTerminated)
|
||||||
{
|
{
|
||||||
LOG.debug("Record pipe.add failed (due to full pipe). Blocking.");
|
long sleepLoopStartTime = System.currentTimeMillis();
|
||||||
SleepUtils.sleep(100, TimeUnit.MILLISECONDS);
|
long now = System.currentTimeMillis();
|
||||||
offerResult = queue.offer(record);
|
while(!offerResult && !isTerminated)
|
||||||
|
{
|
||||||
|
if(now - sleepLoopStartTime > MAX_SLEEP_LOOP_MILLIS)
|
||||||
|
{
|
||||||
|
LOG.warn("Giving up adding record to pipe, due to pipe being full for more than {} millis", MAX_SLEEP_LOOP_MILLIS);
|
||||||
|
throw (new IllegalStateException("Giving up adding record to pipe, due to pipe staying full too long."));
|
||||||
|
}
|
||||||
|
LOG.debug("Record pipe.add failed (due to full pipe). Blocking.");
|
||||||
|
SleepUtils.sleep(BLOCKING_SLEEP_MILLIS, TimeUnit.MILLISECONDS);
|
||||||
|
offerResult = queue.offer(record);
|
||||||
|
now = System.currentTimeMillis();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ public class QPossibleValueTranslator
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public void translatePossibleValuesInRecords(QTableMetaData table, List<QRecord> records)
|
public void translatePossibleValuesInRecords(QTableMetaData table, List<QRecord> records)
|
||||||
{
|
{
|
||||||
if(records == null)
|
if(records == null || table == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -307,8 +307,8 @@ public class QInstanceEnricher
|
|||||||
.withFormField(new QFieldMetaData("theFile", QFieldType.BLOB).withIsRequired(true))
|
.withFormField(new QFieldMetaData("theFile", QFieldType.BLOB).withIsRequired(true))
|
||||||
.withComponent(new QFrontendComponentMetaData()
|
.withComponent(new QFrontendComponentMetaData()
|
||||||
.withType(QComponentType.HELP_TEXT)
|
.withType(QComponentType.HELP_TEXT)
|
||||||
// .withValue("text", "Upload a CSV or XLSX file with the following columns: " + fieldsForHelpText));
|
.withValue("text", "Upload a CSV file with the following columns: " + fieldsForHelpText))
|
||||||
.withValue("text", "Upload a CSV file with the following columns: " + fieldsForHelpText));
|
.withComponent(new QFrontendComponentMetaData().withType(QComponentType.EDIT_FORM));
|
||||||
|
|
||||||
QBackendStepMetaData receiveFileStep = new QBackendStepMetaData()
|
QBackendStepMetaData receiveFileStep = new QBackendStepMetaData()
|
||||||
.withName("receiveFile")
|
.withName("receiveFile")
|
||||||
@ -322,7 +322,9 @@ public class QInstanceEnricher
|
|||||||
.withComponent(new QFrontendComponentMetaData()
|
.withComponent(new QFrontendComponentMetaData()
|
||||||
.withType(QComponentType.HELP_TEXT)
|
.withType(QComponentType.HELP_TEXT)
|
||||||
.withValue("text", "The records below were parsed from your file, and will be inserted if you click Submit."))
|
.withValue("text", "The records below were parsed from your file, and will be inserted if you click Submit."))
|
||||||
.withViewField(new QFieldMetaData("noOfFileRows", QFieldType.INTEGER).withLabel("# of file rows"));
|
.withViewField(new QFieldMetaData("noOfFileRows", QFieldType.INTEGER).withLabel("# of file rows"))
|
||||||
|
.withComponent(new QFrontendComponentMetaData().withType(QComponentType.VIEW_FORM))
|
||||||
|
.withComponent(new QFrontendComponentMetaData().withType(QComponentType.RECORD_LIST));
|
||||||
|
|
||||||
QBackendStepMetaData storeStep = new QBackendStepMetaData()
|
QBackendStepMetaData storeStep = new QBackendStepMetaData()
|
||||||
.withName("storeRecords")
|
.withName("storeRecords")
|
||||||
@ -336,7 +338,9 @@ public class QInstanceEnricher
|
|||||||
.withComponent(new QFrontendComponentMetaData()
|
.withComponent(new QFrontendComponentMetaData()
|
||||||
.withType(QComponentType.HELP_TEXT)
|
.withType(QComponentType.HELP_TEXT)
|
||||||
.withValue("text", "The records below have been inserted."))
|
.withValue("text", "The records below have been inserted."))
|
||||||
.withViewField(new QFieldMetaData("noOfFileRows", QFieldType.INTEGER).withLabel("# of file rows"));
|
.withViewField(new QFieldMetaData("noOfFileRows", QFieldType.INTEGER).withLabel("# of file rows"))
|
||||||
|
.withComponent(new QFrontendComponentMetaData().withType(QComponentType.VIEW_FORM))
|
||||||
|
.withComponent(new QFrontendComponentMetaData().withType(QComponentType.RECORD_LIST));
|
||||||
|
|
||||||
qInstance.addProcess(
|
qInstance.addProcess(
|
||||||
new QProcessMetaData()
|
new QProcessMetaData()
|
||||||
@ -375,9 +379,7 @@ public class QInstanceEnricher
|
|||||||
The values you supply here will be updated in all of the records you are bulk editing.
|
The values you supply here will be updated in all of the records you are bulk editing.
|
||||||
You can clear out the value in a field by flipping the switch on for that field and leaving the input field blank.
|
You can clear out the value in a field by flipping the switch on for that field and leaving the input field blank.
|
||||||
Fields whose switches are off will not be updated."""))
|
Fields whose switches are off will not be updated."""))
|
||||||
.withComponent(new QFrontendComponentMetaData()
|
.withComponent(new QFrontendComponentMetaData().withType(QComponentType.BULK_EDIT_FORM));
|
||||||
.withType(QComponentType.BULK_EDIT_FORM)
|
|
||||||
);
|
|
||||||
|
|
||||||
QBackendStepMetaData receiveValuesStep = new QBackendStepMetaData()
|
QBackendStepMetaData receiveValuesStep = new QBackendStepMetaData()
|
||||||
.withName("receiveValues")
|
.withName("receiveValues")
|
||||||
@ -393,7 +395,9 @@ public class QInstanceEnricher
|
|||||||
.withViewField(new QFieldMetaData(BulkEditReceiveValuesStep.FIELD_VALUES_BEING_UPDATED, QFieldType.STRING))
|
.withViewField(new QFieldMetaData(BulkEditReceiveValuesStep.FIELD_VALUES_BEING_UPDATED, QFieldType.STRING))
|
||||||
.withComponent(new QFrontendComponentMetaData()
|
.withComponent(new QFrontendComponentMetaData()
|
||||||
.withType(QComponentType.HELP_TEXT)
|
.withType(QComponentType.HELP_TEXT)
|
||||||
.withValue("text", "The records below will be updated if you click Submit."));
|
.withValue("text", "The records below will be updated if you click Submit."))
|
||||||
|
.withComponent(new QFrontendComponentMetaData().withType(QComponentType.VIEW_FORM))
|
||||||
|
.withComponent(new QFrontendComponentMetaData().withType(QComponentType.RECORD_LIST));
|
||||||
|
|
||||||
QBackendStepMetaData storeStep = new QBackendStepMetaData()
|
QBackendStepMetaData storeStep = new QBackendStepMetaData()
|
||||||
.withName("storeRecords")
|
.withName("storeRecords")
|
||||||
@ -407,7 +411,9 @@ public class QInstanceEnricher
|
|||||||
.withViewField(new QFieldMetaData(BulkEditReceiveValuesStep.FIELD_VALUES_BEING_UPDATED, QFieldType.STRING))
|
.withViewField(new QFieldMetaData(BulkEditReceiveValuesStep.FIELD_VALUES_BEING_UPDATED, QFieldType.STRING))
|
||||||
.withComponent(new QFrontendComponentMetaData()
|
.withComponent(new QFrontendComponentMetaData()
|
||||||
.withType(QComponentType.HELP_TEXT)
|
.withType(QComponentType.HELP_TEXT)
|
||||||
.withValue("text", "The records below have been updated."));
|
.withValue("text", "The records below have been updated."))
|
||||||
|
.withComponent(new QFrontendComponentMetaData().withType(QComponentType.VIEW_FORM))
|
||||||
|
.withComponent(new QFrontendComponentMetaData().withType(QComponentType.RECORD_LIST));
|
||||||
|
|
||||||
qInstance.addProcess(
|
qInstance.addProcess(
|
||||||
new QProcessMetaData()
|
new QProcessMetaData()
|
||||||
@ -437,7 +443,8 @@ public class QInstanceEnricher
|
|||||||
.withRecordListFields(new ArrayList<>(table.getFields().values()))
|
.withRecordListFields(new ArrayList<>(table.getFields().values()))
|
||||||
.withComponent(new QFrontendComponentMetaData()
|
.withComponent(new QFrontendComponentMetaData()
|
||||||
.withType(QComponentType.HELP_TEXT)
|
.withType(QComponentType.HELP_TEXT)
|
||||||
.withValue("text", "The records below will be deleted if you click Submit."));
|
.withValue("text", "The records below will be deleted if you click Submit."))
|
||||||
|
.withComponent(new QFrontendComponentMetaData().withType(QComponentType.RECORD_LIST));
|
||||||
|
|
||||||
QBackendStepMetaData storeStep = new QBackendStepMetaData()
|
QBackendStepMetaData storeStep = new QBackendStepMetaData()
|
||||||
.withName("delete")
|
.withName("delete")
|
||||||
@ -448,7 +455,8 @@ public class QInstanceEnricher
|
|||||||
.withRecordListFields(new ArrayList<>(table.getFields().values()))
|
.withRecordListFields(new ArrayList<>(table.getFields().values()))
|
||||||
.withComponent(new QFrontendComponentMetaData()
|
.withComponent(new QFrontendComponentMetaData()
|
||||||
.withType(QComponentType.HELP_TEXT)
|
.withType(QComponentType.HELP_TEXT)
|
||||||
.withValue("text", "The records below have been deleted."));
|
.withValue("text", "The records below have been deleted."))
|
||||||
|
.withComponent(new QFrontendComponentMetaData().withType(QComponentType.RECORD_LIST));
|
||||||
|
|
||||||
qInstance.addProcess(
|
qInstance.addProcess(
|
||||||
new QProcessMetaData()
|
new QProcessMetaData()
|
||||||
@ -569,6 +577,7 @@ public class QInstanceEnricher
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** If a table didn't have any sections, generate "sensible defaults"
|
** If a table didn't have any sections, generate "sensible defaults"
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
@ -76,6 +76,17 @@ public class QFieldMetaData
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return ("QFieldMetaData[" + name + "]");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Initialize a fieldMetaData from a reference to a getter on an entity.
|
** Initialize a fieldMetaData from a reference to a getter on an entity.
|
||||||
** e.g., new QFieldMetaData(Order::getOrderNo).
|
** e.g., new QFieldMetaData(Order::getOrderNo).
|
||||||
|
@ -51,6 +51,17 @@ public class QProcessMetaData implements QAppChildMetaData
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return ("QProcessMetaData[" + name + "]");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Getter for name
|
** Getter for name
|
||||||
**
|
**
|
||||||
|
@ -8,6 +8,7 @@ import com.kingsrook.qqq.backend.core.actions.QBackendTransaction;
|
|||||||
import com.kingsrook.qqq.backend.core.actions.processes.BackendStep;
|
import com.kingsrook.qqq.backend.core.actions.processes.BackendStep;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
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.RunBackendStepInput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepOutput;
|
||||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||||
|
|
||||||
|
|
||||||
@ -29,6 +30,32 @@ public abstract class AbstractLoadStep implements BackendStep
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Allow subclasses to do an action before the run is complete - before any
|
||||||
|
** pages of records are passed in.
|
||||||
|
*******************************************************************************/
|
||||||
|
public void preRun(RunBackendStepInput runBackendStepInput, RunBackendStepOutput runBackendStepOutput) throws QException
|
||||||
|
{
|
||||||
|
////////////////////////
|
||||||
|
// noop in base class //
|
||||||
|
////////////////////////
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Allow subclasses to do an action after the run is complete - after the last
|
||||||
|
** page of records is passed in.
|
||||||
|
*******************************************************************************/
|
||||||
|
public void postRun(RunBackendStepInput runBackendStepInput, RunBackendStepOutput runBackendStepOutput) throws QException
|
||||||
|
{
|
||||||
|
////////////////////////
|
||||||
|
// noop in base class //
|
||||||
|
////////////////////////
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
@ -4,6 +4,9 @@ package com.kingsrook.qqq.backend.core.processes.implementations.etl.streamedwit
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import com.kingsrook.qqq.backend.core.actions.processes.BackendStep;
|
import com.kingsrook.qqq.backend.core.actions.processes.BackendStep;
|
||||||
|
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.data.QRecord;
|
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||||
|
|
||||||
|
|
||||||
@ -16,11 +19,37 @@ import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public abstract class AbstractTransformStep implements BackendStep
|
public abstract class AbstractTransformStep implements BackendStep
|
||||||
{
|
{
|
||||||
private List<QRecord> inputRecordPage = new ArrayList<>();
|
private List<QRecord> inputRecordPage = new ArrayList<>();
|
||||||
private List<QRecord> outputRecordPage = new ArrayList<>();
|
private List<QRecord> outputRecordPage = new ArrayList<>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Allow subclasses to do an action before the run is complete - before any
|
||||||
|
** pages of records are passed in.
|
||||||
|
*******************************************************************************/
|
||||||
|
public void preRun(RunBackendStepInput runBackendStepInput, RunBackendStepOutput runBackendStepOutput) throws QException
|
||||||
|
{
|
||||||
|
////////////////////////
|
||||||
|
// noop in base class //
|
||||||
|
////////////////////////
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Allow subclasses to do an action after the run is complete - after the last
|
||||||
|
** page of records is passed in.
|
||||||
|
*******************************************************************************/
|
||||||
|
public void postRun(RunBackendStepInput runBackendStepInput, RunBackendStepOutput runBackendStepOutput) throws QException
|
||||||
|
{
|
||||||
|
////////////////////////
|
||||||
|
// noop in base class //
|
||||||
|
////////////////////////
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Getter for recordPage
|
** Getter for recordPage
|
||||||
**
|
**
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
package com.kingsrook.qqq.backend.core.processes.implementations.etl.streamedwithfrontend;
|
package com.kingsrook.qqq.backend.core.processes.implementations.etl.streamedwithfrontend;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import com.kingsrook.qqq.backend.core.actions.customizers.QCodeLoader;
|
import com.kingsrook.qqq.backend.core.actions.customizers.QCodeLoader;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.values.QPossibleValueTranslator;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.values.QValueFormatter;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput;
|
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||||
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.tables.QTableMetaData;
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -46,4 +51,23 @@ public class BaseStreamedETLStep
|
|||||||
return (QCodeLoader.getBackendStep(AbstractLoadStep.class, codeReference));
|
return (QCodeLoader.getBackendStep(AbstractLoadStep.class, codeReference));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
protected void updateRecordsWithDisplayValuesAndPossibleValues(RunBackendStepInput input, List<QRecord> list)
|
||||||
|
{
|
||||||
|
String destinationTable = input.getValueString(StreamedETLWithFrontendProcess.FIELD_DESTINATION_TABLE);
|
||||||
|
QTableMetaData table = input.getInstance().getTable(destinationTable);
|
||||||
|
|
||||||
|
if(table != null && list != null)
|
||||||
|
{
|
||||||
|
QValueFormatter qValueFormatter = new QValueFormatter();
|
||||||
|
qValueFormatter.setDisplayValuesInRecords(table, list);
|
||||||
|
|
||||||
|
QPossibleValueTranslator qPossibleValueTranslator = new QPossibleValueTranslator(input.getInstance(), input.getSession());
|
||||||
|
qPossibleValueTranslator.translatePossibleValuesInRecords(input.getTable(), list);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,6 +67,8 @@ public class StreamedETLExecuteStep extends BaseStreamedETLStep implements Backe
|
|||||||
AbstractTransformStep transformStep = getTransformStep(runBackendStepInput);
|
AbstractTransformStep transformStep = getTransformStep(runBackendStepInput);
|
||||||
AbstractLoadStep loadStep = getLoadStep(runBackendStepInput);
|
AbstractLoadStep loadStep = getLoadStep(runBackendStepInput);
|
||||||
|
|
||||||
|
transformStep.preRun(runBackendStepInput, runBackendStepOutput);
|
||||||
|
|
||||||
transaction = loadStep.openTransaction(runBackendStepInput);
|
transaction = loadStep.openTransaction(runBackendStepInput);
|
||||||
loadStep.setTransaction(transaction);
|
loadStep.setTransaction(transaction);
|
||||||
|
|
||||||
@ -80,15 +82,9 @@ public class StreamedETLExecuteStep extends BaseStreamedETLStep implements Backe
|
|||||||
);
|
);
|
||||||
|
|
||||||
runBackendStepOutput.addValue(StreamedETLWithFrontendProcess.FIELD_RECORD_COUNT, recordCount);
|
runBackendStepOutput.addValue(StreamedETLWithFrontendProcess.FIELD_RECORD_COUNT, recordCount);
|
||||||
runBackendStepOutput.setRecords(loadedRecordList);
|
|
||||||
|
|
||||||
/////////////////////
|
updateRecordsWithDisplayValuesAndPossibleValues(runBackendStepInput, loadedRecordList);
|
||||||
// commit the work //
|
runBackendStepOutput.setRecords(loadedRecordList);
|
||||||
/////////////////////
|
|
||||||
if(transaction.isPresent())
|
|
||||||
{
|
|
||||||
transaction.get().commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(transformStep instanceof ProcessSummaryProviderInterface processSummaryProvider)
|
if(transformStep instanceof ProcessSummaryProviderInterface processSummaryProvider)
|
||||||
{
|
{
|
||||||
@ -98,6 +94,17 @@ public class StreamedETLExecuteStep extends BaseStreamedETLStep implements Backe
|
|||||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
runBackendStepOutput.addValue(StreamedETLWithFrontendProcess.FIELD_PROCESS_SUMMARY, processSummaryProvider.getProcessSummary(true));
|
runBackendStepOutput.addValue(StreamedETLWithFrontendProcess.FIELD_PROCESS_SUMMARY, processSummaryProvider.getProcessSummary(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
transformStep.postRun(runBackendStepInput, runBackendStepOutput);
|
||||||
|
loadStep.postRun(runBackendStepInput, runBackendStepOutput);
|
||||||
|
|
||||||
|
/////////////////////
|
||||||
|
// commit the work //
|
||||||
|
/////////////////////
|
||||||
|
if(transaction.isPresent())
|
||||||
|
{
|
||||||
|
transaction.get().commit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
{
|
{
|
||||||
|
@ -90,6 +90,7 @@ public class StreamedETLPreviewStep extends BaseStreamedETLStep implements Backe
|
|||||||
extractStep.setRecordPipe(recordPipe);
|
extractStep.setRecordPipe(recordPipe);
|
||||||
|
|
||||||
AbstractTransformStep transformStep = getTransformStep(runBackendStepInput);
|
AbstractTransformStep transformStep = getTransformStep(runBackendStepInput);
|
||||||
|
transformStep.preRun(runBackendStepInput, runBackendStepOutput);
|
||||||
|
|
||||||
List<QRecord> previewRecordList = new ArrayList<>();
|
List<QRecord> previewRecordList = new ArrayList<>();
|
||||||
new AsyncRecordPipeLoop().run("StreamedETL>Preview>ExtractStep", PROCESS_OUTPUT_RECORD_LIST_LIMIT, recordPipe, (status) ->
|
new AsyncRecordPipeLoop().run("StreamedETL>Preview>ExtractStep", PROCESS_OUTPUT_RECORD_LIST_LIMIT, recordPipe, (status) ->
|
||||||
@ -100,7 +101,10 @@ public class StreamedETLPreviewStep extends BaseStreamedETLStep implements Backe
|
|||||||
() -> (consumeRecordsFromPipe(recordPipe, transformStep, runBackendStepInput, runBackendStepOutput, previewRecordList))
|
() -> (consumeRecordsFromPipe(recordPipe, transformStep, runBackendStepInput, runBackendStepOutput, previewRecordList))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
updateRecordsWithDisplayValuesAndPossibleValues(runBackendStepInput, previewRecordList);
|
||||||
runBackendStepOutput.setRecords(previewRecordList);
|
runBackendStepOutput.setRecords(previewRecordList);
|
||||||
|
|
||||||
|
transformStep.postRun(runBackendStepInput, runBackendStepOutput);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -94,11 +94,13 @@ public class StreamedETLValidateStep extends BaseStreamedETLStep implements Back
|
|||||||
AbstractTransformStep transformStep = getTransformStep(runBackendStepInput);
|
AbstractTransformStep transformStep = getTransformStep(runBackendStepInput);
|
||||||
if(!(transformStep instanceof ProcessSummaryProviderInterface processSummaryProvider))
|
if(!(transformStep instanceof ProcessSummaryProviderInterface processSummaryProvider))
|
||||||
{
|
{
|
||||||
|
// todo - really? if this is required, then put it on the AbstractTransformStep class
|
||||||
throw (new QException("Transform Step " + transformStep.getClass().getName() + " does not implement ProcessSummaryProviderInterface."));
|
throw (new QException("Transform Step " + transformStep.getClass().getName() + " does not implement ProcessSummaryProviderInterface."));
|
||||||
}
|
}
|
||||||
|
transformStep.preRun(runBackendStepInput, runBackendStepOutput);
|
||||||
|
|
||||||
List<QRecord> previewRecordList = new ArrayList<>();
|
List<QRecord> previewRecordList = new ArrayList<>();
|
||||||
int recordCount = new AsyncRecordPipeLoop().run("StreamedETL>Preview>ValidateStep", PROCESS_OUTPUT_RECORD_LIST_LIMIT, recordPipe, (status) ->
|
int recordCount = new AsyncRecordPipeLoop().run("StreamedETL>Preview>ValidateStep", null, recordPipe, (status) ->
|
||||||
{
|
{
|
||||||
extractStep.run(runBackendStepInput, runBackendStepOutput);
|
extractStep.run(runBackendStepInput, runBackendStepOutput);
|
||||||
return (runBackendStepOutput);
|
return (runBackendStepOutput);
|
||||||
@ -106,6 +108,7 @@ public class StreamedETLValidateStep extends BaseStreamedETLStep implements Back
|
|||||||
() -> (consumeRecordsFromPipe(recordPipe, transformStep, runBackendStepInput, runBackendStepOutput, previewRecordList))
|
() -> (consumeRecordsFromPipe(recordPipe, transformStep, runBackendStepInput, runBackendStepOutput, previewRecordList))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
updateRecordsWithDisplayValuesAndPossibleValues(runBackendStepInput, previewRecordList);
|
||||||
runBackendStepOutput.setRecords(previewRecordList);
|
runBackendStepOutput.setRecords(previewRecordList);
|
||||||
runBackendStepOutput.addValue(StreamedETLWithFrontendProcess.FIELD_RECORD_COUNT, recordCount);
|
runBackendStepOutput.addValue(StreamedETLWithFrontendProcess.FIELD_RECORD_COUNT, recordCount);
|
||||||
|
|
||||||
@ -113,6 +116,8 @@ public class StreamedETLValidateStep extends BaseStreamedETLStep implements Back
|
|||||||
// get the process summary from the validation step //
|
// get the process summary from the validation step //
|
||||||
//////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////
|
||||||
runBackendStepOutput.addValue(StreamedETLWithFrontendProcess.FIELD_VALIDATION_SUMMARY, processSummaryProvider.getProcessSummary(false));
|
runBackendStepOutput.addValue(StreamedETLWithFrontendProcess.FIELD_VALIDATION_SUMMARY, processSummaryProvider.getProcessSummary(false));
|
||||||
|
|
||||||
|
transformStep.postRun(runBackendStepInput, runBackendStepOutput);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -78,6 +78,10 @@ public class StreamedETLWithFrontendProcess
|
|||||||
public static final String FIELD_VALIDATION_SUMMARY = "validationSummary"; // List<ProcessSummaryLine>
|
public static final String FIELD_VALIDATION_SUMMARY = "validationSummary"; // List<ProcessSummaryLine>
|
||||||
public static final String FIELD_PROCESS_SUMMARY = "processResults"; // List<ProcessSummaryLine>
|
public static final String FIELD_PROCESS_SUMMARY = "processResults"; // List<ProcessSummaryLine>
|
||||||
|
|
||||||
|
public static final String DEFAULT_PREVIEW_MESSAGE_FOR_INSERT = "This is a preview of the records that will be created.";
|
||||||
|
public static final String DEFAULT_PREVIEW_MESSAGE_FOR_UPDATE = "This is a preview of the records that will be updated.";
|
||||||
|
public static final String FIELD_PREVIEW_MESSAGE = "previewMessage";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -106,6 +110,7 @@ public class StreamedETLWithFrontendProcess
|
|||||||
** - FIELD_SUPPORTS_FULL_VALIDATION
|
** - FIELD_SUPPORTS_FULL_VALIDATION
|
||||||
** - FIELD_DEFAULT_QUERY_FILTER
|
** - FIELD_DEFAULT_QUERY_FILTER
|
||||||
** - FIELD_DO_FULL_VALIDATION
|
** - FIELD_DO_FULL_VALIDATION
|
||||||
|
** - FIELD_PREVIEW_MESSAGE
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public static QProcessMetaData defineProcessMetaData(
|
public static QProcessMetaData defineProcessMetaData(
|
||||||
Class<? extends AbstractExtractStep> extractStepClass,
|
Class<? extends AbstractExtractStep> extractStepClass,
|
||||||
@ -119,10 +124,12 @@ public class StreamedETLWithFrontendProcess
|
|||||||
.withCode(new QCodeReference(StreamedETLPreviewStep.class))
|
.withCode(new QCodeReference(StreamedETLPreviewStep.class))
|
||||||
.withInputData(new QFunctionInputMetaData()
|
.withInputData(new QFunctionInputMetaData()
|
||||||
.withField(new QFieldMetaData(FIELD_SOURCE_TABLE, QFieldType.STRING).withDefaultValue(defaultFieldValues.get(FIELD_SOURCE_TABLE)))
|
.withField(new QFieldMetaData(FIELD_SOURCE_TABLE, QFieldType.STRING).withDefaultValue(defaultFieldValues.get(FIELD_SOURCE_TABLE)))
|
||||||
|
.withField(new QFieldMetaData(FIELD_DESTINATION_TABLE, QFieldType.STRING).withDefaultValue(defaultFieldValues.get(FIELD_DESTINATION_TABLE)))
|
||||||
.withField(new QFieldMetaData(FIELD_SUPPORTS_FULL_VALIDATION, QFieldType.BOOLEAN).withDefaultValue(defaultFieldValues.getOrDefault(FIELD_SUPPORTS_FULL_VALIDATION, false)))
|
.withField(new QFieldMetaData(FIELD_SUPPORTS_FULL_VALIDATION, QFieldType.BOOLEAN).withDefaultValue(defaultFieldValues.getOrDefault(FIELD_SUPPORTS_FULL_VALIDATION, false)))
|
||||||
.withField(new QFieldMetaData(FIELD_DEFAULT_QUERY_FILTER, QFieldType.STRING).withDefaultValue(defaultFieldValues.get(FIELD_DEFAULT_QUERY_FILTER)))
|
.withField(new QFieldMetaData(FIELD_DEFAULT_QUERY_FILTER, QFieldType.STRING).withDefaultValue(defaultFieldValues.get(FIELD_DEFAULT_QUERY_FILTER)))
|
||||||
.withField(new QFieldMetaData(FIELD_EXTRACT_CODE, QFieldType.STRING).withDefaultValue(new QCodeReference(extractStepClass)))
|
.withField(new QFieldMetaData(FIELD_EXTRACT_CODE, QFieldType.STRING).withDefaultValue(new QCodeReference(extractStepClass)))
|
||||||
.withField(new QFieldMetaData(FIELD_TRANSFORM_CODE, QFieldType.STRING).withDefaultValue(new QCodeReference(transformStepClass)))
|
.withField(new QFieldMetaData(FIELD_TRANSFORM_CODE, QFieldType.STRING).withDefaultValue(new QCodeReference(transformStepClass)))
|
||||||
|
.withField(new QFieldMetaData(FIELD_PREVIEW_MESSAGE, QFieldType.STRING).withDefaultValue(defaultFieldValues.getOrDefault(FIELD_PREVIEW_MESSAGE, DEFAULT_PREVIEW_MESSAGE_FOR_INSERT)))
|
||||||
);
|
);
|
||||||
|
|
||||||
QFrontendStepMetaData reviewStep = new QFrontendStepMetaData()
|
QFrontendStepMetaData reviewStep = new QFrontendStepMetaData()
|
||||||
@ -142,7 +149,6 @@ public class StreamedETLWithFrontendProcess
|
|||||||
.withName(STEP_NAME_EXECUTE)
|
.withName(STEP_NAME_EXECUTE)
|
||||||
.withCode(new QCodeReference(StreamedETLExecuteStep.class))
|
.withCode(new QCodeReference(StreamedETLExecuteStep.class))
|
||||||
.withInputData(new QFunctionInputMetaData()
|
.withInputData(new QFunctionInputMetaData()
|
||||||
.withField(new QFieldMetaData(FIELD_DESTINATION_TABLE, QFieldType.STRING).withDefaultValue(defaultFieldValues.get(FIELD_DESTINATION_TABLE)))
|
|
||||||
.withField(new QFieldMetaData(FIELD_LOAD_CODE, QFieldType.STRING).withDefaultValue(new QCodeReference(loadStepClass))))
|
.withField(new QFieldMetaData(FIELD_LOAD_CODE, QFieldType.STRING).withDefaultValue(new QCodeReference(loadStepClass))))
|
||||||
.withOutputMetaData(new QFunctionOutputMetaData()
|
.withOutputMetaData(new QFunctionOutputMetaData()
|
||||||
.withField(new QFieldMetaData(FIELD_PROCESS_SUMMARY, QFieldType.STRING))
|
.withField(new QFieldMetaData(FIELD_PROCESS_SUMMARY, QFieldType.STRING))
|
||||||
|
@ -24,6 +24,7 @@ package com.kingsrook.qqq.backend.javalin;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -443,16 +444,21 @@ public class QJavalinProcessHandler
|
|||||||
}
|
}
|
||||||
ProcessState processState = optionalProcessState.get();
|
ProcessState processState = optionalProcessState.get();
|
||||||
|
|
||||||
List<QRecord> records = processState.getRecords();
|
List<QRecord> records = processState.getRecords();
|
||||||
if(CollectionUtils.nullSafeIsEmpty(records))
|
Map<String, Object> resultForCaller = new HashMap<>();
|
||||||
|
|
||||||
|
if(records == null)
|
||||||
{
|
{
|
||||||
throw (new Exception("No records were found for the process."));
|
resultForCaller.put("records", new ArrayList<>());
|
||||||
|
resultForCaller.put("totalRecords", 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
List<QRecord> recordPage = CollectionUtils.safelyGetPage(records, skip, limit);
|
||||||
|
resultForCaller.put("records", recordPage);
|
||||||
|
resultForCaller.put("totalRecords", records.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, Object> resultForCaller = new HashMap<>();
|
|
||||||
List<QRecord> recordPage = CollectionUtils.safelyGetPage(records, skip, limit);
|
|
||||||
resultForCaller.put("records", recordPage);
|
|
||||||
resultForCaller.put("totalRecords", records.size());
|
|
||||||
context.result(JsonUtils.toJson(resultForCaller));
|
context.result(JsonUtils.toJson(resultForCaller));
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
|
@ -402,6 +402,7 @@ public class SampleMetaDataProvider
|
|||||||
values.put(StreamedETLWithFrontendProcess.FIELD_SOURCE_TABLE, TABLE_NAME_PERSON);
|
values.put(StreamedETLWithFrontendProcess.FIELD_SOURCE_TABLE, TABLE_NAME_PERSON);
|
||||||
values.put(StreamedETLWithFrontendProcess.FIELD_DESTINATION_TABLE, TABLE_NAME_PERSON);
|
values.put(StreamedETLWithFrontendProcess.FIELD_DESTINATION_TABLE, TABLE_NAME_PERSON);
|
||||||
values.put(StreamedETLWithFrontendProcess.FIELD_SUPPORTS_FULL_VALIDATION, true);
|
values.put(StreamedETLWithFrontendProcess.FIELD_SUPPORTS_FULL_VALIDATION, true);
|
||||||
|
values.put(StreamedETLWithFrontendProcess.FIELD_PREVIEW_MESSAGE, "This is a preview of what the clones will look like.");
|
||||||
|
|
||||||
QProcessMetaData process = StreamedETLWithFrontendProcess.defineProcessMetaData(
|
QProcessMetaData process = StreamedETLWithFrontendProcess.defineProcessMetaData(
|
||||||
ExtractViaQueryStep.class,
|
ExtractViaQueryStep.class,
|
||||||
|
Reference in New Issue
Block a user