aurora-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From wfar...@apache.org
Subject aurora git commit: Remove StartupRegistry.
Date Fri, 11 Sep 2015 17:31:27 GMT
Repository: aurora
Updated Branches:
  refs/heads/master 12300292d -> 4ad0d36f7


Remove StartupRegistry.

Reviewed at https://reviews.apache.org/r/38014/


Project: http://git-wip-us.apache.org/repos/asf/aurora/repo
Commit: http://git-wip-us.apache.org/repos/asf/aurora/commit/4ad0d36f
Tree: http://git-wip-us.apache.org/repos/asf/aurora/tree/4ad0d36f
Diff: http://git-wip-us.apache.org/repos/asf/aurora/diff/4ad0d36f

Branch: refs/heads/master
Commit: 4ad0d36f73dad078e2e98186a40b137b062b6808
Parents: 1230029
Author: Bill Farner <wfarner@apache.org>
Authored: Fri Sep 11 10:31:16 2015 -0700
Committer: Bill Farner <wfarner@apache.org>
Committed: Fri Sep 11 10:31:16 2015 -0700

----------------------------------------------------------------------
 .../aurora/common/application/AppLauncher.java  |  33 +----
 .../common/application/StartupRegistry.java     |  52 --------
 .../aurora/common/application/StartupStage.java |  31 -----
 .../application/modules/LifecycleModule.java    | 121 -------------------
 .../common/application/modules/StatsModule.java | 111 -----------------
 .../common/stats/TimeSeriesRepository.java      |  16 +--
 .../common/stats/TimeSeriesRepositoryImpl.java  |  69 +++++------
 config/legacy_untested_classes.txt              |   2 +
 .../scheduler/SchedulerServicesModule.java      |  42 -------
 .../apache/aurora/scheduler/app/AppModule.java  |  51 --------
 .../aurora/scheduler/app/LifecycleModule.java   |  70 +++++++++++
 .../aurora/scheduler/app/SchedulerMain.java     |  27 ++++-
 .../aurora/scheduler/stats/StatsModule.java     |  75 ++++++++++++
 .../aurora/scheduler/app/SchedulerIT.java       |   9 +-
 .../local/simulator/ClusterSimulatorModule.java |  17 ++-
 .../aurora/scheduler/async/AsyncModuleTest.java |   2 +-
 .../scheduler/events/PubsubEventModuleTest.java |   9 +-
 .../scheduler/http/JettyServerModuleTest.java   |  21 ++--
 .../preemptor/PreemptorModuleTest.java          |   7 --
 .../scheduler/reconciliation/KillRetryTest.java |   2 +-
 .../aurora/scheduler/sla/SlaModuleTest.java     |   2 +-
 21 files changed, 238 insertions(+), 531 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/aurora/blob/4ad0d36f/commons/src/main/java/org/apache/aurora/common/application/AppLauncher.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/application/AppLauncher.java b/commons/src/main/java/org/apache/aurora/common/application/AppLauncher.java
index 78ed7d0..80b24bd 100644
--- a/commons/src/main/java/org/apache/aurora/common/application/AppLauncher.java
+++ b/commons/src/main/java/org/apache/aurora/common/application/AppLauncher.java
@@ -18,22 +18,15 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import com.google.common.base.Preconditions;
-import com.google.common.base.Throwables;
-import com.google.common.collect.ImmutableList;
 import com.google.inject.Guice;
 import com.google.inject.Injector;
-import com.google.inject.Key;
-import com.google.inject.Module;
 import com.google.inject.util.Modules;
 
-import org.apache.aurora.common.application.modules.AppLauncherModule;
-import org.apache.aurora.common.application.modules.LifecycleModule;
 import org.apache.aurora.common.args.Arg;
 import org.apache.aurora.common.args.ArgFilters;
 import org.apache.aurora.common.args.ArgScanner;
 import org.apache.aurora.common.args.ArgScanner.ArgScanException;
 import org.apache.aurora.common.args.CmdLine;
