Add Login Module
This commit is contained in:
@@ -18,7 +18,6 @@ public sealed class EFUnitOfWork : IUnitOfWork, IAsyncDisposable
|
||||
private readonly ITenantDbContextFactory _factory;
|
||||
private readonly IConnectionMultiplexer? _redis;
|
||||
|
||||
private AppDbContext? _db;
|
||||
private IDbContextTransaction? _tx;
|
||||
private ITenantContext? _tenant;
|
||||
|
||||
@@ -31,40 +30,38 @@ public sealed class EFUnitOfWork : IUnitOfWork, IAsyncDisposable
|
||||
{
|
||||
_scope = scope;
|
||||
_factory = factory;
|
||||
_redis = redis; // optional; null ได้
|
||||
_redis = redis;
|
||||
}
|
||||
|
||||
public async Task BeginAsync(ITenantContext tenant, IsolationLevel isolation = IsolationLevel.ReadCommitted, CancellationToken ct = default)
|
||||
{
|
||||
if (_db is not null) return;
|
||||
if (_tx is not null) return;
|
||||
_tenant = tenant ?? throw new ArgumentNullException(nameof(tenant));
|
||||
|
||||
_scope.EnsureForTenant(tenant);
|
||||
_db = _scope.Get<AppDbContext>();
|
||||
_tx = await _db.Database.BeginTransactionAsync(isolation, ct);
|
||||
var db = _scope.Get<AppDbContext>();
|
||||
_tx = await db.Database.BeginTransactionAsync(isolation, ct);
|
||||
}
|
||||
|
||||
public async Task CommitAsync(CancellationToken ct = default)
|
||||
{
|
||||
if (_db is null) return; // ยังไม่ Begin
|
||||
if (_tx is null) return;
|
||||
|
||||
// track entities ที่เปลี่ยน (เพื่อ invalidate cache แบบแม่นขึ้น)
|
||||
var changedUsers = _db.ChangeTracker.Entries<User>()
|
||||
var db = _scope.Get<AppDbContext>();
|
||||
|
||||
var changedUsers = db.ChangeTracker.Entries<User>()
|
||||
.Where(e => e.State is EntityState.Added or EntityState.Modified or EntityState.Deleted)
|
||||
.Select(e => e.Entity)
|
||||
.ToList();
|
||||
|
||||
var changedIdentities = _db.ChangeTracker.Entries<UserIdentity>()
|
||||
var changedIdentities = db.ChangeTracker.Entries<UserIdentity>()
|
||||
.Where(e => e.State is EntityState.Added or EntityState.Modified or EntityState.Deleted)
|
||||
.Select(e => e.Entity)
|
||||
.ToList();
|
||||
|
||||
await _db.SaveChangesAsync(ct);
|
||||
await db.SaveChangesAsync(ct);
|
||||
await _tx.CommitAsync(ct);
|
||||
|
||||
if (_tx is not null)
|
||||
await _tx.CommitAsync(ct);
|
||||
|
||||
// optional: invalidate/refresh Redis (ล่มก็ไม่พัง UoW)
|
||||
if (_redis is not null && _tenant is not null && (changedUsers.Count > 0 || changedIdentities.Count > 0))
|
||||
{
|
||||
var r = _redis.GetDatabase();
|
||||
@@ -75,8 +72,6 @@ public sealed class EFUnitOfWork : IUnitOfWork, IAsyncDisposable
|
||||
{
|
||||
var keyId = $"eop:{tenantId}:user:id:{u.Id:N}";
|
||||
tasks.Add(r.KeyDeleteAsync(keyId));
|
||||
|
||||
// refresh cache (ถ้าต้องการ)
|
||||
var payload = JsonSerializer.Serialize(u);
|
||||
var ttl = TimeSpan.FromMinutes(5);
|
||||
tasks.Add(r.StringSetAsync(keyId, payload, ttl));
|
||||
@@ -88,7 +83,7 @@ public sealed class EFUnitOfWork : IUnitOfWork, IAsyncDisposable
|
||||
tasks.Add(r.KeyDeleteAsync(k));
|
||||
}
|
||||
|
||||
try { await Task.WhenAll(tasks); } catch { /* swallow */ }
|
||||
try { await Task.WhenAll(tasks); } catch { }
|
||||
}
|
||||
|
||||
await DisposeAsync();
|
||||
@@ -109,11 +104,9 @@ public sealed class EFUnitOfWork : IUnitOfWork, IAsyncDisposable
|
||||
|
||||
public ValueTask DisposeAsync()
|
||||
{
|
||||
try { _tx?.Dispose(); } catch { /* ignore */ }
|
||||
try { _db?.Dispose(); } catch { /* ignore */ }
|
||||
|
||||
_tx = null; _db = null; _tenant = null;
|
||||
|
||||
try { _tx?.Dispose(); } catch { }
|
||||
_tx = null;
|
||||
_tenant = null;
|
||||
return ValueTask.CompletedTask;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user