private boolean shouldReschedule(SingularityRequest newRequest, SingularityRequest oldRequest) {
    if (newRequest.getInstancesSafe() != oldRequest.getInstancesSafe()) {
      return true;
    }
    if (newRequest.isScheduled() && oldRequest.isScheduled()) {
      if (!newRequest.getQuartzScheduleSafe().equals(oldRequest.getQuartzScheduleSafe())) {
        return true;
      }
    }

    return false;
  }
  private void checkActiveRequest(
      SingularityRequestWithState requestWithState,
      Map<SingularityDeployKey, SingularityPendingTaskId> deployKeyToPendingTaskId,
      final long timestamp) {
    final SingularityRequest request = requestWithState.getRequest();

    if (request.getRequestType() == RequestType.ON_DEMAND
        || request.getRequestType() == RequestType.RUN_ONCE) {
      return; // There's no situation where we'd want to schedule an On Demand or Run Once request
              // at startup, so don't even bother with them.
    }

    Optional<SingularityRequestDeployState> requestDeployState =
        deployManager.getRequestDeployState(request.getId());

    if (!requestDeployState.isPresent()
        || !requestDeployState.get().getActiveDeploy().isPresent()) {
      LOG.debug("No active deploy for {} - not scheduling on startup", request.getId());
      return;
    }

    final String activeDeployId = requestDeployState.get().getActiveDeploy().get().getDeployId();

    if (request.isScheduled()) {
      SingularityDeployKey deployKey = new SingularityDeployKey(request.getId(), activeDeployId);
      SingularityPendingTaskId pendingTaskId = deployKeyToPendingTaskId.get(deployKey);

      if (pendingTaskId != null
          && pendingTaskId.getCreatedAt() >= requestWithState.getTimestamp()) {
        LOG.info(
            "Not rescheduling {} because {} is newer than {}",
            request.getId(),
            pendingTaskId,
            requestWithState.getTimestamp());
        return;
      }
    }

    requestManager.addToPendingQueue(
        new SingularityPendingRequest(
            request.getId(),
            activeDeployId,
            timestamp,
            Optional.<String>absent(),
            PendingType.STARTUP,
            Optional.<Boolean>absent(),
            Optional.<String>absent()));
  }
  private Optional<Long> getNextRunAt(
      SingularityRequest request,
      RequestState state,
      SingularityDeployStatistics deployStatistics,
      PendingType pendingType) {
    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 scheduleFrom = new Date(now);

          CronExpression cronExpression = new CronExpression(request.getQuartzScheduleSafe());

          final Date nextRunAtDate = cronExpression.getNextValidTimeAfter(scheduleFrom);

          if (nextRunAtDate == null) {
            return Optional.absent();
          }

          LOG.trace(
              "Calculating nextRunAtDate for {} (schedule: {}): {} (from: {})",
              request.getId(),
              request.getSchedule(),
              nextRunAtDate,
              scheduleFrom);

          nextRunAt =
              Math.max(
                  nextRunAtDate.getTime(),
                  now); // don't create a schedule that is overdue as this is used to indicate that
                        // singularity is not fulfilling requests.

          LOG.trace(
              "Scheduling next run of {} (schedule: {}) at {} (from: {})",
              request.getId(),
              request.getSchedule(),
              nextRunAtDate,
              scheduleFrom);
        } catch (ParseException pe) {
          throw Throwables.propagate(pe);
        }
      }
    }

    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);
  }