Skip to content

Commit 99784ab

Browse files
committed
Populate MEF container to allow early initialization (#7862)
Related to NuGet/Engineering#2980
1 parent 779ef3f commit 99784ab

2 files changed

Lines changed: 46 additions & 17 deletions

File tree

src/NuGetGallery.Services/Providers/RuntimeServiceProvider.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System;
55
using System.Collections.Generic;
6+
using System.ComponentModel.Composition;
67
using System.ComponentModel.Composition.Hosting;
78
using System.IO;
89
using System.Linq;
@@ -41,6 +42,26 @@ public static RuntimeServiceProvider Create(string baseDirectoryPath)
4142
return new RuntimeServiceProvider(compositionContainer);
4243
}
4344

45+
public void ComposeExportedValue<T>(string contractName, T exportedValue)
46+
{
47+
if (_isDisposed)
48+
{
49+
throw new ObjectDisposedException(nameof(RuntimeServiceProvider));
50+
}
51+
52+
_compositionContainer.ComposeExportedValue(contractName, exportedValue);
53+
}
54+
55+
public void ComposeExportedValue<T>(T exportedValue)
56+
{
57+
if (_isDisposed)
58+
{
59+
throw new ObjectDisposedException(nameof(RuntimeServiceProvider));
60+
}
61+
62+
_compositionContainer.ComposeExportedValue(exportedValue);
63+
}
64+
4465
public IEnumerable<T> GetExportedValues<T>()
4566
{
4667
if (_isDisposed)

src/NuGetGallery/App_Start/DefaultDependenciesModule.cs

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
using System.Net.Http;
1212
using System.Net.Mail;
1313
using System.Security.Principal;
14-
using System.Threading;
1514
using System.Threading.Tasks;
1615
using System.Web;
1716
using System.Web.Hosting;
@@ -23,10 +22,12 @@
2322
using Elmah;
2423
using Microsoft.ApplicationInsights.Extensibility;
2524
using Microsoft.ApplicationInsights.Extensibility.Implementation;
25+
using Microsoft.AspNet.TelemetryCorrelation;
2626
using Microsoft.Extensions.DependencyInjection;
2727
using Microsoft.Extensions.Http;
2828
using Microsoft.Extensions.Logging;
2929
using Microsoft.WindowsAzure.ServiceRuntime;
30+
using Microsoft.WindowsAzure.Storage;
3031
using NuGet.Services.Entities;
3132
using NuGet.Services.FeatureFlags;
3233
using NuGet.Services.KeyVault;
@@ -1389,19 +1390,25 @@ private static IAuditingService CombineAuditingServices(IEnumerable<IAuditingSer
13891390
return new AggregateAuditingService(services);
13901391
}
13911392

1392-
private static IEnumerable<T> GetAddInServices<T>(ContainerBuilder builder)
1393+
private static IEnumerable<T> GetAddInServices<T>()
1394+
{
1395+
return GetAddInServices<T>(sp => { });
1396+
}
1397+
1398+
private static IEnumerable<T> GetAddInServices<T>(Action<RuntimeServiceProvider> populateProvider)
13931399
{
13941400
var addInsDirectoryPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin", "add-ins");
13951401

13961402
using (var serviceProvider = RuntimeServiceProvider.Create(addInsDirectoryPath))
13971403
{
1404+
populateProvider(serviceProvider);
13981405
return serviceProvider.GetExportedValues<T>();
13991406
}
14001407
}
14011408

14021409
private static void RegisterAuditingServices(ContainerBuilder builder, IAuditingService defaultAuditingService)
14031410
{
1404-
var auditingServices = GetAddInServices<IAuditingService>(builder);
1411+
var auditingServices = GetAddInServices<IAuditingService>();
14051412
var services = new List<IAuditingService>(auditingServices);
14061413

14071414
if (defaultAuditingService != null)
@@ -1419,26 +1426,27 @@ private static void RegisterAuditingServices(ContainerBuilder builder, IAuditing
14191426

14201427
private static void RegisterCookieComplianceService(ContainerBuilder builder, ConfigurationService configuration, DiagnosticsService diagnostics)
14211428
{
1422-
var service = GetAddInServices<ICookieComplianceService>(builder).FirstOrDefault() as CookieComplianceServiceBase;
1423-
1424-
if (service == null)
1429+
CookieComplianceServiceBase service = null;
1430+
if (configuration.Current.IsHosted)
14251431
{
1426-
service = new NullCookieComplianceService();
1432+
var siteName = configuration.GetSiteRoot(true);
1433+
service = GetAddInServices<ICookieComplianceService>(sp =>
1434+
{
1435+
sp.ComposeExportedValue("Domain", siteName);
1436+
sp.ComposeExportedValue<IDiagnosticsService>(diagnostics);
1437+
}).FirstOrDefault() as CookieComplianceServiceBase;
1438+
1439+
if (service != null)
1440+
{
1441+
// Initialize the service on App_Start to avoid any performance degradation during initial requests.
1442+
HostingEnvironment.QueueBackgroundWorkItem(async cancellationToken => await service.InitializeAsync(siteName, diagnostics, cancellationToken));
1443+
}
14271444
}
14281445

1429-
builder.RegisterInstance(service)
1446+
builder.RegisterInstance(service ?? new NullCookieComplianceService())
14301447
.AsSelf()
14311448
.As<ICookieComplianceService>()
14321449
.SingleInstance();
1433-
1434-
if (configuration.Current.IsHosted)
1435-
{
1436-
var siteName = configuration.GetSiteRoot(true);
1437-
1438-
// We must initialize during app start so that the cookie compliance service is ready when the first
1439-
// request comes in.
1440-
service.InitializeAsync(siteName, diagnostics, CancellationToken.None).Wait();
1441-
}
14421450
}
14431451
}
14441452
}

0 commit comments

Comments
 (0)