Skip to content

Commit

Permalink
Refactor cache provider and remove AutoMapper dependency (fluentcms#2138
Browse files Browse the repository at this point in the history
)

* Refactor cache provider and remove AutoMapper dependency

Added XML documentation to `ICacheProvider` for better clarity.
Removed `AutoMapper` package reference from the project file.
Refactored `InMemoryCacheProvider` to eliminate `AutoMapper` usage.
Updated `TryGetValue` method to use `string` keys consistently.
Simplified `InMemoryCacheProvider` to handle cached values directly.

* Make repository methods virtual for easier overriding

Updated EntityRepository methods (Create, CreateMany, Delete,
DeleteMany, GetAll, GetByIds) and SiteAssociatedRepository's
GetAllForSite to be virtual. Modified GetAllForSite to call
GetAll directly.
  • Loading branch information
pournasserian authored Oct 12, 2024
1 parent 6e72d68 commit 9df88e7
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,35 @@ public abstract class EntityRepository<TEntity>(IEntityRepository<TEntity> entit
{
private static string GetAllCacheKey => $"{typeof(TEntity).Name}_GetAll";

public async Task<TEntity?> Create(TEntity entity, CancellationToken cancellationToken = default)
public virtual async Task<TEntity?> Create(TEntity entity, CancellationToken cancellationToken = default)
{
var newEntity = await entityRepository.Create(entity, cancellationToken);
InvalidateCache();
return newEntity;
}

public async Task<IEnumerable<TEntity>> CreateMany(IEnumerable<TEntity> entities, CancellationToken cancellationToken = default)
public virtual async Task<IEnumerable<TEntity>> CreateMany(IEnumerable<TEntity> entities, CancellationToken cancellationToken = default)
{
var newEntities = await entityRepository.CreateMany(entities, cancellationToken);
InvalidateCache();
return newEntities ?? [];
}

public async Task<TEntity?> Delete(Guid id, CancellationToken cancellationToken = default)
public virtual async Task<TEntity?> Delete(Guid id, CancellationToken cancellationToken = default)
{
var deleted = await entityRepository.Delete(id, cancellationToken);
InvalidateCache();
return deleted;
}

public async Task<IEnumerable<TEntity>> DeleteMany(IEnumerable<Guid> ids, CancellationToken cancellationToken = default)
public virtual async Task<IEnumerable<TEntity>> DeleteMany(IEnumerable<Guid> ids, CancellationToken cancellationToken = default)
{
var deleted = await entityRepository.DeleteMany(ids, cancellationToken);
InvalidateCache();
return deleted;
}

public async Task<IEnumerable<TEntity>> GetAll(CancellationToken cancellationToken = default)
public virtual async Task<IEnumerable<TEntity>> GetAll(CancellationToken cancellationToken = default)
{
var entitiesDict = await GetCachedDictionary(cancellationToken);
return entitiesDict.Values;
Expand All @@ -51,7 +51,7 @@ public async Task<IEnumerable<TEntity>> GetAll(CancellationToken cancellationTok
return default;
}

public async Task<IEnumerable<TEntity>> GetByIds(IEnumerable<Guid> ids, CancellationToken cancellationToken = default)
public virtual async Task<IEnumerable<TEntity>> GetByIds(IEnumerable<Guid> ids, CancellationToken cancellationToken = default)
{
// access to cached dictionary
var entitiesDict = await GetCachedDictionary(cancellationToken);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

public abstract class SiteAssociatedRepository<TEntity>(ISiteAssociatedRepository<TEntity> siteAssociatedRepository, ICacheProvider cacheProvider) : AuditableEntityRepository<TEntity>(siteAssociatedRepository, cacheProvider), ISiteAssociatedRepository<TEntity> where TEntity : ISiteAssociatedEntity
{
public async Task<IEnumerable<TEntity>> GetAllForSite(Guid siteId, CancellationToken cancellationToken = default)
public virtual async Task<IEnumerable<TEntity>> GetAllForSite(Guid siteId, CancellationToken cancellationToken = default)
{
var entities = await siteAssociatedRepository.GetAll(cancellationToken);
var entities = await GetAll(cancellationToken);
return entities.Where(e => e.SiteId == siteId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public abstract class SiteAssociatedRepository<TEntity>(ILiteDBContext liteDbCon
return await base.Update(entity, cancellationToken);
}

public async Task<IEnumerable<TEntity>> GetAllForSite(Guid siteId, CancellationToken cancellationToken = default)
public virtual async Task<IEnumerable<TEntity>> GetAllForSite(Guid siteId, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
return await Collection.Query().Where(x => x.SiteId == siteId).ToListAsync();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,34 @@
namespace FluentCMS.Providers.CacheProviders;

/// <summary>
/// Interface for a cache provider that supports adding, retrieving, and removing cached items.
/// </summary>
public interface ICacheProvider
{
/// <summary>
/// Removes a specific item from the cache by its key.
/// </summary>
/// <param name="key">The unique string identifier for the cache entry.</param>
void Remove(string key);

/// <summary>
/// Adds or updates an item in the cache.
/// </summary>
/// <typeparam name="T">The type of the value to cache.</typeparam>
/// <param name="key">The unique string identifier for the cache entry.</param>
/// <param name="value">The value to cache, of type <typeparamref name="T"/>.</param>
void Set<T>(string key, T value);
bool TryGetValue<T>(object key, out T? value);

/// <summary>
/// Attempts to retrieve a cached item by its key.
/// </summary>
/// <typeparam name="T">The type of the cached item.</typeparam>
/// <param name="key">The unique string identifier for the cache entry.</param>
/// <param name="value">
/// When this method returns, contains the cached item of type <typeparamref name="T"/> if found; otherwise, the default value for the type of the <paramref name="value"/> parameter.
/// </param>
/// <returns>
/// <c>true</c> if the cache contains an item with the specified key; otherwise, <c>false</c>.
/// </returns>
bool TryGetValue<T>(string key, out T? value);
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="AutoMapper" Version="13.0.1" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="8.0.0" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,38 +1,37 @@
using AutoMapper;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Caching.Memory;

namespace FluentCMS.Providers.CacheProviders;

public class InMemoryCacheProvider(IMemoryCache memoryCache, IMapper mapper) : ICacheProvider
public class InMemoryCacheProvider(IMemoryCache memoryCache) : ICacheProvider
{
// Remove an item from the cache by key
public void Remove(string key)
{
memoryCache.Remove(key);
}

public void Set<T>(string key, T value)
{
var cachedValue = mapper.Map<T>(value);
memoryCache.Set(key, cachedValue);
memoryCache.Set(key, value);
}

public bool TryGetValue<T>(object key, out T? value)
public bool TryGetValue<T>(string key, out T? value)
{
if (memoryCache.TryGetValue(key, out object? result))
// Try to get the cached item by key
if (memoryCache.TryGetValue(key, out T? result))
{
if (result == null)
// If the cached value is explicitly null
if (result is null)
{
value = default;
return true;
value = default; // Return default value for type T
return true; // Indicates that a null value was found in cache
}

if (result is T item)
{
value = mapper.Map<T>(item);
return true;
}
value = result; // Return the cached value
return true;
}

// If the item was not found in the cache
value = default;
return false;
}
Expand Down

0 comments on commit 9df88e7

Please sign in to comment.