Browse Source

Another migration strategy.

pull/691/head
Sebastian 5 years ago
parent
commit
8cad69519f
  1. 8
      backend/src/Migrations/MigrationPath.cs
  2. 110
      backend/src/Migrations/Migrations/CreateAppSettings.cs
  3. 31
      backend/src/Migrations/OldEvents/AppPatternAdded.cs
  4. 16
      backend/src/Migrations/OldEvents/AppPatternDeleted.cs
  5. 31
      backend/src/Migrations/OldEvents/AppPatternUpdated.cs
  6. 14
      backend/src/Squidex.Infrastructure/Commands/DomainObject.cs
  7. 16
      backend/src/Squidex.Infrastructure/Commands/IMigratedStateEvent.cs

8
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<PopulateGrainIndexes>();
}
// Version 26: UI Settings.
if (version < 26)
{
yield return serviceProvider.GetRequiredService<CreateAppSettings>();
}
yield return serviceProvider.GetRequiredService<StartEventConsumers>();
}
}

110
backend/src/Migrations/Migrations/CreateAppSettings.cs

@ -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<NamedId<DomainId>, Dictionary<DomainId, (string Name, string Pattern, string? Message)>>();
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
});
}
}
}
}
}

31
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<AppDomainObject.State>
{
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<Pattern>(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);
}
}
}

16
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<AppDomainObject.State>
{
public DomainId PatternId { get; set; }
public IEvent Migrate(AppDomainObject.State state)
{
var newEvent = new AppSettingsUpdated
{
Settings = state.Settings
};
return SimpleMapper.Map(this, newEvent);
}
}
}

31
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<AppDomainObject.State>
{
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<Pattern>(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);
}
}
}

14
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<T> migratable)
{
var payload = migratable.Migrate(Snapshot);
@event = new Envelope<IEvent>(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<CommandResult> ExecuteAsync(IAggregateCommand command);
}
}
}

16
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<T>
{
IEvent Migrate(T state);
}
}
Loading…
Cancel
Save