Skip to content

Commit

Permalink
extensions package for a named client
Browse files Browse the repository at this point in the history
  • Loading branch information
tomasjurasek committed Jan 13, 2021
1 parent c6d0459 commit 761959f
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 49 deletions.
5 changes: 0 additions & 5 deletions Kentico.Kontent.Delivery.Caching/DeliveryCacheOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,5 @@ public class DeliveryCacheOptions
/// Determines whether to use <see cref="Microsoft.Extensions.Caching.Distributed.IDistributedCache" /> or <inheritdoc cref="Microsoft.Extensions.Caching.Memory.IMemoryCache"/>
/// </summary>
public CacheTypeEnum CacheType { get; set; } = CacheTypeEnum.Memory;

/// <summary>
/// Name of an <see cref="IDeliveryCacheManager"/> instance the options are bound to.
/// </summary>
public string Name { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ public static void Configure(this DeliveryCacheOptions o, DeliveryCacheOptions o
o.DefaultExpiration = options.DefaultExpiration;
o.DefaultExpirationType = options.DefaultExpirationType;
o.StaleContentExpiration = options.StaleContentExpiration;
o.Name = options.Name;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,31 +30,17 @@ public static IServiceCollection AddDeliveryClientCache(this IServiceCollection
.RegisterDependencies(options.CacheType)
.Decorate<IDeliveryClient, DeliveryClientCache>();
}

/// <summary>
/// Registers <see cref="IDeliveryClient"/> cache dependencies.
/// </summary>
/// <param name="services">A <see cref="IServiceCollection"/> instance for registering and resolving dependencies.</param>
/// <param name="cacheType"> A <see cref="CacheTypeEnum"/></param>
/// <param name="name">A name of named client which want to use cached.</param>
/// <returns></returns>
public static IServiceCollection RegisterDependencies(this IServiceCollection services, CacheTypeEnum cacheType, string name = null)
private static IServiceCollection RegisterDependencies(this IServiceCollection services, CacheTypeEnum cacheType)
{
switch (cacheType)
{
case CacheTypeEnum.Memory:
if (name == null)
{
services.TryAddSingleton<IDeliveryCacheManager, MemoryCacheManager>();
}
services.TryAddSingleton<IDeliveryCacheManager, MemoryCacheManager>();
services.TryAddSingleton<IMemoryCache, MemoryCache>();
break;

case CacheTypeEnum.Distributed:
if (name == null)
{
services.TryAddSingleton<IDeliveryCacheManager, DistributedCacheManager>();
}
services.TryAddSingleton<IDeliveryCacheManager, DistributedCacheManager>();
services.TryAddSingleton<IDistributedCache, MemoryDistributedCache>();
break;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
using FakeItEasy;
using Autofac;
using FakeItEasy;
using FluentAssertions;
using Kentico.Kontent.Delivery.Abstractions;
using Kentico.Kontent.Delivery.Caching;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System;
using Xunit;

namespace Kentico.Kontent.Delivery.Extensions.Autofac.DependencyInjection.Tests
Expand All @@ -13,15 +13,18 @@ public class DeliveryClientCacheFactoryTests
{
private readonly IOptionsMonitor<DeliveryCacheOptions> _deliveryCacheOptionsMock;
private readonly IDeliveryClientFactory _innerDeliveryClientFactoryMock;
private readonly IServiceProvider _serviceProvider;
private readonly IComponentContext _container;
private readonly IServiceCollection _serviceCollection;

private const string _clientName = "ClientName";

public DeliveryClientCacheFactoryTests()
{
_deliveryCacheOptionsMock = A.Fake<IOptionsMonitor<DeliveryCacheOptions>>();
_innerDeliveryClientFactoryMock = A.Fake<IDeliveryClientFactory>();
_serviceProvider = new ServiceCollection().BuildServiceProvider();
_container = A.Fake<IComponentContext>();
_serviceCollection = new ServiceCollection()
.AddMemoryCache();
}

[Fact]
Expand All @@ -31,7 +34,7 @@ public void GetNamedCacheClient_WithCorrectName_GetClient()
A.CallTo(() => _deliveryCacheOptionsMock.Get(_clientName))
.Returns(deliveryCacheOptions);

var deliveryClientFactory = new DeliveryClientCacheFactory(_innerDeliveryClientFactoryMock, _deliveryCacheOptionsMock, _serviceProvider);
var deliveryClientFactory = new DeliveryClientCacheFactory(_innerDeliveryClientFactoryMock, _deliveryCacheOptionsMock, _serviceCollection.BuildServiceProvider(), _container);

var result = deliveryClientFactory.Get(_clientName);

Expand All @@ -45,7 +48,7 @@ public void GetNamedCacheClient_WithWrongName_GetNull()
A.CallTo(() => _deliveryCacheOptionsMock.Get(_clientName))
.Returns(deliveryCacheOptions);

var deliveryClientFactory = new DeliveryClientCacheFactory(_innerDeliveryClientFactoryMock, _deliveryCacheOptionsMock, _serviceProvider);
var deliveryClientFactory = new DeliveryClientCacheFactory(_innerDeliveryClientFactoryMock, _deliveryCacheOptionsMock, _serviceCollection.BuildServiceProvider(), _container);

var result = deliveryClientFactory.Get("WrongName");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ namespace Kentico.Kontent.Delivery.Extensions.Autofac.DependencyInjection.Tests
{
public class ServiceCollectionExtensionsTests
{
private readonly ServiceCollection _serviceCollection;
private readonly IServiceCollection _serviceCollection;
private readonly IComponentContext _container;

public ServiceCollectionExtensionsTests()
{
_serviceCollection = new ServiceCollection();
_serviceCollection = new ServiceCollection()
.AddMemoryCache()
.AddDistributedMemoryCache();
_container = A.Fake<IComponentContext>();
}

Expand Down Expand Up @@ -61,6 +63,26 @@ public void AddDeliveryNamedClient_CacheWithDeliveryCacheOptions_GetNull(CacheTy
client.Should().BeNull();
}

[Theory]
[InlineData(CacheTypeEnum.Memory)]
[InlineData(CacheTypeEnum.Distributed)]
public void AddDeliveryNamedClient_CacheWithDeliveryCacheOptions_GetNoNamedClientNull(CacheTypeEnum cacheType)
{
_serviceCollection.AddSingleton(_container);
_serviceCollection.AddDeliveryClient("named", new DeliveryOptions() { ProjectId = Guid.NewGuid().ToString() });
_serviceCollection.AddDeliveryClientCache("named", new DeliveryCacheOptions()
{
CacheType = cacheType
});

var sp = _serviceCollection.BuildServiceProvider();
var factory = sp.GetRequiredService<IDeliveryClientFactory>();

var client = factory.Get();

client.Should().BeNull();
}

[Fact]
public void AddDeliveryNamedClient_DeliveryOptions_GetNamedClient()
{
Expand All @@ -87,5 +109,18 @@ public void AddDeliveryNamedClient_DeliveryOptions_GetNull()
client.Should().BeNull();
}

[Fact]
public void AddDeliveryNamedClient_DeliveryOptions_GetNoNamedClientNull()
{
_serviceCollection.AddSingleton(_container);
_serviceCollection.AddDeliveryClient("named", new DeliveryOptions() { ProjectId = Guid.NewGuid().ToString() });
var sp = _serviceCollection.BuildServiceProvider();

var factory = sp.GetRequiredService<IDeliveryClientFactory>();
var client = factory.Get();

client.Should().BeNull();
}

}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using Kentico.Kontent.Delivery.Abstractions;
using Autofac;
using Autofac.Core.Registration;
using Kentico.Kontent.Delivery.Abstractions;
using Kentico.Kontent.Delivery.Caching;
using Kentico.Kontent.Delivery.Caching.Factories;
using Microsoft.Extensions.Caching.Distributed;
Expand All @@ -14,6 +16,7 @@ internal class DeliveryClientCacheFactory : IDeliveryClientFactory
{
private readonly IOptionsMonitor<DeliveryCacheOptions> _deliveryCacheOptions;
private readonly IServiceProvider _serviceProvider;
private readonly IComponentContext _componentContext;
private readonly IDeliveryClientFactory _innerDeliveryClientFactory;
private readonly ConcurrentDictionary<string, IDeliveryClient> _cache = new ConcurrentDictionary<string, IDeliveryClient>();

Expand All @@ -23,10 +26,12 @@ internal class DeliveryClientCacheFactory : IDeliveryClientFactory
/// <param name="deliveryClientFactory">Factory to be decorated.</param>
/// <param name="deliveryCacheOptions">Cache configuration options.</param>
/// <param name="serviceProvider">An <see cref="IServiceProvider"/> instance.</param>
public DeliveryClientCacheFactory(IDeliveryClientFactory deliveryClientFactory, IOptionsMonitor<DeliveryCacheOptions> deliveryCacheOptions, IServiceProvider serviceProvider)
/// <param name="componentContext">An autofac container</param>
public DeliveryClientCacheFactory(IDeliveryClientFactory deliveryClientFactory, IOptionsMonitor<DeliveryCacheOptions> deliveryCacheOptions, IServiceProvider serviceProvider, IComponentContext componentContext)
{
_deliveryCacheOptions = deliveryCacheOptions;
_serviceProvider = serviceProvider;
_componentContext = componentContext;
_innerDeliveryClientFactory = deliveryClientFactory;
}

Expand All @@ -40,32 +45,47 @@ public IDeliveryClient Get(string name)
if (!_cache.TryGetValue(name, out var client))
{
client = _innerDeliveryClientFactory.Get(name);
var cacheOptions = _deliveryCacheOptions.Get(name);
if (cacheOptions.Name == name)
if (client != null)
{
// Build caching services according to the options
IDeliveryCacheManager manager;
if (cacheOptions.CacheType == CacheTypeEnum.Memory)
var cacheOptions = _deliveryCacheOptions.Get(name);
if (cacheOptions != null)
{
var memoryCache = _serviceProvider.GetService<IMemoryCache>();
manager = CacheManagerFactory.Create(memoryCache, Options.Create(cacheOptions));
}
else
{
var distributedCache = _serviceProvider.GetService<IDistributedCache>();
manager = CacheManagerFactory.Create(distributedCache, Options.Create(cacheOptions));
}
// Build caching services according to the options
IDeliveryCacheManager manager;
if (cacheOptions.CacheType == CacheTypeEnum.Memory)
{
var memoryCache = GetNamedServiceOrDefault<IMemoryCache>(name);
manager = CacheManagerFactory.Create(memoryCache, Options.Create(cacheOptions));
}
else
{
var distributedCache = GetNamedServiceOrDefault<IDistributedCache>(name);
manager = CacheManagerFactory.Create(distributedCache, Options.Create(cacheOptions));
}

// Decorate the client with a caching layer
client = new DeliveryClientCache(manager, client);
// Decorate the client with a caching layer
client = new DeliveryClientCache(manager, client);

_cache.TryAdd(name, client);
_cache.TryAdd(name, client);
}
}
}

return client;
}

public IDeliveryClient Get() => _innerDeliveryClientFactory.Get();

private T GetNamedServiceOrDefault<T>(string name)
{
try
{
return _componentContext.ResolveNamed<T>(name);
}
catch (ComponentNotRegisteredException)
{
return _serviceProvider.GetService<T>();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
using Kentico.Kontent.Delivery.Caching.Extensions;
using Kentico.Kontent.Delivery.Configuration;
using Kentico.Kontent.Delivery.Helpers;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using System;

namespace Kentico.Kontent.Delivery.Extensions.Autofac.DependencyInjection.Extensions
Expand Down Expand Up @@ -104,5 +107,21 @@ private static IServiceCollection RegisterOptions(this IServiceCollection servic
{
return services.Configure<DeliveryOptions>(name, (o) => o.Configure(options));
}

private static IServiceCollection RegisterDependencies(this IServiceCollection services, CacheTypeEnum cacheType, string name)
{
switch (cacheType)
{
case CacheTypeEnum.Memory:
services.TryAddSingleton<IMemoryCache, MemoryCache>();
break;

case CacheTypeEnum.Distributed:
services.TryAddSingleton<IDistributedCache, MemoryDistributedCache>();
break;
}

return services;
}
}
}

0 comments on commit 761959f

Please sign in to comment.