Skip to content

Commit 15f6058

Browse files
authored
Blazor9 hybridcache (#46)
* Update packages * Proxy with hybrid cache * Seems to work with hybrid cache Webapp * Readme update for hybrid cache
1 parent 293c399 commit 15f6058

File tree

15 files changed

+62
-77
lines changed

15 files changed

+62
-77
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ LAST PR implemented:
77

88
Next steps or in progress:
99

10+
~~- Hybrid cache for users and tokens (done)~~
1011
- Vat-sales tax module implementation
1112
- .Net 9 (Blazor adaptations)
1213
- SingalR hub to trace tx status

src/Ubik.Accounting.SalesOrVatTax.Api/Ubik.Accounting.SalesOrVatTax.Api.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.21.0" />
2222
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.1" />
2323
<PackageReference Include="Swashbuckle.AspNetCore" Version="7.1.0" />
24-
<PackageReference Include="MassTransit.EntityFrameworkCore" Version="8.3.2" />
25-
<PackageReference Include="MassTransit.RabbitMQ" Version="8.3.2" />
24+
<PackageReference Include="MassTransit.EntityFrameworkCore" Version="8.3.3" />
25+
<PackageReference Include="MassTransit.RabbitMQ" Version="8.3.3" />
2626
</ItemGroup>
2727

2828
<ItemGroup>

src/Ubik.Accounting.Structure.Api/Ubik.Accounting.Structure.Api.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@
2424
<PackageReference Include="Dapper" Version="2.1.35" />
2525
<PackageReference Include="EFCore.NamingConventions" Version="9.0.0" />
2626
<PackageReference Include="LanguageExt.Core" Version="4.4.9" />
27-
<PackageReference Include="MassTransit.EntityFrameworkCore" Version="8.3.2" />
28-
<PackageReference Include="MassTransit.RabbitMQ" Version="8.3.2" />
27+
<PackageReference Include="MassTransit.EntityFrameworkCore" Version="8.3.3" />
28+
<PackageReference Include="MassTransit.RabbitMQ" Version="8.3.3" />
2929
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.0" />
3030
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.0" />
3131
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.0" />

src/Ubik.Accounting.WebApp/Program.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@
4242
{
4343
options.Configuration = redisOptions.ConnectionString;
4444
});
45+
#pragma warning disable EXTEXP0018 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
46+
builder.Services.AddHybridCache();
47+
#pragma warning restore EXTEXP0018 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
4548

4649
//TODO: put that in a lib project Auth
4750
//TODO: this is very dependant to distributed cache (if no cache => no site, see if it's bad)

src/Ubik.Accounting.WebApp/Security/TokenCacheService.cs

Lines changed: 21 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,47 @@
11
using IdentityModel.Client;
22
using Microsoft.Extensions.Caching.Distributed;
3+
using Microsoft.Extensions.Caching.Hybrid;
34
using Microsoft.Extensions.Options;
45
using System.IdentityModel.Tokens.Jwt;
56
using System.Text.Json;
67
using System.Text.Json.Serialization;
8+
using Ubik.Accounting.WebApp.Shared.Security;
79
using Ubik.ApiService.Common.Configure.Options;
810
using Ubik.Security.Contracts.Users.Results;
911

