feat: 实现字典管理后端
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
using Microsoft.Data.Sqlite;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using TakeoutSaaS.Infrastructure.Dictionary.Persistence;
|
||||
|
||||
namespace TakeoutSaaS.Integration.Tests.Fixtures;
|
||||
|
||||
public sealed class DictionarySqliteTestDatabase : IDisposable
|
||||
{
|
||||
private readonly SqliteConnection _connection;
|
||||
private bool _initialized;
|
||||
|
||||
public DictionarySqliteTestDatabase()
|
||||
{
|
||||
_connection = new SqliteConnection("Filename=:memory:");
|
||||
_connection.Open();
|
||||
Options = new DbContextOptionsBuilder<DictionaryDbContext>()
|
||||
.UseSqlite(_connection)
|
||||
.EnableSensitiveDataLogging()
|
||||
.Options;
|
||||
}
|
||||
|
||||
public DbContextOptions<DictionaryDbContext> Options { get; }
|
||||
|
||||
public DictionaryDbContext CreateContext(long tenantId, long userId = 0)
|
||||
{
|
||||
EnsureCreated();
|
||||
return new DictionaryDbContext(
|
||||
Options,
|
||||
new TestTenantProvider(tenantId),
|
||||
userId == 0 ? null : new TestCurrentUserAccessor(userId));
|
||||
}
|
||||
|
||||
public void EnsureCreated()
|
||||
{
|
||||
if (_initialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using var context = new DictionaryDbContext(Options, new TestTenantProvider(1));
|
||||
context.Database.EnsureCreated();
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_connection.Dispose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using System.Collections.Concurrent;
|
||||
using TakeoutSaaS.Application.Dictionary.Abstractions;
|
||||
using TakeoutSaaS.Domain.Dictionary.Enums;
|
||||
|
||||
namespace TakeoutSaaS.Integration.Tests.Fixtures;
|
||||
|
||||
public sealed class TestDictionaryHybridCache : IDictionaryHybridCache
|
||||
{
|
||||
private readonly ConcurrentDictionary<string, object> _cache = new(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
public async Task<T?> GetOrCreateAsync<T>(
|
||||
string key,
|
||||
TimeSpan ttl,
|
||||
Func<CancellationToken, Task<T?>> factory,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (_cache.TryGetValue(key, out var cached) && cached is T typed)
|
||||
{
|
||||
return typed;
|
||||
}
|
||||
|
||||
var value = await factory(cancellationToken);
|
||||
if (value is not null)
|
||||
{
|
||||
_cache[key] = value;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public Task InvalidateAsync(
|
||||
string prefix,
|
||||
CacheInvalidationOperation operation = CacheInvalidationOperation.Update,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
foreach (var key in _cache.Keys)
|
||||
{
|
||||
if (key.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
_cache.TryRemove(key, out _);
|
||||
}
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user