mirror of https://github.com/Squidex/squidex.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
187 lines
6.3 KiB
187 lines
6.3 KiB
// ==========================================================================
|
|
// Squidex Headless CMS
|
|
// ==========================================================================
|
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|
// All rights reserved. Licensed under the MIT license.
|
|
// ==========================================================================
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Threading.Tasks;
|
|
using Squidex.Domain.Apps.Entities.Apps.Indexes;
|
|
using Squidex.Domain.Apps.Entities.Rules.Indexes;
|
|
using Squidex.Domain.Apps.Entities.Schemas.Indexes;
|
|
using Squidex.Domain.Apps.Events;
|
|
using Squidex.Domain.Apps.Events.Apps;
|
|
using Squidex.Domain.Apps.Events.Rules;
|
|
using Squidex.Domain.Apps.Events.Schemas;
|
|
using Squidex.Infrastructure;
|
|
using Squidex.Infrastructure.EventSourcing;
|
|
using Squidex.Infrastructure.Migrations;
|
|
using Squidex.Infrastructure.Tasks;
|
|
|
|
namespace Migrate_01.Migrations
|
|
{
|
|
public class PopulateGrainIndexes : IMigration
|
|
{
|
|
private readonly IAppsIndex indexApps;
|
|
private readonly IRulesIndex indexRules;
|
|
private readonly ISchemasIndex indexSchemas;
|
|
private readonly IEventDataFormatter eventDataFormatter;
|
|
private readonly IEventStore eventStore;
|
|
|
|
public PopulateGrainIndexes(IAppsIndex indexApps, IRulesIndex indexRules, ISchemasIndex indexSchemas,
|
|
IEventDataFormatter eventDataFormatter,
|
|
IEventStore eventStore)
|
|
{
|
|
this.indexApps = indexApps;
|
|
this.indexRules = indexRules;
|
|
this.indexSchemas = indexSchemas;
|
|
this.eventDataFormatter = eventDataFormatter;
|
|
this.eventStore = eventStore;
|
|
}
|
|
|
|
public Task UpdateAsync()
|
|
{
|
|
return Task.WhenAll(
|
|
RebuildAppIndexes(),
|
|
RebuildRuleIndexes(),
|
|
RebuildSchemaIndexes());
|
|
}
|
|
|
|
private async Task RebuildAppIndexes()
|
|
{
|
|
var appsByName = new Dictionary<string, Guid>();
|
|
var appsByUser = new Dictionary<string, HashSet<Guid>>();
|
|
|
|
bool HasApp(NamedId<Guid> appId, bool consistent, out Guid id)
|
|
{
|
|
return appsByName.TryGetValue(appId.Name, out id) && (!consistent || id == appId.Id);
|
|
}
|
|
|
|
HashSet<Guid> Index(string contributorId)
|
|
{
|
|
return appsByUser.GetOrAddNew(contributorId);
|
|
}
|
|
|
|
void RemoveApp(NamedId<Guid> appId, bool consistent)
|
|
{
|
|
if (HasApp(appId, consistent, out var id))
|
|
{
|
|
foreach (var apps in appsByUser.Values)
|
|
{
|
|
apps.Remove(id);
|
|
}
|
|
|
|
appsByName.Remove(appId.Name);
|
|
}
|
|
}
|
|
|
|
await eventStore.QueryAsync(storedEvent =>
|
|
{
|
|
var @event = eventDataFormatter.Parse(storedEvent.Data);
|
|
|
|
switch (@event.Payload)
|
|
{
|
|
case AppCreated created:
|
|
{
|
|
RemoveApp(created.AppId, false);
|
|
|
|
appsByName[created.Name] = created.AppId.Id;
|
|
break;
|
|
}
|
|
|
|
case AppContributorAssigned contributorAssigned:
|
|
{
|
|
if (HasApp(contributorAssigned.AppId, true, out _))
|
|
{
|
|
Index(contributorAssigned.ContributorId).Add(contributorAssigned.AppId.Id);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case AppContributorRemoved contributorRemoved:
|
|
Index(contributorRemoved.ContributorId).Remove(contributorRemoved.AppId.Id);
|
|
break;
|
|
case AppArchived archived:
|
|
RemoveApp(archived.AppId, true);
|
|
break;
|
|
}
|
|
|
|
return TaskHelper.Done;
|
|
}, "^app\\-");
|
|
|
|
await indexApps.RebuildAsync(appsByName);
|
|
|
|
foreach (var (contributorId, apps) in appsByUser)
|
|
{
|
|
await indexApps.RebuildByContributorsAsync(contributorId, apps);
|
|
}
|
|
}
|
|
|
|
private async Task RebuildRuleIndexes()
|
|
{
|
|
var rulesByApp = new Dictionary<Guid, HashSet<Guid>>();
|
|
|
|
HashSet<Guid> Index(RuleEvent @event)
|
|
{
|
|
return rulesByApp.GetOrAddNew(@event.AppId.Id);
|
|
}
|
|
|
|
await eventStore.QueryAsync(storedEvent =>
|
|
{
|
|
var @event = eventDataFormatter.Parse(storedEvent.Data);
|
|
|
|
switch (@event.Payload)
|
|
{
|
|
case RuleCreated created:
|
|
Index(created).Add(created.RuleId);
|
|
break;
|
|
case RuleDeleted deleted:
|
|
Index(deleted).Remove(deleted.RuleId);
|
|
break;
|
|
}
|
|
|
|
return TaskHelper.Done;
|
|
}, "^rule\\-");
|
|
|
|
foreach (var (appId, rules) in rulesByApp)
|
|
{
|
|
await indexRules.RebuildAsync(appId, rules);
|
|
}
|
|
}
|
|
|
|
private async Task RebuildSchemaIndexes()
|
|
{
|
|
var schemasByApp = new Dictionary<Guid, Dictionary<string, Guid>>();
|
|
|
|
Dictionary<string, Guid> Index(SchemaEvent @event)
|
|
{
|
|
return schemasByApp.GetOrAddNew(@event.AppId.Id);
|
|
}
|
|
|
|
await eventStore.QueryAsync(storedEvent =>
|
|
{
|
|
var @event = eventDataFormatter.Parse(storedEvent.Data);
|
|
|
|
switch (@event.Payload)
|
|
{
|
|
case SchemaCreated created:
|
|
Index(created)[created.SchemaId.Name] = created.SchemaId.Id;
|
|
break;
|
|
case SchemaDeleted deleted:
|
|
Index(deleted).Remove(deleted.SchemaId.Name);
|
|
break;
|
|
}
|
|
|
|
return TaskHelper.Done;
|
|
}, "^schema\\-");
|
|
|
|
foreach (var (appId, schemas) in schemasByApp)
|
|
{
|
|
await indexSchemas.RebuildAsync(appId, schemas);
|
|
}
|
|
}
|
|
}
|
|
}
|