sigram commented on a change in pull request #1962: URL: https://github.com/apache/lucene-solr/pull/1962#discussion_r517293581
########## File path: solr/core/src/java/org/apache/solr/cluster/events/impl/ClusterEventProducerFactory.java ########## @@ -0,0 +1,173 @@ +package org.apache.solr.cluster.events.impl; + +import org.apache.solr.api.ContainerPluginsRegistry; +import org.apache.solr.cluster.events.ClusterEvent; +import org.apache.solr.cluster.events.ClusterEventListener; +import org.apache.solr.cluster.events.ClusterEventProducer; +import org.apache.solr.cluster.events.ClusterEventProducerBase; +import org.apache.solr.cluster.events.NoOpProducer; +import org.apache.solr.core.CoreContainer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.invoke.MethodHandles; +import java.util.Set; + +/** + * This class helps in handling the initial registration of plugin-based listeners, + * when both the final {@link ClusterEventProducer} implementation and listeners + * are configured using plugins. + */ +public class ClusterEventProducerFactory extends ClusterEventProducerBase { + private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + + private ContainerPluginsRegistry.PluginRegistryListener initialPluginListener; + private boolean created = false; + + public ClusterEventProducerFactory(CoreContainer cc) { + super(cc); + initialPluginListener = new ContainerPluginsRegistry.PluginRegistryListener() { + @Override + public void added(ContainerPluginsRegistry.ApiInfo plugin) { + if (plugin == null || plugin.getInstance() == null) { + return; + } + Object instance = plugin.getInstance(); + if (instance instanceof ClusterEventListener) { + registerListener((ClusterEventListener) instance); + } + } + + @Override + public void deleted(ContainerPluginsRegistry.ApiInfo plugin) { + if (plugin == null || plugin.getInstance() == null) { + return; + } + Object instance = plugin.getInstance(); + if (instance instanceof ClusterEventListener) { + unregisterListener((ClusterEventListener) instance); + } + } + + @Override + public void modified(ContainerPluginsRegistry.ApiInfo old, ContainerPluginsRegistry.ApiInfo replacement) { + added(replacement); + deleted(old); + } + }; + } + + @Override + public Set<ClusterEvent.EventType> getSupportedEventTypes() { + return NoOpProducer.ALL_EVENT_TYPES; + } + + /** + * This method returns an initial plugin registry listener that helps to capture the + * freshly loaded listener plugins before the final cluster event producer is created. + * @return initial listener + */ + public ContainerPluginsRegistry.PluginRegistryListener getPluginRegistryListener() { + return initialPluginListener; + } + + /** + * Create a {@link ClusterEventProducer} based on the current plugin configurations. + * <p>NOTE: this method can only be called once because it has side-effects, such as + * transferring the initially collected listeners to the resulting producer's instance, and + * installing a {@link org.apache.solr.api.ContainerPluginsRegistry.PluginRegistryListener}. + * Calling this method more than once will result in an exception.</p> + * @param plugins current plugin configurations + * @return configured instance of cluster event producer (with side-effects, see above) + */ + public DelegatingClusterEventProducer create(ContainerPluginsRegistry plugins) { + if (created) { + throw new RuntimeException("this factory can be called only once!"); + } + final DelegatingClusterEventProducer clusterEventProducer = new DelegatingClusterEventProducer(cc); + // since this is a ClusterSingleton, register it as such + cc.getClusterSingletons().getSingletons().put(ClusterEventProducer.PLUGIN_NAME +"_delegate", clusterEventProducer); + ContainerPluginsRegistry.ApiInfo clusterEventProducerInfo = plugins.getPlugin(ClusterEventProducer.PLUGIN_NAME); + if (clusterEventProducerInfo != null) { + // the listener in ClusterSingletons already registered it + clusterEventProducer.setDelegate((ClusterEventProducer) clusterEventProducerInfo.getInstance()); + } else { + // use the default NoOp impl + } + // transfer those listeners that were already registered to the initial impl + transferListeners(clusterEventProducer, plugins); Review comment: No. At this point in the initialization of CoreContainer any source of events will be ignored anyway (because the factory is basically a no-op implementation that doesn't generate any events), and listeners are being transferred before the final implementation is installed. ---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: issues-unsubscr...@lucene.apache.org For additional commands, e-mail: issues-h...@lucene.apache.org