Browse Source

* Migration improved

* Schema field name made invariant.
pull/303/head
Sebastian 8 years ago
parent
commit
31e5aa3342
  1. 2
      src/Squidex.Domain.Apps.Core.Model/Contents/NamedContentData.cs
  2. 3
      src/Squidex.Domain.Apps.Core.Model/Schemas/FieldCollection.cs
  3. 22
      src/Squidex.Domain.Apps.Entities/Rules/RuleEnqueuer.cs
  4. 16
      src/Squidex.Infrastructure/EventSourcing/Grains/EventConsumerManagerGrain.cs
  5. 4
      src/Squidex.Infrastructure/EventSourcing/Grains/IEventConsumerManagerGrain.cs
  6. 6
      src/Squidex/Config/Domain/EntitiesServices.cs
  7. 3
      src/Squidex/app/theme/theme.scss
  8. 1
      src/Squidex/package.json
  9. 4
      tests/Squidex.Domain.Apps.Entities.Tests/Rules/RuleEnqueuerTests.cs
  10. 24
      tests/Squidex.Infrastructure.Tests/EventSourcing/Grains/EventConsumerManagerGrainTests.cs
  11. 45
      tools/Migrate_01/MigrationPath.cs
  12. 30
      tools/Migrate_01/Migrations/StartEventConsumers.cs
  13. 30
      tools/Migrate_01/Migrations/StopEventConsumers.cs

2
src/Squidex.Domain.Apps.Core.Model/Contents/NamedContentData.cs

@ -19,7 +19,7 @@ namespace Squidex.Domain.Apps.Core.Contents
}
public NamedContentData(int capacity)
: base(capacity, EqualityComparer<string>.Default)
: base(capacity, StringComparer.OrdinalIgnoreCase)
{
}

3
src/Squidex.Domain.Apps.Core.Model/Schemas/FieldCollection.cs

@ -9,6 +9,7 @@ using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.Linq;
using Squidex.Infrastructure;
@ -59,7 +60,7 @@ namespace Squidex.Domain.Apps.Core.Schemas
}
else
{
fieldsByName = fieldsOrdered.ToImmutableDictionary(x => x.Name);
fieldsByName = fieldsOrdered.ToImmutableDictionary(x => x.Name, StringComparer.OrdinalIgnoreCase);
}
}

22
src/Squidex.Domain.Apps.Entities/Rules/RuleEnqueuer.cs

@ -5,7 +5,10 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Memory;
using Squidex.Domain.Apps.Core.HandleRules;
using Squidex.Domain.Apps.Entities.Rules.Repositories;
using Squidex.Domain.Apps.Events;
@ -17,8 +20,10 @@ namespace Squidex.Domain.Apps.Entities.Rules
{
public sealed class RuleEnqueuer : IEventConsumer
{
private static readonly TimeSpan CacheDuration = TimeSpan.FromMinutes(2);
private readonly IRuleEventRepository ruleEventRepository;
private readonly IAppProvider appProvider;
private readonly IMemoryCache cache;
private readonly RuleService ruleService;
public string Name
@ -31,15 +36,18 @@ namespace Squidex.Domain.Apps.Entities.Rules
get { return ".*"; }
}
public RuleEnqueuer(IAppProvider appProvider, IRuleEventRepository ruleEventRepository,
public RuleEnqueuer(IAppProvider appProvider, IMemoryCache cache, IRuleEventRepository ruleEventRepository,
RuleService ruleService)
{
Guard.NotNull(appProvider, nameof(appProvider));
Guard.NotNull(cache, nameof(cache));
Guard.NotNull(ruleEventRepository, nameof(ruleEventRepository));
Guard.NotNull(ruleService, nameof(ruleService));
this.appProvider = appProvider;
this.cache = cache;
this.ruleEventRepository = ruleEventRepository;
this.ruleService = ruleService;
}
@ -53,7 +61,7 @@ namespace Squidex.Domain.Apps.Entities.Rules
{
if (@event.Payload is AppEvent appEvent)
{
var rules = await appProvider.GetRulesAsync(appEvent.AppId.Id);
var rules = await GetRulesAsync(appEvent.AppId.Id);
foreach (var ruleEntity in rules)
{
@ -66,5 +74,15 @@ namespace Squidex.Domain.Apps.Entities.Rules
}
}
}
private Task<List<IRuleEntity>> GetRulesAsync(Guid appId)
{
return cache.GetOrCreateAsync(appId, entry =>
{
entry.AbsoluteExpirationRelativeToNow = CacheDuration;
return appProvider.GetRulesAsync(appId);
});
}
}
}

