Skip to content

Commit 00d97a2

Browse files
committed
fix(caching): correct cache expiry time for preset configurations
Cache presets were not respecting their configured DefaultExpiry values due to hardcoded 5-minute fallback in GetExpiry function. The issue affected AddMediumTermCache (expected 10min, got 5min) and other presets. Changes: - Update CopyPresetToOptions to create new GetExpiry function that properly references the configured DefaultExpiry instead of hardcoded value - Add integration tests to verify preset expiry times are correctly applied - Ensure Cache-Control headers still take precedence over default values Fixes cache preset behavior where AddMediumTermCache, AddShortTermCache, and other preset methods now correctly use their documented expiry times.
1 parent 21c9e16 commit 00d97a2

File tree

6 files changed

+148
-32
lines changed

6 files changed

+148
-32
lines changed

src/Reliable.HttpClient.Caching/Abstractions/HttpCacheOptions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public class HttpCacheOptions
7373
return TimeSpan.Zero;
7474
}
7575

76-
// Fall back to default
76+
// This will be overridden to use the correct DefaultExpiry by CopyPresetToOptions
7777
return TimeSpan.FromMinutes(5);
7878
};
7979
}

src/Reliable.HttpClient.Caching/Extensions/HttpClientBuilderExtensions.cs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,26 @@ private static void CopyPresetToOptions(HttpCacheOptions preset, HttpCacheOption
100100
options.CacheableStatusCodes = [.. preset.CacheableStatusCodes];
101101
options.CacheableMethods = [.. preset.CacheableMethods];
102102
options.ShouldCache = preset.ShouldCache;
103-
options.GetExpiry = preset.GetExpiry;
103+
104+
// Create a new GetExpiry function that uses the correct DefaultExpiry
105+
options.GetExpiry = (request, response) =>
106+
{
107+
// Check Cache-Control max-age directive
108+
if (response.Headers.CacheControl?.MaxAge is not null)
109+
{
110+
return response.Headers.CacheControl.MaxAge.Value;
111+
}
112+
113+
// Check Cache-Control no-cache or no-store directives
114+
if (response.Headers.CacheControl is not null)
115+
{
116+
if (response.Headers.CacheControl.NoCache || response.Headers.CacheControl.NoStore)
117+
return TimeSpan.Zero;
118+
}
119+
120+
// Fall back to the configured default expiry
121+
return options.DefaultExpiry;
122+
};
104123
}
105124

106125
/// <summary>

src/Reliable.HttpClient.Caching/Reliable.HttpClient.Caching.csproj

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,17 @@
33
<TargetFrameworks>net6.0;net8.0;net9.0</TargetFrameworks>
44
<AssemblyName>Reliable.HttpClient.Caching</AssemblyName>
55
<PackageId>Reliable.HttpClient.Caching</PackageId>
6-
<Version>1.0.0</Version>
7-
<PackageReleaseNotes>🎉 Stable v1.0.0 Release!
6+
<Version>1.0.1</Version>
7+
<PackageReleaseNotes>🐛 Bug Fix Release v1.0.1
88

9-
✨ New Preset-Based Configuration:
10-
6 cache presets for common scenarios (ShortTerm, MediumTerm, LongTerm, HighPerformance,
11-
Configuration, FileDownload)
12-
One-line setup methods: AddShortTermCache, AddMediumTermCache, AddLongTermCache, etc.
13-
• Combined resilience+caching methods: AddResilienceWithCaching,
14-
AddResilienceWithMediumTermCache, etc.
9+
Fixed cache preset expiry times not being respected:
10+
AddMediumTermCache now correctly uses 10 minutes (was using 5 minutes)
11+
• AddShortTermCache, AddLongTermCache, and other presets now use their documented expiry times
12+
GetExpiry function now properly references configured DefaultExpiry instead of hardcoded
13+
fallback
14+
• Cache-Control headers still take precedence over preset values
1515

