You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aurora.apache.org by wf...@apache.org on 2014/01/17 19:54:11 UTC

git commit: Abort the scheduler if an unchecked exception is handled while transitioning the lifecycle state.

Updated Branches:
  refs/heads/master e3e81a1d9 -> b6fbcde05


Abort the scheduler if an unchecked exception is handled while transitioning
the lifecycle state.

Bugs closed: AURORA-51

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


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

Branch: refs/heads/master
Commit: b6fbcde059cbd0ef75db713a9580860b6abce941
Parents: e3e81a1
Author: Bill Farner <wf...@apache.org>
Authored: Fri Jan 17 10:51:28 2014 -0800
Committer: Bill Farner <wf...@apache.org>
Committed: Fri Jan 17 10:51:28 2014 -0800

----------------------------------------------------------------------
 .../aurora/scheduler/SchedulerLifecycle.java    | 28 +++++++++++-------
 .../scheduler/base/SchedulerException.java      |  2 ++
 .../scheduler/SchedulerLifecycleTest.java       | 31 ++++++++++++++++++--
 3 files changed, 49 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/b6fbcde0/src/main/java/org/apache/aurora/scheduler/SchedulerLifecycle.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/SchedulerLifecycle.java b/src/main/java/org/apache/aurora/scheduler/SchedulerLifecycle.java
