Skip to content

Commit

Permalink
Bugfix/cqrs caching handlers di issues (#140)
Browse files Browse the repository at this point in the history
* Removed ICqrsBuilderExtensions as they were redundant with "CacheDynamicallyCompiledExpressions" extensions, updated the appropriate extensions, and fixed examples.

* Moved caching factory out of the constructors of CommandBus and QueryBus as it will be optional. Added some caching configuration validation.

* Updated version.
  • Loading branch information
jasonmwebb-lv authored Nov 8, 2024
1 parent db6ce60 commit 13855f7
Show file tree
Hide file tree
Showing 10 changed files with 94 additions and 66 deletions.
2 changes: 1 addition & 1 deletion Build/Build.cs
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ protected override void OnBuildInitialized()
{
Log.Information("Generating NuGet packages for projects in solution");
int commitNum = 0;
string NuGetVersionCustom = "2.1.0";
string NuGetVersionCustom = "2.1.1";


//if it's not a tagged release - append the commit number to the package version
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<ItemGroup>
<ProjectReference Include="..\..\..\Src\RCommon.ApplicationServices\RCommon.ApplicationServices.csproj" />
<ProjectReference Include="..\..\..\Src\RCommon.FluentValidation\RCommon.FluentValidation.csproj" />
<ProjectReference Include="..\..\..\Src\RCommon.MemoryCache\RCommon.MemoryCache.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using RCommon.ApplicationServices;
using RCommon.Caching;
using RCommon.FluentValidation;
using RCommon.MemoryCache;
using System.Diagnostics;
using System.Reflection;

Expand All @@ -32,7 +33,6 @@
// Or this way which uses a little magic but is simple
cqrs.AddCommandHandlers((typeof(Program).GetTypeInfo().Assembly));
cqrs.AddQueryHandlers((typeof(Program).GetTypeInfo().Assembly));
cqrs.AddMemoryCachingForHandlers<IMemoryCachingBuilder>();
})
.WithValidation<FluentValidationBuilder>(validation =>
{
Expand All @@ -43,8 +43,17 @@
options.ValidateCommands = true;
options.ValidateQueries = true;
});
})
.WithMemoryCaching<InMemoryCachingBuilder>(cache =>
{
cache.Configure(x =>
{
x.ExpirationScanFrequency = TimeSpan.FromMinutes(1);
});
cache.CacheDynamicallyCompiledExpressions();
});



