use of org.quartz.CronExpression in project pinot by linkedin.
the class DetectionJobScheduler method runBackfill.
/**
* Sequentially performs anomaly detection for all the monitoring windows that are located between backfillStartTime
* and backfillEndTime. A lightweight job is performed right after each detection job and notified is set to false in
* order to silence the mail alerts.
*
* NOTE: We assume that the backfill window for the same function DOES NOT overlap. In other words, this function
* does not guarantees correctness of the detections result if it is invoked twice with the same parameters.
*
* @param functionId the id of the anomaly function, which has to be an active function
* @param backfillStartTime the start time for backfilling
* @param backfillEndTime the end time for backfilling
* @param force set to false to resume from previous backfill if there exists any
* @return task id
*/
public Long runBackfill(long functionId, DateTime backfillStartTime, DateTime backfillEndTime, boolean force) {
AnomalyFunctionDTO anomalyFunction = DAO_REGISTRY.getAnomalyFunctionDAO().findById(functionId);
Long jobId = null;
String dataset = anomalyFunction.getCollection();
boolean isActive = anomalyFunction.getIsActive();
if (!isActive) {
LOG.info("Skipping function {}", functionId);
return null;
}
BackfillKey backfillKey = new BackfillKey(functionId, backfillStartTime, backfillEndTime);
Thread returnedThread = existingBackfillJobs.putIfAbsent(backfillKey, Thread.currentThread());
// If returned thread is not current thread, then a backfill job is already running
if (returnedThread != null) {
LOG.info("Function: {} Dataset: {} Aborting... An existing back-fill job is running...", functionId, dataset);
return null;
}
try {
CronExpression cronExpression = null;
try {
cronExpression = new CronExpression(anomalyFunction.getCron());
} catch (ParseException e) {
LOG.error("Function: {} Dataset: {} Failed to parse cron expression", functionId, dataset);
return null;
}
long monitoringWindowSize = TimeUnit.MILLISECONDS.convert(anomalyFunction.getWindowSize(), anomalyFunction.getWindowUnit());
DateTime currentStart;
if (force) {
currentStart = backfillStartTime;
} else {
currentStart = computeResumeStartTime(functionId, cronExpression, backfillStartTime, backfillEndTime);
}
DateTime currentEnd = currentStart.plus(monitoringWindowSize);
// Make the end time inclusive
DateTime endBoundary = new DateTime(cronExpression.getNextValidTimeAfter(backfillEndTime.toDate()));
List<Long> startTimes = new ArrayList<>();
List<Long> endTimes = new ArrayList<>();
LOG.info("Function: {} Dataset: {} Begin regenerate anomalies for each monitoring window between {} and {}", functionId, dataset, currentStart, endBoundary);
while (currentEnd.isBefore(endBoundary)) {
if (Thread.currentThread().isInterrupted()) {
LOG.info("Function: {} Dataset: {} Terminating adhoc function.", functionId, dataset);
return null;
}
String monitoringWindowStart = ISODateTimeFormat.dateHourMinute().print(currentStart);
String monitoringWindowEnd = ISODateTimeFormat.dateHourMinute().print(currentEnd);
LOG.info("Function: {} Dataset: {} Adding adhoc time range {}({}) to {}({})", functionId, dataset, currentStart, monitoringWindowStart, currentEnd, monitoringWindowEnd);
startTimes.add(currentStart.getMillis());
endTimes.add(currentEnd.getMillis());
currentStart = new DateTime(cronExpression.getNextValidTimeAfter(currentStart.toDate()));
currentEnd = currentStart.plus(monitoringWindowSize);
}
// If any time periods found, for which detection needs to be run, run anomaly function update detection status
List<DetectionStatusDTO> findAllInTimeRange = DAO_REGISTRY.getDetectionStatusDAO().findAllInTimeRangeForFunctionAndDetectionRun(backfillStartTime.getMillis(), currentStart.getMillis(), functionId, false);
jobId = runAnomalyFunctionAndUpdateDetectionStatus(startTimes, endTimes, anomalyFunction, findAllInTimeRange);
LOG.info("Function: {} Dataset: {} Generated job for detecting anomalies for each monitoring window " + "whose start is located in range {} -- {}", functionId, dataset, backfillStartTime, currentStart);
} finally {
existingBackfillJobs.remove(backfillKey, Thread.currentThread());
}
return jobId;
}
use of org.quartz.CronExpression in project sling by apache.
the class ScheduleInfoImpl method getNextScheduledExecution.
public Date getNextScheduledExecution() {
final Calendar now = Calendar.getInstance();
switch(this.scheduleType) {
case DATE:
return this.at;
case DAILY:
final Calendar next = Calendar.getInstance();
next.set(Calendar.HOUR_OF_DAY, this.hourOfDay);
next.set(Calendar.MINUTE, this.minuteOfHour);
if (next.before(now)) {
next.add(Calendar.DAY_OF_WEEK, 1);
}
return next.getTime();
case WEEKLY:
final Calendar nextW = Calendar.getInstance();
nextW.set(Calendar.HOUR_OF_DAY, this.hourOfDay);
nextW.set(Calendar.MINUTE, this.minuteOfHour);
nextW.set(Calendar.DAY_OF_WEEK, this.dayOfWeek);
if (nextW.before(now)) {
nextW.add(Calendar.WEEK_OF_YEAR, 1);
}
return nextW.getTime();
case HOURLY:
final Calendar nextH = Calendar.getInstance();
nextH.set(Calendar.MINUTE, this.minuteOfHour);
if (nextH.before(now)) {
nextH.add(Calendar.HOUR_OF_DAY, 1);
}
return nextH.getTime();
case MONTHLY:
final Calendar nextM = Calendar.getInstance();
nextM.set(Calendar.HOUR_OF_DAY, this.hourOfDay);
nextM.set(Calendar.MINUTE, this.minuteOfHour);
nextM.set(Calendar.DAY_OF_MONTH, this.dayOfWeek);
if (nextM.before(now)) {
nextM.add(Calendar.MONTH, 1);
}
return nextM.getTime();
case YEARLY:
final Calendar nextY = Calendar.getInstance();
nextY.set(Calendar.HOUR_OF_DAY, this.hourOfDay);
nextY.set(Calendar.MINUTE, this.minuteOfHour);
nextY.set(Calendar.DAY_OF_MONTH, this.dayOfWeek);
nextY.set(Calendar.MONTH, this.monthOfYear - 1);
if (nextY.before(now)) {
nextY.add(Calendar.YEAR, 1);
}
return nextY.getTime();
case CRON:
try {
final CronExpression exp = new CronExpression(this.expression);
return exp.getNextValidTimeAfter(new Date());
} catch (final ParseException e) {
// as we check the expression in check() everything should be fine here
}
}
return null;
}
use of org.quartz.CronExpression in project nifi by apache.
the class QuartzSchedulingAgent method doSchedule.
@Override
public void doSchedule(final ReportingTaskNode taskNode, final LifecycleState scheduleState) {
final List<AtomicBoolean> existingTriggers = canceledTriggers.get(taskNode);
if (existingTriggers != null) {
throw new IllegalStateException("Cannot schedule " + taskNode.getReportingTask().getIdentifier() + " because it is already scheduled to run");
}
final String cronSchedule = taskNode.getSchedulingPeriod();
final CronExpression cronExpression;
try {
cronExpression = new CronExpression(cronSchedule);
} catch (final Exception pe) {
throw new IllegalStateException("Cannot schedule Reporting Task " + taskNode.getReportingTask().getIdentifier() + " to run because its scheduling period is not valid");
}
final ReportingTaskWrapper taskWrapper = new ReportingTaskWrapper(taskNode, scheduleState);
final AtomicBoolean canceled = new AtomicBoolean(false);
final Runnable command = new Runnable() {
@Override
public void run() {
if (canceled.get()) {
return;
}
taskWrapper.run();
if (canceled.get()) {
return;
}
final Date date = cronExpression.getTimeAfter(new Date());
final long delay = date.getTime() - System.currentTimeMillis();
logger.debug("Finished running Reporting Task {}; next scheduled time is at {} after a delay of {} milliseconds", taskNode, date, delay);
flowEngine.schedule(this, delay, TimeUnit.MILLISECONDS);
}
};
final List<AtomicBoolean> triggers = new ArrayList<>(1);
triggers.add(canceled);
canceledTriggers.put(taskNode, triggers);
final Date initialDate = cronExpression.getTimeAfter(new Date());
final long initialDelay = initialDate.getTime() - System.currentTimeMillis();
flowEngine.schedule(command, initialDelay, TimeUnit.MILLISECONDS);
scheduleState.setScheduled(true);
logger.info("Scheduled Reporting Task {} to run threads on schedule {}", taskNode, cronSchedule);
}
use of org.quartz.CronExpression in project nifi by apache.
the class QuartzSchedulingAgent method doSchedule.
@Override
public synchronized void doSchedule(final Connectable connectable, final LifecycleState scheduleState) {
final List<AtomicBoolean> existingTriggers = canceledTriggers.get(connectable);
if (existingTriggers != null) {
throw new IllegalStateException("Cannot schedule " + connectable + " because it is already scheduled to run");
}
final String cronSchedule = connectable.getSchedulingPeriod();
final CronExpression cronExpression;
try {
cronExpression = new CronExpression(cronSchedule);
} catch (final Exception pe) {
throw new IllegalStateException("Cannot schedule " + connectable + " to run because its scheduling period is not valid");
}
final List<AtomicBoolean> triggers = new ArrayList<>();
for (int i = 0; i < connectable.getMaxConcurrentTasks(); i++) {
final ConnectableTask continuallyRunTask = new ConnectableTask(this, connectable, flowController, contextFactory, scheduleState, encryptor);
final AtomicBoolean canceled = new AtomicBoolean(false);
final Runnable command = new Runnable() {
@Override
public void run() {
if (canceled.get()) {
return;
}
try {
continuallyRunTask.invoke();
} catch (final RuntimeException re) {
throw re;
} catch (final Exception e) {
throw new ProcessException(e);
}
if (canceled.get()) {
return;
}
final Date date = cronExpression.getTimeAfter(new Date());
final long delay = date.getTime() - System.currentTimeMillis();
logger.debug("Finished task for {}; next scheduled time is at {} after a delay of {} milliseconds", connectable, date, delay);
flowEngine.schedule(this, delay, TimeUnit.MILLISECONDS);
}
};
final Date initialDate = cronExpression.getTimeAfter(new Date());
final long initialDelay = initialDate.getTime() - System.currentTimeMillis();
flowEngine.schedule(command, initialDelay, TimeUnit.MILLISECONDS);
triggers.add(canceled);
}
canceledTriggers.put(connectable, triggers);
logger.info("Scheduled {} to run with {} threads on schedule {}", connectable, connectable.getMaxConcurrentTasks(), cronSchedule);
}
use of org.quartz.CronExpression in project nifi by apache.
the class StandardReportingTaskDAO method validateProposedConfiguration.
private List<String> validateProposedConfiguration(final ReportingTaskNode reportingTask, final ReportingTaskDTO reportingTaskDTO) {
final List<String> validationErrors = new ArrayList<>();
// get the current scheduling strategy
SchedulingStrategy schedulingStrategy = reportingTask.getSchedulingStrategy();
// validate the new scheduling strategy if appropriate
if (isNotNull(reportingTaskDTO.getSchedulingStrategy())) {
try {
// this will be the new scheduling strategy so use it
schedulingStrategy = SchedulingStrategy.valueOf(reportingTaskDTO.getSchedulingStrategy());
} catch (IllegalArgumentException iae) {
validationErrors.add(String.format("Scheduling strategy: Value must be one of [%s]", StringUtils.join(SchedulingStrategy.values(), ", ")));
}
}
// validate the scheduling period based on the scheduling strategy
if (isNotNull(reportingTaskDTO.getSchedulingPeriod())) {
switch(schedulingStrategy) {
case TIMER_DRIVEN:
final Matcher schedulingMatcher = FormatUtils.TIME_DURATION_PATTERN.matcher(reportingTaskDTO.getSchedulingPeriod());
if (!schedulingMatcher.matches()) {
validationErrors.add("Scheduling period is not a valid time duration (ie 30 sec, 5 min)");
}
break;
case CRON_DRIVEN:
try {
new CronExpression(reportingTaskDTO.getSchedulingPeriod());
} catch (final ParseException pe) {
throw new IllegalArgumentException(String.format("Scheduling Period '%s' is not a valid cron expression: %s", reportingTaskDTO.getSchedulingPeriod(), pe.getMessage()));
} catch (final Exception e) {
throw new IllegalArgumentException("Scheduling Period is not a valid cron expression: " + reportingTaskDTO.getSchedulingPeriod());
}
break;
}
}
return validationErrors;
}
Aggregations