135 lines
3.8 KiB
C#
135 lines
3.8 KiB
C#
using Microsoft.Extensions.Logging;
|
|
using Raven.Client.Documents;
|
|
using Raven.Client.Documents.Session;
|
|
|
|
namespace zero.Architecture;
|
|
|
|
public class BlueprintInterceptor : Interceptor<ZeroEntity>, IBlueprintInterceptor
|
|
{
|
|
protected IZeroContext Context { get; set; }
|
|
|
|
protected IZeroStore Store { get; set; }
|
|
|
|
protected ILogger<BlueprintInterceptor> Logger { get; set; }
|
|
|
|
protected IBlueprintService BlueprintService { get; set; }
|
|
|
|
IList<Application> apps;
|
|
|
|
string configuredZeroDatabase;
|
|
|
|
|
|
public BlueprintInterceptor(IZeroContext context, IZeroStore store, ILogger<BlueprintInterceptor> logger, IBlueprintService blueprintService)
|
|
{
|
|
Gravity = -1;
|
|
Context = context;
|
|
Store = store;
|
|
Logger = logger;
|
|
BlueprintService = blueprintService;
|
|
configuredZeroDatabase = context.Options.For<RavenOptions>().Database;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Only run when operations are on the zero database
|
|
/// </summary>
|
|
public override bool CanHandle(InterceptorParameters args, Type modelType) => args.Context.Store.ResolvedDatabase == configuredZeroDatabase;
|
|
|
|
|
|
/// <inheritdoc />
|
|
public override Task Created(InterceptorParameters args, ZeroEntity model) => Saved(args, model, false);
|
|
|
|
|
|
/// <inheritdoc />
|
|
public override Task Updated(InterceptorParameters args, ZeroEntity model) => Saved(args, model, true);
|
|
|
|
|
|
/// <inheritdoc />
|
|
public async Task Saved(InterceptorParameters args, ZeroEntity model, bool update = false)
|
|
{
|
|
if (!BlueprintService.TryGetBlueprint(model, out Blueprint blueprint))
|
|
{
|
|
blueprint = new DefaultShallowBlueprint(model.GetType());
|
|
}
|
|
|
|
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)
|
|
{
|
|
child = ObjectCopycat.Clone(model);
|
|
child.Blueprint = new()
|
|
{
|
|
TargetId = model.Id
|
|
};
|
|
}
|
|
else
|
|
{
|
|
blueprint.Apply(model, child);
|
|
}
|
|
|
|
count += 1;
|
|
|
|
InterceptorInstruction<ZeroEntity> interceptor = update ? args.Interceptors.ForUpdate(model) : args.Interceptors.ForCreate(model);
|
|
interceptor.Filter(x => x is not IBlueprintInterceptor);
|
|
|
|
await interceptor.Start(args.Operations);
|
|
await session.StoreAsync(child);
|
|
await interceptor.Complete();
|
|
await session.SaveChangesAsync();
|
|
}
|
|
|
|
Logger.LogDebug("Blueprint: Synced {count} children for {name} ({id})", count, model.Name, model.Id);
|
|
}
|
|
|
|
|
|
/// <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;
|
|
|
|
InterceptorInstruction<ZeroEntity> interceptor = args.Interceptors.ForDelete(model);
|
|
interceptor.Filter(x => x is not IBlueprintInterceptor);
|
|
|
|
await interceptor.Start(args.Operations);
|
|
session.Delete(model.Id);
|
|
await interceptor.Complete();
|
|
await session.SaveChangesAsync();
|
|
}
|
|
|
|
Logger.LogDebug("Blueprint: Deleted {count} children for {name} ({id})", count, model.Name, model.Id);
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Get all applications to choose from
|
|
/// </summary>
|
|
async Task<IList<Application>> GetApplications()
|
|
{
|
|
if (apps != null)
|
|
{
|
|
return apps;
|
|
}
|
|
|
|
IAsyncDocumentSession session = Store.Session(global: true);
|
|
apps = await session.Query<Application>().ToListAsync();
|
|
return apps;
|
|
}
|
|
} |