5050using NuGetGallery . Infrastructure . Search . Correlation ;
5151using NuGetGallery . Security ;
5252using SecretReaderFactory = NuGetGallery . Configuration . SecretReader . SecretReaderFactory ;
53+ using Microsoft . Extensions . Http ;
5354
5455namespace NuGetGallery
5556{
@@ -62,6 +63,8 @@ public static class BindingKeys
6263 public const string PackageValidationEnqueuer = "PackageValidationEnqueuerBindingKey" ;
6364 public const string SymbolsPackageValidationEnqueuer = "SymbolsPackageValidationEnqueuerBindingKey" ;
6465 public const string EmailPublisherTopic = "EmailPublisherBindingKey" ;
66+
67+ public const string PreviewSearchClient = "PreviewSearchClientBindingKey" ;
6568 }
6669
6770 protected override void Load ( ContainerBuilder builder )
@@ -137,8 +140,7 @@ protected override void Load(ContainerBuilder builder)
137140 . As < Lucene . Net . Store . Directory > ( )
138141 . SingleInstance ( ) ;
139142
140- ConfigureResilientSearch ( loggerFactory , configuration , telemetryService , services ) ;
141- ConfigureSearch ( builder , configuration ) ;
143+ ConfigureSearch ( loggerFactory , configuration , telemetryService , services , builder ) ;
142144
143145 builder . RegisterType < DateTimeProvider > ( ) . AsSelf ( ) . As < IDateTimeProvider > ( ) . SingleInstance ( ) ;
144146
@@ -671,60 +673,104 @@ private void RegisterAsynchronousValidation(ContainerBuilder builder, IDiagnosti
671673 . InstancePerLifetimeScope ( ) ;
672674 }
673675
674- private static void ConfigureSearch ( ContainerBuilder builder , IGalleryConfigurationService configuration )
676+ private static List < ( string name , Uri searchUri ) > GetSearchClientsFromConfiguration ( IGalleryConfigurationService configuration )
675677 {
676- if ( configuration . Current . SearchServiceUriPrimary == null && configuration . Current . SearchServiceUriSecondary == null )
678+ var searchClients = new List < ( string name , Uri searchUri ) > ( ) ;
679+
680+ if ( configuration . Current . SearchServiceUriPrimary != null )
677681 {
678- builder . RegisterType < LuceneSearchService > ( )
679- . AsSelf ( )
680- . As < ISearchService > ( )
681- . InstancePerLifetimeScope ( ) ;
682- builder . RegisterType < LuceneIndexingService > ( )
683- . AsSelf ( )
684- . As < IIndexingService > ( )
685- . InstancePerLifetimeScope ( ) ;
682+ searchClients . Add ( ( SearchClientConfiguration . SearchPrimaryInstance , configuration . Current . SearchServiceUriPrimary ) ) ;
686683 }
687- else
684+ if ( configuration . Current . SearchServiceUriSecondary != null )
688685 {
689- builder . RegisterType < ExternalSearchService > ( )
690- . AsSelf ( )
691- . As < ISearchService > ( )
692- . As < IIndexingService > ( )
693- . InstancePerLifetimeScope ( ) ;
686+ searchClients . Add ( ( SearchClientConfiguration . SearchSecondaryInstance , configuration . Current . SearchServiceUriSecondary ) ) ;
694687 }
688+
689+ return searchClients ;
695690 }
696691
697- private static List < ( string name , Uri searchUri ) > GetSearchClientsFromConfiguration ( IGalleryConfigurationService configuration )
692+ private static List < ( string name , Uri searchUri ) > GetPreviewSearchClientsFromConfiguration ( IGalleryConfigurationService configuration )
698693 {
699- List < ( string name , Uri searchUri ) > searchClients = new List < ( string name , Uri searchUri ) > ( ) ;
700- if ( configuration . Current . SearchServiceUriPrimary != null )
694+ var searchClients = new List < ( string name , Uri searchUri ) > ( ) ;
695+
696+ if ( configuration . Current . PreviewSearchServiceUriPrimary != null )
701697 {
702- searchClients . Add ( ( SearchClientConfiguration . SearchPrimaryInstance , configuration . Current . SearchServiceUriPrimary ) ) ;
698+ searchClients . Add ( ( SearchClientConfiguration . PreviewSearchPrimaryInstance , configuration . Current . PreviewSearchServiceUriPrimary ) ) ;
703699 }
704- if ( configuration . Current . SearchServiceUriSecondary != null )
700+ if ( configuration . Current . PreviewSearchServiceUriSecondary != null )
705701 {
706- searchClients . Add ( ( SearchClientConfiguration . SearchSecondaryInstance , configuration . Current . SearchServiceUriSecondary ) ) ;
702+ searchClients . Add ( ( SearchClientConfiguration . PreviewSearchSecondaryInstance , configuration . Current . PreviewSearchServiceUriSecondary ) ) ;
707703 }
708704
709705 return searchClients ;
710706 }
711707
712- private static void ConfigureResilientSearch ( ILoggerFactory loggerFactory , IGalleryConfigurationService configuration , ITelemetryService telemetryService , ServiceCollection services )
708+ private static void ConfigureSearch (
709+ ILoggerFactory loggerFactory ,
710+ IGalleryConfigurationService configuration ,
711+ ITelemetryService telemetryService ,
712+ ServiceCollection services ,
713+ ContainerBuilder builder )
713714 {
714715 var searchClients = GetSearchClientsFromConfiguration ( configuration ) ;
715716
716717 if ( searchClients . Count >= 1 )
717718 {
718- var logger = loggerFactory . CreateLogger < SearchClientPolicies > ( ) ;
719719 services . AddTransient < CorrelatingHttpClientHandler > ( ) ;
720720 services . AddTransient ( ( s ) => new TracingHttpHandler ( DependencyResolver . Current . GetService < IDiagnosticsService > ( ) . SafeGetSource ( "ExternalSearchService" ) ) ) ;
721721
722- foreach ( var searchClient in searchClients )
723- {
724- // The policy handlers will be applied from the bottom to the top.
725- // The most inner one is the one added last.
726- services . AddHttpClient < IHttpClientWrapper , HttpClientWrapper > ( searchClient . name ,
727- c =>
722+ // Register the default search service implementation and its dependencies.
723+ RegisterSearchService (
724+ loggerFactory ,
725+ configuration ,
726+ telemetryService ,
727+ services ,
728+ builder ,
729+ searchClients ) ;
730+
731+ // Register the preview search service and its dependencies with a binding key.
732+ var previewSearchClients = GetPreviewSearchClientsFromConfiguration ( configuration ) ;
733+ RegisterSearchService (
734+ loggerFactory ,
735+ configuration ,
736+ telemetryService ,
737+ services ,
738+ builder ,
739+ previewSearchClients ,
740+ BindingKeys . PreviewSearchClient ) ;
741+ }
742+ else
743+ {
744+ builder . RegisterType < LuceneSearchService > ( )
745+ . AsSelf ( )
746+ . As < ISearchService > ( )
747+ . InstancePerLifetimeScope ( ) ;
748+ builder . RegisterType < LuceneIndexingService > ( )
749+ . AsSelf ( )
750+ . As < IIndexingService > ( )
751+ . InstancePerLifetimeScope ( ) ;
752+ }
753+ }
754+
755+ private static void RegisterSearchService (
756+ ILoggerFactory loggerFactory ,
757+ IGalleryConfigurationService configuration ,
758+ ITelemetryService telemetryService ,
759+ ServiceCollection services ,
760+ ContainerBuilder builder ,
761+ List < ( string name , Uri searchUri ) > searchClients ,
762+ string bindingKey = null )
763+ {
764+ var logger = loggerFactory . CreateLogger < SearchClientPolicies > ( ) ;
765+
766+ foreach ( var searchClient in searchClients )
767+ {
768+ // The policy handlers will be applied from the bottom to the top.
769+ // The most inner one is the one added last.
770+ services
771+ . AddHttpClient < IHttpClientWrapper , HttpClientWrapper > (
772+ searchClient . name ,
773+ c =>
728774 {
729775 c . BaseAddress = searchClient . searchUri ;
730776 c . Timeout = TimeSpan . FromMilliseconds ( configuration . Current . SearchHttpClientTimeoutInMilliseconds ) ;
@@ -744,12 +790,66 @@ private static void ConfigureResilientSearch(ILoggerFactory loggerFactory, IGall
744790 logger ,
745791 searchClient . name ,
746792 telemetryService ) ) ;
747- }
748- services . AddTransient < IResilientSearchClient , ResilientSearchHttpClient > ( ) ;
749- services . AddTransient < ISearchClient , GallerySearchClient > ( ) ;
750793 }
751- }
752794
795+ var registrationBuilder = builder
796+ . Register ( c =>
797+ {
798+ var httpClientFactory = c . Resolve < IHttpClientFactory > ( ) ;
799+ var httpClientWrapperFactory = c . Resolve < ITypedHttpClientFactory < HttpClientWrapper > > ( ) ;
800+ var httpClientWrappers = new List < IHttpClientWrapper > ( searchClients . Count ) ;
801+ foreach ( var searchClient in searchClients )
802+ {
803+ var httpClient = httpClientFactory . CreateClient ( searchClient . name ) ;
804+ var httpClientWrapper = httpClientWrapperFactory . CreateClient ( httpClient ) ;
805+ httpClientWrappers . Add ( httpClientWrapper ) ;
806+ }
807+
808+ return new ResilientSearchHttpClient (
809+ httpClientWrappers ,
810+ c . Resolve < ILogger < ResilientSearchHttpClient > > ( ) ,
811+ c . Resolve < ITelemetryService > ( ) ) ;
812+ } ) ;
813+
814+ if ( bindingKey != null )
815+ {
816+ registrationBuilder
817+ . Named < IResilientSearchClient > ( bindingKey )
818+ . InstancePerLifetimeScope ( ) ;
819+
820+ builder
821+ . RegisterType < GallerySearchClient > ( )
822+ . WithParameter ( new ResolvedParameter (
823+ ( pi , ctx ) => pi . ParameterType == typeof ( IResilientSearchClient ) ,
824+ ( pi , ctx ) => ctx . ResolveKeyed < IResilientSearchClient > ( bindingKey ) ) )
825+ . Named < ISearchClient > ( bindingKey )
826+ . InstancePerLifetimeScope ( ) ;
827+
828+ builder . RegisterType < ExternalSearchService > ( )
829+ . WithParameter ( new ResolvedParameter (
830+ ( pi , ctx ) => pi . ParameterType == typeof ( ISearchClient ) ,
831+ ( pi , ctx ) => ctx . ResolveKeyed < ISearchClient > ( bindingKey ) ) )
832+ . Named < ISearchService > ( bindingKey )
833+ . InstancePerLifetimeScope ( ) ;
834+ }
835+ else
836+ {
837+ registrationBuilder
838+ . As < IResilientSearchClient > ( )
839+ . InstancePerLifetimeScope ( ) ;
840+
841+ builder
842+ . RegisterType < GallerySearchClient > ( )
843+ . As < ISearchClient > ( )
844+ . InstancePerLifetimeScope ( ) ;
845+
846+ builder . RegisterType < ExternalSearchService > ( )
847+ . AsSelf ( )
848+ . As < ISearchService > ( )
849+ . As < IIndexingService > ( )
850+ . InstancePerLifetimeScope ( ) ;
851+ }
852+ }
753853
754854 private static void ConfigureAutocomplete ( ContainerBuilder builder , IGalleryConfigurationService configuration )
755855 {
0 commit comments