index 247e940..f8b6623 100644
--- a/src/main/java/org/apache/aurora/scheduler/SchedulerLifecycle.java
+++ b/src/main/java/org/apache/aurora/scheduler/SchedulerLifecycle.java
@@ -224,13 +224,8 @@ public class SchedulerLifecycle implements EventSubscriber {
 
     final Closure<Transition<State>> prepareStorage = new Closure<Transition<State>>() {
       @Override public void execute(Transition<State> transition) {
-        try {
-          storage.prepare();
-          stateMachine.transition(State.STORAGE_PREPARED);
-        } catch (RuntimeException e) {
-          stateMachine.transition(State.DEAD);
-          throw e;
-        }
+        storage.prepare();
+        stateMachine.transition(State.STORAGE_PREPARED);
       }
     };
 
@@ -365,18 +360,18 @@ public class SchedulerLifecycle implements EventSubscriber {
         .initialState(State.IDLE)
         .logTransitions()
         .addState(
-            Closures.filter(NOT_DEAD, prepareStorage),
+            dieOnError(Closures.filter(NOT_DEAD, prepareStorage)),
             State.IDLE,
             State.PREPARING_STORAGE, State.DEAD)
         .addState(
             State.PREPARING_STORAGE,
             State.STORAGE_PREPARED, State.DEAD)
         .addState(
-            Closures.filter(NOT_DEAD, handleLeading),
+            dieOnError(Closures.filter(NOT_DEAD, handleLeading)),
             State.STORAGE_PREPARED,
             State.LEADER_AWAITING_REGISTRATION, State.DEAD)
         .addState(
-            Closures.filter(NOT_DEAD, handleRegistered),
+            dieOnError(Closures.filter(NOT_DEAD, handleRegistered)),
             State.LEADER_AWAITING_REGISTRATION,
             State.REGISTERED_LEADER, State.DEAD)
         .addState(
@@ -397,6 +392,19 @@ public class SchedulerLifecycle implements EventSubscriber {
     this.leadershipListener = new SchedulerCandidateImpl(stateMachine, leaderControl);
   }
 
+  private Closure<Transition<State>> dieOnError(final Closure<Transition<State>> closure) {
+    return new Closure<Transition<State>>() {
+      @Override public void execute(Transition<State> transition) {
+        try {
+          closure.execute(transition);
+        } catch (RuntimeException e) {
+          stateMachine.transition(State.DEAD);
+          throw e;
+        }
+      }
+    };
+  }
+
   /**
    * Prepares a scheduler to offer itself as a leader candidate.  After this call the scheduler will
    * host a live log replica and start syncing data from the leader via the log until it gets called

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/b6fbcde0/src/main/java/org/apache/aurora/scheduler/base/SchedulerException.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/base/SchedulerException.java b/src/main/java/org/apache/aurora/scheduler/base/SchedulerException.java
index 2522b51..c9dc25d 100644
--- a/src/main/java/org/apache/aurora/scheduler/base/SchedulerException.java
+++ b/src/main/java/org/apache/aurora/scheduler/base/SchedulerException.java
@@ -17,6 +17,8 @@ package org.apache.aurora.scheduler.base;
 
 /**
  * Indicates some form of unexpected scheduler exception.
+ * TOOO(wfarner): This really should be a checked exception, or the semantics of its
+ * use should change.
  */
 public class SchedulerException extends RuntimeException {
   public SchedulerException(String message) {

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/b6fbcde0/src/test/java/org/apache/aurora/scheduler/SchedulerLifecycleTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/SchedulerLifecycleTest.java b/src/test/java/org/apache/aurora/scheduler/SchedulerLifecycleTest.java
index da7a167..ce9b393 100644
--- a/src/test/java/org/apache/aurora/scheduler/SchedulerLifecycleTest.java
+++ b/src/test/java/org/apache/aurora/scheduler/SchedulerLifecycleTest.java
@@ -30,6 +30,7 @@ import org.apache.aurora.scheduler.events.EventSink;
 import org.apache.aurora.scheduler.events.PubsubEvent.DriverRegistered;
 import org.apache.aurora.scheduler.events.PubsubEvent.SchedulerActive;
 import org.apache.aurora.scheduler.storage.Storage.MutateWork.NoResult.Quiet;
+import org.apache.aurora.scheduler.storage.Storage.StorageException;
 import org.apache.aurora.scheduler.storage.testing.StorageTestUtil;
 import org.apache.mesos.Protos.Status;
 import org.apache.mesos.SchedulerDriver;
@@ -40,6 +41,7 @@ import org.junit.Test;
 
 import static org.easymock.EasyMock.capture;
 import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
 import static org.junit.Assert.fail;
 
 public class SchedulerLifecycleTest extends EasyMockTest {
@@ -85,7 +87,7 @@ public class SchedulerLifecycleTest extends EasyMockTest {
   }
 
   @Test
-  public void testAutoFailover() throws Throwable {
+  public void testAutoFailover() throws Exception {
     // Test that when timed failover is initiated, cleanup is done in a way that should allow the
     // application to tear down cleanly.  Specifically, neglecting to call leaderControl.leave()
     // can result in a lame duck scheduler process.
@@ -121,7 +123,7 @@ public class SchedulerLifecycleTest extends EasyMockTest {
   }
 
   @Test
-  public void testDefeatedBeforeRegistered() throws Throwable {
+  public void testDefeatedBeforeRegistered() throws Exception {
     storageUtil.storage.prepare();
     storageUtil.storage.start(EasyMock.<Quiet>anyObject());
     storageUtil.expectOperations();
@@ -144,4 +146,29 @@ public class SchedulerLifecycleTest extends EasyMockTest {
     leaderListener.onLeading(leaderControl);
     leaderListener.onDefeated(null);
   }
+
+  @Test
+  public void testStorageStartFails() throws Exception {
+    storageUtil.storage.prepare();
+
+    storageUtil.expectOperations();
+    storageUtil.storage.start(EasyMock.<Quiet>anyObject());
+    expectLastCall().andThrow(new StorageException("Recovery failed."));
+
+    leaderControl.leave();
+    driver.stop();
+    storageUtil.storage.stop();
+    shutdownRegistry.execute();
+
+    control.replay();
+
+    LeadershipListener leaderListener = schedulerLifecycle.prepare();
+
+    try {
+      leaderListener.onLeading(leaderControl);
+      fail();
+    } catch (StorageException e) {
+      // Expected.
+    }
+  }
 }