Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ public virtual IServiceCollection RegisterServices(IServiceCollection services)
{
return new VmrInfo(string.Empty, string.Empty);
});
services.TryAddSingleton<IRedisCacheClient, NoOpRedisClient>();
services.TryAddSingleton<IDistributedCacheClient, NoOpCacheClient>();

return services;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,22 @@
#nullable enable
namespace Microsoft.DotNet.DarcLib;

public interface IRedisCacheClient
/// <summary>
/// Generic interface for caching POCOs. Implementations should create keys based on the provided key and
/// object type to avoid collisions.
/// </summary>
public interface IDistributedCacheClient
{
Task<bool> TrySetAsync<T>(string key, T value, TimeSpan? expiration = null) where T : class;
Task<T?> TryGetAsync<T>(string key) where T : class;
Task<bool> DeleteAsync(string key);
}

// This no-op redis client is used when DarcLib is invoked through CLI operations where redis is not available.
public class NoOpRedisClient : IRedisCacheClient
/// <summary>
/// This no-op cache client the default implementation of IDistributedCacheClient in DarcLib. Caching is not mandatory
/// and requires explicit implemnetation if used.
/// </summary>
public class NoOpCacheClient : IDistributedCacheClient
{
public Task<bool> TrySetAsync<T>(string key, T value, TimeSpan? expiration = null) where T : class
{
Expand Down
8 changes: 5 additions & 3 deletions src/Microsoft.DotNet.Darc/DarcLib/Remote.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public sealed class Remote : IRemote
private readonly ISourceMappingParser _sourceMappingParser;
private readonly IRemoteFactory _remoteFactory;
private readonly IAssetLocationResolver _locationResolver;
private readonly IRedisCacheClient _cache;
private readonly IDistributedCacheClient _cache;
private readonly ILogger _logger;

//[DependencyUpdate]: <> (Begin)
Expand All @@ -43,7 +43,7 @@ public Remote(
ISourceMappingParser sourceMappingParser,
IRemoteFactory remoteFactory,
IAssetLocationResolver locationResolver,
IRedisCacheClient cacheClient,
IDistributedCacheClient cacheClient,
ILogger logger)
{
_logger = logger;
Expand All @@ -53,7 +53,9 @@ public Remote(
_remoteFactory = remoteFactory;
_locationResolver = locationResolver;
_fileManager = new DependencyFileManager(remoteGitClient, _versionDetailsParser, _logger);
_cache = cacheClient;
_cache = cacheClient ?? throw new ArgumentNullException(
nameof(cacheClient),
"The cache client must not be null. Please use the no-op implementation of IDistributedCacheClient provided in this package.");
}

public async Task CreateNewBranchAsync(string repoUri, string baseBranch, string newBranch)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public static async Task AddRedisCache(

builder.Services.AddSingleton(redisConfig);
builder.Services.AddSingleton<IRedisCacheFactory, RedisCacheFactory>();
builder.Services.AddSingleton<IRedisCacheClient, RedisCacheClient>();
builder.Services.AddSingleton<IDistributedCacheClient, RedisCacheClient>();
}

public static void AddMetricRecorder(this IHostApplicationBuilder builder)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@
namespace ProductConstructionService.Common;

/// <summary>
/// This class acts as a delegate for RedisCache and RedisCacheFactory.
/// It is needed because DarcLib does not depend on ProductConstructionService and can only access caching through a delegate.
/// This class acts as a delegate for RedisCache and RedisCacheFactory. It is needed because DarcLib
/// does not depend on ProductConstructionService and can only implement caching there through a delegate.
/// </summary>
internal class RedisCacheClient : IRedisCacheClient
internal class RedisCacheClient : IDistributedCacheClient
Copy link
Member

@premun premun Jul 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@adamzip I was asking in Teams but probably you missed that one - why does it need to be Distributed? It can very well be just memory cache, no? Isn't it misleading? It just needs to be a cache?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be persistent if possible but I suppose technically it can be a memory cache, yes. So do you propose just ICacheClient?

{
private static readonly TimeSpan DefaultExpiration = TimeSpan.FromDays(15);
private readonly IRedisCacheFactory _factory;
private readonly ILogger<RedisCacheClient> _logger;

Expand All @@ -26,11 +27,11 @@ public RedisCacheClient(IRedisCacheFactory factory, ILogger<RedisCacheClient> lo
return await _factory.Create<T>(key).TryGetStateAsync();
}

public async Task<bool> TrySetAsync<T>(string key, T value, TimeSpan? expiration = null) where T : class
public async Task<bool> TrySetAsync<T>(string key, T value, TimeSpan? expiration) where T : class
{
try
{
await _factory.Create<T>(key).SetAsync(value, expiration);
await _factory.Create<T>(key).SetAsync(value, expiration ?? DefaultExpiration);
}
catch (Exception ex)
{
Expand Down
2 changes: 1 addition & 1 deletion test/Microsoft.DotNet.DarcLib.Tests/RemoteTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ See [Dependency Description Format](https://github.com/dotnet/arcade/blob/main/D
sourceMappingParser.Object,
Mock.Of<IRemoteFactory>(),
new AssetLocationResolver(barClient.Object),
new NoOpRedisClient(),
new NoOpCacheClient(),
logger);

await remote.MergeDependencyPullRequestAsync("https://github.com/test/test2", mergePullRequest);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ where subscription.Id.Equals(subscriptionToFind)
SourceMappingParser.Object,
RemoteFactory.Object,
new AssetLocationResolver(BarClient.Object),
new NoOpRedisClient(),
new NoOpCacheClient(),
NullLogger.Instance);
RemoteFactory.Setup(m => m.CreateRemoteAsync(It.IsAny<string>())).ReturnsAsync(MockRemote);

Expand Down