aboutsummaryrefslogtreecommitdiffstats
path: root/container-di/src/main
diff options
context:
space:
mode:
authorgjoranv <gv@yahoo-inc.com>2017-05-18 16:03:06 +0200
committergjoranv <gv@yahoo-inc.com>2017-05-18 16:19:15 +0200
commitf692397d9af72e7992229d7e3d34975bf7dace3b (patch)
tree4c6d7cec89ad62755684196e72f613ea1f65ec7c /container-di/src/main
parenta20ede3c2016d6542020651fc51733d4fbc33c63 (diff)
Exit if the first component graph cannot be created successfully.
- Add ignored test to use for manual verification.
Diffstat (limited to 'container-di/src/main')
-rw-r--r--container-di/src/main/scala/com/yahoo/container/di/Container.scala76
1 files changed, 55 insertions, 21 deletions
diff --git a/container-di/src/main/scala/com/yahoo/container/di/Container.scala b/container-di/src/main/scala/com/yahoo/container/di/Container.scala
index bc3f9fbe79e..a710e588f7f 100644
--- a/container-di/src/main/scala/com/yahoo/container/di/Container.scala
+++ b/container-di/src/main/scala/com/yahoo/container/di/Container.scala
@@ -1,23 +1,23 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.container.di
+import java.util.{IdentityHashMap, Random}
+import java.util.logging.{Level, Logger}
+
+import com.google.inject.{Guice, Injector}
+import com.yahoo.config._
+import com.yahoo.container.bundle.BundleInstantiationSpecification
import com.yahoo.container.di.ConfigRetriever.{BootstrapConfigs, ComponentsConfigs}
+import com.yahoo.container.di.Container._
+import com.yahoo.container.di.componentgraph.core.ComponentNode.ComponentConstructorException
import com.yahoo.container.di.componentgraph.core.{ComponentGraph, ComponentNode, JerseyNode}
import com.yahoo.container.di.config.{RestApiContext, SubscriberFactory}
-import Container._
+import com.yahoo.container.{BundlesConfig, ComponentsConfig}
+import com.yahoo.protect.Process
+import com.yahoo.vespa.config.ConfigKey
import scala.collection.JavaConversions._
import scala.math.max
-import com.yahoo.config._
-import com.yahoo.vespa.config.ConfigKey
-import java.util.IdentityHashMap
-import java.util.logging.{Level, Logger}
-
-import com.yahoo.container.bundle.BundleInstantiationSpecification
-import com.google.inject.{Guice, Injector}
-import com.yahoo.container.di.componentgraph.core.ComponentNode.ComponentConstructorException
-import com.yahoo.container.{BundlesConfig, ComponentsConfig}
-import com.yahoo.log.LogLevel
/**
@@ -46,9 +46,9 @@ class Container(
def deconstructObsoleteComponents(oldGraph: ComponentGraph, newGraph: ComponentGraph) {
val oldComponents = new IdentityHashMap[AnyRef, AnyRef]()
- oldGraph.allComponentsAndProviders foreach(oldComponents.put(_, null))
- newGraph.allComponentsAndProviders foreach(oldComponents.remove(_))
- oldComponents.keySet foreach(componentDeconstructor.deconstruct(_))
+ oldGraph.allComponentsAndProviders foreach (oldComponents.put(_, null))
+ newGraph.allComponentsAndProviders foreach (oldComponents.remove(_))
+ oldComponents.keySet foreach (componentDeconstructor.deconstruct(_))
}
try {
@@ -58,18 +58,52 @@ class Container(
deconstructObsoleteComponents(oldGraph, newGraph)
newGraph
} catch {
- case userException : ComponentConstructorException =>
- invalidateGeneration("Failed to set up new component graph due to error when constructing one of the components.", userException)
+ case userException: ComponentConstructorException =>
+ invalidateGeneration(oldGraph.generation, userException)
throw userException
- case t : Throwable =>
- invalidateGeneration("Failed to set up new component graph.", t)
+ case t: Throwable =>
+ invalidateGeneration(oldGraph.generation, t)
throw t
}
}
- private def invalidateGeneration(message: String, cause: Throwable) {
- log.log(Level.WARNING, message, cause)
- leastGeneration = max(configurer.getComponentsGeneration, configurer.getBootstrapGeneration) + 1
+ private def invalidateGeneration(generation: Long, cause: Throwable) {
+ val maxWaitToExit = 180L
+
+ def newGraphErrorMessage(generation: Long, cause: Throwable): String = {
+ val exitMessage = s"Exiting within $maxWaitToExit seconds."
+ val retainMessage = "Retaining previous component generation."
+ generation match {
+ case 0 =>
+ cause match {
+ case _: ComponentConstructorException => s"Failed to set up first component graph due to error when constructing one of the components. $exitMessage"
+ case _ => s"Failed to set up first component graph. $exitMessage"
+ }
+ case _ =>
+ cause match {
+ case _: ComponentConstructorException => s"Failed to set up new component graph due to error when constructing one of the components. $retainMessage"
+ case _ => s"Failed to set up new component graph. $retainMessage"
+ }
+ }
+ }
+
+ def logAndDie(message: String, cause: Throwable): Unit = {
+ log.log(Level.SEVERE, message)
+ try {
+ Thread.sleep((new Random(System.nanoTime).nextDouble * maxWaitToExit * 1000).toLong)
+ } catch {
+ case _: InterruptedException => // Do nothing
+ }
+ Process.logAndDie("Exited.", cause)
+ }
+
+ val message = newGraphErrorMessage(generation, cause)
+ generation match {
+ case 0 => logAndDie(message, cause)
+ case _ =>
+ log.log(Level.WARNING, message, cause)
+ leastGeneration = max(configurer.getComponentsGeneration, configurer.getBootstrapGeneration) + 1
+ }
}
final def createNewGraph(graph: ComponentGraph = new ComponentGraph,