[WIP] Add debug output of entities

features/nuget_autobuild
Matija Koželj 2 years ago
parent 9381a4e4c6
commit 018a48dd65

@ -10,118 +10,120 @@ using System.Collections.Immutable;
namespace Connected.Entities.Caching;
public abstract class EntityCacheClient<TEntity, TPrimaryKey> : StatefulCacheClient<TEntity, TPrimaryKey>, IEntityCacheClient<TEntity, TPrimaryKey>
where TEntity : class, IPrimaryKey<TPrimaryKey>, IEntity
where TPrimaryKey : notnull
where TEntity : class, IPrimaryKey<TPrimaryKey>, IEntity
where TPrimaryKey : notnull
{
protected EntityCacheClient(IEntityCacheContext context, string key) : base(context.Cache, key)
{
Context = context;
}
private IEntityCacheContext Context { get; }
protected override sealed async Task OnInitializing()
{
using var ctx = Context.ContextProvider.Create();
var transaction = ctx.GetService<ITransactionContext?>();
try
{
if (await OnInitializing(ctx) is ImmutableList<TEntity> ds)
{
foreach (var r in ds)
Set(r.Id, r, TimeSpan.Zero);
}
if (transaction is not null)
await transaction.Commit();
}
catch
{
if (transaction is not null)
await transaction.Rollback();
throw;
}
}
protected virtual async Task<ImmutableList<TEntity>?> OnInitializing(IContext context)
{
if (context.GetService<IStorageProvider>() is not IStorageProvider db)
return default;
return await (from dc in db.Open<TEntity>()
select dc).AsEntities();
}
protected override async Task OnInvalidate(TPrimaryKey id)
{
using var ctx = Context.ContextProvider.Create();
var transaction = ctx.GetService<ITransactionContext>();
try
{
if (OnInvalidating(ctx, id) is TEntity entity && entity is IPrimaryKey<TPrimaryKey> pk)
Set(pk.Id, entity, TimeSpan.Zero);
if (transaction is not null)
await transaction.Commit();
}
catch
{
if (transaction is not null)
await transaction.Rollback();
throw;
}
}
protected virtual async Task<TEntity?> OnInvalidating(IContext context, TPrimaryKey id)
{
if (context.GetService<IStorageProvider>() is not IStorageProvider provider)
return default;
return await (from dc in provider.Open<TEntity>()
where TypeComparer.Compare(dc.Id, id)
select dc).AsEntity();
}
async Task IEntityCacheClient<TEntity, TPrimaryKey>.Refresh(TPrimaryKey id)
{
await Refresh(id);
}
async Task IEntityCacheClient<TEntity, TPrimaryKey>.Remove(TPrimaryKey id)
{
await Remove(id);
}
protected override void Set(TPrimaryKey id, TEntity instance)
{
Set(id, instance, TimeSpan.Zero);
}
protected override void Set(TPrimaryKey id, TEntity instance, TimeSpan duration)
{
if (instance is IConcurrentEntity<TPrimaryKey> concurrent)
{
if (Get(id) is TEntity existing && existing is IConcurrentEntity<TPrimaryKey> existingConcurrent)
{
lock (existingConcurrent)
{
if (existingConcurrent.Sync != concurrent.Sync)
throw new InvalidOperationException(SR.ErrConcurrent);
concurrent.GetType().GetProperty(nameof(IConcurrentEntity<TPrimaryKey>.Sync))?.SetValue(concurrent, concurrent.Sync + 1);
Set(id, instance, duration);
return;
}
}
}
base.Set(id, instance, duration);
}
protected EntityCacheClient(IEntityCacheContext context, string key) : base(context.Cache, key)
{
Context = context;
}
private IEntityCacheContext Context { get; }
protected override sealed async Task OnInitializing()
{
using var ctx = Context.ContextProvider.Create();
var transaction = ctx.GetService<ITransactionContext?>();
try
{
if (await OnInitializing(ctx) is ImmutableList<TEntity> ds)
{
foreach (var r in ds)
Set(r.Id, r, TimeSpan.Zero);
}
if (transaction is not null)
await transaction.Commit();
}
catch
{
if (transaction is not null)
await transaction.Rollback();
throw;
}
}
protected virtual async Task<ImmutableList<TEntity>?> OnInitializing(IContext context)
{
if (context.GetService<IStorageProvider>() is not IStorageProvider db)
return default;
return await (from dc in db.Open<TEntity>()
select dc).AsEntities();
}
protected override async Task OnInvalidate(TPrimaryKey id)
{
using var ctx = Context.ContextProvider.Create();
var transaction = ctx.GetService<ITransactionContext>();
try
{
if (OnInvalidating(ctx, id) is TEntity entity && entity is IPrimaryKey<TPrimaryKey> pk)
Set(pk.Id, entity, TimeSpan.Zero);
if (transaction is not null)
await transaction.Commit();
}
catch
{
if (transaction is not null)
await transaction.Rollback();
throw;
}
}
protected virtual async Task<TEntity?> OnInvalidating(IContext context, TPrimaryKey id)
{
if (context.GetService<IStorageProvider>() is not IStorageProvider provider)
return default;
var entities = provider.Open<TEntity>().AsEntities();
return await (from dc in provider.Open<TEntity>()
where TypeComparer.Compare(dc.Id, id)
select dc).AsEntity();
}
async Task IEntityCacheClient<TEntity, TPrimaryKey>.Refresh(TPrimaryKey id)
{
await Refresh(id);
}
async Task IEntityCacheClient<TEntity, TPrimaryKey>.Remove(TPrimaryKey id)
{
await Remove(id);
}
protected override void Set(TPrimaryKey id, TEntity instance)
{
Set(id, instance, TimeSpan.Zero);
}
protected override void Set(TPrimaryKey id, TEntity instance, TimeSpan duration)
{
if (instance is IConcurrentEntity<TPrimaryKey> concurrent)
{
if (Get(id) is TEntity existing && existing is IConcurrentEntity<TPrimaryKey> existingConcurrent)
{
lock (existingConcurrent)
{
if (existingConcurrent.Sync != concurrent.Sync)
throw new InvalidOperationException(SR.ErrConcurrent);
concurrent.GetType().GetProperty(nameof(IConcurrentEntity<TPrimaryKey>.Sync))?.SetValue(concurrent, concurrent.Sync + 1);
Set(id, instance, duration);
return;
}
}
}
base.Set(id, instance, duration);
}
}

Loading…
Cancel
Save