mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 13:10:44 +00:00
CE-936 Switch scheduledJobTypes PVS to be based on schedulable types in the instance, not just the enum (e.g., in support of app-defined types)
This commit is contained in:
@ -73,7 +73,7 @@ public class ScheduledJob extends QRecordEntity
|
|||||||
@QField(displayFormat = DisplayFormat.COMMAS)
|
@QField(displayFormat = DisplayFormat.COMMAS)
|
||||||
private Integer repeatSeconds;
|
private Integer repeatSeconds;
|
||||||
|
|
||||||
@QField(isRequired = true, maxLength = 100, valueTooLongBehavior = ValueTooLongBehavior.ERROR, possibleValueSourceName = ScheduledJobType.NAME)
|
@QField(isRequired = true, maxLength = 100, valueTooLongBehavior = ValueTooLongBehavior.ERROR, possibleValueSourceName = ScheduledJobTypePossibleValueSource.NAME)
|
||||||
private String type;
|
private String type;
|
||||||
|
|
||||||
@QField(isRequired = true)
|
@QField(isRequired = true)
|
||||||
|
@ -22,102 +22,16 @@
|
|||||||
package com.kingsrook.qqq.backend.core.model.scheduledjobs;
|
package com.kingsrook.qqq.backend.core.model.scheduledjobs;
|
||||||
|
|
||||||
|
|
||||||
import com.kingsrook.qqq.backend.core.instances.QInstanceEnricher;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.PossibleValueEnum;
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
** enum of core schedulable types that QQQ schedule manager directly knows about.
|
||||||
**
|
**
|
||||||
|
** note though, that applications can define their own schedulable types,
|
||||||
|
** by adding SchedulableType meta-data to the QInstance, and providing classes
|
||||||
|
** that implement SchedulableRunner.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public enum ScheduledJobType implements PossibleValueEnum<String>
|
public enum ScheduledJobType
|
||||||
{
|
{
|
||||||
PROCESS,
|
PROCESS,
|
||||||
QUEUE_PROCESSOR,
|
QUEUE_PROCESSOR,
|
||||||
TABLE_AUTOMATIONS,
|
TABLE_AUTOMATIONS
|
||||||
// todo - future - USER_REPORT
|
|
||||||
;
|
|
||||||
|
|
||||||
public static final String NAME = "scheduledJobType";
|
|
||||||
|
|
||||||
private final String label;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
** Constructor
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
ScheduledJobType()
|
|
||||||
{
|
|
||||||
this.label = QInstanceEnricher.nameToLabel(QInstanceEnricher.inferNameFromBackendName(name()));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
** Get instance by id
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
public static ScheduledJobType getById(String id)
|
|
||||||
{
|
|
||||||
if(id == null)
|
|
||||||
{
|
|
||||||
return (null);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(ScheduledJobType value : ScheduledJobType.values())
|
|
||||||
{
|
|
||||||
if(value.name().equals(id))
|
|
||||||
{
|
|
||||||
return (value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (null);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
** Getter for id
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
public String getId()
|
|
||||||
{
|
|
||||||
return name();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
** Getter for label
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
public String getLabel()
|
|
||||||
{
|
|
||||||
return label;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
@Override
|
|
||||||
public String getPossibleValueId()
|
|
||||||
{
|
|
||||||
return name();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
@Override
|
|
||||||
public String getPossibleValueLabel()
|
|
||||||
{
|
|
||||||
return (label);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* QQQ - Low-code Application Framework for Engineers.
|
||||||
|
* Copyright (C) 2021-2024. 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.model.scheduledjobs;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.values.QCustomPossibleValueProvider;
|
||||||
|
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||||
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.values.SearchPossibleValueSourceInput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValue;
|
||||||
|
import com.kingsrook.qqq.backend.core.scheduler.schedulable.SchedulableType;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public class ScheduledJobTypePossibleValueSource implements QCustomPossibleValueProvider<String>
|
||||||
|
{
|
||||||
|
public static final String NAME = "scheduledJobType";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Override
|
||||||
|
public QPossibleValue<String> getPossibleValue(Serializable idValue)
|
||||||
|
{
|
||||||
|
SchedulableType schedulableType = QContext.getQInstance().getSchedulableType(String.valueOf(idValue));
|
||||||
|
if(schedulableType != null)
|
||||||
|
{
|
||||||
|
return schedulableTypeToPossibleValue(schedulableType);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Override
|
||||||
|
public List<QPossibleValue<String>> search(SearchPossibleValueSourceInput input) throws QException
|
||||||
|
{
|
||||||
|
List<QPossibleValue<String>> rs = new ArrayList<>();
|
||||||
|
for(SchedulableType schedulableType : CollectionUtils.nonNullMap(QContext.getQInstance().getSchedulableTypes()).values())
|
||||||
|
{
|
||||||
|
rs.add(schedulableTypeToPossibleValue(schedulableType));
|
||||||
|
}
|
||||||
|
return rs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private static QPossibleValue<String> schedulableTypeToPossibleValue(SchedulableType schedulableType)
|
||||||
|
{
|
||||||
|
return new QPossibleValue<>(schedulableType.getName(), schedulableType.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -64,7 +64,7 @@ public class ScheduledJobsMetaDataProvider
|
|||||||
{
|
{
|
||||||
defineStandardTables(instance, backendName, backendDetailEnricher);
|
defineStandardTables(instance, backendName, backendDetailEnricher);
|
||||||
instance.addPossibleValueSource(QPossibleValueSource.newForTable(ScheduledJob.TABLE_NAME));
|
instance.addPossibleValueSource(QPossibleValueSource.newForTable(ScheduledJob.TABLE_NAME));
|
||||||
instance.addPossibleValueSource(QPossibleValueSource.newForEnum(ScheduledJobType.NAME, ScheduledJobType.values()));
|
instance.addPossibleValueSource(defineScheduledJobTypePossibleValueSource());
|
||||||
instance.addPossibleValueSource(defineSchedulersPossibleValueSource());
|
instance.addPossibleValueSource(defineSchedulersPossibleValueSource());
|
||||||
defineStandardJoins(instance);
|
defineStandardJoins(instance);
|
||||||
defineStandardWidgets(instance);
|
defineStandardWidgets(instance);
|
||||||
@ -215,6 +215,19 @@ public class ScheduledJobsMetaDataProvider
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private QPossibleValueSource defineScheduledJobTypePossibleValueSource()
|
||||||
|
{
|
||||||
|
return (new QPossibleValueSource()
|
||||||
|
.withName(ScheduledJobTypePossibleValueSource.NAME)
|
||||||
|
.withType(QPossibleValueSourceType.CUSTOM)
|
||||||
|
.withCustomCodeReference(new QCodeReference(ScheduledJobTypePossibleValueSource.class)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
@ -224,7 +237,6 @@ public class ScheduledJobsMetaDataProvider
|
|||||||
.withName(SchedulersPossibleValueSource.NAME)
|
.withName(SchedulersPossibleValueSource.NAME)
|
||||||
.withType(QPossibleValueSourceType.CUSTOM)
|
.withType(QPossibleValueSourceType.CUSTOM)
|
||||||
.withCustomCodeReference(new QCodeReference(SchedulersPossibleValueSource.class)));
|
.withCustomCodeReference(new QCodeReference(SchedulersPossibleValueSource.class)));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -122,9 +122,9 @@ public class QScheduleManager
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public static void defineDefaultSchedulableTypesInInstance(QInstance qInstance)
|
public static void defineDefaultSchedulableTypesInInstance(QInstance qInstance)
|
||||||
{
|
{
|
||||||
qInstance.addSchedulableType(new SchedulableType().withName(ScheduledJobType.PROCESS.getId()).withRunner(new QCodeReference(SchedulableProcessRunner.class)));
|
qInstance.addSchedulableType(new SchedulableType().withName(ScheduledJobType.PROCESS.name()).withRunner(new QCodeReference(SchedulableProcessRunner.class)));
|
||||||
qInstance.addSchedulableType(new SchedulableType().withName(ScheduledJobType.QUEUE_PROCESSOR.getId()).withRunner(new QCodeReference(SchedulableSQSQueueRunner.class)));
|
qInstance.addSchedulableType(new SchedulableType().withName(ScheduledJobType.QUEUE_PROCESSOR.name()).withRunner(new QCodeReference(SchedulableSQSQueueRunner.class)));
|
||||||
qInstance.addSchedulableType(new SchedulableType().withName(ScheduledJobType.TABLE_AUTOMATIONS.getId()).withRunner(new QCodeReference(SchedulableTableAutomationsRunner.class)));
|
qInstance.addSchedulableType(new SchedulableType().withName(ScheduledJobType.TABLE_AUTOMATIONS.name()).withRunner(new QCodeReference(SchedulableTableAutomationsRunner.class)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -321,8 +321,8 @@ public class QScheduleManager
|
|||||||
throw (new QException("Missing a type " + exceptionSuffix));
|
throw (new QException("Missing a type " + exceptionSuffix));
|
||||||
}
|
}
|
||||||
|
|
||||||
ScheduledJobType scheduledJobType = ScheduledJobType.getById(scheduledJob.getType());
|
SchedulableType schedulableType = qInstance.getSchedulableType(scheduledJob.getType());
|
||||||
if(scheduledJobType == null)
|
if(schedulableType == null)
|
||||||
{
|
{
|
||||||
throw (new QException("Unrecognized type [" + scheduledJob.getType() + "] " + exceptionSuffix));
|
throw (new QException("Unrecognized type [" + scheduledJob.getType() + "] " + exceptionSuffix));
|
||||||
}
|
}
|
||||||
@ -330,8 +330,6 @@ public class QScheduleManager
|
|||||||
QSchedulerInterface scheduler = getScheduler(scheduledJob.getSchedulerName());
|
QSchedulerInterface scheduler = getScheduler(scheduledJob.getSchedulerName());
|
||||||
Map<String, Serializable> paramMap = new HashMap<>(scheduledJob.getJobParametersMap());
|
Map<String, Serializable> paramMap = new HashMap<>(scheduledJob.getJobParametersMap());
|
||||||
|
|
||||||
SchedulableType schedulableType = qInstance.getSchedulableType(scheduledJob.getType());
|
|
||||||
|
|
||||||
SchedulableRunner runner = QCodeLoader.getAdHoc(SchedulableRunner.class, schedulableType.getRunner());
|
SchedulableRunner runner = QCodeLoader.getAdHoc(SchedulableRunner.class, schedulableType.getRunner());
|
||||||
runner.validateParams(schedulableIdentity, new HashMap<>(paramMap));
|
runner.validateParams(schedulableIdentity, new HashMap<>(paramMap));
|
||||||
|
|
||||||
@ -387,7 +385,7 @@ public class QScheduleManager
|
|||||||
Map<String, String> paramMap = new HashMap<>();
|
Map<String, String> paramMap = new HashMap<>();
|
||||||
paramMap.put("processName", process.getName());
|
paramMap.put("processName", process.getName());
|
||||||
|
|
||||||
SchedulableType schedulableType = qInstance.getSchedulableType(ScheduledJobType.PROCESS.getId());
|
SchedulableType schedulableType = qInstance.getSchedulableType(ScheduledJobType.PROCESS.name());
|
||||||
|
|
||||||
if(process.getVariantBackend() == null || VariantRunStrategy.SERIAL.equals(process.getVariantRunStrategy()))
|
if(process.getVariantBackend() == null || VariantRunStrategy.SERIAL.equals(process.getVariantRunStrategy()))
|
||||||
{
|
{
|
||||||
@ -437,7 +435,7 @@ public class QScheduleManager
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
private void setupTableAutomations(QTableMetaData table) throws QException
|
private void setupTableAutomations(QTableMetaData table) throws QException
|
||||||
{
|
{
|
||||||
SchedulableType schedulableType = qInstance.getSchedulableType(ScheduledJobType.TABLE_AUTOMATIONS.getId());
|
SchedulableType schedulableType = qInstance.getSchedulableType(ScheduledJobType.TABLE_AUTOMATIONS.name());
|
||||||
QTableAutomationDetails automationDetails = table.getAutomationDetails();
|
QTableAutomationDetails automationDetails = table.getAutomationDetails();
|
||||||
QSchedulerInterface scheduler = getScheduler(automationDetails.getSchedule().getSchedulerName());
|
QSchedulerInterface scheduler = getScheduler(automationDetails.getSchedule().getSchedulerName());
|
||||||
|
|
||||||
@ -466,7 +464,7 @@ public class QScheduleManager
|
|||||||
{
|
{
|
||||||
SchedulableIdentity schedulableIdentity = SchedulableIdentityFactory.of(queue);
|
SchedulableIdentity schedulableIdentity = SchedulableIdentityFactory.of(queue);
|
||||||
QSchedulerInterface scheduler = getScheduler(queue.getSchedule().getSchedulerName());
|
QSchedulerInterface scheduler = getScheduler(queue.getSchedule().getSchedulerName());
|
||||||
SchedulableType schedulableType = qInstance.getSchedulableType(ScheduledJobType.QUEUE_PROCESSOR.getId());
|
SchedulableType schedulableType = qInstance.getSchedulableType(ScheduledJobType.QUEUE_PROCESSOR.name());
|
||||||
boolean allowedToStart = SchedulerUtils.allowedToStart(queue.getName());
|
boolean allowedToStart = SchedulerUtils.allowedToStart(queue.getName());
|
||||||
|
|
||||||
Map<String, String> paramMap = new HashMap<>();
|
Map<String, String> paramMap = new HashMap<>();
|
||||||
|
@ -29,7 +29,6 @@ import com.kingsrook.qqq.backend.core.context.QContext;
|
|||||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.queues.QQueueMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.queues.QQueueMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.scheduledjobs.ScheduledJob;
|
import com.kingsrook.qqq.backend.core.model.scheduledjobs.ScheduledJob;
|
||||||
import com.kingsrook.qqq.backend.core.model.scheduledjobs.ScheduledJobType;
|
|
||||||
import com.kingsrook.qqq.backend.core.scheduler.schedulable.SchedulableType;
|
import com.kingsrook.qqq.backend.core.scheduler.schedulable.SchedulableType;
|
||||||
import com.kingsrook.qqq.backend.core.scheduler.schedulable.runner.SchedulableRunner;
|
import com.kingsrook.qqq.backend.core.scheduler.schedulable.runner.SchedulableRunner;
|
||||||
|
|
||||||
@ -46,18 +45,17 @@ public class SchedulableIdentityFactory
|
|||||||
public static BasicSchedulableIdentity of(ScheduledJob scheduledJob)
|
public static BasicSchedulableIdentity of(ScheduledJob scheduledJob)
|
||||||
{
|
{
|
||||||
String description = "";
|
String description = "";
|
||||||
ScheduledJobType scheduledJobType = ScheduledJobType.getById(scheduledJob.getType());
|
SchedulableType schedulableType = QContext.getQInstance().getSchedulableType(scheduledJob.getType());
|
||||||
if(scheduledJobType != null)
|
if(schedulableType != null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
SchedulableType schedulableType = QContext.getQInstance().getSchedulableType(scheduledJob.getType());
|
|
||||||
SchedulableRunner runner = QCodeLoader.getAdHoc(SchedulableRunner.class, schedulableType.getRunner());
|
SchedulableRunner runner = QCodeLoader.getAdHoc(SchedulableRunner.class, schedulableType.getRunner());
|
||||||
description = runner.getDescription(new HashMap<>(scheduledJob.getJobParametersMap()));
|
description = runner.getDescription(new HashMap<>(scheduledJob.getJobParametersMap()));
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
{
|
{
|
||||||
description = "type: " + scheduledJobType;
|
description = "type: " + schedulableType.getName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ class QScheduleManagerTest extends BaseTest
|
|||||||
.withId(1)
|
.withId(1)
|
||||||
.withIsActive(true)
|
.withIsActive(true)
|
||||||
.withSchedulerName(TestUtils.SIMPLE_SCHEDULER_NAME)
|
.withSchedulerName(TestUtils.SIMPLE_SCHEDULER_NAME)
|
||||||
.withType(type.getId())
|
.withType(type.name())
|
||||||
.withRepeatSeconds(1)
|
.withRepeatSeconds(1)
|
||||||
.withJobParameters(new ArrayList<>());
|
.withJobParameters(new ArrayList<>());
|
||||||
|
|
||||||
|
@ -156,7 +156,6 @@ class QuartzSchedulerTest extends BaseTest
|
|||||||
void testRemovingNoLongerNeededJobsDuringSetupSchedules() throws SchedulerException
|
void testRemovingNoLongerNeededJobsDuringSetupSchedules() throws SchedulerException
|
||||||
{
|
{
|
||||||
QInstance qInstance = QContext.getQInstance();
|
QInstance qInstance = QContext.getQInstance();
|
||||||
QScheduleManager.defineDefaultSchedulableTypesInInstance(qInstance);
|
|
||||||
QuartzTestUtils.setupInstanceForQuartzTests();
|
QuartzTestUtils.setupInstanceForQuartzTests();
|
||||||
|
|
||||||
////////////////////////////
|
////////////////////////////
|
||||||
@ -167,7 +166,7 @@ class QuartzSchedulerTest extends BaseTest
|
|||||||
qInstance.addProcess(test1);
|
qInstance.addProcess(test1);
|
||||||
qInstance.addProcess(test2);
|
qInstance.addProcess(test2);
|
||||||
|
|
||||||
SchedulableType schedulableType = qInstance.getSchedulableType(ScheduledJobType.PROCESS.getId());
|
SchedulableType schedulableType = qInstance.getSchedulableType(ScheduledJobType.PROCESS.name());
|
||||||
|
|
||||||
QuartzScheduler quartzScheduler = QuartzScheduler.initInstance(qInstance, QuartzTestUtils.QUARTZ_SCHEDULER_NAME, QuartzTestUtils.getQuartzProperties(), () -> QContext.getQSession());
|
QuartzScheduler quartzScheduler = QuartzScheduler.initInstance(qInstance, QuartzTestUtils.QUARTZ_SCHEDULER_NAME, QuartzTestUtils.getQuartzProperties(), () -> QContext.getQSession());
|
||||||
quartzScheduler.start();
|
quartzScheduler.start();
|
||||||
|
Reference in New Issue
Block a user