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) 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.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Diagnostics.Contracts; using System.Diagnostics.Contracts;
using System.Globalization;
using System.Linq; using System.Linq;
using Squidex.Infrastructure; using Squidex.Infrastructure;
@ -59,7 +60,7 @@ namespace Squidex.Domain.Apps.Core.Schemas
} }
else 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. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using System;
using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Memory;
using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Domain.Apps.Core.HandleRules;
using Squidex.Domain.Apps.Entities.Rules.Repositories; using Squidex.Domain.Apps.Entities.Rules.Repositories;
using Squidex.Domain.Apps.Events; using Squidex.Domain.Apps.Events;
@ -17,8 +20,10 @@ namespace Squidex.Domain.Apps.Entities.Rules
{ {
public sealed class RuleEnqueuer : IEventConsumer public sealed class RuleEnqueuer : IEventConsumer
{ {
private static readonly TimeSpan CacheDuration = TimeSpan.FromMinutes(2);
private readonly IRuleEventRepository ruleEventRepository; private readonly IRuleEventRepository ruleEventRepository;
private readonly IAppProvider appProvider; private readonly IAppProvider appProvider;
private readonly IMemoryCache cache;
private readonly RuleService ruleService; private readonly RuleService ruleService;
public string Name public string Name
@ -31,15 +36,18 @@ namespace Squidex.Domain.Apps.Entities.Rules
get { return ".*"; } get { return ".*"; }
} }
public RuleEnqueuer(IAppProvider appProvider, IRuleEventRepository ruleEventRepository, public RuleEnqueuer(IAppProvider appProvider, IMemoryCache cache, IRuleEventRepository ruleEventRepository,
RuleService ruleService) RuleService ruleService)
{ {
Guard.NotNull(appProvider, nameof(appProvider)); Guard.NotNull(appProvider, nameof(appProvider));
Guard.NotNull(cache, nameof(cache));
Guard.NotNull(ruleEventRepository, nameof(ruleEventRepository)); Guard.NotNull(ruleEventRepository, nameof(ruleEventRepository));
Guard.NotNull(ruleService, nameof(ruleService)); Guard.NotNull(ruleService, nameof(ruleService));
this.appProvider = appProvider; this.appProvider = appProvider;
this.cache = cache;
this.ruleEventRepository = ruleEventRepository; this.ruleEventRepository = ruleEventRepository;
this.ruleService = ruleService; this.ruleService = ruleService;
} }
@ -53,7 +61,7 @@ namespace Squidex.Domain.Apps.Entities.Rules
{ {
if (@event.Payload is AppEvent appEvent) 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) 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()); 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) public Task ResetAsync(string consumerName)
{ {
var eventConsumer = GrainFactory.GetGrain<IEventConsumerGrain>(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 ActivateAsync(string streamName);
Task StopAllAsync();
Task StopAsync(string consumerName); Task StopAsync(string consumerName);
Task StartAllAsync();
Task StartAsync(string consumerName); Task StartAsync(string consumerName);
Task ResetAsync(string consumerName); Task ResetAsync(string consumerName);

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

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

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

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

1
src/Squidex/package.json

@ -49,7 +49,6 @@
"@angular/compiler-cli": "6.0.4", "@angular/compiler-cli": "6.0.4",
"@ngtools/webpack": "6.0.8", "@ngtools/webpack": "6.0.8",
"@types/core-js": "2.5.0", "@types/core-js": "2.5.0",
"@types/dragula": "2.1.33",
"@types/jasmine": "2.8.8", "@types/jasmine": "2.8.8",
"@types/mousetrap": "1.6", "@types/mousetrap": "1.6",
"@types/node": "10.1.2", "@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.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using FakeItEasy; using FakeItEasy;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Options;
using NodaTime; using NodaTime;
using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Domain.Apps.Core.HandleRules;
using Squidex.Domain.Apps.Core.Rules; using Squidex.Domain.Apps.Core.Rules;
@ -25,6 +27,7 @@ namespace Squidex.Domain.Apps.Entities.Rules
public class RuleEnqueuerTests public class RuleEnqueuerTests
{ {
private readonly IAppProvider appProvider = A.Fake<IAppProvider>(); 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 IRuleEventRepository ruleEventRepository = A.Fake<IRuleEventRepository>();
private readonly RuleService ruleService = A.Fake<RuleService>(); private readonly RuleService ruleService = A.Fake<RuleService>();
private readonly Instant now = SystemClock.Instance.GetCurrentInstant(); private readonly Instant now = SystemClock.Instance.GetCurrentInstant();
@ -35,6 +38,7 @@ namespace Squidex.Domain.Apps.Entities.Rules
{ {
sut = new RuleEnqueuer( sut = new RuleEnqueuer(
appProvider, appProvider,
cache,
ruleEventRepository, ruleEventRepository,
ruleService); ruleService);
} }

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

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

45
tools/Migrate_01/MigrationPath.cs

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