Search in sources :

Example 1 with RFC5545Schedule

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());
    }
}
Also used : RFC5545Schedule(com.hubspot.singularity.helpers.RFC5545Schedule) CronExpression(org.quartz.CronExpression) ParseException(java.text.ParseException) SingularityDeployStatistics(com.hubspot.singularity.SingularityDeployStatistics) Date(java.util.Date) InvalidRecurrenceRuleException(org.dmfs.rfc5545.recur.InvalidRecurrenceRuleException)

Example 2 with RFC5545Schedule

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);
}
Also used : PendingType(com.hubspot.singularity.SingularityPendingRequest.PendingType) RFC5545Schedule(com.hubspot.singularity.helpers.RFC5545Schedule) CronExpression(org.quartz.CronExpression) ParseException(java.text.ParseException) Date(java.util.Date) InvalidRecurrenceRuleException(org.dmfs.rfc5545.recur.InvalidRecurrenceRuleException)

Aggregations

RFC5545Schedule (com.hubspot.singularity.helpers.RFC5545Schedule)2 ParseException (java.text.ParseException)2 Date (java.util.Date)2 InvalidRecurrenceRuleException (org.dmfs.rfc5545.recur.InvalidRecurrenceRuleException)2 CronExpression (org.quartz.CronExpression)2 SingularityDeployStatistics (com.hubspot.singularity.SingularityDeployStatistics)1 PendingType (com.hubspot.singularity.SingularityPendingRequest.PendingType)1