services.AddTransient<ITestApplicationService, TestApplicationService>();

}).Build();
Expand Down
1 change: 1 addition & 0 deletions Examples/Caching/Examples.Caching.MemoryCaching/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
x.ExpirationScanFrequency = TimeSpan.FromMinutes(1);
});
cache.CacheDynamicallyCompiledExpressions();

})
.WithDistributedCaching<DistributedMemoryCacheBuilder>(cache =>
{
Expand Down
8 changes: 5 additions & 3 deletions Src/RCommon.ApplicationServices/Commands/CommandBus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,16 @@ public class CommandBus : ICommandBus
private readonly IServiceProvider _serviceProvider;
private readonly IValidationService _validationService;
private readonly IOptions<CqrsValidationOptions> _validationOptions;
private readonly ICacheService _cacheService;
private ICacheService _cacheService;
private readonly CachingOptions _cachingOptions;

public CommandBus(ILogger<CommandBus> logger, IServiceProvider serviceProvider, IValidationService validationService,
IOptions<CqrsValidationOptions> validationOptions, IOptions<CachingOptions> cachingOptions, ICommonFactory<ExpressionCachingStrategy, ICacheService> cacheFactory)
IOptions<CqrsValidationOptions> validationOptions, IOptions<CachingOptions> cachingOptions)
{
_logger = logger;
_serviceProvider = serviceProvider;
_validationService = validationService;
_validationOptions = validationOptions;
_cacheService = cacheFactory.Create(ExpressionCachingStrategy.Default);
_cachingOptions = cachingOptions.Value;
}

Expand Down Expand Up @@ -134,6 +133,9 @@ private CommandExecutionDetails GetCommandExecutionDetails(Type commandType)
{
if (_cachingOptions.CachingEnabled && _cachingOptions.CacheDynamicallyCompiledExpressions)
{
var cachingFactory = _serviceProvider.GetService<ICommonFactory<ExpressionCachingStrategy, ICacheService>>();
Guard.Against<InvalidCacheException>(cachingFactory == null, "We could not properly inject the caching factory: 'ICommonFactory<ExpressionCachingStrategy, ICacheService>>' into the CommandBus");
_cacheService = cachingFactory.Create(ExpressionCachingStrategy.Default);
return _cacheService.GetOrCreate(CacheKey.With(GetType(), commandType.GetCacheKey()), () => this.BuildCommandDetails(commandType));
}
return this.BuildCommandDetails(commandType);
Expand Down
42 changes: 0 additions & 42 deletions Src/RCommon.ApplicationServices/ICqrsBuilderExtensions.cs

This file was deleted.

16 changes: 16 additions & 0 deletions Src/RCommon.ApplicationServices/InvalidCacheException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace RCommon.ApplicationServices
{
public class InvalidCacheException : GeneralException
{
public InvalidCacheException(string message):base(message)
{

}
}
}
8 changes: 5 additions & 3 deletions Src/RCommon.ApplicationServices/Queries/QueryBus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,16 @@ private class HandlerFuncMapping
private readonly IValidationService _validationService;
private readonly IOptions<CqrsValidationOptions> _validationOptions;
private readonly CachingOptions _cachingOptions;
private readonly ICacheService _cacheService;
private ICacheService _cacheService;

public QueryBus(ILogger<QueryBus> logger, IServiceProvider serviceProvider, IValidationService validationService,
IOptions<CqrsValidationOptions> validationOptions, IOptions<CachingOptions> cachingOptions, ICommonFactory<ExpressionCachingStrategy, ICacheService> cacheFactory)
IOptions<CqrsValidationOptions> validationOptions, IOptions<CachingOptions> cachingOptions)
{
_logger = logger;
_serviceProvider = serviceProvider;
_validationService = validationService;
_validationOptions = validationOptions;
_cachingOptions = cachingOptions.Value;
_cacheService = cacheFactory.Create(ExpressionCachingStrategy.Default);
}

public async Task<TResult> DispatchQueryAsync<TResult>(IQuery<TResult> query, CancellationToken cancellationToken = default)
Expand Down Expand Up @@ -92,6 +91,9 @@ private HandlerFuncMapping GetHandlerFuncMapping(Type queryType)
{
if (_cachingOptions.CachingEnabled && _cachingOptions.CacheDynamicallyCompiledExpressions)
{
var cachingFactory = _serviceProvider.GetService<ICommonFactory<ExpressionCachingStrategy, ICacheService>>();
Guard.Against<InvalidCacheException>(cachingFactory == null, "We could not properly inject the caching factory: 'ICommonFactory<ExpressionCachingStrategy, ICacheService>>' into the QueryBus");
_cacheService = cachingFactory.Create(ExpressionCachingStrategy.Default);
return _cacheService.GetOrCreate(CacheKey.With(GetType(), queryType.GetCacheKey()),
() => this.BuildHandlerFuncMapping(queryType));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,17 @@ public static IDistributedMemoryCachingBuilder Configure(this IDistributedMemory
/// </summary>
/// <param name="builder">Builder</param>
/// <returns>Same builder to allow chaining</returns>
/// <remarks>The most performant way to do this is through InMemoryCache but this works fine</remarks>
/// <remarks>This is the most performant way to cache expressions!</remarks>
public static IDistributedMemoryCachingBuilder CacheDynamicallyCompiledExpressions(this IDistributedMemoryCachingBuilder builder)
{

// Add Caching services
builder.Services.TryAddTransient<ICacheService, DistributedMemoryCacheService>();
builder.Services.TryAddTransient<DistributedMemoryCacheService>();
builder.Services.TryAddTransient<ICommonFactory<ExpressionCachingStrategy, ICacheService>, CommonFactory<ExpressionCachingStrategy, ICacheService>>();
ConfigureCachingOptions(builder);

// Add Caching Factory
builder.Services.TryAddTransient<Func<ExpressionCachingStrategy, ICacheService>>(serviceProvider => strategy =>
{
switch (strategy)
Expand All @@ -37,14 +45,26 @@ public static IDistributedMemoryCachingBuilder CacheDynamicallyCompiledExpressio
return serviceProvider.GetService<DistributedMemoryCacheService>();
}
});
builder.Services.TryAddTransient<ICommonFactory<ExpressionCachingStrategy, ICacheService>, CommonFactory<ExpressionCachingStrategy, ICacheService>>();

builder.Services.Configure<CachingOptions>(x =>
{
x.CachingEnabled = true;
x.CacheDynamicallyCompiledExpressions = true;
});
return builder;
}

private static void ConfigureCachingOptions(IDistributedMemoryCachingBuilder builder, Action<CachingOptions> configure = null)
{

if (configure == null)
{
builder.Services.Configure<CachingOptions>(x =>
{
x.CachingEnabled = true;
x.CacheDynamicallyCompiledExpressions = true;
});
}
else
{
builder.Services.Configure(configure);
}

}
}
}
35 changes: 27 additions & 8 deletions Src/RCommon.MemoryCache/IInMemoryCachingBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ public static IInMemoryCachingBuilder Configure(this IInMemoryCachingBuilder bui
/// <remarks>This is the most performant way to cache expressions!</remarks>
public static IInMemoryCachingBuilder CacheDynamicallyCompiledExpressions(this IInMemoryCachingBuilder builder)
{

// Add Caching services
builder.Services.TryAddTransient<ICacheService, InMemoryCacheService>();
builder.Services.TryAddTransient<InMemoryCacheService>();
builder.Services.TryAddTransient<ICommonFactory<ExpressionCachingStrategy, ICacheService>, CommonFactory<ExpressionCachingStrategy, ICacheService>>();
ConfigureCachingOptions(builder);

// Add Caching Factory
builder.Services.TryAddTransient<Func<ExpressionCachingStrategy, ICacheService>>(serviceProvider => strategy =>
{
switch (strategy)
Expand All @@ -37,15 +45,26 @@ public static IInMemoryCachingBuilder CacheDynamicallyCompiledExpressions(this I
return serviceProvider.GetService<InMemoryCacheService>();
}
});
builder.Services.TryAddTransient<ICacheService, InMemoryCacheService>();
builder.Services.TryAddTransient<ICommonFactory<ExpressionCachingStrategy, ICacheService>, CommonFactory<ExpressionCachingStrategy, ICacheService>>();

builder.Services.Configure<CachingOptions>(x =>
{
x.CachingEnabled = true;
x.CacheDynamicallyCompiledExpressions = true;
});

return builder;
}

private static void ConfigureCachingOptions(IInMemoryCachingBuilder builder, Action<CachingOptions> configure = null)
{

if (configure == null)
{
builder.Services.Configure<CachingOptions>(x =>
{
x.CachingEnabled = true;
x.CacheDynamicallyCompiledExpressions = true;
});
}
else
{
builder.Services.Configure(configure);
}

}
}
}

0 comments on commit 13855f7

Please sign in to comment.