@@ -370,85 +370,12 @@ public GapicSpannerRpc(final SpannerOptions options) {
370370
371371 if (options .getChannelProvider () == null
372372 && isEnableDirectAccess
373- && isEnableGcpFallbackEnv ()) {
374- InstantiatingGrpcChannelProvider .Builder cloudPathProviderBuilder =
375- createChannelProviderBuilder (
376- options , headerProviderWithUserAgent , /* isEnableDirectAccess= */ false );
377-
378- final AtomicReference <ManagedChannelBuilder > cloudPathBuilderRef = new AtomicReference <>();
379- cloudPathProviderBuilder .setChannelConfigurator (
380- builder -> {
381- if (options .getChannelConfigurator () != null ) {
382- builder = options .getChannelConfigurator ().apply (builder );
383- }
384- cloudPathBuilderRef .set (builder );
385- return builder ;
386- });
387-
388- // Build the cloudPathProvider to extract the builder which will be provided to
389- // FallbackChannelBuilder.
390- try (TransportChannel ignored = cloudPathProviderBuilder .build ().getTransportChannel ()) {
391- } catch (Exception e ) {
392- throw asSpannerException (e );
393- }
394-
395- ManagedChannelBuilder cloudPathBuilder = cloudPathBuilderRef .get ();
396- if (cloudPathBuilder == null ) {
397- throw new IllegalStateException ("CloudPath builder was not captured." );
398- }
399-
400- try {
401- Credentials credentials = credentialsProvider .getCredentials ();
402- if (credentials != null ) {
403- cloudPathBuilder .intercept (
404- new ClientInterceptor () {
405- @ Override
406- public <ReqT , RespT > ClientCall <ReqT , RespT > interceptCall (
407- MethodDescriptor <ReqT , RespT > method , CallOptions callOptions , Channel next ) {
408- return next .newCall (
409- method ,
410- callOptions .withCallCredentials (MoreCallCredentials .from (credentials )));
411- }
412- });
413- }
414- } catch (Exception e ) {
415- throw asSpannerException (e );
416- }
417-
418- defaultChannelProviderBuilder .setChannelConfigurator (
419- directPathBuilder -> {
420- if (options .getChannelConfigurator () != null ) {
421- directPathBuilder = options .getChannelConfigurator ().apply (directPathBuilder );
422- }
423-
424- String jsonApiConfig = parseGrpcGcpApiConfig ();
425- GcpManagedChannelOptions gcpOptions = grpcGcpOptionsWithMetricsAndDcp (options );
426- if (gcpOptions == null ) {
427- gcpOptions = GcpManagedChannelOptions .newBuilder ().build ();
428- }
429-
430- GcpManagedChannelBuilder primaryGcpBuilder =
431- GcpManagedChannelBuilder .forDelegateBuilder (directPathBuilder )
432- .withApiConfigJsonString (jsonApiConfig )
433- .withOptions (gcpOptions );
434-
435- GcpManagedChannelBuilder fallbackGcpBuilder =
436- GcpManagedChannelBuilder .forDelegateBuilder (cloudPathBuilder )
437- .withApiConfigJsonString (jsonApiConfig )
438- .withOptions (gcpOptions );
439-
440- GcpFallbackOpenTelemetry fallbackTelemetry =
441- GcpFallbackOpenTelemetry .newBuilder ()
442- .withSdk (options .getOpenTelemetry ())
443- .disableAllMetrics ()
444- .enableMetrics (Arrays .asList ("fallback_count" , "call_status" ))
445- .build ();
446-
447- return new FallbackChannelBuilder (
448- primaryGcpBuilder ,
449- fallbackGcpBuilder ,
450- createFallbackChannelOptions (fallbackTelemetry , 1 ));
451- });
373+ && options .isEnableGcpFallback ()) {
374+ setupGcpFallback (
375+ defaultChannelProviderBuilder ,
376+ options ,
377+ headerProviderWithUserAgent ,
378+ credentialsProvider );
452379 }
453380
454381 boolean enableLocationApi = options .isEnableLocationApi ();
@@ -666,6 +593,96 @@ private static String parseGrpcGcpApiConfig() {
666593 }
667594 }
668595
596+ private void setupGcpFallback (
597+ InstantiatingGrpcChannelProvider .Builder defaultChannelProviderBuilder ,
598+ final SpannerOptions options ,
599+ final HeaderProvider headerProviderWithUserAgent ,
600+ final CredentialsProvider credentialsProvider ) {
601+ InstantiatingGrpcChannelProvider .Builder cloudPathProviderBuilder =
602+ createChannelProviderBuilder (
603+ options , headerProviderWithUserAgent , /* isEnableDirectAccess= */ false );
604+
605+ final ApiFunction <ManagedChannelBuilder , ManagedChannelBuilder > existingCloudPathConfigurator =
606+ cloudPathProviderBuilder .getChannelConfigurator ();
607+ final AtomicReference <ManagedChannelBuilder > cloudPathBuilderRef = new AtomicReference <>();
608+ cloudPathProviderBuilder .setChannelConfigurator (
609+ builder -> {
610+ ManagedChannelBuilder effectiveBuilder = builder ;
611+ if (existingCloudPathConfigurator != null ) {
612+ effectiveBuilder = existingCloudPathConfigurator .apply (effectiveBuilder );
613+ }
614+ cloudPathBuilderRef .set (effectiveBuilder );
615+ return effectiveBuilder ;
616+ });
617+
618+ // Build the cloudPathProvider to extract the builder which will be provided to
619+ // FallbackChannelBuilder.
620+ try (TransportChannel ignored = cloudPathProviderBuilder .build ().getTransportChannel ()) {
621+ } catch (Exception e ) {
622+ throw asSpannerException (e );
623+ }
624+
625+ ManagedChannelBuilder cloudPathBuilder = cloudPathBuilderRef .get ();
626+ if (cloudPathBuilder == null ) {
627+ throw new IllegalStateException ("CloudPath builder was not captured." );
628+ }
629+
630+ try {
631+ Credentials credentials = credentialsProvider .getCredentials ();
632+ if (credentials != null ) {
633+ cloudPathBuilder .intercept (
634+ new ClientInterceptor () {
635+ @ Override
636+ public <ReqT , RespT > ClientCall <ReqT , RespT > interceptCall (
637+ MethodDescriptor <ReqT , RespT > method , CallOptions callOptions , Channel next ) {
638+ return next .newCall (
639+ method , callOptions .withCallCredentials (MoreCallCredentials .from (credentials )));
640+ }
641+ });
642+ }
643+ } catch (Exception e ) {
644+ throw asSpannerException (e );
645+ }
646+
647+ final ApiFunction <ManagedChannelBuilder , ManagedChannelBuilder > existingConfigurator =
648+ defaultChannelProviderBuilder .getChannelConfigurator ();
649+ defaultChannelProviderBuilder .setChannelConfigurator (
650+ directPathBuilder -> {
651+ ManagedChannelBuilder builder = directPathBuilder ;
652+ if (existingConfigurator != null ) {
653+ builder = existingConfigurator .apply (builder );
654+ }
655+
656+ String jsonApiConfig = parseGrpcGcpApiConfig ();
657+ GcpManagedChannelOptions gcpOptions = grpcGcpOptionsWithMetricsAndDcp (options );
658+ if (gcpOptions == null ) {
659+ gcpOptions = GcpManagedChannelOptions .newBuilder ().build ();
660+ }
661+
662+ GcpManagedChannelBuilder primaryGcpBuilder =
663+ GcpManagedChannelBuilder .forDelegateBuilder (builder )
664+ .withApiConfigJsonString (jsonApiConfig )
665+ .withOptions (gcpOptions );
666+
667+ GcpManagedChannelBuilder fallbackGcpBuilder =
668+ GcpManagedChannelBuilder .forDelegateBuilder (cloudPathBuilder )
669+ .withApiConfigJsonString (jsonApiConfig )
670+ .withOptions (gcpOptions );
671+
672+ GcpFallbackOpenTelemetry fallbackTelemetry =
673+ GcpFallbackOpenTelemetry .newBuilder ()
674+ .withSdk (options .getOpenTelemetry ())
675+ .disableAllMetrics ()
676+ .enableMetrics (Arrays .asList ("fallback_count" , "call_status" ))
677+ .build ();
678+
679+ return new FallbackChannelBuilder (
680+ primaryGcpBuilder ,
681+ fallbackGcpBuilder ,
682+ createFallbackChannelOptions (fallbackTelemetry , 1 ));
683+ });
684+ }
685+
669686 private InstantiatingGrpcChannelProvider .Builder createChannelProviderBuilder (
670687 final SpannerOptions options ,
671688 final HeaderProvider headerProviderWithUserAgent ,
@@ -865,15 +882,6 @@ public static boolean isEnableDirectPathBoundToken() {
865882 return !Boolean .parseBoolean (System .getenv ("GOOGLE_SPANNER_DISABLE_DIRECT_ACCESS_BOUND_TOKEN" ));
866883 }
867884
868- @ VisibleForTesting static Boolean enableGcpFallbackEnv = null ;
869-
870- public static boolean isEnableGcpFallbackEnv () {
871- if (enableGcpFallbackEnv != null ) {
872- return enableGcpFallbackEnv ;
873- }
874- return Boolean .parseBoolean (System .getenv ("GOOGLE_SPANNER_ENABLE_GCP_FALLBACK" ));
875- }
876-
877885 private static final RetrySettings ADMIN_REQUESTS_LIMIT_EXCEEDED_RETRY_SETTINGS =
878886 RetrySettings .newBuilder ()
879887 .setInitialRetryDelayDuration (Duration .ofSeconds (5L ))
0 commit comments