16
src/Squidex.Infrastructure/EventSourcing/Grains/EventConsumerManagerGrain.cs

@ -70,6 +70,22 @@ namespace Squidex.Infrastructure.EventSourcing.Grains
return new Immutable<List<EventConsumerInfo>>(consumerInfos.Select(r => r.Value).ToList());
}
public Task StartAllAsync()
{
return Task.WhenAll(
eventConsumers
.Select(c => GrainFactory.GetGrain<IEventConsumerGrain>(c.Name))
.Select(c => c.StartAsync()));
}
public Task StopAllAsync()
{
return Task.WhenAll(
eventConsumers
.Select(c => GrainFactory.GetGrain<IEventConsumerGrain>(c.Name))
.Select(c => c.StopAsync()));
}
public Task ResetAsync(string consumerName)
{
var eventConsumer = GrainFactory.GetGrain<IEventConsumerGrain>(consumerName);

4
src/Squidex.Infrastructure/EventSourcing/Grains/IEventConsumerManagerGrain.cs

@ -16,8 +16,12 @@ namespace Squidex.Infrastructure.EventSourcing.Grains
{
Task ActivateAsync(string streamName);
Task StopAllAsync();
Task StopAsync(string consumerName);
Task StartAllAsync();
Task StartAsync(string consumerName);
Task ResetAsync(string consumerName);

6
src/Squidex/Config/Domain/EntitiesServices.cs

@ -187,6 +187,12 @@ namespace Squidex.Config.Domain
services.AddTransientAs<RebuildAssets>()
.As<IMigration>();
services.AddTransientAs<StartEventConsumers>()
.As<IMigration>();
services.AddTransientAs<StopEventConsumers>()
.As<IMigration>();
services.AddTransientAs<Rebuilder>()
.AsSelf();
}

3
src/Squidex/app/theme/theme.scss

@ -6,9 +6,6 @@
// Pikaday
@import '~pikaday/css/pikaday.css';
// Dragula
@import '~dragula/dist/dragula.css';
// Bootstrap Overrides
@import '_bootstrap.scss';

1
src/Squidex/package.json

@ -49,7 +49,6 @@
"@angular/compiler-cli": "6.0.4",
"@ngtools/webpack": "6.0.8",
"@types/core-js": "2.5.0",
"@types/dragula": "2.1.33",
"@types/jasmine": "2.8.8",
"@types/mousetrap": "1.6",
"@types/node": "10.1.2",

4
tests/Squidex.Domain.Apps.Entities.Tests/Rules/RuleEnqueuerTests.cs

@ -9,6 +9,8 @@ using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using FakeItEasy;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Options;
using NodaTime;
using Squidex.Domain.Apps.Core.HandleRules;
using Squidex.Domain.Apps.Core.Rules;
@ -25,6 +27,7 @@ namespace Squidex.Domain.Apps.Entities.Rules
public class RuleEnqueuerTests
{
private readonly IAppProvider appProvider = A.Fake<IAppProvider>();
private readonly IMemoryCache cache = new MemoryCache(Options.Create(new MemoryCacheOptions()));
private readonly IRuleEventRepository ruleEventRepository = A.Fake<IRuleEventRepository>();
private readonly RuleService ruleService = A.Fake<RuleService>();
private readonly Instant now = SystemClock.Instance.GetCurrentInstant();
@ -35,6 +38,7 @@ namespace Squidex.Domain.Apps.Entities.Rules
{
sut = new RuleEnqueuer(
appProvider,
cache,
ruleEventRepository,
ruleService);
}

24
tests/Squidex.Infrastructure.Tests/EventSourcing/Grains/EventConsumerManagerGrainTests.cs

@ -102,6 +102,18 @@ namespace Squidex.Infrastructure.EventSourcing.Grains
.MustNotHaveHappened();
}
[Fact]
public async Task Should_start_all_grains()
{
await sut.StartAllAsync();
A.CallTo(() => grainA.StartAsync())
.MustHaveHappened();
A.CallTo(() => grainB.StartAsync())
.MustHaveHappened();
}
[Fact]
public async Task Should_start_matching_grain()
{
@ -114,6 +126,18 @@ namespace Squidex.Infrastructure.EventSourcing.Grains
.MustNotHaveHappened();
}
[Fact]
public async Task Should_stop_all_grains()
{
await sut.StopAllAsync();
A.CallTo(() => grainA.StopAsync())
.MustHaveHappened();
A.CallTo(() => grainB.StopAsync())
.MustHaveHappened();
}
[Fact]
public async Task Should_stop_matching_grain()
{

45
tools/Migrate_01/MigrationPath.cs

@ -7,6 +7,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.DependencyInjection;
using Migrate_01.Migrations;
using Squidex.Infrastructure.Migrations;
@ -15,7 +16,7 @@ namespace Migrate_01
{
public sealed class MigrationPath : IMigrationPath
{
private const int CurrentVersion = 12;
private const int CurrentVersion = 11;
private readonly IServiceProvider serviceProvider;
public MigrationPath(IServiceProvider serviceProvider)
@ -30,60 +31,54 @@ namespace Migrate_01
return (CurrentVersion, null);
}
var migrations = new List<IMigration>();
var migrations = ResolveMigrators(version).Where(x => x != null).ToList();
return (CurrentVersion, migrations);
}
private IEnumerable<IMigration> ResolveMigrators(int version)
{
yield return serviceProvider.GetRequiredService<StopEventConsumers>();
// Version 06: Convert Event store. Must always be executed first.
if (version < 6)
{
migrations.Add(serviceProvider.GetRequiredService<ConvertEventStore>());
yield return serviceProvider.GetRequiredService<ConvertEventStore>();
}
// Version 07: Introduces AppId for backups.
else if (version < 7)
{
migrations.Add(serviceProvider.GetRequiredService<ConvertEventStoreAppId>());
yield return serviceProvider.GetRequiredService<ConvertEventStoreAppId>();
}
// Version 05: Fixes the broken command architecture and requires a rebuild of all snapshots.
if (version < 5)
{
migrations.Add(serviceProvider.GetRequiredService<RebuildSnapshots>());
yield return serviceProvider.GetRequiredService<RebuildSnapshots>();
}
// Version 09: Grain indexes.
if (version < 9)
{
var migration = serviceProvider.GetService<ConvertOldSnapshotStores>();
if (migration != null)
{
migrations.Add(migration);
}
migrations.Add(serviceProvider.GetRequiredService<PopulateGrainIndexes>());
yield return serviceProvider.GetService<ConvertOldSnapshotStores>();
yield return serviceProvider.GetRequiredService<PopulateGrainIndexes>();
}
// Version 11: Introduce content drafts.
// Version 12: Fix problems with datetimes.
if (version < 12)
if (version < 11)
{
var migration = serviceProvider.GetService<DeleteContentCollections>();
if (migration != null)
{
migrations.Add(migration);
}
migrations.Add(serviceProvider.GetRequiredService<RebuildContents>());
yield return serviceProvider.GetService<DeleteContentCollections>();
yield return serviceProvider.GetRequiredService<RebuildContents>();
}
// Version 01: Introduce app patterns.
if (version < 1)
{
migrations.Add(serviceProvider.GetRequiredService<AddPatterns>());
yield return serviceProvider.GetRequiredService<AddPatterns>();
}
return (CurrentVersion, migrations);
yield return serviceProvider.GetRequiredService<StartEventConsumers>();
}
}
}

