Files
mixtape/zero.Core/Architecture/Blueprints/BlueprintInterceptor.cs
T

135 lines
3.8 KiB
C#
Raw Normal View History

2021-11-22 14:29:22 +01:00
using Microsoft.Extensions.Logging;
using Raven.Client.Documents;
using Raven.Client.Documents.Session;
2021-11-19 16:11:12 +01:00
2021-11-22 14:29:22 +01:00
namespace zero.Architecture;
2021-11-19 16:11:12 +01:00
2021-11-22 14:29:22 +01:00
public class BlueprintInterceptor : Interceptor<ZeroEntity>, IBlueprintInterceptor
{
protected IZeroContext Context { get; set; }
2021-11-19 16:11:12 +01:00
2021-11-22 14:29:22 +01:00
protected IZeroStore Store { get; set; }
2021-11-19 16:11:12 +01:00
2021-11-22 14:29:22 +01:00
protected ILogger<BlueprintInterceptor> Logger { get; set; }
2021-11-19 16:11:12 +01:00
2021-11-22 14:29:22 +01:00
protected IBlueprintService BlueprintService { get; set; }
IList<Application> apps;
string configuredZeroDatabase;
2021-11-19 16:11:12 +01:00
2021-11-27 18:09:27 +01:00
public BlueprintInterceptor(IZeroContext context, IZeroStore store, ILogger<BlueprintInterceptor> logger, IBlueprintService blueprintService)
2021-11-22 14:29:22 +01:00
{
2021-11-22 16:03:02 +01:00
Gravity = -1;
2021-11-22 14:29:22 +01:00
Context = context;
Store = store;
Logger = logger;
BlueprintService = blueprintService;
configuredZeroDatabase = context.Options.For<RavenOptions>().Database;
}
2021-11-19 16:11:12 +01:00
2021-11-22 14:29:22 +01:00
/// <summary>
/// Only run when operations are on the zero database
/// </summary>
public override bool CanHandle(InterceptorParameters args, Type modelType) => args.Context.Store.ResolvedDatabase == configuredZeroDatabase;
2021-11-19 16:11:12 +01:00
2021-11-22 14:29:22 +01:00
/// <inheritdoc />
public override Task Created(InterceptorParameters args, ZeroEntity model) => Saved(args, model, false);
2021-11-19 16:11:12 +01:00
2021-11-22 14:29:22 +01:00
/// <inheritdoc />
public override Task Updated(InterceptorParameters args, ZeroEntity model) => Saved(args, model, true);
2021-11-19 16:11:12 +01:00
2021-11-22 14:29:22 +01:00
/// <inheritdoc />
public async Task Saved(InterceptorParameters args, ZeroEntity model, bool update = false)
{
if (!BlueprintService.TryGetBlueprint(model, out Blueprint blueprint))
{
2021-12-26 13:27:59 +01:00
blueprint = new DefaultShallowBlueprint(model.GetType());
2021-11-22 14:29:22 +01:00
}
2021-11-19 16:11:12 +01:00
2021-11-22 14:29:22 +01:00
int count = 0;
foreach (Application app in await GetApplications())
{
using ZeroContextScope scope = Context.CreateScope(app);
IZeroDocumentSession session = scope.Store.Session(scope.Database);
ZeroEntity child = await session.LoadAsync<ZeroEntity>(model.Id);
if (child == null)
{
2021-11-26 12:31:33 +01:00
child = ObjectCopycat.Clone(model);
2021-12-26 13:27:59 +01:00
child.Blueprint = new()
{
TargetId = model.Id
};
2021-11-22 14:29:22 +01:00
}
else
{
blueprint.Apply(model, child);
}
count += 1;
2021-11-27 18:09:27 +01:00
InterceptorInstruction<ZeroEntity> interceptor = update ? args.Interceptors.ForUpdate(model) : args.Interceptors.ForCreate(model);
2021-11-22 14:29:22 +01:00
interceptor.Filter(x => x is not IBlueprintInterceptor);
2021-12-28 13:23:14 +01:00
await interceptor.Start(args.Operations);
2021-11-22 14:29:22 +01:00
await session.StoreAsync(child);
await interceptor.Complete();
await session.SaveChangesAsync();
}
Logger.LogDebug("Blueprint: Synced {count} children for {name} ({id})", count, model.Name, model.Id);
}
2021-11-19 16:11:12 +01:00
2021-11-22 14:29:22 +01:00
/// <inheritdoc />
public override async Task Deleted(InterceptorParameters args, ZeroEntity model)
{
if (!BlueprintService.TryGetBlueprint(model, out Blueprint blueprint))
{
return;
}
int count = 0;
foreach (Application app in await GetApplications())
{
using ZeroContextScope scope = Context.CreateScope(app);
IZeroDocumentSession session = scope.Store.Session(scope.Database);
count += 1;
2021-11-27 18:09:27 +01:00
InterceptorInstruction<ZeroEntity> interceptor = args.Interceptors.ForDelete(model);
2021-11-22 14:29:22 +01:00
interceptor.Filter(x => x is not IBlueprintInterceptor);
2021-12-28 13:23:14 +01:00
await interceptor.Start(args.Operations);
2021-11-22 14:29:22 +01:00
session.Delete(model.Id);
await interceptor.Complete();
await session.SaveChangesAsync();
}
Logger.LogDebug("Blueprint: Deleted {count} children for {name} ({id})", count, model.Name, model.Id);
}
2021-11-19 16:11:12 +01:00
2021-11-22 14:29:22 +01:00
/// <summary>
/// Get all applications to choose from
/// </summary>
async Task<IList<Application>> GetApplications()
{
if (apps != null)
{
return apps;
}
2021-11-19 16:11:12 +01:00
2021-11-22 14:29:22 +01:00
IAsyncDocumentSession session = Store.Session(global: true);
apps = await session.Query<Application>().ToListAsync();
return apps;
}
}