From 8cad69519f2173c0d31b2e3221172abdd45e900b Mon Sep 17 00:00:00 2001 From: Sebastian Date: Tue, 27 Apr 2021 13:14:16 +0200 Subject: [PATCH] Another migration strategy. --- backend/src/Migrations/MigrationPath.cs | 8 +- .../Migrations/CreateAppSettings.cs | 110 ------------------ .../Migrations/OldEvents/AppPatternAdded.cs | 31 ++++- .../Migrations/OldEvents/AppPatternDeleted.cs | 16 ++- .../Migrations/OldEvents/AppPatternUpdated.cs | 31 ++++- .../Commands/DomainObject.cs | 14 ++- .../Commands/IMigratedStateEvent.cs | 16 +++ 7 files changed, 104 insertions(+), 122 deletions(-) delete mode 100644 backend/src/Migrations/Migrations/CreateAppSettings.cs create mode 100644 backend/src/Squidex.Infrastructure/Commands/IMigratedStateEvent.cs diff --git a/backend/src/Migrations/MigrationPath.cs b/backend/src/Migrations/MigrationPath.cs index 4c0085cb0..24a8eb610 100644 --- a/backend/src/Migrations/MigrationPath.cs +++ b/backend/src/Migrations/MigrationPath.cs @@ -18,7 +18,7 @@ namespace Migrations { public sealed class MigrationPath : IMigrationPath { - private const int CurrentVersion = 26; + private const int CurrentVersion = 25; private readonly IServiceProvider serviceProvider; public MigrationPath(IServiceProvider serviceProvider) @@ -136,12 +136,6 @@ namespace Migrations yield return serviceProvider.GetRequiredService(); } - // Version 26: UI Settings. - if (version < 26) - { - yield return serviceProvider.GetRequiredService(); - } - yield return serviceProvider.GetRequiredService(); } } diff --git a/backend/src/Migrations/Migrations/CreateAppSettings.cs b/backend/src/Migrations/Migrations/CreateAppSettings.cs deleted file mode 100644 index 828cdae2d..000000000 --- a/backend/src/Migrations/Migrations/CreateAppSettings.cs +++ /dev/null @@ -1,110 +0,0 @@ -// ========================================================================== -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex UG (haftungsbeschraenkt) -// All rights reserved. Licensed under the MIT license. -// ========================================================================== - -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Migrations.OldEvents; -using Squidex.Domain.Apps.Core.Apps; -using Squidex.Domain.Apps.Entities.Apps.Commands; -using Squidex.Domain.Apps.Events.Apps; -using Squidex.Infrastructure; -using Squidex.Infrastructure.Collections; -using Squidex.Infrastructure.Commands; -using Squidex.Infrastructure.EventSourcing; -using Squidex.Infrastructure.Migrations; - -#pragma warning disable CS0618 // Type or member is obsolete - -namespace Migrations.Migrations -{ - public sealed class CreateAppSettings : IMigration - { - private readonly ICommandBus commandBus; - private readonly IEventDataFormatter eventDataFormatter; - private readonly IEventStore eventStore; - - public CreateAppSettings(ICommandBus commandBus, - IEventDataFormatter eventDataFormatter, - IEventStore eventStore) - { - this.commandBus = commandBus; - this.eventDataFormatter = eventDataFormatter; - this.eventStore = eventStore; - } - - public async Task UpdateAsync() - { - var apps = new Dictionary, Dictionary>(); - - await foreach (var storedEvent in eventStore.QueryAllAsync("^app\\-")) - { - var @event = eventDataFormatter.ParseIfKnown(storedEvent); - - if (@event != null) - { - switch (@event.Payload) - { - case AppPatternAdded patternAdded: - { - var patterns = apps.GetOrAddNew(patternAdded.AppId); - - patterns[patternAdded.PatternId] = (patternAdded.Name, patternAdded.Pattern, patternAdded.Message); - break; - } - - case AppPatternUpdated patternUpdated: - { - var patterns = apps.GetOrAddNew(patternUpdated.AppId); - - patterns[patternUpdated.PatternId] = (patternUpdated.Name, patternUpdated.Pattern, patternUpdated.Message); - break; - } - - case AppPatternDeleted patternDeleted: - { - var patterns = apps.GetOrAddNew(patternDeleted.AppId); - - patterns.Remove(patternDeleted.PatternId); - break; - } - - case AppArchived appArchived: - { - apps.Remove(appArchived.AppId); - break; - } - } - } - } - - var actor = RefToken.Client("Migrator"); - - foreach (var (appId, patterns) in apps) - { - if (patterns.Count > 0) - { - var settings = new AppSettings - { - Patterns = patterns.Values.Select(x => new Pattern(x.Name, x.Pattern) - { - Message = x.Message - }).ToReadOnlyCollection() - }; - - await commandBus.PublishAsync(new UpdateAppSettings - { - AppId = appId, - Settings = settings, - FromRule = true, - Actor = actor - }); - } - } - } - } -} diff --git a/backend/src/Migrations/OldEvents/AppPatternAdded.cs b/backend/src/Migrations/OldEvents/AppPatternAdded.cs index 291c30064..1fc64bd49 100644 --- a/backend/src/Migrations/OldEvents/AppPatternAdded.cs +++ b/backend/src/Migrations/OldEvents/AppPatternAdded.cs @@ -6,15 +6,22 @@ // ========================================================================== using System; +using System.Collections.Generic; +using Squidex.Domain.Apps.Core.Apps; +using Squidex.Domain.Apps.Entities.Apps.DomainObject; using Squidex.Domain.Apps.Events; +using Squidex.Domain.Apps.Events.Apps; using Squidex.Infrastructure; +using Squidex.Infrastructure.Collections; +using Squidex.Infrastructure.Commands; using Squidex.Infrastructure.EventSourcing; +using Squidex.Infrastructure.Reflection; namespace Migrations.OldEvents { [EventType(nameof(AppPatternAdded))] [Obsolete("New Event introduced")] - public sealed class AppPatternAdded : AppEvent + public sealed class AppPatternAdded : AppEvent, IMigratedStateEvent { public DomainId PatternId { get; set; } @@ -23,5 +30,27 @@ namespace Migrations.OldEvents public string Pattern { get; set; } public string? Message { get; set; } + + public IEvent Migrate(AppDomainObject.State state) + { + var newSettings = new AppSettings + { + Patterns = new List(state.Settings.Patterns) + { + new Pattern(Name, Pattern) + { + Message = Message + } + }.ToReadOnlyCollection(), + Editors = state.Settings.Editors + }; + + var newEvent = new AppSettingsUpdated + { + Settings = newSettings + }; + + return SimpleMapper.Map(this, newEvent); + } } } diff --git a/backend/src/Migrations/OldEvents/AppPatternDeleted.cs b/backend/src/Migrations/OldEvents/AppPatternDeleted.cs index 60df9c105..922cdd68f 100644 --- a/backend/src/Migrations/OldEvents/AppPatternDeleted.cs +++ b/backend/src/Migrations/OldEvents/AppPatternDeleted.cs @@ -6,16 +6,30 @@ // ========================================================================== using System; +using Squidex.Domain.Apps.Entities.Apps.DomainObject; using Squidex.Domain.Apps.Events; +using Squidex.Domain.Apps.Events.Apps; using Squidex.Infrastructure; +using Squidex.Infrastructure.Commands; using Squidex.Infrastructure.EventSourcing; +using Squidex.Infrastructure.Reflection; namespace Migrations.OldEvents { [EventType(nameof(AppPatternDeleted))] [Obsolete("New Event introduced")] - public sealed class AppPatternDeleted : AppEvent + public sealed class AppPatternDeleted : AppEvent, IMigratedStateEvent { public DomainId PatternId { get; set; } + + public IEvent Migrate(AppDomainObject.State state) + { + var newEvent = new AppSettingsUpdated + { + Settings = state.Settings + }; + + return SimpleMapper.Map(this, newEvent); + } } } diff --git a/backend/src/Migrations/OldEvents/AppPatternUpdated.cs b/backend/src/Migrations/OldEvents/AppPatternUpdated.cs index 77566146c..d276de945 100644 --- a/backend/src/Migrations/OldEvents/AppPatternUpdated.cs +++ b/backend/src/Migrations/OldEvents/AppPatternUpdated.cs @@ -6,15 +6,22 @@ // ========================================================================== using System; +using System.Collections.Generic; +using Squidex.Domain.Apps.Core.Apps; +using Squidex.Domain.Apps.Entities.Apps.DomainObject; using Squidex.Domain.Apps.Events; +using Squidex.Domain.Apps.Events.Apps; using Squidex.Infrastructure; +using Squidex.Infrastructure.Collections; +using Squidex.Infrastructure.Commands; using Squidex.Infrastructure.EventSourcing; +using Squidex.Infrastructure.Reflection; namespace Migrations.OldEvents { [EventType(nameof(AppPatternUpdated))] [Obsolete("New Event introduced")] - public sealed class AppPatternUpdated : AppEvent + public sealed class AppPatternUpdated : AppEvent, IMigratedStateEvent { public DomainId PatternId { get; set; } @@ -23,5 +30,27 @@ namespace Migrations.OldEvents public string Pattern { get; set; } public string? Message { get; set; } + + public IEvent Migrate(AppDomainObject.State state) + { + var newSettings = new AppSettings + { + Patterns = new List(state.Settings.Patterns) + { + new Pattern(Name, Pattern) + { + Message = Message + } + }.ToReadOnlyCollection(), + Editors = state.Settings.Editors + }; + + var newEvent = new AppSettingsUpdated + { + Settings = newSettings + }; + + return SimpleMapper.Map(this, newEvent); + } } } diff --git a/backend/src/Squidex.Infrastructure/Commands/DomainObject.cs b/backend/src/Squidex.Infrastructure/Commands/DomainObject.cs index edf7ad6e3..9ade10d14 100644 --- a/backend/src/Squidex.Infrastructure/Commands/DomainObject.cs +++ b/backend/src/Squidex.Infrastructure/Commands/DomainObject.cs @@ -103,7 +103,17 @@ namespace Squidex.Infrastructure.Commands snapshot.Version = version; snapshots.Add(snapshot, version, true); }), - @event => ApplyEvent(@event, true)); + @event => + { + if (@event is IMigratedStateEvent migratable) + { + var payload = migratable.Migrate(Snapshot); + + @event = new Envelope(payload, @event.Headers); + } + + return ApplyEvent(@event, true); + }); } public virtual async Task EnsureLoadedAsync(bool silent = false) @@ -360,4 +370,4 @@ namespace Squidex.Infrastructure.Commands public abstract Task ExecuteAsync(IAggregateCommand command); } -} \ No newline at end of file +} diff --git a/backend/src/Squidex.Infrastructure/Commands/IMigratedStateEvent.cs b/backend/src/Squidex.Infrastructure/Commands/IMigratedStateEvent.cs new file mode 100644 index 000000000..136ff1ac7 --- /dev/null +++ b/backend/src/Squidex.Infrastructure/Commands/IMigratedStateEvent.cs @@ -0,0 +1,16 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using Squidex.Infrastructure.EventSourcing; + +namespace Squidex.Infrastructure.Commands +{ + public interface IMigratedStateEvent + { + IEvent Migrate(T state); + } +}