30
tools/Migrate_01/Migrations/StartEventConsumers.cs

@ -0,0 +1,30 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Threading.Tasks;
using Orleans;
using Squidex.Infrastructure.EventSourcing.Grains;
using Squidex.Infrastructure.Migrations;
using Squidex.Infrastructure.Orleans;
namespace Migrate_01.Migrations
{
public sealed class StartEventConsumers : IMigration
{
private readonly IEventConsumerManagerGrain eventConsumerManager;
public StartEventConsumers(IGrainFactory grainFactory)
{
eventConsumerManager = grainFactory.GetGrain<IEventConsumerManagerGrain>(SingleGrain.Id);
}
public Task UpdateAsync()
{
return eventConsumerManager.StartAllAsync();
}
}
}

30
tools/Migrate_01/Migrations/StopEventConsumers.cs

@ -0,0 +1,30 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Threading.Tasks;
using Orleans;
using Squidex.Infrastructure.EventSourcing.Grains;
using Squidex.Infrastructure.Migrations;
using Squidex.Infrastructure.Orleans;
namespace Migrate_01.Migrations
{
public sealed class StopEventConsumers : IMigration
{
private readonly IEventConsumerManagerGrain eventConsumerManager;
public StopEventConsumers(IGrainFactory grainFactory)
{
eventConsumerManager = grainFactory.GetGrain<IEventConsumerManagerGrain>(SingleGrain.Id);
}
public Task UpdateAsync()
{
return eventConsumerManager.StopAllAsync();
}
}
}
Loading…
Cancel
Save