aboutsummaryrefslogtreecommitdiffstats
path: root/container-core/src/main/java/com/yahoo/container/di/CloudSubscriberFactory.java
diff options
context:
space:
mode:
authorHenning Baldersheim <balder@yahoo-inc.com>2021-10-14 18:01:16 +0200
committerGitHub <noreply@github.com>2021-10-14 18:01:16 +0200
commit868c29b272eb7773d5c4515cb33640a44074d05a (patch)
tree1fdcbfbb9840a92e8068e20296a94c12a5da389f /container-core/src/main/java/com/yahoo/container/di/CloudSubscriberFactory.java
parentffcc28f2b9180ad8774c67fddbebc81b41f2fc6c (diff)
Revert "Container config improvements [run-systemtest]"
Diffstat (limited to 'container-core/src/main/java/com/yahoo/container/di/CloudSubscriberFactory.java')
-rw-r--r--container-core/src/main/java/com/yahoo/container/di/CloudSubscriberFactory.java84
1 files changed, 80 insertions, 4 deletions
diff --git a/container-core/src/main/java/com/yahoo/container/di/CloudSubscriberFactory.java b/container-core/src/main/java/com/yahoo/container/di/CloudSubscriberFactory.java
index a6327b01e21..d50d56f8987 100644
--- a/container-core/src/main/java/com/yahoo/container/di/CloudSubscriberFactory.java
+++ b/container-core/src/main/java/com/yahoo/container/di/CloudSubscriberFactory.java
@@ -2,19 +2,24 @@
package com.yahoo.container.di;
import com.yahoo.config.ConfigInstance;
+import com.yahoo.config.subscription.ConfigHandle;
import com.yahoo.config.subscription.ConfigSource;
import com.yahoo.config.subscription.ConfigSourceSet;
+import com.yahoo.config.subscription.ConfigSubscriber;
import com.yahoo.container.di.config.Subscriber;
import com.yahoo.container.di.config.SubscriberFactory;
import com.yahoo.vespa.config.ConfigKey;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.WeakHashMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
/**
* @author Tony Vaagenes
@@ -22,6 +27,8 @@ import java.util.WeakHashMap;
*/
public class CloudSubscriberFactory implements SubscriberFactory {
+ private static final Logger log = Logger.getLogger(CloudSubscriberFactory.class.getName());
+
private final ConfigSource configSource;
private final Map<CloudSubscriber, Integer> activeSubscribers = new WeakHashMap<>();
@@ -32,16 +39,16 @@ public class CloudSubscriberFactory implements SubscriberFactory {
}
@Override
- public Subscriber getSubscriber(Set<? extends ConfigKey<?>> configKeys, String name) {
+ public Subscriber getSubscriber(Set<? extends ConfigKey<?>> configKeys) {
Set<ConfigKey<ConfigInstance>> subscriptionKeys = new HashSet<>();
for(ConfigKey<?> key: configKeys) {
@SuppressWarnings("unchecked") // ConfigKey is defined as <CONFIGCLASS extends ConfigInstance>
ConfigKey<ConfigInstance> invariant = (ConfigKey<ConfigInstance>) key;
subscriptionKeys.add(invariant);
}
- CloudSubscriber subscriber = new CloudSubscriber(name, configSource, subscriptionKeys);
+ CloudSubscriber subscriber = new CloudSubscriber(subscriptionKeys, configSource);
- testGeneration.ifPresent(subscriber.getSubscriber()::reload); // TODO: test specific code, remove
+ testGeneration.ifPresent(subscriber.subscriber::reload); // TODO: test specific code, remove
activeSubscribers.put(subscriber, 0);
return subscriber;
@@ -53,7 +60,76 @@ public class CloudSubscriberFactory implements SubscriberFactory {
testGeneration = Optional.of(generation);
List<CloudSubscriber> subscribers = new ArrayList<>(activeSubscribers.keySet());
- subscribers.forEach(s -> s.getSubscriber().reload(generation));
+ subscribers.forEach(s -> s.subscriber.reload(generation));
+ }
+
+ private static class CloudSubscriber implements Subscriber {
+
+ private final ConfigSubscriber subscriber;
+ private final Map<ConfigKey<ConfigInstance>, ConfigHandle<ConfigInstance>> handles = new HashMap<>();
+
+ // if waitNextGeneration has not yet been called, -1 should be returned
+ private long generation = -1L;
+
+ private CloudSubscriber(Set<ConfigKey<ConfigInstance>> keys, ConfigSource configSource) {
+ this.subscriber = new ConfigSubscriber(configSource);
+ keys.forEach(k -> handles.put(k, subscriber.subscribe(k.getConfigClass(), k.getConfigId())));
+ }
+
+ @Override
+ public boolean configChanged() {
+ return handles.values().stream().anyMatch(ConfigHandle::isChanged);
+ }
+
+ @Override
+ public long generation() {
+ return generation;
+ }
+
+ //mapValues returns a view,, so we need to force evaluation of it here to prevent deferred evaluation.
+ @Override
+ public Map<ConfigKey<ConfigInstance>, ConfigInstance> config() {
+ Map<ConfigKey<ConfigInstance>, ConfigInstance> ret = new HashMap<>();
+ handles.forEach((k, v) -> ret.put(k, v.getConfig()));
+ return ret;
+ }
+
+ @Override
+ public long waitNextGeneration(boolean isInitializing) {
+ if (handles.isEmpty())
+ throw new IllegalStateException("No config keys registered");
+
+ // Catch and just log config exceptions due to missing config values for parameters that do
+ // not have a default value. These exceptions occur when the user has removed a component
+ // from services.xml, and the component takes a config that has parameters without a
+ // default value in the def-file. There is a new 'components' config underway, where the
+ // component is removed, so this old config generation will soon be replaced by a new one.
+ boolean gotNextGen = false;
+ int numExceptions = 0;
+ while ( ! gotNextGen) {
+ try {
+ if (subscriber.nextGeneration(isInitializing))
+ gotNextGen = true;
+ }
+ catch (IllegalArgumentException e) {
+ numExceptions++;
+ log.log(Level.WARNING, "Got exception from the config system (ignore if you just removed a " +
+ "component from your application that used the mentioned config) Subscriber info: " +
+ subscriber.toString(), e);
+ if (numExceptions >= 5)
+ throw new IllegalArgumentException("Failed retrieving the next config generation", e);
+ }
+ }
+
+ generation = subscriber.getGeneration();
+ return generation;
+ }
+
+ @Override
+ public void close() {
+ subscriber.close();
+ }
+
}
public static class Provider implements com.google.inject.Provider<SubscriberFactory> {