From b3733a0d0b08377601edee806459cb9eec1024d0 Mon Sep 17 00:00:00 2001 From: gjoranv Date: Wed, 6 Oct 2021 12:15:04 +0200 Subject: Move CloudSubscriber to separate class file. --- .../com/yahoo/container/di/CloudSubscriber.java | 99 ++++++++++++++++++++++ .../yahoo/container/di/CloudSubscriberFactory.java | 77 +---------------- 2 files changed, 101 insertions(+), 75 deletions(-) create mode 100644 container-core/src/main/java/com/yahoo/container/di/CloudSubscriber.java (limited to 'container-core/src') diff --git a/container-core/src/main/java/com/yahoo/container/di/CloudSubscriber.java b/container-core/src/main/java/com/yahoo/container/di/CloudSubscriber.java new file mode 100644 index 00000000000..4efb36d4b29 --- /dev/null +++ b/container-core/src/main/java/com/yahoo/container/di/CloudSubscriber.java @@ -0,0 +1,99 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +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.ConfigSubscriber; +import com.yahoo.container.di.config.Subscriber; +import com.yahoo.vespa.config.ConfigKey; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +import static java.util.logging.Level.FINE; + +/** + * @author gjoranv + * @author Tony Vaagenes + * @author ollivir + */ +public class CloudSubscriber implements Subscriber { + private static final Logger log = Logger.getLogger(CloudSubscriber.class.getName()); + + private final ConfigSubscriber subscriber; + private final Map, ConfigHandle> handles = new HashMap<>(); + + // if waitNextGeneration has not yet been called, -1 should be returned + private long generation = -1L; + + CloudSubscriber(Set> 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, ConfigInstance> config() { + Map, 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; + log.log(FINE, () -> this + " got next config generation " + subscriber.getGeneration() + "\n" + subscriber.toString()); + } + } + catch (IllegalArgumentException e) { + numExceptions++; + log.log(Level.WARNING, this + " 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(); + } + + // TODO: Remove, only used by test specific code in CloudSubscriberFactory + ConfigSubscriber getSubscriber() { + return subscriber; + } + +} 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 665da965148..38f7ded28f8 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 @@ -29,8 +29,6 @@ import static java.util.logging.Level.FINE; */ public class CloudSubscriberFactory implements SubscriberFactory { - private static final Logger log = Logger.getLogger(CloudSubscriberFactory.class.getName()); - private final ConfigSource configSource; private final Map activeSubscribers = new WeakHashMap<>(); @@ -50,7 +48,7 @@ public class CloudSubscriberFactory implements SubscriberFactory { } CloudSubscriber subscriber = new CloudSubscriber(subscriptionKeys, configSource); - testGeneration.ifPresent(subscriber.subscriber::reload); // TODO: test specific code, remove + testGeneration.ifPresent(subscriber.getSubscriber()::reload); // TODO: test specific code, remove activeSubscribers.put(subscriber, 0); return subscriber; @@ -62,78 +60,7 @@ public class CloudSubscriberFactory implements SubscriberFactory { testGeneration = Optional.of(generation); List subscribers = new ArrayList<>(activeSubscribers.keySet()); - subscribers.forEach(s -> s.subscriber.reload(generation)); - } - - private static class CloudSubscriber implements Subscriber { - - private final ConfigSubscriber subscriber; - private final Map, ConfigHandle> handles = new HashMap<>(); - - // if waitNextGeneration has not yet been called, -1 should be returned - private long generation = -1L; - - private CloudSubscriber(Set> 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, ConfigInstance> config() { - Map, 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; - log.log(FINE, () -> this + " got next config generation " + subscriber.getGeneration() + "\n" + subscriber.toString()); - } - } - catch (IllegalArgumentException e) { - numExceptions++; - log.log(Level.WARNING, this + " 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(); - } - + subscribers.forEach(s -> s.getSubscriber().reload(generation)); } public static class Provider implements com.google.inject.Provider { -- cgit v1.2.3