From f7d0fe5fdfad579e867f01acc1d41b2ec77bd785 Mon Sep 17 00:00:00 2001 From: Jon Bratseth Date: Fri, 1 Jun 2018 01:07:33 +0200 Subject: Separate internal redeploys from application package changes Separate system internal redeploys from application package changes such that we can ignore config updates originating from application package changes if restart on deploy is true, as the config change will be followed by a restart - but continue to effect config changes originating from internal system changes as those will not (and should not) be followed by a restart. --- .../java/com/yahoo/container/di/config/Subscriber.java | 1 + .../com/yahoo/container/di/CloudSubscriberFactory.scala | 6 +++++- .../scala/com/yahoo/container/di/ConfigRetriever.scala | 10 ++++++---- .../main/scala/com/yahoo/container/di/Container.scala | 17 ++++++++--------- 4 files changed, 20 insertions(+), 14 deletions(-) (limited to 'container-di/src/main') diff --git a/container-di/src/main/java/com/yahoo/container/di/config/Subscriber.java b/container-di/src/main/java/com/yahoo/container/di/config/Subscriber.java index 9fd30f888b9..0feab7779ad 100644 --- a/container-di/src/main/java/com/yahoo/container/di/config/Subscriber.java +++ b/container-di/src/main/java/com/yahoo/container/di/config/Subscriber.java @@ -14,6 +14,7 @@ public interface Subscriber { long waitNextGeneration(); long generation(); + boolean internalRedeploy(); boolean configChanged(); Map, ConfigInstance> config(); diff --git a/container-di/src/main/scala/com/yahoo/container/di/CloudSubscriberFactory.scala b/container-di/src/main/scala/com/yahoo/container/di/CloudSubscriberFactory.scala index afef3e96821..e38ff9d4491 100644 --- a/container-di/src/main/scala/com/yahoo/container/di/CloudSubscriberFactory.scala +++ b/container-di/src/main/scala/com/yahoo/container/di/CloudSubscriberFactory.scala @@ -50,9 +50,12 @@ object CloudSubscriberFactory { private val handles: Map[ConfigKeyT, ConfigHandle[_ <: ConfigInstance]] = keys.map(subscribe).toMap - //if waitNextGeneration has not yet been called, -1 should be returned + // if waitNextGeneration has not yet been called, -1 should be returned var generation: Long = -1 + // True if this reconfiguration was caused by a system-internal redeploy, not an external application change + var internalRedeploy: Boolean = false + private def subscribe(key: ConfigKeyT) = (key, subscriber.subscribe(key.getConfigClass, key.getConfigId)) override def configChanged = handles.values.exists(_.isChanged) @@ -86,6 +89,7 @@ object CloudSubscriberFactory { } generation = subscriber.getGeneration + internalRedeploy = subscriber.isInternalRedeploy generation } diff --git a/container-di/src/main/scala/com/yahoo/container/di/ConfigRetriever.scala b/container-di/src/main/scala/com/yahoo/container/di/ConfigRetriever.scala index dc94d789f7b..0d829b0456d 100644 --- a/container-di/src/main/scala/com/yahoo/container/di/ConfigRetriever.scala +++ b/container-di/src/main/scala/com/yahoo/container/di/ConfigRetriever.scala @@ -29,25 +29,27 @@ final class ConfigRetriever(bootstrapKeys: Set[ConfigKeyT], @tailrec - final def getConfigs(componentConfigKeys: Set[ConfigKeyT], leastGeneration: Long): ConfigSnapshot = { + final def getConfigs(componentConfigKeys: Set[ConfigKeyT], leastGeneration: Long, restartOnRedeploy: Boolean = false): ConfigSnapshot = { require(componentConfigKeys intersect bootstrapKeys isEmpty) log.log(DEBUG, "getConfigs: " + componentConfigKeys) setupComponentSubscriber(componentConfigKeys ++ bootstrapKeys) - getConfigsOptional(leastGeneration) match { + getConfigsOptional(leastGeneration, restartOnRedeploy) match { case Some(snapshot) => resetComponentSubscriberIfBootstrap(snapshot); snapshot - case None => getConfigs(componentConfigKeys, leastGeneration) + case None => getConfigs(componentConfigKeys, leastGeneration, restartOnRedeploy) } } - private def getConfigsOptional(leastGeneration: Long): Option[ConfigSnapshot] = { + private def getConfigsOptional(leastGeneration: Long, restartOnRedeploy: Boolean): Option[ConfigSnapshot] = { val newestComponentGeneration = componentSubscriber.waitNextGeneration() log.log(DEBUG, s"getConfigsOptional: new component generation: $newestComponentGeneration") // leastGeneration is only used to ensure newer generation when the previous generation was invalidated due to an exception if (newestComponentGeneration < leastGeneration) { None + } else if (restartOnRedeploy && ! componentSubscriber.internalRedeploy()) { // Don't reconfig - wait for restart + None } else if (bootstrapSubscriber.generation < newestComponentGeneration) { val newestBootstrapGeneration = bootstrapSubscriber.waitNextGeneration() log.log(DEBUG, s"getConfigsOptional: new bootstrap generation: ${bootstrapSubscriber.generation}") 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 0ef01e5aa3d..2a185d41a6c 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 @@ -44,9 +44,9 @@ class Container( var leastGeneration = -1L @throws(classOf[InterruptedException]) - def getNewConfigGraph(oldGraph: ComponentGraph = new ComponentGraph, - fallbackInjector: GuiceInjector = Guice.createInjector(), - restartOnRedeploy: Boolean = false): ComponentGraph = { + def getNewComponentGraph(oldGraph: ComponentGraph = new ComponentGraph, + fallbackInjector: GuiceInjector = Guice.createInjector(), + restartOnRedeploy: Boolean = false): ComponentGraph = { def deconstructObsoleteComponents(oldGraph: ComponentGraph, newGraph: ComponentGraph) { val oldComponents = new IdentityHashMap[AnyRef, AnyRef]() @@ -56,8 +56,7 @@ class Container( } try { - val newGraph = getConfigAndCreateGraph(oldGraph, fallbackInjector) - if (restartOnRedeploy) return oldGraph // wait for restart to cause reconfig instead + val newGraph = getConfigAndCreateGraph(oldGraph, fallbackInjector, restartOnRedeploy) newGraph.reuseNodes(oldGraph) constructComponents(newGraph) deconstructObsoleteComponents(oldGraph, newGraph) @@ -115,9 +114,10 @@ class Container( } final def getConfigAndCreateGraph(graph: ComponentGraph = new ComponentGraph, - fallbackInjector: Injector): ComponentGraph = { + fallbackInjector: Injector, + restartOnRedeploy: Boolean): ComponentGraph = { - val snapshot = configurer.getConfigs(graph.configKeys, leastGeneration) + val snapshot = configurer.getConfigs(graph.configKeys, leastGeneration, restartOnRedeploy) log.log(DEBUG, """createNewGraph: @@ -141,8 +141,7 @@ class Container( .format(getBootstrapGeneration, getComponentsGeneration, previousConfigGeneration).stripMargin) installBundles(configs) getConfigAndCreateGraph( - createComponentsGraph(configs, getBootstrapGeneration,fallbackInjector), - fallbackInjector) + createComponentsGraph(configs, getBootstrapGeneration,fallbackInjector), fallbackInjector, restartOnRedeploy) case ComponentsConfigs(configs) => log.log(DEBUG, """Got components configs, -- cgit v1.2.3