refactor: prevents global stats config freeze in ConfiguratorRegistry.getConfigurators() (#11991)

This commit is contained in:
Abhishek Agrawal 2025-04-04 05:53:08 +00:00 committed by GitHub
parent c8d1e6e39c
commit d4c46a7f1f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 30 additions and 26 deletions

View File

@ -33,9 +33,9 @@ final class ConfiguratorRegistry {
@GuardedBy("this") @GuardedBy("this")
private boolean wasConfiguratorsSet; private boolean wasConfiguratorsSet;
@GuardedBy("this") @GuardedBy("this")
private boolean configFrozen;
@GuardedBy("this")
private List<Configurator> configurators = Collections.emptyList(); private List<Configurator> configurators = Collections.emptyList();
@GuardedBy("this")
private int configuratorsCallCountBeforeSet = 0;
ConfiguratorRegistry() {} ConfiguratorRegistry() {}
@ -56,11 +56,10 @@ final class ConfiguratorRegistry {
* @throws IllegalStateException if this method is called more than once * @throws IllegalStateException if this method is called more than once
*/ */
public synchronized void setConfigurators(List<? extends Configurator> configurators) { public synchronized void setConfigurators(List<? extends Configurator> configurators) {
if (configFrozen) { if (wasConfiguratorsSet) {
throw new IllegalStateException("Configurators are already set"); throw new IllegalStateException("Configurators are already set");
} }
this.configurators = Collections.unmodifiableList(new ArrayList<>(configurators)); this.configurators = Collections.unmodifiableList(new ArrayList<>(configurators));
configFrozen = true;
wasConfiguratorsSet = true; wasConfiguratorsSet = true;
} }
@ -68,10 +67,20 @@ final class ConfiguratorRegistry {
* Returns a list of the configurators in this registry. * Returns a list of the configurators in this registry.
*/ */
public synchronized List<Configurator> getConfigurators() { public synchronized List<Configurator> getConfigurators() {
configFrozen = true; if (!wasConfiguratorsSet) {
configuratorsCallCountBeforeSet++;
}
return configurators; return configurators;
} }
/**
* Returns the number of times getConfigurators() was called before
* setConfigurators() was successfully invoked.
*/
public synchronized int getConfiguratorsCallCountBeforeSet() {
return configuratorsCallCountBeforeSet;
}
public synchronized boolean wasSetConfiguratorsCalled() { public synchronized boolean wasSetConfiguratorsCalled() {
return wasConfiguratorsSet; return wasConfiguratorsSet;
} }

View File

@ -48,4 +48,8 @@ public final class InternalConfiguratorRegistry {
public static boolean wasSetConfiguratorsCalled() { public static boolean wasSetConfiguratorsCalled() {
return ConfiguratorRegistry.getDefaultRegistry().wasSetConfiguratorsCalled(); return ConfiguratorRegistry.getDefaultRegistry().wasSetConfiguratorsCalled();
} }
public static int getConfiguratorsCallCountBeforeSet() {
return ConfiguratorRegistry.getDefaultRegistry().getConfiguratorsCallCountBeforeSet();
}
} }

View File

@ -85,14 +85,12 @@ public class ConfiguratorRegistryTest {
@Override @Override
public void run() { public void run() {
assertThat(ConfiguratorRegistry.getDefaultRegistry().getConfigurators()).isEmpty(); assertThat(ConfiguratorRegistry.getDefaultRegistry().getConfigurators()).isEmpty();
NoopConfigurator noopConfigurator = new NoopConfigurator();
try { ConfiguratorRegistry.getDefaultRegistry()
ConfiguratorRegistry.getDefaultRegistry() .setConfigurators(Arrays.asList(noopConfigurator));
.setConfigurators(Arrays.asList(new NoopConfigurator())); assertThat(ConfiguratorRegistry.getDefaultRegistry().getConfigurators())
fail("should have failed for invoking set call after get is already called"); .containsExactly(noopConfigurator);
} catch (IllegalStateException e) { assertThat(InternalConfiguratorRegistry.getConfiguratorsCallCountBeforeSet()).isEqualTo(1);
assertThat(e).hasMessageThat().isEqualTo("Configurators are already set");
}
} }
} }

View File

@ -529,12 +529,9 @@ public class ManagedChannelImplBuilderTest {
List<ClientInterceptor> effectiveInterceptors = List<ClientInterceptor> effectiveInterceptors =
builder.getEffectiveInterceptors("unused:///"); builder.getEffectiveInterceptors("unused:///");
assertThat(effectiveInterceptors).hasSize(2); assertThat(effectiveInterceptors).hasSize(2);
try { InternalConfiguratorRegistry.setConfigurators(Collections.emptyList());
InternalConfiguratorRegistry.setConfigurators(Collections.emptyList()); assertThat(InternalConfiguratorRegistry.getConfigurators()).isEmpty();
fail("exception expected"); assertThat(InternalConfiguratorRegistry.getConfiguratorsCallCountBeforeSet()).isEqualTo(1);
} catch (IllegalStateException e) {
assertThat(e).hasMessageThat().contains("Configurators are already set");
}
} }
} }

View File

@ -18,7 +18,6 @@ package io.grpc.internal;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import io.grpc.InternalConfigurator; import io.grpc.InternalConfigurator;
import io.grpc.InternalConfiguratorRegistry; import io.grpc.InternalConfiguratorRegistry;
@ -145,12 +144,9 @@ public class ServerImplBuilderTest {
}); });
assertThat(builder.getTracerFactories()).hasSize(2); assertThat(builder.getTracerFactories()).hasSize(2);
assertThat(builder.interceptors).hasSize(0); assertThat(builder.interceptors).hasSize(0);
try { InternalConfiguratorRegistry.setConfigurators(Collections.emptyList());
InternalConfiguratorRegistry.setConfigurators(Collections.emptyList()); assertThat(InternalConfiguratorRegistry.getConfigurators()).isEmpty();
fail("exception expected"); assertThat(InternalConfiguratorRegistry.getConfiguratorsCallCountBeforeSet()).isEqualTo(1);
} catch (IllegalStateException e) {
assertThat(e).hasMessageThat().contains("Configurators are already set");
}
} }
} }