public void shutdown() throws IOException {
    final long truncatedNow = segmentGranularity.truncate(new DateTime()).getMillis();
    final long end = segmentGranularity.increment(truncatedNow) + windowMillis;
    final Duration timeUntilShutdown = new Duration(System.currentTimeMillis(), end);

    log.info("Shutdown at approx. %s (in %s)", new DateTime(end), timeUntilShutdown);

    ScheduledExecutors.scheduleWithFixedDelay(
        scheduledExecutor,
        timeUntilShutdown,
        new Callable<ScheduledExecutors.Signal>() {
          @Override
          public ScheduledExecutors.Signal call() throws Exception {
            try {
              valveOn.set(false);
            } catch (Exception e) {
              throw Throwables.propagate(e);
            }

            return ScheduledExecutors.Signal.STOP;
          }
        });

    beginRejectionPolicy = true;
  }
  public GracefulShutdownFirehose(
      Firehose firehose, IndexGranularity segmentGranularity, Period windowPeriod) {
    this.firehose = firehose;
    this.segmentGranularity = segmentGranularity;
    this.windowMillis = windowPeriod.toStandardDuration().getMillis() * 2;
    this.scheduledExecutor =
        Executors.newScheduledThreadPool(
            1,
            new ThreadFactoryBuilder()
                .setDaemon(true)
                .setNameFormat("firehose_scheduled_%d")
                .build());

    final long truncatedNow = segmentGranularity.truncate(new DateTime()).getMillis();
    final long end = segmentGranularity.increment(truncatedNow);

    this.rejectionPolicy =
        new IntervalRejectionPolicyFactory(new Interval(truncatedNow, end)).create(windowPeriod);
  }