-import org.apache.aurora.common.base.ExceptionalCommand;
 
 /**
  * An application launcher that sets up a framework for pluggable binding modules.  This class
@@ -43,11 +36,6 @@ import org.apache.aurora.common.base.ExceptionalCommand;
  * If your application uses command line arguments all {@link Arg} fields annotated with
  * {@link CmdLine} will be discovered and command line arguments will be validated against this set,
  * parsed and applied.
- *
- * A bootstrap module will be automatically applied ({@link AppLauncherModule}), which provides
- * overridable default bindings for things like quit/abort hooks and a health check function.
- * A {@link LifecycleModule} is also automatically applied to perform startup and shutdown
- * actions.
  */
 public final class AppLauncher {
 
@@ -60,28 +48,9 @@ public final class AppLauncher {
   private void run(Application application) {
     Lifecycle lifecycle = null;
     try {
-      Iterable<Module> modules = ImmutableList.<Module>builder()
-          .add(new LifecycleModule())
-          .add(new AppLauncherModule())
-          .addAll(application.getModules())
-          .build();
-
-      Injector injector = Guice.createInjector(Modules.combine(modules));
-
-      ExceptionalCommand startupCommand =
-          injector.getInstance(Key.get(ExceptionalCommand.class, StartupStage.class));
+      Injector injector = Guice.createInjector(application.getModules());
       lifecycle = injector.getInstance(Lifecycle.class);
-
       injector.injectMembers(application);
-
-      LOG.info("Executing startup actions.");
-      try {
-        startupCommand.execute();
-      } catch (Exception e) {
-        LOG.log(Level.SEVERE, "Startup action failed, quitting.", e);
-        throw Throwables.propagate(e);
-      }
-
       try {
         application.run();
       } finally {

http://git-wip-us.apache.org/repos/asf/aurora/blob/4ad0d36f/commons/src/main/java/org/apache/aurora/common/application/StartupRegistry.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/application/StartupRegistry.java b/commons/src/main/java/org/apache/aurora/common/application/StartupRegistry.java
deleted file mode 100644
index 997ee77..0000000
--- a/commons/src/main/java/org/apache/aurora/common/application/StartupRegistry.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/**
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.aurora.common.application;
-
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.logging.Logger;
-
-import com.google.common.base.Preconditions;
-import com.google.inject.Inject;
-
-import org.apache.aurora.common.base.ExceptionalCommand;
-
-/**
- * A registry that executes a set of commands.  The registry will synchronously execute commands
- * when {@link #execute()} is invoked, returning early if any action throws an exception.
- * Only one call to {@link #execute()} will have an effect, all subsequent calls will be ignored.
- */
-public class StartupRegistry implements ExceptionalCommand<Exception> {
-
-  private static final Logger LOG = Logger.getLogger(StartupRegistry.class.getName());
-
-  private final Set<ExceptionalCommand> startupActions;
-  private final AtomicBoolean started = new AtomicBoolean(false);
-
-  @Inject
-  public StartupRegistry(@StartupStage Set<ExceptionalCommand> startupActions) {
-    this.startupActions = Preconditions.checkNotNull(startupActions);
-  }
-
-  @Override
-  public void execute() throws Exception {
-    if (!started.compareAndSet(false, true)) {
-      LOG.warning("Startup actions cannot be executed more than once, ignoring.");
-    }
-
-    for (ExceptionalCommand<?> startupAction : startupActions) {
-      startupAction.execute();
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/aurora/blob/4ad0d36f/commons/src/main/java/org/apache/aurora/common/application/StartupStage.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/application/StartupStage.java b/commons/src/main/java/org/apache/aurora/common/application/StartupStage.java
deleted file mode 100644
index 8050901..0000000
--- a/commons/src/main/java/org/apache/aurora/common/application/StartupStage.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.aurora.common.application;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-import com.google.inject.BindingAnnotation;
-
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.ElementType.PARAMETER;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-/**
- * Binding annotation used for the startup registry.
- */
-@BindingAnnotation
-@Target({ FIELD, PARAMETER, METHOD }) @Retention(RUNTIME)
-public @interface StartupStage { }

http://git-wip-us.apache.org/repos/asf/aurora/blob/4ad0d36f/commons/src/main/java/org/apache/aurora/common/application/modules/LifecycleModule.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/application/modules/LifecycleModule.java b/commons/src/main/java/org/apache/aurora/common/application/modules/LifecycleModule.java
deleted file mode 100644
index 1b6bd08..0000000
--- a/commons/src/main/java/org/apache/aurora/common/application/modules/LifecycleModule.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/**
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.aurora.common.application.modules;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-import com.google.inject.AbstractModule;
-import com.google.inject.Binder;
-import com.google.inject.BindingAnnotation;
-import com.google.inject.Inject;
-import com.google.inject.Key;
-import com.google.inject.Singleton;
-import com.google.inject.multibindings.Multibinder;
-
-import org.apache.aurora.common.application.Lifecycle;
-import org.apache.aurora.common.application.ShutdownRegistry;
-import org.apache.aurora.common.application.ShutdownStage;
-import org.apache.aurora.common.application.StartupRegistry;
-import org.apache.aurora.common.application.StartupStage;
-import org.apache.aurora.common.base.Command;
-import org.apache.aurora.common.base.ExceptionalCommand;
-
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.ElementType.PARAMETER;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * Binding module for startup and shutdown controller and registries.
- *
- * Bindings provided by this module:
- * <ul>
- *   <li>{@code @StartupStage ExceptionalCommand} - Command to execute all startup actions.
- *   <li>{@code ShutdownRegistry} - Registry for adding shutdown actions.
- *   <li>{@code @ShutdownStage Command} - Command to execute all shutdown commands.
- * </ul>
- * @author William Farner
- */
-public class LifecycleModule extends AbstractModule {
-
-  /**
-   * Binding annotation used for local services.
-   * This is used to ensure the LocalService bindings are visibile within the package only, to
-   * prevent injection inadvertently triggering a service launch.
-   */
-  @BindingAnnotation
-  @Target({ FIELD, PARAMETER, METHOD }) @Retention(RUNTIME)
-  @interface Service { }
-
-  @Override
-  protected void configure() {
-    bind(Lifecycle.class).in(Singleton.class);
-
-    bind(Key.get(ExceptionalCommand.class, StartupStage.class)).to(StartupRegistry.class);
-    bind(StartupRegistry.class).in(Singleton.class);
-
-    bind(ShutdownRegistry.class).to(ShutdownRegistry.ShutdownRegistryImpl.class);
-    bind(Key.get(Command.class, ShutdownStage.class)).to(ShutdownRegistry.ShutdownRegistryImpl.class);
-    bind(ShutdownRegistry.ShutdownRegistryImpl.class).in(Singleton.class);
-    bindStartupAction(binder(), ShutdownHookRegistration.class);
-  }
-
-  /**
-   * Thrown when a local service fails to launch.
-   */
-  public static class LaunchException extends Exception {
-    public LaunchException(String msg) {
-      super(msg);
-    }
-
-    public LaunchException(String msg, Throwable cause) {
-      super(msg, cause);
-    }
-  }
-
-  /**
-   * Adds a startup action to the startup registry binding.
-   *
-   * @param binder Binder to bind against.
-   * @param actionClass Class to bind (and instantiate via guice) for execution at startup.
-   */
-  public static void bindStartupAction(Binder binder,
-      Class<? extends ExceptionalCommand> actionClass) {
-
-    Multibinder.newSetBinder(binder, ExceptionalCommand.class, StartupStage.class)
-        .addBinding().to(actionClass);
-  }
-
-  /**
-   * Startup command to register the shutdown registry as a process shutdown hook.
-   */
-  private static class ShutdownHookRegistration implements Command {
-    private final Command shutdownCommand;
-
-    @Inject ShutdownHookRegistration(@ShutdownStage Command shutdownCommand) {
-      this.shutdownCommand = checkNotNull(shutdownCommand);
-    }
-
-    @Override public void execute() {
-      Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
-        @Override public void run() {
-          shutdownCommand.execute();
-        }
-      }, "ShutdownRegistry-Hook"));
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/aurora/blob/4ad0d36f/commons/src/main/java/org/apache/aurora/common/application/modules/StatsModule.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/application/modules/StatsModule.java b/commons/src/main/java/org/apache/aurora/common/application/modules/StatsModule.java
deleted file mode 100644
index 3959ce3..0000000
--- a/commons/src/main/java/org/apache/aurora/common/application/modules/StatsModule.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/**
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.aurora.common.application.modules;
-
-import java.util.logging.Logger;
-
-import com.google.common.base.Supplier;
-import com.google.inject.AbstractModule;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
-import com.google.inject.TypeLiteral;
-import com.google.inject.name.Names;
-
-import org.apache.aurora.common.application.ShutdownRegistry;
-import org.apache.aurora.common.args.Arg;
-import org.apache.aurora.common.args.CmdLine;
-import org.apache.aurora.common.base.Command;
-import org.apache.aurora.common.quantity.Amount;
-import org.apache.aurora.common.quantity.Time;
-import org.apache.aurora.common.stats.JvmStats;
-import org.apache.aurora.common.stats.Stat;
-import org.apache.aurora.common.stats.StatRegistry;
-import org.apache.aurora.common.stats.Stats;
-import org.apache.aurora.common.stats.TimeSeriesRepository;
-import org.apache.aurora.common.stats.TimeSeriesRepositoryImpl;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * Binding module for injections related to the in-process stats system.
- *
- * This modules supports two command line arguments:
- * <ul>
- *   <li>{@code stat_sampling_interval} - Statistic value sampling interval.
- *   <li>{@code stat_retention_period} - Time for a stat to be retained in memory before expring.
- * </ul>
- *
- * Bindings required by this module:
- * <ul>
- *   <li>{@code ShutdownRegistry} - Shutdown hook registry.
- *   <li>{@code BuildInfo} - Build information for the application.
- * </ul>
- *
- * @author William Farner
- */
-public class StatsModule extends AbstractModule {
-
-  @CmdLine(name = "stat_sampling_interval", help = "Statistic value sampling interval.")
-  private static final Arg<Amount<Long, Time>> SAMPLING_INTERVAL =
-      Arg.create(Amount.of(1L, Time.SECONDS));
-
-  @CmdLine(name = "stat_retention_period",
-      help = "Time for a stat to be retained in memory before expiring.")
-  private static final Arg<Amount<Long, Time>> RETENTION_PERIOD =
-      Arg.create(Amount.of(1L, Time.HOURS));
-
-  @Override
-  protected void configure() {
-    requireBinding(ShutdownRegistry.class);
-
-    // Bindings for TimeSeriesRepositoryImpl.
-    bind(StatRegistry.class).toInstance(Stats.STAT_REGISTRY);
-    bind(new TypeLiteral<Amount<Long, Time>>() { })
-        .annotatedWith(Names.named(TimeSeriesRepositoryImpl.SAMPLE_RETENTION_PERIOD))
-        .toInstance(RETENTION_PERIOD.get());
-    bind(new TypeLiteral<Amount<Long, Time>>() { })
-        .annotatedWith(Names.named(TimeSeriesRepositoryImpl.SAMPLE_PERIOD))
-        .toInstance(SAMPLING_INTERVAL.get());
-    bind(TimeSeriesRepository.class).to(TimeSeriesRepositoryImpl.class).in(Singleton.class);
-
-    bind(new TypeLiteral<Supplier<Iterable<Stat<?>>>>() { }).toInstance(
-        new Supplier<Iterable<Stat<?>>>() {
-          @Override public Iterable<Stat<?>> get() {
-            return Stats.getVariables();
-          }
-        }
-    );
-
-    LifecycleModule.bindStartupAction(binder(), StartStatPoller.class);
-  }
-
-  public static final class StartStatPoller implements Command {
-    private static final Logger LOG = Logger.getLogger(StartStatPoller.class.getName());
-    private final ShutdownRegistry shutdownRegistry;
-    private final TimeSeriesRepository timeSeriesRepository;
-
-    @Inject StartStatPoller(
-        ShutdownRegistry shutdownRegistry,
-        TimeSeriesRepository timeSeriesRepository) {
-
-      this.shutdownRegistry = checkNotNull(shutdownRegistry);
-      this.timeSeriesRepository = checkNotNull(timeSeriesRepository);
-    }
-
-    @Override public void execute() {
-      JvmStats.export();
-      timeSeriesRepository.start(shutdownRegistry);
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/aurora/blob/4ad0d36f/commons/src/main/java/org/apache/aurora/common/stats/TimeSeriesRepository.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/stats/TimeSeriesRepository.java b/commons/src/main/java/org/apache/aurora/common/stats/TimeSeriesRepository.java
index 6928e48..ad6ebe6 100644
--- a/commons/src/main/java/org/apache/aurora/common/stats/TimeSeriesRepository.java
+++ b/commons/src/main/java/org/apache/aurora/common/stats/TimeSeriesRepository.java
@@ -15,8 +15,6 @@ package org.apache.aurora.common.stats;
 
 import java.util.Set;
 
-import org.apache.aurora.common.application.ShutdownRegistry;
-
 /**
  * A repository for time series data.
  *
@@ -25,19 +23,11 @@ import org.apache.aurora.common.application.ShutdownRegistry;
 public interface TimeSeriesRepository {
 
   /**
-   * Starts the time series sampler.
-   *
-   * @param shutdownRegistry An action registry that the repository can use to register a shutdown
-   *    for the sampler.
-   */
-  public void start(ShutdownRegistry shutdownRegistry);
-
-  /**
    * Fetches the names of all available time series.
    *
    * @return Available time series, which can then be obtained by calling {@link #get(String)}.
    */
-  public Set<String> getAvailableSeries();
+  Set<String> getAvailableSeries();
 
   /**
    * Fetches a time series by name.
@@ -46,12 +36,12 @@ public interface TimeSeriesRepository {
    * @return The time series registered with the given name, or {@code null} if no such time series
    *     has been registered.
    */
-  public TimeSeries get(String name);
+  TimeSeries get(String name);
 
   /**
    * Gets an ordered iterable of the timestamps that all timeseries were sampled at.
    *
    * @return All current timestamps.
    */
-  public Iterable<Number> getTimestamps();
+  Iterable<Number> getTimestamps();
 }

http://git-wip-us.apache.org/repos/asf/aurora/blob/4ad0d36f/commons/src/main/java/org/apache/aurora/common/stats/TimeSeriesRepositoryImpl.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/stats/TimeSeriesRepositoryImpl.java b/commons/src/main/java/org/apache/aurora/common/stats/TimeSeriesRepositoryImpl.java
index b0f2d06..c314a0d 100644
--- a/commons/src/main/java/org/apache/aurora/common/stats/TimeSeriesRepositoryImpl.java
+++ b/commons/src/main/java/org/apache/aurora/common/stats/TimeSeriesRepositoryImpl.java
@@ -16,8 +16,6 @@ package org.apache.aurora.common.stats;
 import java.util.Set;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.ScheduledThreadPoolExecutor;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import com.google.common.annotations.VisibleForTesting;
@@ -28,12 +26,11 @@ import com.google.common.cache.LoadingCache;
 import com.google.common.collect.EvictingQueue;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
+import com.google.common.util.concurrent.AbstractScheduledService;
 import com.google.common.util.concurrent.ThreadFactoryBuilder;
 import com.google.inject.Inject;
 import com.google.inject.name.Named;
 
-import org.apache.aurora.common.application.ShutdownRegistry;
-import org.apache.aurora.common.base.Command;
 import org.apache.aurora.common.quantity.Amount;
 import org.apache.aurora.common.quantity.Time;
 import org.apache.aurora.common.util.Clock;
@@ -45,7 +42,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
  *
  * @author John Sirois
  */
-public class TimeSeriesRepositoryImpl implements TimeSeriesRepository {
+public class TimeSeriesRepositoryImpl
+    extends AbstractScheduledService implements TimeSeriesRepository {
 
   private static final Logger LOG = Logger.getLogger(TimeSeriesRepositoryImpl.class.getName());
 
@@ -107,42 +105,37 @@ public class TimeSeriesRepositoryImpl implements TimeSeriesRepository {
     timestamps = EvictingQueue.create(retainedSampleLimit);
   }
 
-  /**
-   * Starts the variable sampler, which will fetch variables {@link Stats} on the given period.
-   *
-   */
+  private final ScheduledExecutorService executor = new ScheduledThreadPoolExecutor(
+      1 /* One thread. */,
+      new ThreadFactoryBuilder().setNameFormat("VariableSampler-%d").setDaemon(true).build());
+
   @Override
-  public void start(ShutdownRegistry shutdownRegistry) {
-    checkNotNull(shutdownRegistry);
-    checkNotNull(samplePeriod);
-    Preconditions.checkArgument(samplePeriod.getValue() > 0);
-
-    final ScheduledExecutorService executor = new ScheduledThreadPoolExecutor(1 /* One thread. */,
-        new ThreadFactoryBuilder().setNameFormat("VariableSampler-%d").setDaemon(true).build());
-
-    final AtomicBoolean shouldSample = new AtomicBoolean(true);
-    final Runnable sampler = new Runnable() {
-      @Override public void run() {
-        if (shouldSample.get()) {
-          try {
-            runSampler(Clock.SYSTEM_CLOCK);
-          } catch (Exception e) {
-            LOG.log(Level.SEVERE, "ignoring runSampler failure", e);
-          }
-        }
-      }
-    };
+  protected void startUp() throws Exception {
+    JvmStats.export();
+  }
 
-    executor.scheduleAtFixedRate(sampler, samplePeriod.getValue(), samplePeriod.getValue(),
+  @Override
+  protected Scheduler scheduler() {
+    return Scheduler.newFixedRateSchedule(
+        samplePeriod.getValue(),
+        samplePeriod.getValue(),
         samplePeriod.getUnit().getTimeUnit());
-    shutdownRegistry.addAction(new Command() {
-      @Override
-      public void execute() throws RuntimeException {
-        shouldSample.set(false);
-        executor.shutdown();
-        LOG.info("Variable sampler shut down");
-      }
-    });
+  }
+
+  @Override
+  protected ScheduledExecutorService executor() {
+    return executor;
+  }
+
+  @Override
+  protected void runOneIteration() throws Exception {
+    runSampler(Clock.SYSTEM_CLOCK);
+  }
+
+  @Override
+  protected void shutDown() throws Exception {
+    executor.shutdown();
+    LOG.info("Variable sampler shut down");
   }
 
   @VisibleForTesting

http://git-wip-us.apache.org/repos/asf/aurora/blob/4ad0d36f/config/legacy_untested_classes.txt
----------------------------------------------------------------------
diff --git a/config/legacy_untested_classes.txt b/config/legacy_untested_classes.txt
index 4bae43a..346b947 100644
--- a/config/legacy_untested_classes.txt
+++ b/config/legacy_untested_classes.txt
@@ -3,6 +3,7 @@ org/apache/aurora/auth/UnsecureAuthModule$UnsecureCapabilityValidator$1
 org/apache/aurora/auth/UnsecureAuthModule$UnsecureCapabilityValidator$2
 org/apache/aurora/scheduler/app/SchedulerMain$2
 org/apache/aurora/scheduler/app/SchedulerMain$3
+org/apache/aurora/scheduler/app/SchedulerMain$4
 org/apache/aurora/scheduler/async/OfferQueue$OfferQueueImpl$2
 org/apache/aurora/scheduler/base/Conversions$1
 org/apache/aurora/scheduler/base/Conversions$2
@@ -53,6 +54,7 @@ org/apache/aurora/scheduler/log/mesos/MesosLogStreamModule$5
 org/apache/aurora/scheduler/mesos/DriverFactoryImpl
 org/apache/aurora/scheduler/mesos/LibMesosLoadingModule
 org/apache/aurora/scheduler/stats/AsyncStatsModule$OfferAdapter$1
+org/apache/aurora/scheduler/stats/StatsModule$3
 org/apache/aurora/scheduler/storage/log/LogStorage$RecoveryFailedException
 org/apache/aurora/scheduler/storage/mem/Util
 org/apache/aurora/scheduler/storage/mem/Util$1

http://git-wip-us.apache.org/repos/asf/aurora/blob/4ad0d36f/src/main/java/org/apache/aurora/scheduler/SchedulerServicesModule.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/SchedulerServicesModule.java b/src/main/java/org/apache/aurora/scheduler/SchedulerServicesModule.java
index 1077816..7b110b9 100644
--- a/src/main/java/org/apache/aurora/scheduler/SchedulerServicesModule.java
+++ b/src/main/java/org/apache/aurora/scheduler/SchedulerServicesModule.java
@@ -14,10 +14,7 @@
 package org.apache.aurora.scheduler;
 
 import java.util.Set;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
 
-import javax.inject.Inject;
 import javax.inject.Singleton;
 
 import com.google.common.util.concurrent.Service;
@@ -30,14 +27,8 @@ import com.google.inject.multibindings.Multibinder;
 
 import org.apache.aurora.GuavaUtils;
 import org.apache.aurora.GuavaUtils.ServiceManagerIface;
-import org.apache.aurora.common.application.ShutdownRegistry;
-import org.apache.aurora.common.application.modules.LifecycleModule;
-import org.apache.aurora.common.base.Command;
-import org.apache.aurora.common.base.ExceptionalCommand;
 import org.apache.aurora.scheduler.SchedulerLifecycle.SchedulerActive;
 
-import static java.util.Objects.requireNonNull;
-
 /**
  * Coordinates scheduler startup.
  */
@@ -69,44 +60,11 @@ public class SchedulerServicesModule extends AbstractModule {
 
   @Override
   protected void configure() {
-    LifecycleModule.bindStartupAction(binder(), ServiceManagerAdapterCommand.class);
-
     // Add a binding.
     Multibinder.newSetBinder(binder(), Service.class, AppStartup.class);
     Multibinder.newSetBinder(binder(), Service.class, SchedulerActive.class);
   }
 
-  /**
-   * Adapter to make twitter.common.application startup call into Guava's ServiceManager.
-   */
-  @Singleton
-  static class ServiceManagerAdapterCommand implements Command {
-    private final ShutdownRegistry shutdownRegistry;
-    private final ServiceManagerIface serviceManager;
-
-    @Inject
-    ServiceManagerAdapterCommand(
-        ShutdownRegistry shutdownRegistry,
-        @AppStartup final ServiceManagerIface serviceManager) {
-
-      this.shutdownRegistry = requireNonNull(shutdownRegistry);
-      this.serviceManager = requireNonNull(serviceManager);
-    }
-
-    @Override
-    public void execute() {
-      serviceManager.startAsync();
-      shutdownRegistry.addAction(new ExceptionalCommand<TimeoutException>() {
-        @Override
-        public void execute() throws TimeoutException {
-          serviceManager.stopAsync();
-          serviceManager.awaitStopped(5L, TimeUnit.SECONDS);
-        }
-      });
-      serviceManager.awaitHealthy();
-    }
-  }
-
   @Provides
   @Singleton
   @AppStartup

http://git-wip-us.apache.org/repos/asf/aurora/blob/4ad0d36f/src/main/java/org/apache/aurora/scheduler/app/AppModule.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/app/AppModule.java b/src/main/java/org/apache/aurora/scheduler/app/AppModule.java
index 6892a70..bf8ab31 100644
--- a/src/main/java/org/apache/aurora/scheduler/app/AppModule.java
+++ b/src/main/java/org/apache/aurora/scheduler/app/AppModule.java
@@ -13,23 +13,15 @@
  */
 package org.apache.aurora.scheduler.app;
 
-import java.util.Arrays;
 import java.util.List;
 import java.util.logging.Logger;
 
-import javax.inject.Inject;
 import javax.inject.Singleton;
 
-import com.google.common.base.Function;
-import com.google.common.base.Joiner;
-import com.google.common.collect.Iterables;
 import com.google.inject.AbstractModule;
 import com.google.inject.Provides;
 
 import org.apache.aurora.GuiceUtils;
-import org.apache.aurora.common.application.ShutdownRegistry;
-import org.apache.aurora.common.application.modules.LifecycleModule;
-import org.apache.aurora.common.base.Command;
 import org.apache.aurora.common.inject.TimedInterceptor;
 import org.apache.aurora.common.net.pool.DynamicHostSet;
 import org.apache.aurora.common.stats.Stats;
@@ -69,7 +61,6 @@ import org.apache.zookeeper.data.ACL;
 import static java.util.Objects.requireNonNull;
 
 import static org.apache.aurora.common.base.MorePreconditions.checkNotBlank;
-
 import static org.apache.aurora.gen.apiConstants.THRIFT_API_VERSION;
 
 /**
@@ -116,8 +107,6 @@ public class AppModule extends AbstractModule {
     PubsubEventModule.bindSchedulingFilterDelegate(binder()).to(SchedulingFilterImpl.class);
     bind(SchedulingFilterImpl.class).in(Singleton.class);
 
-    LifecycleModule.bindStartupAction(binder(), RegisterShutdownStackPrinter.class);
-
     install(new AsyncModule());
     install(new OffersModule());
     install(new PruningModule());
@@ -137,46 +126,6 @@ public class AppModule extends AbstractModule {
     bind(StatsProvider.class).toInstance(Stats.STATS_PROVIDER);
   }
 
-  /**
-   * Command to register a thread stack printer that identifies initiator of a shutdown.
-   */
-  private static class RegisterShutdownStackPrinter implements Command {
-    private static final Function<StackTraceElement, String> STACK_ELEM_TOSTRING =
-        new Function<StackTraceElement, String>() {
-          @Override
-          public String apply(StackTraceElement element) {
-            return element.getClassName() + "." + element.getMethodName()
-                + String.format("(%s:%s)", element.getFileName(), element.getLineNumber());
-          }
-        };
-
-    private final ShutdownRegistry shutdownRegistry;
-
-    @Inject
-    RegisterShutdownStackPrinter(ShutdownRegistry shutdownRegistry) {
-      this.shutdownRegistry = shutdownRegistry;
-    }
-
-    @Override
-    public void execute() {
-      shutdownRegistry.addAction(new Command() {
-        @Override
-        public void execute() {
-          Thread thread = Thread.currentThread();
-          String message = new StringBuilder()
-              .append("Thread: ").append(thread.getName())
-              .append(" (id ").append(thread.getId()).append(")")
-              .append("\n")
-              .append(Joiner.on("\n  ").join(
-                  Iterables.transform(Arrays.asList(thread.getStackTrace()), STACK_ELEM_TOSTRING)))
-              .toString();
-
-          LOG.info("Shutdown initiated by: " + message);
-        }
-      });
-    }
-  }
-
   @Provides
   @Singleton
   List<ACL> provideAcls() {

http://git-wip-us.apache.org/repos/asf/aurora/blob/4ad0d36f/src/main/java/org/apache/aurora/scheduler/app/LifecycleModule.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/app/LifecycleModule.java b/src/main/java/org/apache/aurora/scheduler/app/LifecycleModule.java
new file mode 100644
index 0000000..ec85aac
--- /dev/null
+++ b/src/main/java/org/apache/aurora/scheduler/app/LifecycleModule.java
@@ -0,0 +1,70 @@
+/**
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.aurora.scheduler.app;
+
+import javax.inject.Inject;
+
+import com.google.common.util.concurrent.AbstractIdleService;
+import com.google.inject.AbstractModule;
+import com.google.inject.Key;
+import com.google.inject.Singleton;
+
+import org.apache.aurora.common.application.Lifecycle;
+import org.apache.aurora.common.application.ShutdownRegistry;
+import org.apache.aurora.common.application.ShutdownRegistry.ShutdownRegistryImpl;
+import org.apache.aurora.common.application.ShutdownStage;
+import org.apache.aurora.common.base.Command;
+import org.apache.aurora.scheduler.SchedulerServicesModule;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Binding module for a shutdown registry.
+ */
+public class LifecycleModule extends AbstractModule {
+
+  @Override
+  protected void configure() {
+    bind(Lifecycle.class).in(Singleton.class);
+
+    bind(ShutdownRegistry.class).to(ShutdownRegistryImpl.class);
+    bind(Key.get(Command.class, ShutdownStage.class)).to(ShutdownRegistryImpl.class);
+    bind(ShutdownRegistryImpl.class).in(Singleton.class);
+    SchedulerServicesModule.addAppStartupServiceBinding(binder())
+        .to(TearDownShutdownRegistry.class);
+  }
+
+  /**
+   * Startup command to register the shutdown registry as a process shutdown hook.
+   * TODO(wfarner): Replace the shutdown registry with services and remove this behavior.
+   */
+  private static class TearDownShutdownRegistry extends AbstractIdleService {
+    private final Command shutdownCommand;
+
+    @Inject
+    TearDownShutdownRegistry(@ShutdownStage Command shutdownCommand) {
+      this.shutdownCommand = checkNotNull(shutdownCommand);
+    }
+
+    @Override
+    protected void startUp() {
+      // no-op
+    }
+
+    @Override
+    protected void shutDown() {
+      shutdownCommand.execute();
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/4ad0d36f/src/main/java/org/apache/aurora/scheduler/app/SchedulerMain.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/app/SchedulerMain.java b/src/main/java/org/apache/aurora/scheduler/app/SchedulerMain.java
index acca4b4..89399f1 100644
--- a/src/main/java/org/apache/aurora/scheduler/app/SchedulerMain.java
+++ b/src/main/java/org/apache/aurora/scheduler/app/SchedulerMain.java
@@ -15,6 +15,8 @@ package org.apache.aurora.scheduler.app;
 
 import java.net.InetSocketAddress;
 import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 import java.util.logging.Logger;
 
 import javax.inject.Inject;
@@ -28,10 +30,11 @@ import com.google.common.net.HostAndPort;
 import com.google.inject.AbstractModule;
 import com.google.inject.Module;
 
+import org.apache.aurora.GuavaUtils.ServiceManagerIface;
 import org.apache.aurora.common.application.AppLauncher;
 import org.apache.aurora.common.application.Application;
 import org.apache.aurora.common.application.Lifecycle;
-import org.apache.aurora.common.application.modules.StatsModule;
+import org.apache.aurora.common.application.modules.AppLauncherModule;
 import org.apache.aurora.common.args.Arg;
 import org.apache.aurora.common.args.CmdLine;
 import org.apache.aurora.common.args.constraints.NotEmpty;
@@ -47,6 +50,7 @@ import org.apache.aurora.common.zookeeper.guice.client.ZooKeeperClientModule;
 import org.apache.aurora.common.zookeeper.guice.client.ZooKeeperClientModule.ClientConfig;
 import org.apache.aurora.common.zookeeper.guice.client.flagged.FlaggedClientConfig;
 import org.apache.aurora.gen.Volume;
+import org.apache.aurora.scheduler.AppStartup;
 import org.apache.aurora.scheduler.ResourceSlot;
 import org.apache.aurora.scheduler.SchedulerLifecycle;
 import org.apache.aurora.scheduler.cron.quartz.CronModule;
@@ -55,6 +59,7 @@ import org.apache.aurora.scheduler.log.mesos.MesosLogStreamModule;
 import org.apache.aurora.scheduler.mesos.CommandLineDriverSettingsModule;
 import org.apache.aurora.scheduler.mesos.ExecutorSettings;
 import org.apache.aurora.scheduler.mesos.LibMesosLoadingModule;
+import org.apache.aurora.scheduler.stats.StatsModule;
 import org.apache.aurora.scheduler.storage.Storage;
 import org.apache.aurora.scheduler.storage.backup.BackupModule;
 import org.apache.aurora.scheduler.storage.db.DbModule;
@@ -129,6 +134,9 @@ public class SchedulerMain implements Application {
   @Inject private HttpService httpService;
   @Inject private SchedulerLifecycle schedulerLifecycle;
   @Inject private Lifecycle appLifecycle;
+  @Inject
+  @AppStartup
+  private ServiceManagerIface startupServices;
 
   private static Iterable<? extends Module> getExtraModules() {
     Builder<Module> modules = ImmutableList.builder();
@@ -183,6 +191,8 @@ public class SchedulerMain implements Application {
   public Iterable<? extends Module> getModules() {
     ClientConfig zkClientConfig = FlaggedClientConfig.create();
     return ImmutableList.<Module>builder()
+        .add(new LifecycleModule())
+        .add(new AppLauncherModule())
         .add(new BackupModule(SnapshotStoreImpl.class))
         .addAll(
             getModules(
@@ -215,7 +225,21 @@ public class SchedulerMain implements Application {
         .build();
   }
 
+  private void stop() {
+    LOG.info("Stopping scheduler services.");
+    try {
+      startupServices.stopAsync().awaitStopped(5L, TimeUnit.SECONDS);
+    } catch (TimeoutException e) {
+      LOG.info("Shutdown did not complete in time: " + e);
+    }
+    appLifecycle.shutdown();
+  }
+
   public void run() {
+    startupServices.startAsync();
+    Runtime.getRuntime().addShutdownHook(new Thread(SchedulerMain.this::stop, "ShutdownHook"));
+    startupServices.awaitHealthy();
+
     // Setup log4j to match our jul glog config in order to pick up zookeeper logging.
     Configuration logConfiguration = RootLogConfig.configurationFromFlags();
     logConfiguration.apply();
@@ -240,6 +264,7 @@ public class SchedulerMain implements Application {
     }
 
     appLifecycle.awaitShutdown();
+    stop();
   }
 
   public static void main(String... args) {

http://git-wip-us.apache.org/repos/asf/aurora/blob/4ad0d36f/src/main/java/org/apache/aurora/scheduler/stats/StatsModule.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/stats/StatsModule.java b/src/main/java/org/apache/aurora/scheduler/stats/StatsModule.java
new file mode 100644
index 0000000..6399e78
--- /dev/null
+++ b/src/main/java/org/apache/aurora/scheduler/stats/StatsModule.java
@@ -0,0 +1,75 @@
+/**
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.aurora.scheduler.stats;
+
+import com.google.common.base.Supplier;
+import com.google.inject.AbstractModule;
+import com.google.inject.Singleton;
+import com.google.inject.TypeLiteral;
+import com.google.inject.name.Names;
+
+import org.apache.aurora.common.application.ShutdownRegistry;
+import org.apache.aurora.common.args.Arg;
+import org.apache.aurora.common.args.CmdLine;
+import org.apache.aurora.common.quantity.Amount;
+import org.apache.aurora.common.quantity.Time;
+import org.apache.aurora.common.stats.Stat;
+import org.apache.aurora.common.stats.StatRegistry;
+import org.apache.aurora.common.stats.Stats;
+import org.apache.aurora.common.stats.TimeSeriesRepository;
+import org.apache.aurora.common.stats.TimeSeriesRepositoryImpl;
+import org.apache.aurora.scheduler.SchedulerServicesModule;
+
+/**
+ * Binding module for injections related to the in-process stats system.
+ */
+public class StatsModule extends AbstractModule {
+
+  @CmdLine(name = "stat_sampling_interval", help = "Statistic value sampling interval.")
+  private static final Arg<Amount<Long, Time>> SAMPLING_INTERVAL =
+      Arg.create(Amount.of(1L, Time.SECONDS));
+
+  @CmdLine(name = "stat_retention_period",
+      help = "Time for a stat to be retained in memory before expiring.")
+  private static final Arg<Amount<Long, Time>> RETENTION_PERIOD =
+      Arg.create(Amount.of(1L, Time.HOURS));
+
+  @Override
+  protected void configure() {
+    requireBinding(ShutdownRegistry.class);
+
+    // Bindings for TimeSeriesRepositoryImpl.
+    bind(StatRegistry.class).toInstance(Stats.STAT_REGISTRY);
+    bind(new TypeLiteral<Amount<Long, Time>>() { })
+        .annotatedWith(Names.named(TimeSeriesRepositoryImpl.SAMPLE_RETENTION_PERIOD))
+        .toInstance(RETENTION_PERIOD.get());
+    bind(new TypeLiteral<Amount<Long, Time>>() { })
+        .annotatedWith(Names.named(TimeSeriesRepositoryImpl.SAMPLE_PERIOD))
+        .toInstance(SAMPLING_INTERVAL.get());
+    bind(TimeSeriesRepository.class).to(TimeSeriesRepositoryImpl.class);
+    bind(TimeSeriesRepositoryImpl.class).in(Singleton.class);
+
+    bind(new TypeLiteral<Supplier<Iterable<Stat<?>>>>() { }).toInstance(
+        new Supplier<Iterable<Stat<?>>>() {
+          @Override
+          public Iterable<Stat<?>> get() {
+            return Stats.getVariables();
+          }
+        }
+    );
+
+    SchedulerServicesModule.addAppStartupServiceBinding(binder())
+        .to(TimeSeriesRepositoryImpl.class);
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/4ad0d36f/src/test/java/org/apache/aurora/scheduler/app/SchedulerIT.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/app/SchedulerIT.java b/src/test/java/org/apache/aurora/scheduler/app/SchedulerIT.java
index c58ce71..7f141df 100644
--- a/src/test/java/org/apache/aurora/scheduler/app/SchedulerIT.java
+++ b/src/test/java/org/apache/aurora/scheduler/app/SchedulerIT.java
@@ -43,12 +43,10 @@ import com.google.inject.Injector;
 import com.google.inject.Key;
 import com.google.inject.Module;
 
+import org.apache.aurora.GuavaUtils;
 import org.apache.aurora.codec.ThriftBinaryCodec.CodingException;
 import org.apache.aurora.common.application.Lifecycle;
-import org.apache.aurora.common.application.StartupStage;
 import org.apache.aurora.common.application.modules.AppLauncherModule;
-import org.apache.aurora.common.application.modules.LifecycleModule;
-import org.apache.aurora.common.base.ExceptionalCommand;
 import org.apache.aurora.common.net.pool.DynamicHostSet.HostChangeMonitor;
 import org.apache.aurora.common.quantity.Amount;
 import org.apache.aurora.common.quantity.Data;
@@ -74,6 +72,7 @@ import org.apache.aurora.gen.storage.SaveTasks;
 import org.apache.aurora.gen.storage.Snapshot;
 import org.apache.aurora.gen.storage.Transaction;
 import org.apache.aurora.gen.storage.storageConstants;
+import org.apache.aurora.scheduler.AppStartup;
 import org.apache.aurora.scheduler.ResourceSlot;
 import org.apache.aurora.scheduler.async.AsyncModule.AsyncExecutor;
 import org.apache.aurora.scheduler.async.FlushableWorkQueue;
@@ -223,8 +222,6 @@ public class SchedulerIT extends BaseZooKeeperTest {
     injector.injectMembers(main);
     lifecycle = injector.getInstance(Lifecycle.class);
 
-    injector.getInstance(Key.get(ExceptionalCommand.class, StartupStage.class)).execute();
-
     // Mimic AppLauncher running main.
     executor.submit(new Runnable() {
       @Override
@@ -244,6 +241,8 @@ public class SchedulerIT extends BaseZooKeeperTest {
         MoreExecutors.shutdownAndAwaitTermination(executor, 10, TimeUnit.SECONDS);
       }
     });
+    injector.getInstance(Key.get(GuavaUtils.ServiceManagerIface.class, AppStartup.class))
+        .awaitHealthy();
   }
 
   private void awaitSchedulerReady() throws Exception {

http://git-wip-us.apache.org/repos/asf/aurora/blob/4ad0d36f/src/test/java/org/apache/aurora/scheduler/app/local/simulator/ClusterSimulatorModule.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/app/local/simulator/ClusterSimulatorModule.java b/src/test/java/org/apache/aurora/scheduler/app/local/simulator/ClusterSimulatorModule.java
index 4af49d5..ea87688 100644
--- a/src/test/java/org/apache/aurora/scheduler/app/local/simulator/ClusterSimulatorModule.java
+++ b/src/test/java/org/apache/aurora/scheduler/app/local/simulator/ClusterSimulatorModule.java
@@ -19,11 +19,11 @@ import javax.inject.Inject;
 import javax.inject.Singleton;
 
 import com.google.common.eventbus.EventBus;
+import com.google.common.util.concurrent.AbstractIdleService;
 import com.google.inject.AbstractModule;
 import com.google.inject.multibindings.Multibinder;
 
-import org.apache.aurora.common.application.modules.LifecycleModule;
-import org.apache.aurora.common.base.Command;
+import org.apache.aurora.scheduler.SchedulerServicesModule;
 import org.apache.mesos.Protos;
 import org.apache.mesos.Protos.Offer;
 
@@ -58,10 +58,10 @@ public class ClusterSimulatorModule extends AbstractModule {
         .toInstance(dedicated(baseOffer("slave-5", "c", 24, 128 * 1024, 1824 * 1024), "database"));
     offers.addBinding()
         .toInstance(dedicated(baseOffer("slave-6", "c", 24, 128 * 1024, 1824 * 1024), "database"));
-    LifecycleModule.bindStartupAction(binder(), Register.class);
+    SchedulerServicesModule.addAppStartupServiceBinding(binder()).to(Register.class);
   }
 
-  static class Register implements Command {
+  static class Register extends AbstractIdleService {
     private final EventBus eventBus;
     private final FakeSlaves slaves;
 
@@ -72,8 +72,13 @@ public class ClusterSimulatorModule extends AbstractModule {
     }
 
     @Override
-    public void execute() {
-      eventBus .register(slaves);
+    protected void startUp() throws Exception {
+      eventBus.register(slaves);
+    }
+
+    @Override
+    protected void shutDown() {
+      // No-op.
     }
   }
 

http://git-wip-us.apache.org/repos/asf/aurora/blob/4ad0d36f/src/test/java/org/apache/aurora/scheduler/async/AsyncModuleTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/async/AsyncModuleTest.java b/src/test/java/org/apache/aurora/scheduler/async/AsyncModuleTest.java
index d0faf13..259ed86 100644
--- a/src/test/java/org/apache/aurora/scheduler/async/AsyncModuleTest.java
+++ b/src/test/java/org/apache/aurora/scheduler/async/AsyncModuleTest.java
@@ -24,11 +24,11 @@ import com.google.inject.Key;
 import com.google.inject.Module;
 import com.google.inject.TypeLiteral;
 
-import org.apache.aurora.common.application.modules.LifecycleModule;
 import org.apache.aurora.common.stats.StatsProvider;
 import org.apache.aurora.common.testing.easymock.EasyMockTest;
 import org.apache.aurora.common.util.Clock;
 import org.apache.aurora.scheduler.AppStartup;
+import org.apache.aurora.scheduler.app.LifecycleModule;
 import org.apache.aurora.scheduler.async.AsyncModule.RegisterGauges;
 import org.apache.aurora.scheduler.storage.testing.StorageTestUtil;
 import org.apache.aurora.scheduler.testing.FakeStatsProvider;

http://git-wip-us.apache.org/repos/asf/aurora/blob/4ad0d36f/src/test/java/org/apache/aurora/scheduler/events/PubsubEventModuleTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/events/PubsubEventModuleTest.java b/src/test/java/org/apache/aurora/scheduler/events/PubsubEventModuleTest.java
index cb38c3e..4709b77 100644
--- a/src/test/java/org/apache/aurora/scheduler/events/PubsubEventModuleTest.java
+++ b/src/test/java/org/apache/aurora/scheduler/events/PubsubEventModuleTest.java
@@ -27,12 +27,12 @@ import com.google.inject.Injector;
 import com.google.inject.Key;
 import com.google.inject.Module;
 
-import org.apache.aurora.common.application.StartupStage;
-import org.apache.aurora.common.application.modules.LifecycleModule;
-import org.apache.aurora.common.base.ExceptionalCommand;
+import org.apache.aurora.GuavaUtils;
 import org.apache.aurora.common.stats.StatsProvider;
 import org.apache.aurora.common.testing.easymock.EasyMockTest;
+import org.apache.aurora.scheduler.AppStartup;
 import org.apache.aurora.scheduler.SchedulerServicesModule;
+import org.apache.aurora.scheduler.app.LifecycleModule;
 import org.apache.aurora.scheduler.async.AsyncModule.AsyncExecutor;
 import org.apache.aurora.scheduler.filter.SchedulingFilter;
 import org.apache.aurora.scheduler.testing.FakeStatsProvider;
@@ -81,7 +81,8 @@ public class PubsubEventModuleTest extends EasyMockTest {
             PubsubEventModule.bindSubscriber(binder(), ThrowingSubscriber.class);
           }
         });
-    injector.getInstance(Key.get(ExceptionalCommand.class, StartupStage.class)).execute();
+    injector.getInstance(Key.get(GuavaUtils.ServiceManagerIface.class, AppStartup.class))
+        .startAsync().awaitHealthy();
     assertEquals(0L, statsProvider.getLongValue(PubsubEventModule.EXCEPTIONS_STAT));
     injector.getInstance(EventBus.class).post("hello");
     assertEquals(1L, statsProvider.getLongValue(PubsubEventModule.EXCEPTIONS_STAT));

http://git-wip-us.apache.org/repos/asf/aurora/blob/4ad0d36f/src/test/java/org/apache/aurora/scheduler/http/JettyServerModuleTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/http/JettyServerModuleTest.java b/src/test/java/org/apache/aurora/scheduler/http/JettyServerModuleTest.java
index ed8e811..3794b96 100644
--- a/src/test/java/org/apache/aurora/scheduler/http/JettyServerModuleTest.java
+++ b/src/test/java/org/apache/aurora/scheduler/http/JettyServerModuleTest.java
@@ -22,6 +22,7 @@ import com.google.common.util.concurrent.RateLimiter;
 import com.google.inject.AbstractModule;
 import com.google.inject.Guice;
 import com.google.inject.Injector;
+import com.google.inject.Key;
 import com.google.inject.Module;
 import com.google.inject.Provider;
 import com.google.inject.TypeLiteral;
@@ -32,10 +33,7 @@ import com.sun.jersey.api.client.config.ClientConfig;
 import com.sun.jersey.api.client.config.DefaultClientConfig;
 import com.sun.jersey.api.json.JSONConfiguration;
 
-import org.apache.aurora.common.application.ShutdownRegistry.ShutdownRegistryImpl;
-import org.apache.aurora.common.application.StartupRegistry;
-import org.apache.aurora.common.application.modules.LifecycleModule;
-import org.apache.aurora.common.application.modules.StatsModule;
+import org.apache.aurora.GuavaUtils.ServiceManagerIface;
 import org.apache.aurora.common.base.Command;
 import org.apache.aurora.common.net.pool.DynamicHostSet;
 import org.apache.aurora.common.net.pool.DynamicHostSet.HostChangeMonitor;
@@ -46,7 +44,9 @@ import org.apache.aurora.common.testing.easymock.EasyMockTest;
 import org.apache.aurora.common.thrift.ServiceInstance;
 import org.apache.aurora.common.util.BackoffStrategy;
 import org.apache.aurora.gen.ServerInfo;
+import org.apache.aurora.scheduler.AppStartup;
 import org.apache.aurora.scheduler.SchedulerServicesModule;
+import org.apache.aurora.scheduler.app.LifecycleModule;
 import org.apache.aurora.scheduler.async.AsyncModule;
 import org.apache.aurora.scheduler.cron.CronJobManager;
 import org.apache.aurora.scheduler.http.api.GsonMessageBodyHandler;
@@ -55,6 +55,7 @@ import org.apache.aurora.scheduler.scheduling.RescheduleCalculator;
 import org.apache.aurora.scheduler.scheduling.TaskGroups.TaskGroupsSettings;
 import org.apache.aurora.scheduler.scheduling.TaskScheduler;
 import org.apache.aurora.scheduler.state.LockManager;
+import org.apache.aurora.scheduler.stats.StatsModule;
 import org.apache.aurora.scheduler.storage.Storage;
 import org.apache.aurora.scheduler.storage.entities.IServerInfo;
 import org.apache.aurora.scheduler.storage.testing.StorageTestUtil;
@@ -142,17 +143,9 @@ public abstract class JettyServerModuleTest extends EasyMockTest {
 
   protected void replayAndStart() {
     control.replay();
-
-    final ShutdownRegistryImpl shutdownRegistry = injector.getInstance(ShutdownRegistryImpl.class);
-    addTearDown(new TearDown() {
-      @Override
-      public void tearDown() {
-        shutdownRegistry.execute();
-      }
-    });
     try {
-
-      injector.getInstance(StartupRegistry.class).execute();
+      injector.getInstance(Key.get(ServiceManagerIface.class, AppStartup.class))
+          .startAsync().awaitHealthy();
     } catch (Exception e) {
       throw Throwables.propagate(e);
     }

http://git-wip-us.apache.org/repos/asf/aurora/blob/4ad0d36f/src/test/java/org/apache/aurora/scheduler/preemptor/PreemptorModuleTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/preemptor/PreemptorModuleTest.java b/src/test/java/org/apache/aurora/scheduler/preemptor/PreemptorModuleTest.java
index 3f045ff..2c3e5f3 100644
--- a/src/test/java/org/apache/aurora/scheduler/preemptor/PreemptorModuleTest.java
+++ b/src/test/java/org/apache/aurora/scheduler/preemptor/PreemptorModuleTest.java
@@ -17,12 +17,8 @@ import com.google.common.base.Optional;
 import com.google.inject.AbstractModule;
 import com.google.inject.Guice;
 import com.google.inject.Injector;
-import com.google.inject.Key;
 import com.google.inject.Module;
 
-import org.apache.aurora.common.application.StartupStage;
-import org.apache.aurora.common.application.modules.LifecycleModule;
-import org.apache.aurora.common.base.ExceptionalCommand;
 import org.apache.aurora.common.quantity.Amount;
 import org.apache.aurora.common.quantity.Time;
 import org.apache.aurora.common.testing.easymock.EasyMockTest;
@@ -52,7 +48,6 @@ public class PreemptorModuleTest extends EasyMockTest {
   private Injector createInjector(Module module) {
     return Guice.createInjector(
         module,
-        new LifecycleModule(),
         new AbstractModule() {
           private <T> void bindMock(Class<T> clazz) {
             bind(clazz).toInstance(createMock(clazz));
@@ -78,8 +73,6 @@ public class PreemptorModuleTest extends EasyMockTest {
 
     control.replay();
 
-    injector.getInstance(Key.get(ExceptionalCommand.class, StartupStage.class)).execute();
-
     injector.getBindings();
     assertEquals(
         Optional.absent(),

http://git-wip-us.apache.org/repos/asf/aurora/blob/4ad0d36f/src/test/java/org/apache/aurora/scheduler/reconciliation/KillRetryTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/reconciliation/KillRetryTest.java b/src/test/java/org/apache/aurora/scheduler/reconciliation/KillRetryTest.java
index 2f8fc10..a561d09 100644
--- a/src/test/java/org/apache/aurora/scheduler/reconciliation/KillRetryTest.java
+++ b/src/test/java/org/apache/aurora/scheduler/reconciliation/KillRetryTest.java
@@ -24,7 +24,6 @@ import com.google.inject.AbstractModule;
 import com.google.inject.Guice;
 import com.google.inject.Injector;
 
-import org.apache.aurora.common.application.modules.LifecycleModule;
 import org.apache.aurora.common.quantity.Amount;
 import org.apache.aurora.common.quantity.Time;
 import org.apache.aurora.common.stats.StatsProvider;
@@ -33,6 +32,7 @@ import org.apache.aurora.common.util.BackoffStrategy;
 import org.apache.aurora.gen.AssignedTask;
 import org.apache.aurora.gen.ScheduleStatus;
 import org.apache.aurora.gen.ScheduledTask;
+import org.apache.aurora.scheduler.app.LifecycleModule;
 import org.apache.aurora.scheduler.async.AsyncModule.AsyncExecutor;
 import org.apache.aurora.scheduler.async.DelayExecutor;
 import org.apache.aurora.scheduler.base.Query;

http://git-wip-us.apache.org/repos/asf/aurora/blob/4ad0d36f/src/test/java/org/apache/aurora/scheduler/sla/SlaModuleTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/sla/SlaModuleTest.java b/src/test/java/org/apache/aurora/scheduler/sla/SlaModuleTest.java
index 6371645..3e9ef10 100644
--- a/src/test/java/org/apache/aurora/scheduler/sla/SlaModuleTest.java
+++ b/src/test/java/org/apache/aurora/scheduler/sla/SlaModuleTest.java
@@ -27,7 +27,6 @@ import com.google.inject.Key;
 import com.google.inject.Module;
 
 import org.apache.aurora.common.application.modules.AppLauncherModule;
-import org.apache.aurora.common.application.modules.LifecycleModule;
 import org.apache.aurora.common.quantity.Amount;
 import org.apache.aurora.common.quantity.Time;
 import org.apache.aurora.common.stats.Stat;
@@ -35,6 +34,7 @@ import org.apache.aurora.common.stats.StatsProvider;
 import org.apache.aurora.common.testing.easymock.EasyMockTest;
 import org.apache.aurora.common.util.Clock;
 import org.apache.aurora.common.util.testing.FakeClock;
+import org.apache.aurora.scheduler.app.LifecycleModule;
 import org.apache.aurora.scheduler.base.Query;
 import org.apache.aurora.scheduler.sla.SlaModule.SlaUpdater;
 import org.apache.aurora.scheduler.storage.Storage;


Mime
View raw message