diff options
Diffstat (limited to 'container-core/src/main/java/com/yahoo/container/di/ConfigRetriever.java')
-rw-r--r-- | container-core/src/main/java/com/yahoo/container/di/ConfigRetriever.java | 87 |
1 files changed, 45 insertions, 42 deletions
diff --git a/container-core/src/main/java/com/yahoo/container/di/ConfigRetriever.java b/container-core/src/main/java/com/yahoo/container/di/ConfigRetriever.java index ff238bd2497..1e7f3e06049 100644 --- a/container-core/src/main/java/com/yahoo/container/di/ConfigRetriever.java +++ b/container-core/src/main/java/com/yahoo/container/di/ConfigRetriever.java @@ -5,9 +5,9 @@ import com.google.common.collect.Sets; import com.yahoo.config.ConfigInstance; import com.yahoo.container.di.componentgraph.core.Keys; import com.yahoo.container.di.config.Subscriber; -import com.yahoo.container.di.config.SubscriberFactory; import com.yahoo.vespa.config.ConfigKey; +import java.util.Collections; import java.util.HashSet; import java.util.Map; import java.util.Optional; @@ -29,21 +29,20 @@ public final class ConfigRetriever { private final Set<ConfigKey<? extends ConfigInstance>> bootstrapKeys; private Set<ConfigKey<? extends ConfigInstance>> componentSubscriberKeys; - - private final SubscriberFactory subscriberFactory; private final Subscriber bootstrapSubscriber; private Subscriber componentSubscriber; - private int componentSubscriberIndex; + private final Function<Set<ConfigKey<? extends ConfigInstance>>, Subscriber> subscribe; - public ConfigRetriever(Set<ConfigKey<? extends ConfigInstance>> bootstrapKeys, SubscriberFactory subscriberFactory) { + public ConfigRetriever(Set<ConfigKey<? extends ConfigInstance>> bootstrapKeys, + Function<Set<ConfigKey<? extends ConfigInstance>>, Subscriber> subscribe) { this.bootstrapKeys = bootstrapKeys; this.componentSubscriberKeys = new HashSet<>(); - this.subscriberFactory = subscriberFactory; + this.subscribe = subscribe; if (bootstrapKeys.isEmpty()) { throw new IllegalArgumentException("Bootstrap key set is empty"); } - this.bootstrapSubscriber = this.subscriberFactory.getSubscriber(bootstrapKeys, "bootstrap"); - this.componentSubscriber = this.subscriberFactory.getSubscriber(componentSubscriberKeys, "component_" + ++componentSubscriberIndex); + this.bootstrapSubscriber = subscribe.apply(bootstrapKeys); + this.componentSubscriber = subscribe.apply(componentSubscriberKeys); } public ConfigSnapshot getConfigs(Set<ConfigKey<? extends ConfigInstance>> componentConfigKeys, @@ -52,56 +51,55 @@ public final class ConfigRetriever { while (true) { Optional<ConfigSnapshot> maybeSnapshot = getConfigsOnce(componentConfigKeys, leastGeneration, isInitializing); if (maybeSnapshot.isPresent()) { - return maybeSnapshot.get(); + var configSnapshot = maybeSnapshot.get(); + resetComponentSubscriberIfBootstrap(configSnapshot); + return configSnapshot; } } } - private Optional<ConfigSnapshot> getConfigsOnce(Set<ConfigKey<? extends ConfigInstance>> componentConfigKeys, - long leastGeneration, boolean isInitializing) { + Optional<ConfigSnapshot> getConfigsOnce(Set<ConfigKey<? extends ConfigInstance>> componentConfigKeys, + long leastGeneration, boolean isInitializing) { if (!Sets.intersection(componentConfigKeys, bootstrapKeys).isEmpty()) { throw new IllegalArgumentException( "Component config keys [" + componentConfigKeys + "] overlaps with bootstrap config keys [" + bootstrapKeys + "]"); } + log.log(FINE, () -> "getConfigsOnce: " + componentConfigKeys); + Set<ConfigKey<? extends ConfigInstance>> allKeys = new HashSet<>(componentConfigKeys); allKeys.addAll(bootstrapKeys); setupComponentSubscriber(allKeys); - var maybeSnapshot = getConfigsOptional(leastGeneration, isInitializing); - log.log(FINE, () -> "getConfigsOnce returning " + maybeSnapshot); - return maybeSnapshot; + return getConfigsOptional(leastGeneration, isInitializing); } private Optional<ConfigSnapshot> getConfigsOptional(long leastGeneration, boolean isInitializing) { - if (componentSubscriber.generation() < bootstrapSubscriber.generation()) { - return getComponentsSnapshot(leastGeneration, isInitializing); - } - long newestBootstrapGeneration = bootstrapSubscriber.waitNextGeneration(isInitializing); - log.log(FINE, () -> "getConfigsOptional: new bootstrap generation: " + newestBootstrapGeneration); - - // leastGeneration is used to ensure newer generation (than the latest bootstrap or component gen) - // when the previous generation was invalidated due to an exception upon creating the component graph. - if (newestBootstrapGeneration < leastGeneration) { - return Optional.empty(); - } - return bootstrapConfigIfChanged(); - } - - private Optional<ConfigSnapshot> getComponentsSnapshot(long leastGeneration, boolean isInitializing) { - long newestBootstrapGeneration = bootstrapSubscriber.generation(); long newestComponentGeneration = componentSubscriber.waitNextGeneration(isInitializing); + log.log(FINE, () -> "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) { - log.log(FINE, () -> "Component generation too old: " + componentSubscriber.generation() + " < " + leastGeneration); return Optional.empty(); - } - if (newestComponentGeneration == newestBootstrapGeneration) { - log.log(FINE, () -> "getConfigsOptional: new component generation: " + componentSubscriber.generation()); - return componentsConfigIfChanged(); - } else { - // Should not be a normal case, and hence a warning to allow investigation. - log.warning("Did not get same generation for bootstrap (" + newestBootstrapGeneration + + } else if (bootstrapSubscriber.generation() < newestComponentGeneration) { + long newestBootstrapGeneration = bootstrapSubscriber.waitNextGeneration(isInitializing); + log.log(FINE, () -> "getConfigsOptional: new bootstrap generation: " + bootstrapSubscriber.generation()); + Optional<ConfigSnapshot> bootstrapConfig = bootstrapConfigIfChanged(); + if (bootstrapConfig.isPresent()) { + return bootstrapConfig; + } else { + if (newestBootstrapGeneration == newestComponentGeneration) { + log.log(FINE, () -> "Got new components configs with unchanged bootstrap configs."); + return componentsConfigIfChanged(); + } else { + // This should not be a normal case, and hence a warning to allow investigation. + log.warning("Did not get same generation for bootstrap (" + newestBootstrapGeneration + ") and components configs (" + newestComponentGeneration + ")."); - return Optional.empty(); + return Optional.empty(); + } + } + } else { + // bootstrapGen==componentGen (happens only when a new component subscriber returns first config after bootstrap) + return componentsConfigIfChanged(); } } @@ -122,14 +120,19 @@ public final class ConfigRetriever { } } + private void resetComponentSubscriberIfBootstrap(ConfigSnapshot snapshot) { + if (snapshot instanceof BootstrapConfigs) { + setupComponentSubscriber(Collections.emptySet()); + } + } + private void setupComponentSubscriber(Set<ConfigKey<? extends ConfigInstance>> keys) { if (! componentSubscriberKeys.equals(keys)) { componentSubscriber.close(); - log.log(FINE, () -> "Closed " + componentSubscriber); componentSubscriberKeys = keys; try { - componentSubscriber = subscriberFactory.getSubscriber(keys, "component_" + ++componentSubscriberIndex); - log.log(FINE, () -> "Set up new subscriber " + componentSubscriber + " for keys: " + keys); + log.log(FINE, () -> "Setting up new component subscriber for keys: " + keys); + componentSubscriber = subscribe.apply(keys); } catch (Throwable e) { log.log(Level.WARNING, "Failed setting up subscriptions for component configs: " + e.getMessage()); log.log(Level.WARNING, "Config keys: " + keys); |