using System; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Options; using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Notifications; using Umbraco.Cms.Core.PropertyEditors; using Umbraco.Cms.Core.PublishedCache; using Umbraco.Cms.Core.Scoping; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Infrastructure.PublishedCache; using Umbraco.Cms.Infrastructure.PublishedCache.DataSource; using Umbraco.Cms.Infrastructure.PublishedCache.Persistence; namespace Umbraco.Extensions { /// /// Extension methods for for the Umbraco's NuCache /// public static class UmbracoBuilderExtensions { /// /// Adds Umbraco NuCache dependencies /// public static IUmbracoBuilder AddNuCache(this IUmbracoBuilder builder) { // register the NuCache database data source builder.Services.TryAddSingleton(); builder.Services.TryAddSingleton(); builder.Services.TryAddSingleton(); // register the NuCache published snapshot service // must register default options, required in the service ctor builder.Services.TryAddTransient(factory => new PublishedSnapshotServiceOptions()); builder.SetPublishedSnapshotService(); builder.Services.TryAddSingleton(); // replace this service since we want to improve the content/media // mapping lookups if we are using nucache. // TODO: Gotta wonder how much this does actually improve perf? It's a lot of weird code to make this happen so hope it's worth it builder.Services.AddUnique(factory => { var idkSvc = new IdKeyMap(factory.GetRequiredService()); if (factory.GetRequiredService() is PublishedSnapshotService publishedSnapshotService) { idkSvc.SetMapper(UmbracoObjectTypes.Document, id => publishedSnapshotService.GetDocumentUid(id), uid => publishedSnapshotService.GetDocumentId(uid)); idkSvc.SetMapper(UmbracoObjectTypes.Media, id => publishedSnapshotService.GetMediaUid(id), uid => publishedSnapshotService.GetMediaId(uid)); } return idkSvc; }); builder.AddNuCacheNotifications(); builder.AddNotificationHandler(); builder.Services.AddSingleton(s => { IOptions options = s.GetRequiredService>(); switch (options.Value.NuCacheSerializerType) { case NuCacheSerializerType.JSON: return new JsonContentNestedDataSerializerFactory(); case NuCacheSerializerType.MessagePack: return ActivatorUtilities.CreateInstance(s); default: throw new IndexOutOfRangeException(); } }); builder.Services.AddSingleton(s => { IOptions options = s.GetRequiredService>(); if (options.Value.NuCacheSerializerType == NuCacheSerializerType.MessagePack && options.Value.UnPublishedContentCompression) { return s.GetRequiredService(); } return s.GetRequiredService(); }); builder.Services.AddSingleton(s => new ContentDataSerializer(new DictionaryOfPropertyDataSerializer())); // add the NuCache health check (hidden from type finder) // TODO: no NuCache health check yet // composition.HealthChecks().Add(); return builder; } private static IUmbracoBuilder AddNuCacheNotifications(this IUmbracoBuilder builder) { builder .AddNotificationHandler() .AddNotificationHandler() #pragma warning disable CS0618 // Type or member is obsolete .AddNotificationHandler() .AddNotificationHandler() .AddNotificationHandler() .AddNotificationHandler() .AddNotificationHandler() .AddNotificationHandler() .AddNotificationHandler() #pragma warning restore CS0618 // Type or member is obsolete ; return builder; } } }