use of com.hubspot.singularity.helpers.RFC5545Schedule in project Singularity by HubSpot.
the class SingularityJobPoller method getExpectedRuntime.
private Optional<Long> getExpectedRuntime(SingularityRequest request, SingularityTaskId taskId) {
if (request.getScheduledExpectedRuntimeMillis().isPresent()) {
return request.getScheduledExpectedRuntimeMillis();
} else {
final Optional<SingularityDeployStatistics> deployStatistics = deployManager.getDeployStatistics(taskId.getRequestId(), taskId.getDeployId());
if (deployStatistics.isPresent() && deployStatistics.get().getAverageRuntimeMillis().isPresent()) {
return deployStatistics.get().getAverageRuntimeMillis();
}
String scheduleExpression = request.getScheduleTypeSafe() == ScheduleType.RFC5545 ? request.getSchedule().get() : request.getQuartzScheduleSafe();
Date nextRunAtDate;
try {
if (request.getScheduleTypeSafe() == ScheduleType.RFC5545) {
final RFC5545Schedule rfc5545Schedule = new RFC5545Schedule(scheduleExpression);
nextRunAtDate = rfc5545Schedule.getNextValidTime();
} else {
final CronExpression cronExpression = new CronExpression(scheduleExpression);
final Date startDate = new Date(taskId.getStartedAt());
nextRunAtDate = cronExpression.getNextValidTimeAfter(startDate);
}
if (nextRunAtDate == null) {
String msg = String.format("No next run date found for %s (%s)", taskId, scheduleExpression);
LOG.warn(msg);
exceptionNotifier.notify(msg, ImmutableMap.of("taskId", taskId.toString()));
return Optional.absent();
}
} catch (ParseException | InvalidRecurrenceRuleException e) {
LOG.warn("Unable to parse schedule of type {} for expression {} (taskId: {}, err: {})", request.getScheduleTypeSafe(), scheduleExpression, taskId, e);
exceptionNotifier.notify(String.format("Unable to parse schedule (%s)", e.getMessage()), e, ImmutableMap.of("taskId", taskId.toString(), "scheduleExpression", scheduleExpression, "scheduleType", request.getScheduleTypeSafe().toString()));
return Optional.absent();
}
return Optional.of(nextRunAtDate.getTime() - taskId.getStartedAt());
}
}
use of com.hubspot.singularity.helpers.RFC5545Schedule in project Singularity by HubSpot.
the class SingularityScheduler method getNextRunAt.
private Optional<Long> getNextRunAt(SingularityRequest request, RequestState state, SingularityDeployStatistics deployStatistics, SingularityPendingRequest pendingRequest, Optional<SingularityPendingDeploy> maybePendingDeploy) {
PendingType pendingType = pendingRequest.getPendingType();
final long now = System.currentTimeMillis();
long nextRunAt = now;
if (request.isScheduled()) {
if (pendingType == PendingType.IMMEDIATE || pendingType == PendingType.RETRY) {
LOG.info("Scheduling requested immediate run of {}", request.getId());
} else {
try {
Date nextRunAtDate = null;
Date scheduleFrom = null;
if (request.getScheduleTypeSafe() == ScheduleType.RFC5545) {
final RFC5545Schedule rfc5545Schedule = new RFC5545Schedule(request.getSchedule().get());
nextRunAtDate = rfc5545Schedule.getNextValidTime();
scheduleFrom = new Date(rfc5545Schedule.getStartDateTime().getMillis());
} else {
scheduleFrom = new Date(now);
final CronExpression cronExpression = new CronExpression(request.getQuartzScheduleSafe());
if (request.getScheduleTimeZone().isPresent()) {
cronExpression.setTimeZone(TimeZone.getTimeZone(request.getScheduleTimeZone().get()));
}
nextRunAtDate = cronExpression.getNextValidTimeAfter(scheduleFrom);
}
if (nextRunAtDate == null) {
return Optional.absent();
}
LOG.trace("Calculating nextRunAtDate for {} (schedule: {}): {} (from: {})", request.getId(), request.getSchedule(), nextRunAtDate, scheduleFrom);
// don't create a schedule that is overdue as this is used to indicate that singularity is not fulfilling requests.
nextRunAt = Math.max(nextRunAtDate.getTime(), now);
LOG.trace("Scheduling next run of {} (schedule: {}) at {} (from: {})", request.getId(), request.getSchedule(), nextRunAtDate, scheduleFrom);
} catch (ParseException | InvalidRecurrenceRuleException pe) {
throw Throwables.propagate(pe);
}
}
}
if (!request.isLongRunning() && pendingRequest.getRunAt().isPresent()) {
nextRunAt = Math.max(nextRunAt, pendingRequest.getRunAt().get());
}
if (pendingType == PendingType.TASK_DONE && request.getWaitAtLeastMillisAfterTaskFinishesForReschedule().or(0L) > 0) {
nextRunAt = Math.max(nextRunAt, now + request.getWaitAtLeastMillisAfterTaskFinishesForReschedule().get());
LOG.trace("Adjusted next run of {} to {} (by {}) due to waitAtLeastMillisAfterTaskFinishesForReschedule", request.getId(), nextRunAt, JavaUtils.durationFromMillis(request.getWaitAtLeastMillisAfterTaskFinishesForReschedule().get()));
}
if (state == RequestState.SYSTEM_COOLDOWN && pendingType != PendingType.NEW_DEPLOY) {
final long prevNextRunAt = nextRunAt;
nextRunAt = Math.max(nextRunAt, now + TimeUnit.SECONDS.toMillis(configuration.getCooldownMinScheduleSeconds()));
LOG.trace("Adjusted next run of {} to {} (from: {}) due to cooldown", request.getId(), nextRunAt, prevNextRunAt);
}
return Optional.of(nextRunAt);
}
Aggregations