16-
🚀 Zero-Configuration Setup:
17-
• Automatic IMemoryCache registration - no manual setup required
18-
• Smart defaults covering 95% of use cases
19-
• Reduced configuration complexity from ~10 lines to 1 line
20-
21-
🔧 Advanced Features:
22-
• Memory cache and custom cache providers support
23-
• Smart cache key generation with SHA256 hashing
24-
• HTTP Cache-Control headers support
25-
• Cache invalidation and management APIs
26-
• Full .NET 6.0, 8.0, 9.0 support
16+
Breaking: None - this is a bug fix that corrects behavior to match documentation
2717
</PackageReleaseNotes>
2818
<Authors>Andrey Krisanov</Authors>
2919
<Company></Company>
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
using Microsoft.Extensions.DependencyInjection;
2+
using Microsoft.Extensions.Options;
3+
using Reliable.HttpClient.Caching.Abstractions;
4+
using Reliable.HttpClient.Caching.Extensions;
5+
using Xunit;
6+
7+
namespace Reliable.HttpClient.Caching.Tests;
8+
9+
public class CachePresetsIntegrationTests
10+
{
11+
[Fact]
12+
public void AddMediumTermCache_ShouldUseTenMinutesExpiry()
13+
{
14+
// Arrange
15+
var services = new ServiceCollection();
16+
services.AddMemoryCache();
17+
18+
// Act
19+
services.AddHttpClient<TestClient>()
20+
.AddMediumTermCache<string>();
21+
22+
ServiceProvider serviceProvider = services.BuildServiceProvider();
23+
24+
// Get the configured options for the named client
25+
IOptionsSnapshot<HttpCacheOptions> optionsSnapshot = serviceProvider.GetRequiredService<IOptionsSnapshot<HttpCacheOptions>>();
26+
HttpCacheOptions options = optionsSnapshot.Get("TestClient");
27+
28+
// Assert
29+
Assert.Equal(TimeSpan.FromMinutes(10), options.DefaultExpiry);
30+
31+
// Test GetExpiry function with a mock response
32+
var request = new HttpRequestMessage(HttpMethod.Get, "https://test.com");
33+
var response = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
34+
35+
TimeSpan expiry = options.GetExpiry(request, response);
36+
Assert.Equal(TimeSpan.FromMinutes(10), expiry);
37+
}
38+
39+
[Fact]
40+
public void AddShortTermCache_ShouldUseOneMinuteExpiry()
41+
{
42+
// Arrange
43+
var services = new ServiceCollection();
44+
services.AddMemoryCache();
45+
46+
// Act
47+
services.AddHttpClient<TestClient>()
48+
.AddShortTermCache<string>();
49+
50+
ServiceProvider serviceProvider = services.BuildServiceProvider();
51+
52+
// Get the configured options for the named client
53+
IOptionsSnapshot<HttpCacheOptions> optionsSnapshot = serviceProvider.GetRequiredService<IOptionsSnapshot<HttpCacheOptions>>();
54+
HttpCacheOptions options = optionsSnapshot.Get("TestClient");
55+
56+
// Assert
57+
Assert.Equal(TimeSpan.FromMinutes(1), options.DefaultExpiry);
58+
59+
// Test GetExpiry function with a mock response
60+
var request = new HttpRequestMessage(HttpMethod.Get, "https://test.com");
61+
var response = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
62+
63+
TimeSpan expiry = options.GetExpiry(request, response);
64+
Assert.Equal(TimeSpan.FromMinutes(1), expiry);
65+
}
66+
67+
[Fact]
68+
public void AddHighPerformanceCache_ShouldUseFiveMinutesExpiry()
69+
{
70+
// Arrange
71+
var services = new ServiceCollection();
72+
services.AddMemoryCache();
73+
74+
// Act
75+
services.AddHttpClient<TestClient>()
76+
.AddHighPerformanceCache<string>();
77+
78+
ServiceProvider serviceProvider = services.BuildServiceProvider();
79+
80+
// Get the configured options for the named client
81+
IOptionsSnapshot<HttpCacheOptions> optionsSnapshot = serviceProvider.GetRequiredService<IOptionsSnapshot<HttpCacheOptions>>();
82+
HttpCacheOptions options = optionsSnapshot.Get("TestClient");
83+
84+
// Assert
85+
Assert.Equal(TimeSpan.FromMinutes(5), options.DefaultExpiry);
86+
87+
// Test GetExpiry function with a mock response
88+
var request = new HttpRequestMessage(HttpMethod.Get, "https://test.com");
89+
var response = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
90+
91+
TimeSpan expiry = options.GetExpiry(request, response);
92+
Assert.Equal(TimeSpan.FromMinutes(5), expiry);
93+
}
94+
95+
private class TestClient
96+
{
97+
}
98+
}

tests/Reliable.HttpClient.Caching.Tests/Reliable.HttpClient.Caching.Tests.csproj

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
<Project Sdk="Microsoft.NET.Sdk">
2-
32
<PropertyGroup>
4-
<TargetFramework>net8.0</TargetFramework>
3+
<TargetFramework>net9.0</TargetFramework>
54
<ImplicitUsings>enable</ImplicitUsings>
65
<Nullable>enable</Nullable>
76
<IsPackable>false</IsPackable>
@@ -30,5 +29,4 @@
3029
<ProjectReference
3130
Include="..\..\src\Reliable.HttpClient.Caching\Reliable.HttpClient.Caching.csproj" />
3231
</ItemGroup>
33-
3432
</Project>
Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,28 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
3-
<TargetFramework>net8.0</TargetFramework>
3+
<TargetFramework>net9.0</TargetFramework>
4+
<ImplicitUsings>enable</ImplicitUsings>
5+
<Nullable>enable</Nullable>
46
<IsPackable>false</IsPackable>
5-
<AssemblyName>Reliable.HttpClient.Tests</AssemblyName>
7+
<IsTestProject>true</IsTestProject>
68
</PropertyGroup>
79

810
<ItemGroup>
9-
<ProjectReference Include="../../src/Reliable.HttpClient/Reliable.HttpClient.csproj" />
10-
<PackageReference Include="coverlet.collector" Version="6.0.4" />
11-
<PackageReference Include="FluentAssertions" Version="8.6.0" />
12-
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
11+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
12+
<PackageReference Include="xunit" Version="2.9.2" />
13+
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
14+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
15+
<PrivateAssets>all</PrivateAssets>
16+
</PackageReference>
17+
<PackageReference Include="coverlet.collector" Version="6.0.2">
18+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
19+
<PrivateAssets>all</PrivateAssets>
20+
</PackageReference>
21+
<PackageReference Include="FluentAssertions" Version="6.12.1" />
1322
<PackageReference Include="Moq" Version="4.20.72" />
14-
<PackageReference Include="xunit" Version="2.9.3" />
15-
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.4" />
23+
</ItemGroup>
24+
25+
<ItemGroup>
26+
<ProjectReference Include="../../src/Reliable.HttpClient/Reliable.HttpClient.csproj" />
1627
</ItemGroup>
1728
</Project>

0 commit comments

Comments
 (0)