mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-19 05:30:43 +00:00
Adding queues and queue providers; Adding schedules and ScheduleManager
This commit is contained in:
@ -28,6 +28,7 @@ import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Supplier;
|
||||
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;
|
||||
@ -39,6 +40,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
|
||||
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.scheduler.StandardScheduledExecutor;
|
||||
import com.kingsrook.qqq.backend.core.utils.SleepUtils;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
@ -49,9 +51,9 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for PollingAutomationExecutor
|
||||
** Unit test for StandardScheduledExecutor
|
||||
*******************************************************************************/
|
||||
class PollingAutomationExecutorTest
|
||||
class StandardScheduledExecutorTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
@ -89,7 +91,7 @@ class PollingAutomationExecutorTest
|
||||
////////////////////////////////////////////////
|
||||
// have the polling executor run "for awhile" //
|
||||
////////////////////////////////////////////////
|
||||
runPollingAutomationExecutorForAwhile(qInstance);
|
||||
runPollingAutomationExecutorForAwhile(qInstance, QSession::new);
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
// query for the records - assert their status //
|
||||
@ -112,8 +114,6 @@ class PollingAutomationExecutorTest
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@ -140,15 +140,14 @@ class PollingAutomationExecutorTest
|
||||
));
|
||||
new InsertAction().execute(insertInput);
|
||||
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
QSession session = new QSession();
|
||||
session.setIdReference(uuid);
|
||||
PollingAutomationExecutor.getInstance().setSessionSupplier(() -> session);
|
||||
|
||||
////////////////////////////////////////////////
|
||||
// have the polling executor run "for awhile" //
|
||||
////////////////////////////////////////////////
|
||||
runPollingAutomationExecutorForAwhile(qInstance);
|
||||
runPollingAutomationExecutorForAwhile(qInstance, () -> session);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// assert that the uuid we put in our session was present in the CaptureSessionIdAutomationHandler //
|
||||
@ -183,12 +182,17 @@ class PollingAutomationExecutorTest
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private void runPollingAutomationExecutorForAwhile(QInstance qInstance)
|
||||
private void runPollingAutomationExecutorForAwhile(QInstance qInstance, Supplier<QSession> sessionSupplier)
|
||||
{
|
||||
PollingAutomationExecutor pollingAutomationExecutor = PollingAutomationExecutor.getInstance();
|
||||
PollingAutomationRunner pollingAutomationRunner = new PollingAutomationRunner(qInstance, TestUtils.POLLING_AUTOMATION, sessionSupplier);
|
||||
|
||||
StandardScheduledExecutor pollingAutomationExecutor = new StandardScheduledExecutor(pollingAutomationRunner);
|
||||
pollingAutomationExecutor.setInitialDelayMillis(0);
|
||||
pollingAutomationExecutor.setDelayMillis(100);
|
||||
pollingAutomationExecutor.start(qInstance, TestUtils.POLLING_AUTOMATION);
|
||||
pollingAutomationExecutor.setQInstance(qInstance);
|
||||
pollingAutomationExecutor.setName(TestUtils.POLLING_AUTOMATION);
|
||||
pollingAutomationExecutor.setSessionSupplier(sessionSupplier);
|
||||
pollingAutomationExecutor.start();
|
||||
SleepUtils.sleep(1, TimeUnit.SECONDS);
|
||||
pollingAutomationExecutor.stop();
|
||||
}
|
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2022. 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.scheduler;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import com.kingsrook.qqq.backend.core.actions.processes.BackendStep;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QInstanceValidationException;
|
||||
import com.kingsrook.qqq.backend.core.instances.QInstanceValidator;
|
||||
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.metadata.QInstance;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QBackendStepMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.scheduleing.QScheduleMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.session.QSession;
|
||||
import com.kingsrook.qqq.backend.core.utils.SleepUtils;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for ScheduleManager
|
||||
*******************************************************************************/
|
||||
class ScheduleManagerTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@AfterEach
|
||||
void afterEach()
|
||||
{
|
||||
ScheduleManager.resetSingleton();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testStartAndStop()
|
||||
{
|
||||
QInstance qInstance = TestUtils.defineInstance();
|
||||
ScheduleManager scheduleManager = ScheduleManager.getInstance(qInstance);
|
||||
scheduleManager.start();
|
||||
|
||||
assertThat(scheduleManager.getExecutors()).isNotEmpty();
|
||||
|
||||
scheduleManager.stopAsync();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testScheduledProcess() throws QInstanceValidationException
|
||||
{
|
||||
QInstance qInstance = TestUtils.defineInstance();
|
||||
new QInstanceValidator().validate(qInstance);
|
||||
qInstance.getAutomationProviders().clear();
|
||||
qInstance.getQueueProviders().clear();
|
||||
|
||||
qInstance.addProcess(
|
||||
new QProcessMetaData()
|
||||
.withName("testScheduledProcess")
|
||||
.withSchedule(new QScheduleMetaData().withRepeatMillis(2).withInitialDelaySeconds(0))
|
||||
.withStepList(List.of(new QBackendStepMetaData()
|
||||
.withName("step")
|
||||
.withCode(new QCodeReference(BasicStep.class))))
|
||||
);
|
||||
|
||||
BasicStep.counter = 0;
|
||||
|
||||
ScheduleManager scheduleManager = ScheduleManager.getInstance(qInstance);
|
||||
scheduleManager.setSessionSupplier(QSession::new);
|
||||
scheduleManager.start();
|
||||
SleepUtils.sleep(50, TimeUnit.MILLISECONDS);
|
||||
scheduleManager.stopAsync();
|
||||
|
||||
System.out.println("Ran: " + BasicStep.counter + " times");
|
||||
assertTrue(BasicStep.counter > 1, "Scheduled process should have ran at least twice");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public static class BasicStep implements BackendStep
|
||||
{
|
||||
static int counter = 0;
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void run(RunBackendStepInput runBackendStepInput, RunBackendStepOutput runBackendStepOutput) throws QException
|
||||
{
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -38,6 +38,7 @@ 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.instances.QMetaDataVariableInterpreter;
|
||||
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;
|
||||
@ -72,6 +73,9 @@ 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.queues.QQueueMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.queues.QQueueProviderMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.queues.SQSQueueProviderMetaData;
|
||||
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;
|
||||
@ -121,7 +125,8 @@ public class TestUtils
|
||||
public static final String POSSIBLE_VALUE_SOURCE_CUSTOM = "custom"; // custom-type
|
||||
public static final String POSSIBLE_VALUE_SOURCE_AUTOMATION_STATUS = "automationStatus";
|
||||
|
||||
public static final String POLLING_AUTOMATION = "polling";
|
||||
public static final String POLLING_AUTOMATION = "polling";
|
||||
public static final String DEFAULT_QUEUE_PROVIDER = "defaultQueueProvider";
|
||||
|
||||
|
||||
|
||||
@ -156,6 +161,9 @@ public class TestUtils
|
||||
|
||||
qInstance.addAutomationProvider(definePollingAutomationProvider());
|
||||
|
||||
qInstance.addQueueProvider(defineSqsProvider());
|
||||
qInstance.addQueue(defineTestSqsQueue());
|
||||
|
||||
defineWidgets(qInstance);
|
||||
defineApps(qInstance);
|
||||
|
||||
@ -841,4 +849,41 @@ public class TestUtils
|
||||
return (new QPossibleValue<>(idValue, "Custom[" + idValue + "]"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private static QQueueProviderMetaData defineSqsProvider()
|
||||
{
|
||||
QMetaDataVariableInterpreter interpreter = new QMetaDataVariableInterpreter();
|
||||
|
||||
String accessKey = interpreter.interpret("${env.SQS_ACCESS_KEY}");
|
||||
String secretKey = interpreter.interpret("${env.SQS_SECRET_KEY}");
|
||||
String region = interpreter.interpret("${env.SQS_REGION}");
|
||||
String baseURL = interpreter.interpret("${env.SQS_BASE_URL}");
|
||||
|
||||
return (new SQSQueueProviderMetaData()
|
||||
.withName(DEFAULT_QUEUE_PROVIDER)
|
||||
.withAccessKey(accessKey)
|
||||
.withSecretKey(secretKey)
|
||||
.withRegion(region)
|
||||
.withBaseURL(baseURL));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private static QQueueMetaData defineTestSqsQueue()
|
||||
{
|
||||
return (new QQueueMetaData()
|
||||
.withName("testSQSQueue")
|
||||
.withProviderName(DEFAULT_QUEUE_PROVIDER)
|
||||
.withQueueName("test-queue")
|
||||
.withProcessName("receiveEasypostTrackerWebhook"));
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user