139 lines
4.2 KiB
Java
139 lines
4.2 KiB
Java
package eu.dnetlib.manager.wf.cron;
|
|
|
|
import java.time.LocalDateTime;
|
|
import java.time.temporal.ChronoUnit;
|
|
|
|
import org.apache.commons.logging.Log;
|
|
import org.apache.commons.logging.LogFactory;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
import org.springframework.scheduling.annotation.Scheduled;
|
|
import org.springframework.scheduling.support.CronExpression;
|
|
import org.springframework.stereotype.Service;
|
|
|
|
import eu.dnetlib.manager.history.WorkflowLogger;
|
|
import eu.dnetlib.manager.wf.model.WorkflowInstance;
|
|
import eu.dnetlib.manager.wf.repository.WorkflowInstanceRepository;
|
|
import eu.dnetlib.manager.wf.workflows.procs.ProcessRegistry;
|
|
import eu.dnetlib.manager.wf.workflows.procs.WorkflowExecutor;
|
|
import eu.dnetlib.manager.wf.workflows.procs.WorkflowProcess;
|
|
|
|
@Service
|
|
public class ScheduledWorkflowLauncher {
|
|
|
|
private static final Log log = LogFactory.getLog(ScheduledWorkflowLauncher.class);
|
|
|
|
@Autowired
|
|
private WorkflowExecutor workflowExecutor;
|
|
|
|
@Autowired
|
|
private ProcessRegistry processRegistry;
|
|
|
|
@Autowired
|
|
private WorkflowInstanceRepository workflowInstanceRepository;
|
|
|
|
@Autowired
|
|
private WorkflowLogger logger;
|
|
|
|
@Value("${'dnet.workflow.scheduler.windowSize'}")
|
|
private int windowSize; // 1800000 are 30 minutes
|
|
|
|
@Scheduled(cron = "${'dnet.workflow.scheduler.cron'}")
|
|
public void verifySheduledWorkflows() {
|
|
log.debug("Verifying scheduled workflows - START");
|
|
|
|
workflowInstanceRepository.findAll()
|
|
.stream()
|
|
.filter(WorkflowInstance::isEnabled)
|
|
.filter(WorkflowInstance::isConfigured)
|
|
.filter(WorkflowInstance::isSchedulingEnabled)
|
|
.filter(this::isNotRunning)
|
|
.filter(this::isReady)
|
|
.forEach(instance -> {
|
|
try {
|
|
workflowExecutor.startWorkflowInstance(instance, null, null, null);
|
|
} catch (final Exception e) {
|
|
log.error("Error launching scheduled wf instance: " + instance.getId(), e);
|
|
}
|
|
});
|
|
log.debug("Verifying scheduled workflows - END");
|
|
}
|
|
|
|
private boolean isReady(final WorkflowInstance instance) {
|
|
final LocalDateTime lastExecutionDate = calculateLastExecutionDate(instance.getId());
|
|
|
|
final LocalDateTime now = LocalDateTime.now();
|
|
|
|
final String cron = instance.getCronExpression();
|
|
|
|
if (CronExpression.isValidExpression(cron)) {
|
|
final int minInterval = instance.getCronMinInterval(); // in minutes
|
|
|
|
final boolean res;
|
|
if (lastExecutionDate != null) {
|
|
final long elapsed = ChronoUnit.MINUTES.between(lastExecutionDate, now);
|
|
res = elapsed > minInterval && verifyCron(cron, now);
|
|
} else {
|
|
res = verifyCron(cron, now);
|
|
}
|
|
|
|
if (log.isDebugEnabled()) {
|
|
log.debug("**************************************************************");
|
|
log.debug("WORKFLOW INSTANCE ID : " + instance.getId());
|
|
log.debug("NOW : " + now);
|
|
log.debug("LAST EXECUTION DATE : " + lastExecutionDate);
|
|
log.debug("MIN INTERVAL (minutes) : " + minInterval);
|
|
log.debug("WINDOW SIZE (ms) : " + windowSize);
|
|
log.debug("MUST BE EXECUTED : " + res);
|
|
log.debug("**************************************************************");
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private LocalDateTime calculateLastExecutionDate(final String id) {
|
|
return logger.getLastExecutionForInstance(id)
|
|
.map(e -> e.getEndDate())
|
|
.orElse(LocalDateTime.MIN);
|
|
}
|
|
|
|
private boolean verifyCron(final String cronExpression, final LocalDateTime now) {
|
|
try {
|
|
final CronExpression cron = CronExpression.parse(cronExpression);
|
|
|
|
final LocalDateTime date = now.minus(windowSize, ChronoUnit.MINUTES);
|
|
final LocalDateTime nextDate = cron.next(date);
|
|
|
|
if (log.isDebugEnabled()) {
|
|
log.debug("NEXT EXECUTION DATE: " + nextDate);
|
|
log.debug("FIRED : " + nextDate.isBefore(now));
|
|
}
|
|
return nextDate.isBefore(now);
|
|
} catch (final Exception e) {
|
|
log.error("Error calculating next cron event: " + cronExpression, e);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private boolean isNotRunning(final WorkflowInstance instance) {
|
|
final WorkflowProcess p = processRegistry.findProcsByInstanceId(instance.getId());
|
|
|
|
if (p != null) {
|
|
switch (p.getStatus()) {
|
|
case CREATED:
|
|
return false;
|
|
case EXECUTING:
|
|
return false;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
}
|