1012
namespace Ubik.Accounting.WebApp.Security
1113
{
12-
public class TokenCacheService(IDistributedCache cache, IOptions<AuthServerOptions> authOptions, IHttpClientFactory factory)
14+
public class TokenCacheService(HybridCache cache, IOptions<AuthServerOptions> authOptions, IHttpClientFactory factory)
1315
{
14-
private readonly IDistributedCache _cache = cache;
1516
private readonly AuthServerOptions _authOptions = authOptions.Value;
1617
private readonly HttpClient _httpClient = factory.CreateClient("TokenClient");
1718

18-
private static readonly JsonSerializerOptions _serializerOptions = new()
19-
{
20-
PropertyNamingPolicy = null,
21-
WriteIndented = true,
22-
AllowTrailingCommas = true,
23-
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
24-
};
25-
2619
public async Task RemoveUserTokenAsync(string key)
2720
{
28-
await _cache.RemoveAsync($"webapp_{key}");
21+
await cache.RemoveAsync($"webapp_{key}");
2922
}
3023

3124
public async Task SetUserTokenAsync(TokenCacheEntry token)
3225
{
33-
var toCache = JsonSerializer.SerializeToUtf8Bytes(token, options: _serializerOptions);
34-
35-
await _cache.SetAsync($"webapp_{token.UserId}", toCache,
36-
new DistributedCacheEntryOptions { SlidingExpiration = TimeSpan.FromMinutes(120) });
26+
await cache.SetAsync($"webapp_{token.UserId}", token, new HybridCacheEntryOptions()
27+
{
28+
Expiration = TimeSpan.FromMinutes(120),
29+
LocalCacheExpiration = TimeSpan.FromSeconds(10)
30+
});
3731
}
3832

3933
public async Task<TokenCacheEntry?> GetUserTokenAsync(string? userId)
4034
{
4135
if (userId == null) return null;
4236

43-
var token = await _cache.GetAsync($"webapp_{userId}");
37+
var token = await cache.GetOrCreateAsync<TokenCacheEntry?>($"webapp_{userId}", factory: null!,
38+
new HybridCacheEntryOptions() { Flags = HybridCacheEntryFlags.DisableUnderlyingData });
4439

4540
if (token == null) return null;
4641

47-
var cachedResult = JsonSerializer.Deserialize<TokenCacheEntry>(token, _serializerOptions);
48-
49-
if (cachedResult == null) return null;
42+
token = await RefreshTokenAsync(token, userId);
5043

51-
cachedResult = await RefreshTokenAsync(cachedResult, userId);
52-
53-
return cachedResult;
44+
return token;
5445
}
5546

5647
private async Task<TokenCacheEntry?> RefreshTokenAsync(TokenCacheEntry actualToken, string userId)
@@ -109,22 +100,22 @@ private Dictionary<string, string> ValuesForRefresh(string token)
109100
}
110101
public async Task SetUserInfoAsync(UserAdminOrMeResult userInfo)
111102
{
112-
var toCache = JsonSerializer.SerializeToUtf8Bytes(userInfo, options: _serializerOptions);
103+
await cache.SetAsync($"webapp_{userInfo.Email}_auth", userInfo, new HybridCacheEntryOptions()
104+
{
105+
Expiration = TimeSpan.FromMinutes(_authOptions.CookieRefreshTimeInMinutes + 120),
106+
LocalCacheExpiration = TimeSpan.FromSeconds(15)
107+
});
113108

114-
await _cache.SetAsync($"webapp_{userInfo.Email}_auth", toCache, new DistributedCacheEntryOptions { SlidingExpiration = TimeSpan.FromMinutes(_authOptions.CookieRefreshTimeInMinutes + 120) });
115109
}
116110

117111
public async Task<UserAdminOrMeResult?> GetUserInfoAsync(string? userEmail)
118112
{
119113
if (userEmail == null) return null;
120114

121-
var user = await _cache.GetAsync($"webapp_{userEmail}_auth");
122-
123-
if (user == null) return null;
124-
125-
var cachedResult = JsonSerializer.Deserialize<UserAdminOrMeResult>(user, _serializerOptions);
115+
var user = await cache.GetOrCreateAsync<UserAdminOrMeResult?>($"webapp_{userEmail}_auth", factory: null!,
116+
new HybridCacheEntryOptions() { Flags = HybridCacheEntryFlags.DisableUnderlyingData });
126117

127-
return cachedResult;
118+
return user ?? null;
128119
}
129120
}
130121

src/Ubik.Accounting.WebApp/Styles/app.output.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@
107107
}
108108

109109
/*
110-
! tailwindcss v3.4.15 | MIT License | https://tailwindcss.com
110+
! tailwindcss v3.4.16 | MIT License | https://tailwindcss.com
111111
*/
112112

113113
/*

src/Ubik.Accounting.WebApp/Ubik.Accounting.WebApp.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
<PrivateAssets>all</PrivateAssets>
3030
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
3131
</PackageReference>
32+
<PackageReference Include="Microsoft.Extensions.Caching.Hybrid" Version="9.0.0-preview.9.24556.5" />
3233
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="9.0.0" />
3334
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.0" />
3435
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.21.0" />

src/Ubik.Accounting.WebApp/package-lock.json

Lines changed: 12 additions & 22 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Ubik.Accounting.WebApp/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"dependencies": {
66
"autoprefixer": "^10.4.16",
77
"postcss": "^8.4.31",
8-
"tailwindcss": "^3.4.15"
8+
"tailwindcss": "^3.4.16"
99
},
1010
"devDependencies": {
1111
"@tailwindcss/forms": "^0.5.7",

src/Ubik.ApiService.Common/Ubik.ApiService.Common.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
<ItemGroup>
1010
<PackageReference Include="Asp.Versioning.Mvc" Version="8.1.0" />
1111
<PackageReference Include="Asp.Versioning.Mvc.ApiExplorer" Version="8.1.0" />
12-
<PackageReference Include="MassTransit.EntityFrameworkCore" Version="8.3.2" />
13-
<PackageReference Include="MassTransit.RabbitMQ" Version="8.3.2" />
12+
<PackageReference Include="MassTransit.EntityFrameworkCore" Version="8.3.3" />
13+
<PackageReference Include="MassTransit.RabbitMQ" Version="8.3.3" />
1414
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.0" />
1515
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="9.0.0" />
1616
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.0" />

0 commit comments

Comments
 (0)