mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-19 05:30:43 +00:00
QQQ-40 getting closer to production-ready on automations
This commit is contained in:
@ -11,12 +11,10 @@ import com.kingsrook.qqq.backend.core.actions.automation.AutomationStatus;
|
||||
import com.kingsrook.qqq.backend.core.actions.automation.RecordAutomationHandler;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.InsertAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.QueryAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.UpdateAction;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput;
|
||||
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.actions.tables.update.UpdateInput;
|
||||
import com.kingsrook.qqq.backend.core.model.automation.RecordAutomationInput;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||
@ -99,56 +97,6 @@ class PollingAutomationExecutorTest
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testUpdate() throws QException
|
||||
{
|
||||
QInstance qInstance = TestUtils.defineInstance();
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// insert 2 people - one who should be logged by logger-on-update automation //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
InsertInput insertInput = new InsertInput(qInstance);
|
||||
insertInput.setSession(new QSession());
|
||||
insertInput.setTableName(TestUtils.TABLE_NAME_PERSON_MEMORY);
|
||||
insertInput.setRecords(List.of(
|
||||
new QRecord().withValue("id", 1).withValue("firstName", "Tim"),
|
||||
new QRecord().withValue("id", 2).withValue("firstName", "Darin")
|
||||
));
|
||||
new InsertAction().execute(insertInput);
|
||||
|
||||
////////////////////////////////////////////////
|
||||
// have the polling executor run "for awhile" //
|
||||
////////////////////////////////////////////////
|
||||
runPollingAutomationExecutorForAwhile(qInstance);
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// assert that the update-automation didn't run //
|
||||
//////////////////////////////////////////////////
|
||||
assertThat(TestUtils.LogPersonUpdate.updatedIds).isNullOrEmpty();
|
||||
|
||||
UpdateInput updateInput = new UpdateInput(qInstance);
|
||||
updateInput.setSession(new QSession());
|
||||
updateInput.setTableName(TestUtils.TABLE_NAME_PERSON_MEMORY);
|
||||
updateInput.setRecords(List.of(
|
||||
new QRecord().withValue("id", 1).withValue("lastName", "now with a LastName"),
|
||||
new QRecord().withValue("id", 2).withValue("lastName", "now with a LastName")
|
||||
));
|
||||
new UpdateAction().execute(updateInput);
|
||||
|
||||
////////////////////////////////////////////////
|
||||
// have the polling executor run "for awhile" //
|
||||
////////////////////////////////////////////////
|
||||
runPollingAutomationExecutorForAwhile(qInstance);
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// assert that the update-automation DID run now //
|
||||
///////////////////////////////////////////////////
|
||||
assertThat(TestUtils.LogPersonUpdate.updatedIds).contains(2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -166,14 +114,14 @@ class PollingAutomationExecutorTest
|
||||
.getAutomationDetails().getActions().get(0)
|
||||
.setCodeReference(new QCodeReference(CaptureSessionIdAutomationHandler.class));
|
||||
|
||||
/////////////////////
|
||||
// insert a person //
|
||||
/////////////////////
|
||||
////////////////////////////////////////////////////////////
|
||||
// insert a person that will trigger the on-insert action //
|
||||
////////////////////////////////////////////////////////////
|
||||
InsertInput insertInput = new InsertInput(qInstance);
|
||||
insertInput.setSession(new QSession());
|
||||
insertInput.setTableName(TestUtils.TABLE_NAME_PERSON_MEMORY);
|
||||
insertInput.setRecords(List.of(
|
||||
new QRecord().withValue("id", 1).withValue("firstName", "Tim")
|
||||
new QRecord().withValue("id", 1).withValue("firstName", "Tim").withValue("birthDate", LocalDate.now())
|
||||
));
|
||||
new InsertAction().execute(insertInput);
|
||||
|
||||
|
@ -0,0 +1,226 @@
|
||||
package com.kingsrook.qqq.backend.core.actions.automation.polling;
|
||||
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.Month;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import com.kingsrook.qqq.backend.core.actions.automation.AutomationStatus;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.InsertAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.UpdateAction;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.update.UpdateInput;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||
import com.kingsrook.qqq.backend.core.model.session.QSession;
|
||||
import com.kingsrook.qqq.backend.core.modules.backend.implementations.memory.MemoryRecordStore;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for PollingAutomationRunner
|
||||
*******************************************************************************/
|
||||
class PollingAutomationRunnerTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@BeforeEach
|
||||
@AfterEach
|
||||
void beforeAndAfterEach()
|
||||
{
|
||||
MemoryRecordStore.getInstance().reset();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Test a cycle that does an insert, some automations, then and an update, and more automations.
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testInsertAndUpdate() throws QException
|
||||
{
|
||||
QInstance qInstance = TestUtils.defineInstance();
|
||||
PollingAutomationRunner pollingAutomationRunner = new PollingAutomationRunner(qInstance, TestUtils.POLLING_AUTOMATION, null);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// insert 2 person records, one who should be both updated by the insert action, and should be logged by logger-on-update automation //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
InsertInput insertInput = new InsertInput(qInstance);
|
||||
insertInput.setSession(new QSession());
|
||||
insertInput.setTableName(TestUtils.TABLE_NAME_PERSON_MEMORY);
|
||||
insertInput.setRecords(List.of(
|
||||
new QRecord().withValue("id", 1).withValue("firstName", "Tim").withValue("birthDate", LocalDate.now()),
|
||||
new QRecord().withValue("id", 2).withValue("firstName", "Darin")
|
||||
));
|
||||
new InsertAction().execute(insertInput);
|
||||
assertAllRecordsAutomationStatus(AutomationStatus.PENDING_INSERT_AUTOMATIONS);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// assert that the update-automation won't run - as no UPDATE has happened on the table //
|
||||
// even though the insert action does update the records!! //
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
pollingAutomationRunner.run();
|
||||
assertThat(TestUtils.LogPersonUpdate.updatedIds).isNullOrEmpty();
|
||||
assertAllRecordsAutomationStatus(AutomationStatus.OK);
|
||||
|
||||
////////////////////////////////////////////
|
||||
// make sure the minor person was updated //
|
||||
////////////////////////////////////////////
|
||||
Optional<QRecord> updatedMinorRecord = TestUtils.queryTable(TestUtils.TABLE_NAME_PERSON_MEMORY).stream().filter(r -> r.getValueInteger("id").equals(1)).findFirst();
|
||||
assertThat(updatedMinorRecord)
|
||||
.isPresent()
|
||||
.get()
|
||||
.extracting(r -> r.getValueString("firstName"))
|
||||
.isEqualTo("Tim" + TestUtils.CheckAge.SUFFIX_FOR_MINORS);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// run automations again - make sure that there haven't been any updates triggered yet //
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
pollingAutomationRunner.run();
|
||||
assertThat(TestUtils.LogPersonUpdate.updatedIds).isNullOrEmpty();
|
||||
assertAllRecordsAutomationStatus(AutomationStatus.OK);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// now do an user-driven update - this SHOULD trigger the update automation next time we run automations. //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
UpdateInput updateInput = new UpdateInput(qInstance);
|
||||
updateInput.setSession(new QSession());
|
||||
updateInput.setTableName(TestUtils.TABLE_NAME_PERSON_MEMORY);
|
||||
updateInput.setRecords(List.of(
|
||||
new QRecord().withValue("id", 1).withValue("lastName", "now with a LastName"),
|
||||
new QRecord().withValue("id", 2).withValue("lastName", "now with a LastName")
|
||||
));
|
||||
new UpdateAction().execute(updateInput);
|
||||
assertAllRecordsAutomationStatus(AutomationStatus.PENDING_UPDATE_AUTOMATIONS);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
// assert that the update-automation DOES run now - and that it only runs once //
|
||||
// note that it will only run on a sub-set of the records //
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
pollingAutomationRunner.run();
|
||||
assertThat(TestUtils.LogPersonUpdate.updatedIds)
|
||||
.contains(2)
|
||||
.hasSize(1);
|
||||
assertAllRecordsAutomationStatus(AutomationStatus.OK);
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// re-run and assert no further automations happen //
|
||||
/////////////////////////////////////////////////////
|
||||
TestUtils.LogPersonUpdate.updatedIds.clear();
|
||||
pollingAutomationRunner.run();
|
||||
assertThat(TestUtils.LogPersonUpdate.updatedIds).isNullOrEmpty();
|
||||
assertAllRecordsAutomationStatus(AutomationStatus.OK);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Test a large-ish number - to demonstrate paging working.
|
||||
**
|
||||
** Note - this caught an issue during original development, where the QueryFilter
|
||||
** attached to the Action was being re-used, w/ new "id IN *" criteria being re-added
|
||||
** to it - so, good test.
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testMultiPages() throws QException
|
||||
{
|
||||
QInstance qInstance = TestUtils.defineInstance();
|
||||
PollingAutomationRunner pollingAutomationRunner = new PollingAutomationRunner(qInstance, TestUtils.POLLING_AUTOMATION, null);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// insert many people - half who should be updated by the AgeChecker automation //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
InsertInput insertInput = new InsertInput(qInstance);
|
||||
insertInput.setSession(new QSession());
|
||||
insertInput.setTableName(TestUtils.TABLE_NAME_PERSON_MEMORY);
|
||||
|
||||
insertInput.setRecords(new ArrayList<>());
|
||||
int SIZE = 2_500;
|
||||
for(int i = 0; i < SIZE; i++)
|
||||
{
|
||||
insertInput.getRecords().add(new QRecord().withValue("firstName", "Tim").withValue("lastName", "Number " + i).withValue("birthDate", LocalDate.now()));
|
||||
insertInput.getRecords().add(new QRecord().withValue("firstName", "Darin").withValue("lastName", "Number " + i));
|
||||
}
|
||||
|
||||
new InsertAction().execute(insertInput);
|
||||
assertAllRecordsAutomationStatus(AutomationStatus.PENDING_INSERT_AUTOMATIONS);
|
||||
|
||||
/////////////////////////
|
||||
// run the automations //
|
||||
/////////////////////////
|
||||
pollingAutomationRunner.run();
|
||||
assertAllRecordsAutomationStatus(AutomationStatus.OK);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// make sure that all 'minor' persons were updated (e.g., all the Tim's) //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
int updatedMinorsCount = 0;
|
||||
for(QRecord qRecord : TestUtils.queryTable(TestUtils.TABLE_NAME_PERSON_MEMORY))
|
||||
{
|
||||
if(qRecord.getValueString("firstName").startsWith("Tim"))
|
||||
{
|
||||
assertEquals("Tim" + TestUtils.CheckAge.SUFFIX_FOR_MINORS, qRecord.getValueString("firstName"));
|
||||
updatedMinorsCount++;
|
||||
}
|
||||
}
|
||||
|
||||
assertEquals(SIZE, updatedMinorsCount, "Expected number of updated records");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Test a cycle that does an insert, some automations, then and an update, and more automations.
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testRunningProcess() throws QException
|
||||
{
|
||||
QInstance qInstance = TestUtils.defineInstance();
|
||||
PollingAutomationRunner pollingAutomationRunner = new PollingAutomationRunner(qInstance, TestUtils.POLLING_AUTOMATION, null);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// insert 2 person records, one who should be both updated by the insert action, and should be logged by logger-on-update automation //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
InsertInput insertInput = new InsertInput(qInstance);
|
||||
insertInput.setSession(new QSession());
|
||||
insertInput.setTableName(TestUtils.TABLE_NAME_PERSON_MEMORY);
|
||||
insertInput.setRecords(List.of(
|
||||
new QRecord().withValue("id", 1).withValue("firstName", "Tim").withValue("birthDate", LocalDate.of(1886, Month.JUNE, 6)),
|
||||
new QRecord().withValue("id", 2).withValue("firstName", "Darin").withValue("birthDate", LocalDate.of(1904, Month.APRIL, 4))
|
||||
));
|
||||
new InsertAction().execute(insertInput);
|
||||
|
||||
pollingAutomationRunner.run();
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// make sure the process ran - which means, it would have updated Tim's birth year to 1900 //
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Optional<QRecord> updatedMinorRecord = TestUtils.queryTable(TestUtils.TABLE_NAME_PERSON_MEMORY).stream().filter(r -> r.getValueInteger("id").equals(1)).findFirst();
|
||||
assertThat(updatedMinorRecord)
|
||||
.isPresent()
|
||||
.get()
|
||||
.extracting(r -> r.getValueLocalDate("birthDate").getYear())
|
||||
.isEqualTo(1900);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private void assertAllRecordsAutomationStatus(AutomationStatus pendingInsertAutomations) throws QException
|
||||
{
|
||||
assertThat(TestUtils.queryTable(TestUtils.TABLE_NAME_PERSON_MEMORY))
|
||||
.isNotEmpty()
|
||||
.allMatch(r -> pendingInsertAutomations.getId().equals(r.getValue(TestUtils.standardQqqAutomationStatusField().getName())));
|
||||
}
|
||||
}
|
@ -81,7 +81,7 @@ class ReportActionTest
|
||||
public void testBigger() throws Exception
|
||||
{
|
||||
// int recordCount = 2_000_000; // to really stress locally, use this.
|
||||
int recordCount = 50_000;
|
||||
int recordCount = 10_000;
|
||||
String filename = "/tmp/ReportActionTest.csv";
|
||||
|
||||
runReport(recordCount, filename, ReportFormat.CSV, false);
|
||||
|
@ -22,6 +22,8 @@
|
||||
package com.kingsrook.qqq.backend.core.modules.backend.implementations.memory;
|
||||
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.Month;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import com.kingsrook.qqq.backend.core.actions.customizers.TableCustomizers;
|
||||
@ -54,6 +56,7 @@ import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
|
||||
@ -193,6 +196,101 @@ class MemoryBackendModuleTest
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testQueryOperators() throws QException
|
||||
{
|
||||
QInstance qInstance = TestUtils.defineInstance();
|
||||
QTableMetaData table = qInstance.getTable(TestUtils.TABLE_NAME_SHAPE);
|
||||
QSession session = new QSession();
|
||||
|
||||
InsertInput insertInput = new InsertInput(qInstance);
|
||||
insertInput.setSession(session);
|
||||
insertInput.setTableName(table.getName());
|
||||
insertInput.setRecords(List.of(
|
||||
new QRecord().withValue("id", 1).withValue("name", "Square").withValue("date", LocalDate.of(1980, Month.MAY, 31)),
|
||||
new QRecord().withValue("id", 2).withValue("name", "Triangle").withValue("date", LocalDate.of(1999, Month.DECEMBER, 31))
|
||||
));
|
||||
new InsertAction().execute(insertInput);
|
||||
|
||||
assertEquals(2, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.IN, List.of(1, 2))).size());
|
||||
assertEquals(1, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.IN, List.of(2, 3))).size());
|
||||
|
||||
assertEquals(2, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.NOT_IN, List.of(3, 4))).size());
|
||||
assertEquals(1, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.NOT_IN, List.of(2, 3))).size());
|
||||
|
||||
assertEquals(1, queryShapes(qInstance, table, session, new QFilterCriteria("name", QCriteriaOperator.EQUALS, List.of("Square"))).size());
|
||||
assertEquals("Square", queryShapes(qInstance, table, session, new QFilterCriteria("name", QCriteriaOperator.EQUALS, List.of("Square"))).get(0).getValue("name"));
|
||||
assertEquals(0, queryShapes(qInstance, table, session, new QFilterCriteria("notAFieldSoNull", QCriteriaOperator.EQUALS, List.of("Square"))).size());
|
||||
|
||||
assertEquals(2, queryShapes(qInstance, table, session, new QFilterCriteria("name", QCriteriaOperator.NOT_EQUALS, List.of("notFound"))).size());
|
||||
assertEquals("Square", queryShapes(qInstance, table, session, new QFilterCriteria("name", QCriteriaOperator.NOT_EQUALS, List.of("Triangle"))).get(0).getValue("name"));
|
||||
|
||||
assertEquals(1, queryShapes(qInstance, table, session, new QFilterCriteria("name", QCriteriaOperator.CONTAINS, List.of("ria"))).size());
|
||||
assertEquals("Triangle", queryShapes(qInstance, table, session, new QFilterCriteria("name", QCriteriaOperator.CONTAINS, List.of("ria"))).get(0).getValue("name"));
|
||||
|
||||
assertEquals(2, queryShapes(qInstance, table, session, new QFilterCriteria("name", QCriteriaOperator.NOT_CONTAINS, List.of("notFound"))).size());
|
||||
assertEquals("Square", queryShapes(qInstance, table, session, new QFilterCriteria("name", QCriteriaOperator.NOT_CONTAINS, List.of("ria"))).get(0).getValue("name"));
|
||||
|
||||
assertThrows(QException.class, () -> queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.CONTAINS, List.of("ria"))));
|
||||
assertThrows(QException.class, () -> queryShapes(qInstance, table, session, new QFilterCriteria("name", QCriteriaOperator.CONTAINS, List.of(1))));
|
||||
assertThrows(QException.class, () -> queryShapes(qInstance, table, session, new QFilterCriteria("name", QCriteriaOperator.CONTAINS, List.of())));
|
||||
|
||||
assertEquals(0, queryShapes(qInstance, table, session, new QFilterCriteria("date", QCriteriaOperator.GREATER_THAN, List.of(LocalDate.of(2022, Month.SEPTEMBER, 1)))).size());
|
||||
assertEquals(1, queryShapes(qInstance, table, session, new QFilterCriteria("date", QCriteriaOperator.GREATER_THAN, List.of(LocalDate.of(1990, Month.JANUARY, 1)))).size());
|
||||
assertEquals(2, queryShapes(qInstance, table, session, new QFilterCriteria("date", QCriteriaOperator.GREATER_THAN, List.of(LocalDate.of(1970, Month.JANUARY, 1)))).size());
|
||||
assertEquals(0, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.GREATER_THAN, List.of(2))).size());
|
||||
assertEquals(1, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.GREATER_THAN, List.of(1))).size());
|
||||
assertEquals(2, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.GREATER_THAN, List.of(0))).size());
|
||||
|
||||
assertEquals(0, queryShapes(qInstance, table, session, new QFilterCriteria("date", QCriteriaOperator.GREATER_THAN_OR_EQUALS, List.of(LocalDate.of(2022, Month.SEPTEMBER, 1)))).size());
|
||||
assertEquals(1, queryShapes(qInstance, table, session, new QFilterCriteria("date", QCriteriaOperator.GREATER_THAN_OR_EQUALS, List.of(LocalDate.of(1990, Month.JANUARY, 1)))).size());
|
||||
assertEquals(2, queryShapes(qInstance, table, session, new QFilterCriteria("date", QCriteriaOperator.GREATER_THAN_OR_EQUALS, List.of(LocalDate.of(1970, Month.JANUARY, 1)))).size());
|
||||
assertEquals(2, queryShapes(qInstance, table, session, new QFilterCriteria("date", QCriteriaOperator.GREATER_THAN_OR_EQUALS, List.of(LocalDate.of(1980, Month.MAY, 31)))).size());
|
||||
assertEquals(0, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.GREATER_THAN_OR_EQUALS, List.of(3))).size());
|
||||
assertEquals(1, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.GREATER_THAN_OR_EQUALS, List.of(2))).size());
|
||||
assertEquals(2, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.GREATER_THAN_OR_EQUALS, List.of(1))).size());
|
||||
assertEquals(2, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.GREATER_THAN_OR_EQUALS, List.of(0))).size());
|
||||
|
||||
assertEquals(2, queryShapes(qInstance, table, session, new QFilterCriteria("date", QCriteriaOperator.LESS_THAN, List.of(LocalDate.of(2022, Month.SEPTEMBER, 1)))).size());
|
||||
assertEquals(1, queryShapes(qInstance, table, session, new QFilterCriteria("date", QCriteriaOperator.LESS_THAN, List.of(LocalDate.of(1990, Month.JANUARY, 1)))).size());
|
||||
assertEquals(0, queryShapes(qInstance, table, session, new QFilterCriteria("date", QCriteriaOperator.LESS_THAN, List.of(LocalDate.of(1970, Month.JANUARY, 1)))).size());
|
||||
assertEquals(2, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.LESS_THAN, List.of(3))).size());
|
||||
assertEquals(1, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.LESS_THAN, List.of(2))).size());
|
||||
assertEquals(0, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.LESS_THAN, List.of(1))).size());
|
||||
|
||||
assertEquals(2, queryShapes(qInstance, table, session, new QFilterCriteria("date", QCriteriaOperator.LESS_THAN_OR_EQUALS, List.of(LocalDate.of(2022, Month.SEPTEMBER, 1)))).size());
|
||||
assertEquals(1, queryShapes(qInstance, table, session, new QFilterCriteria("date", QCriteriaOperator.LESS_THAN_OR_EQUALS, List.of(LocalDate.of(1990, Month.JANUARY, 1)))).size());
|
||||
assertEquals(1, queryShapes(qInstance, table, session, new QFilterCriteria("date", QCriteriaOperator.LESS_THAN_OR_EQUALS, List.of(LocalDate.of(1980, Month.MAY, 31)))).size());
|
||||
assertEquals(0, queryShapes(qInstance, table, session, new QFilterCriteria("date", QCriteriaOperator.LESS_THAN_OR_EQUALS, List.of(LocalDate.of(1970, Month.JANUARY, 1)))).size());
|
||||
assertEquals(2, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.LESS_THAN_OR_EQUALS, List.of(3))).size());
|
||||
assertEquals(2, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.LESS_THAN_OR_EQUALS, List.of(2))).size());
|
||||
assertEquals(1, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.LESS_THAN_OR_EQUALS, List.of(1))).size());
|
||||
assertEquals(0, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.LESS_THAN_OR_EQUALS, List.of(0))).size());
|
||||
|
||||
assertThrows(QException.class, () -> queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.GREATER_THAN, List.of())));
|
||||
assertThrows(QException.class, () -> queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.GREATER_THAN_OR_EQUALS, List.of())));
|
||||
assertThrows(QException.class, () -> queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.LESS_THAN, List.of())));
|
||||
assertThrows(QException.class, () -> queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.LESS_THAN_OR_EQUALS, List.of())));
|
||||
assertThrows(QException.class, () -> queryShapes(qInstance, table, session, new QFilterCriteria("name", QCriteriaOperator.LESS_THAN_OR_EQUALS, List.of("Bob"))));
|
||||
}
|
||||
|
||||
|
||||
|
||||
private List<QRecord> queryShapes(QInstance qInstance, QTableMetaData table, QSession session, QFilterCriteria criteria) throws QException
|
||||
{
|
||||
QueryInput queryInput = new QueryInput(qInstance);
|
||||
queryInput.setSession(session);
|
||||
queryInput.setTableName(table.getName());
|
||||
queryInput.setFilter(new QQueryFilter().withCriteria(criteria));
|
||||
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
||||
return queryOutput.getRecords();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
|
@ -24,11 +24,13 @@ package com.kingsrook.qqq.backend.core.utils;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
import java.time.Month;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.actions.automation.AutomationStatus;
|
||||
import com.kingsrook.qqq.backend.core.actions.automation.RecordAutomationHandler;
|
||||
import com.kingsrook.qqq.backend.core.actions.dashboard.PersonsByCreateDateBarChart;
|
||||
import com.kingsrook.qqq.backend.core.actions.processes.BackendStep;
|
||||
import com.kingsrook.qqq.backend.core.actions.processes.person.addtopeoplesage.AddAge;
|
||||
import com.kingsrook.qqq.backend.core.actions.processes.person.addtopeoplesage.GetAgeStatistics;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.InsertAction;
|
||||
@ -36,6 +38,8 @@ import com.kingsrook.qqq.backend.core.actions.tables.QueryAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.UpdateAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.values.QCustomPossibleValueProvider;
|
||||
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.tables.insert.InsertInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QCriteriaOperator;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterCriteria;
|
||||
@ -67,10 +71,10 @@ import com.kingsrook.qqq.backend.core.model.metadata.processes.QFunctionInputMet
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QFunctionOutputMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QRecordListMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.automation.AutomationStatusTracking;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.automation.AutomationStatusTrackingType;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.automation.QTableAutomationDetails;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.automation.TableAutomationAction;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.automation.TriggerEvent;
|
||||
import com.kingsrook.qqq.backend.core.model.session.QSession;
|
||||
@ -105,6 +109,7 @@ public class TestUtils
|
||||
|
||||
public static final String PROCESS_NAME_GREET_PEOPLE = "greet";
|
||||
public static final String PROCESS_NAME_GREET_PEOPLE_INTERACTIVE = "greetInteractive";
|
||||
public static final String PROCESS_NAME_INCREASE_BIRTHDATE = "increaseBirthdate";
|
||||
public static final String PROCESS_NAME_ADD_TO_PEOPLES_AGE = "addToPeoplesAge";
|
||||
public static final String TABLE_NAME_PERSON_FILE = "personFile";
|
||||
public static final String TABLE_NAME_PERSON_MEMORY = "personMemory";
|
||||
@ -146,6 +151,7 @@ public class TestUtils
|
||||
qInstance.addProcess(defineProcessAddToPeoplesAge());
|
||||
qInstance.addProcess(new BasicETLProcess().defineProcessMetaData());
|
||||
qInstance.addProcess(new StreamedETLProcess().defineProcessMetaData());
|
||||
qInstance.addProcess(defineProcessIncreasePersonBirthdate());
|
||||
|
||||
qInstance.addAutomationProvider(definePollingAutomationProvider());
|
||||
|
||||
@ -170,6 +176,72 @@ public class TestUtils
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private static QProcessMetaData defineProcessIncreasePersonBirthdate()
|
||||
{
|
||||
return new QProcessMetaData()
|
||||
.withName(PROCESS_NAME_INCREASE_BIRTHDATE)
|
||||
.withTableName(TABLE_NAME_PERSON_MEMORY)
|
||||
|
||||
.addStep(new QFrontendStepMetaData()
|
||||
.withName("preview")
|
||||
)
|
||||
|
||||
.addStep(new QBackendStepMetaData()
|
||||
.withName("doWork")
|
||||
.withCode(new QCodeReference(IncreaseBirthdateStep.class))
|
||||
.withInputData(new QFunctionInputMetaData()
|
||||
.withRecordListMetaData(new QRecordListMetaData().withTableName(TABLE_NAME_PERSON_MEMORY)))
|
||||
.withOutputMetaData(new QFunctionOutputMetaData()
|
||||
.withFieldList(List.of(new QFieldMetaData("outputMessage", QFieldType.STRING).withDefaultValue("Success!"))))
|
||||
)
|
||||
|
||||
.addStep(new QFrontendStepMetaData()
|
||||
.withName("results")
|
||||
.withFormField(new QFieldMetaData("outputMessage", QFieldType.STRING))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public static class IncreaseBirthdateStep implements BackendStep
|
||||
{
|
||||
/*******************************************************************************
|
||||
** Execute the backend step - using the request as input, and the result as output.
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Override
|
||||
public void run(RunBackendStepInput runBackendStepInput, RunBackendStepOutput runBackendStepOutput) throws QException
|
||||
{
|
||||
List<QRecord> recordsToUpdate = new ArrayList<>();
|
||||
for(QRecord record : runBackendStepInput.getRecords())
|
||||
{
|
||||
LocalDate birthDate = record.getValueLocalDate("birthDate");
|
||||
|
||||
if(birthDate != null && birthDate.getYear() < 1900)
|
||||
{
|
||||
recordsToUpdate.add(new QRecord()
|
||||
.withValue("id", record.getValue("id"))
|
||||
.withValue("birthDate", birthDate.withYear(1900))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
UpdateInput updateInput = new UpdateInput(runBackendStepInput.getInstance());
|
||||
updateInput.setSession(runBackendStepInput.getSession());
|
||||
updateInput.setTableName(TABLE_NAME_PERSON_MEMORY);
|
||||
updateInput.setRecords(recordsToUpdate);
|
||||
new UpdateAction().execute(updateInput);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@ -392,6 +464,16 @@ public class TestUtils
|
||||
*******************************************************************************/
|
||||
public static QTableMetaData definePersonMemoryTable()
|
||||
{
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// the checkAge automation will only run on persons younger than this date //
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
LocalDate youngPersonLimitDate = LocalDate.now().minusYears(18);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// the increaseBirthdate automation will only run on persons born before this date //
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
LocalDate increaseBirthdateLimitDate = LocalDate.of(1900, Month.JANUARY, 1);
|
||||
|
||||
return (new QTableMetaData()
|
||||
.withName(TABLE_NAME_PERSON_MEMORY)
|
||||
.withBackendName(MEMORY_BACKEND_NAME)
|
||||
@ -403,12 +485,19 @@ public class TestUtils
|
||||
.withAction(new TableAutomationAction()
|
||||
.withName("checkAgeOnInsert")
|
||||
.withTriggerEvent(TriggerEvent.POST_INSERT)
|
||||
.withFilter(new QQueryFilter().withCriteria(new QFilterCriteria("birthDate", QCriteriaOperator.GREATER_THAN, List.of(youngPersonLimitDate))))
|
||||
.withCodeReference(new QCodeReference(CheckAge.class))
|
||||
)
|
||||
.withAction(new TableAutomationAction()
|
||||
.withName("increaseBirthdate")
|
||||
.withTriggerEvent(TriggerEvent.POST_INSERT)
|
||||
.withFilter(new QQueryFilter().withCriteria(new QFilterCriteria("birthDate", QCriteriaOperator.LESS_THAN, List.of(increaseBirthdateLimitDate))))
|
||||
.withProcessName(PROCESS_NAME_INCREASE_BIRTHDATE)
|
||||
)
|
||||
.withAction(new TableAutomationAction()
|
||||
.withName("logOnUpdatePerFilter")
|
||||
.withTriggerEvent(TriggerEvent.POST_UPDATE)
|
||||
.withFilter(new QQueryFilter().withCriteria(new QFilterCriteria("firstName", QCriteriaOperator.EQUALS, List.of("Darin"))))
|
||||
.withFilter(new QQueryFilter().withCriteria(new QFilterCriteria("firstName", QCriteriaOperator.CONTAINS, List.of("Darin"))))
|
||||
.withCodeReference(new QCodeReference(LogPersonUpdate.class))
|
||||
)
|
||||
);
|
||||
@ -437,7 +526,6 @@ public class TestUtils
|
||||
LocalDate birthDate = record.getValueLocalDate("birthDate");
|
||||
if(birthDate != null && birthDate.isAfter(limitDate))
|
||||
{
|
||||
LOG.info("Person [" + record.getValueInteger("id") + "] is a minor - updating their firstName to state such.");
|
||||
recordsToUpdate.add(new QRecord()
|
||||
.withValue("id", record.getValue("id"))
|
||||
.withValue("firstName", record.getValueString("firstName") + SUFFIX_FOR_MINORS)
|
||||
|
Reference in New Issue
Block a user