mirror of https://github.com/Squidex/squidex.git
42 changed files with 576 additions and 338 deletions
@ -0,0 +1,23 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System.Threading.Tasks; |
||||
|
using Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents; |
||||
|
using Squidex.Domain.Apps.Core.Rules.Triggers; |
||||
|
using Squidex.Domain.Apps.Events; |
||||
|
using Squidex.Infrastructure.EventSourcing; |
||||
|
|
||||
|
namespace Squidex.Domain.Apps.Core.HandleRules.Triggers |
||||
|
{ |
||||
|
public sealed class UsageTriggerHandler : RuleTriggerHandler<UsageTrigger, AppUsageExceeded, EnrichedUsageExceededEvent> |
||||
|
{ |
||||
|
protected override bool Trigger(EnrichedUsageExceededEvent @event, UsageTrigger trigger) |
||||
|
{ |
||||
|
return true; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,69 +1,69 @@ |
|||||
// ==========================================================================
|
//// ==========================================================================
|
||||
// Squidex Headless CMS
|
//// Squidex Headless CMS
|
||||
// ==========================================================================
|
//// ==========================================================================
|
||||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
//// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
// All rights reserved. Licensed under the MIT license.
|
//// All rights reserved. Licensed under the MIT license.
|
||||
// ==========================================================================
|
//// ==========================================================================
|
||||
|
|
||||
using System.Threading.Tasks; |
//using System.Threading.Tasks;
|
||||
using Orleans; |
//using Orleans;
|
||||
using Squidex.Domain.Apps.Core.HandleRules; |
//using Squidex.Domain.Apps.Core.HandleRules;
|
||||
using Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents; |
//using Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents;
|
||||
using Squidex.Domain.Apps.Core.Rules.Triggers; |
//using Squidex.Domain.Apps.Core.Rules.Triggers;
|
||||
using Squidex.Domain.Apps.Events; |
//using Squidex.Domain.Apps.Events;
|
||||
using Squidex.Domain.Apps.Events.Rules; |
//using Squidex.Domain.Apps.Events.Rules;
|
||||
using Squidex.Infrastructure; |
//using Squidex.Infrastructure;
|
||||
using Squidex.Infrastructure.Orleans; |
//using Squidex.Infrastructure.Orleans;
|
||||
using Squidex.Infrastructure.Tasks; |
//using Squidex.Infrastructure.Tasks;
|
||||
|
|
||||
namespace Squidex.Domain.Apps.Entities.Rules.UsageTracking |
//namespace Squidex.Domain.Apps.Entities.Rules.UsageTracking
|
||||
{ |
//{
|
||||
public sealed class UsageTriggerHandler : RuleTriggerHandler<UsageTrigger, AppEvent, EnrichedUsageExceededEvent> |
// public sealed class UsageTriggerHandler : RuleTriggerHandler<UsageTrigger, AppEvent, EnrichedUsageExceededEvent>
|
||||
{ |
// {
|
||||
private readonly IUsageTrackerGrain usageTrackerGrain; |
// private readonly IUsageTrackerGrain usageTrackerGrain;
|
||||
|
|
||||
public UsageTriggerHandler(IGrainFactory grainFactory) |
// public UsageTriggerHandler(IGrainFactory grainFactory)
|
||||
{ |
// {
|
||||
Guard.NotNull(grainFactory, nameof(grainFactory)); |
// Guard.NotNull(grainFactory, nameof(grainFactory));
|
||||
|
|
||||
usageTrackerGrain = grainFactory.GetGrain<IUsageTrackerGrain>(SingleGrain.Id); |
// usageTrackerGrain = grainFactory.GetGrain<IUsageTrackerGrain>(SingleGrain.Id);
|
||||
} |
// }
|
||||
|
|
||||
protected override async Task<bool> TriggersAsync(AppEvent @event, UsageTrigger trigger) |
// protected override async Task<bool> Trigger(AppEvent @event, UsageTrigger trigger)
|
||||
{ |
// {
|
||||
switch (@event) |
// switch (@event)
|
||||
{ |
// {
|
||||
case RuleDeleted _: |
// case RuleDeleted _:
|
||||
await usageTrackerGrain.RemoveTargetAsync(@event.AppId); |
// await usageTrackerGrain.RemoveTargetAsync(@event.AppId);
|
||||
break; |
// break;
|
||||
case RuleEnabled _: |
// case RuleEnabled _:
|
||||
await usageTrackerGrain.ActivateTargetAsync(@event.AppId); |
// await usageTrackerGrain.ActivateTargetAsync(@event.AppId);
|
||||
break; |
// break;
|
||||
case RuleDisabled _: |
// case RuleDisabled _:
|
||||
await usageTrackerGrain.DeactivateTargetAsync(@event.AppId); |
// await usageTrackerGrain.DeactivateTargetAsync(@event.AppId);
|
||||
break; |
// break;
|
||||
case RuleCreated ruleCreated: |
// case RuleCreated ruleCreated:
|
||||
if (ruleCreated.Trigger is UsageTrigger createdTrigger) |
// if (ruleCreated.Trigger is UsageTrigger createdTrigger)
|
||||
{ |
// {
|
||||
await usageTrackerGrain.AddTargetAsync(ruleCreated.AppId, createdTrigger.Limit); |
// await usageTrackerGrain.AddTargetAsync(ruleCreated.AppId, createdTrigger.Limit);
|
||||
} |
// }
|
||||
|
|
||||
break; |
// break;
|
||||
case RuleUpdated ruleUpdated: |
// case RuleUpdated ruleUpdated:
|
||||
if (ruleUpdated.Trigger is UsageTrigger updatedTrigger) |
// if (ruleUpdated.Trigger is UsageTrigger updatedTrigger)
|
||||
{ |
// {
|
||||
await usageTrackerGrain.AddTargetAsync(ruleUpdated.AppId, updatedTrigger.Limit); |
// await usageTrackerGrain.AddTargetAsync(ruleUpdated.AppId, updatedTrigger.Limit);
|
||||
} |
// }
|
||||
|
|
||||
break; |
// break;
|
||||
} |
// }
|
||||
|
|
||||
return @event is AppUsageExceeded; |
// return @event is AppUsageExceeded;
|
||||
} |
// }
|
||||
|
|
||||
protected override Task<bool> TriggersAsync(EnrichedUsageExceededEvent @event, UsageTrigger trigger) |
// protected override Task<bool> Trigger(EnrichedUsageExceededEvent @event, UsageTrigger trigger)
|
||||
{ |
// {
|
||||
return TaskHelper.True; |
// return TaskHelper.True;
|
||||
} |
// }
|
||||
} |
// }
|
||||
} |
//}
|
||||
|
|||||
@ -0,0 +1,20 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System; |
||||
|
|
||||
|
namespace Squidex.Infrastructure |
||||
|
{ |
||||
|
public sealed class None |
||||
|
{ |
||||
|
public static readonly Type Type = typeof(None); |
||||
|
|
||||
|
private None() |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,54 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using Squidex.Domain.Apps.Core.HandleRules; |
||||
|
using Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents; |
||||
|
using Squidex.Domain.Apps.Core.HandleRules.Triggers; |
||||
|
using Squidex.Domain.Apps.Core.Rules.Triggers; |
||||
|
using Squidex.Domain.Apps.Events; |
||||
|
using Squidex.Domain.Apps.Events.Contents; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Squidex.Domain.Apps.Core.Operations.HandleRules.Triggers |
||||
|
{ |
||||
|
public class UsageTriggerHandlerTests |
||||
|
{ |
||||
|
private readonly IRuleTriggerHandler sut = new UsageTriggerHandler(); |
||||
|
|
||||
|
[Fact] |
||||
|
public void Should_not_trigger_precheck_when_event_type_not_correct() |
||||
|
{ |
||||
|
var result = sut.Trigger(new ContentCreated(), new UsageTrigger()); |
||||
|
|
||||
|
Assert.False(result); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Should_trigger_precheck_when_event_type_correct() |
||||
|
{ |
||||
|
var result = sut.Trigger(new AppUsageExceeded(), new UsageTrigger()); |
||||
|
|
||||
|
Assert.True(result); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Should_not_trigger_check_when_event_type_not_correct() |
||||
|
{ |
||||
|
var result = sut.Trigger(new EnrichedContentEvent(), new UsageTrigger()); |
||||
|
|
||||
|
Assert.False(result); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Should_trigger_check_when_type_correct() |
||||
|
{ |
||||
|
var result = sut.Trigger(new AppUsageExceeded(), new UsageTrigger()); |
||||
|
|
||||
|
Assert.True(result); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,101 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using FakeItEasy; |
||||
|
using Squidex.Infrastructure.States; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Squidex.Infrastructure.Orleans |
||||
|
{ |
||||
|
public class GrainOfGuidTests |
||||
|
{ |
||||
|
private readonly IPersistence<MyGrain.GrainState> persistence = A.Fake<IPersistence<MyGrain.GrainState>>(); |
||||
|
private readonly IStore<Guid> store = A.Fake<IStore<Guid>>(); |
||||
|
private readonly Guid id = Guid.NewGuid(); |
||||
|
private readonly MyGrain sut; |
||||
|
private HandleSnapshot<MyGrain.GrainState> read; |
||||
|
|
||||
|
public sealed class MyGrain : GrainOfGuid<MyGrain.GrainState> |
||||
|
{ |
||||
|
public sealed class GrainState |
||||
|
{ |
||||
|
public Guid Id { get; set; } |
||||
|
} |
||||
|
|
||||
|
public GrainState PublicState |
||||
|
{ |
||||
|
get { return State; } |
||||
|
} |
||||
|
|
||||
|
public MyGrain(IStore<Guid> store) |
||||
|
: base(store) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public Task PublicWriteAsync() |
||||
|
{ |
||||
|
return WriteStateAsync(); |
||||
|
} |
||||
|
|
||||
|
public Task PublicClearAsync() |
||||
|
{ |
||||
|
return ClearStateAsync(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public GrainOfGuidTests() |
||||
|
{ |
||||
|
A.CallTo(() => persistence.ReadAsync(EtagVersion.Any)) |
||||
|
.Invokes(_ => |
||||
|
{ |
||||
|
read(new MyGrain.GrainState { Id = id }); |
||||
|
}); |
||||
|
|
||||
|
A.CallTo(() => store.WithSnapshots(typeof(MyGrain), id, A<HandleSnapshot<MyGrain.GrainState>>.Ignored)) |
||||
|
.Invokes(new Action<Type, Guid, HandleSnapshot<MyGrain.GrainState>>((type, id, callback) => |
||||
|
{ |
||||
|
read = callback; |
||||
|
})) |
||||
|
.Returns(persistence); |
||||
|
|
||||
|
sut = new MyGrain(store); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_read_on_activate() |
||||
|
{ |
||||
|
await sut.ActivateAsync(id); |
||||
|
|
||||
|
Assert.Equal(id, sut.PublicState.Id); |
||||
|
|
||||
|
A.CallTo(() => persistence.ReadAsync(EtagVersion.Any)) |
||||
|
.MustHaveHappened(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_invoke_persistence_on_write() |
||||
|
{ |
||||
|
await sut.ActivateAsync(id); |
||||
|
await sut.PublicWriteAsync(); |
||||
|
|
||||
|
A.CallTo(() => persistence.WriteSnapshotAsync(sut.PublicState)) |
||||
|
.MustHaveHappened(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_invoke_persistence_on_clear() |
||||
|
{ |
||||
|
await sut.ActivateAsync(id); |
||||
|
await sut.PublicClearAsync(); |
||||
|
|
||||
|
A.CallTo(() => persistence.DeleteAsync()) |
||||
|
.MustHaveHappened(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,101 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using FakeItEasy; |
||||
|
using Squidex.Infrastructure.States; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Squidex.Infrastructure.Orleans |
||||
|
{ |
||||
|
public class GrainOfStringTests |
||||
|
{ |
||||
|
private readonly IPersistence<MyGrain.GrainState> persistence = A.Fake<IPersistence<MyGrain.GrainState>>(); |
||||
|
private readonly IStore<string> store = A.Fake<IStore<string>>(); |
||||
|
private readonly string id = Guid.NewGuid().ToString(); |
||||
|
private readonly MyGrain sut; |
||||
|
private HandleSnapshot<MyGrain.GrainState> read; |
||||
|
|
||||
|
public sealed class MyGrain : GrainOfString<MyGrain.GrainState> |
||||
|
{ |
||||
|
public sealed class GrainState |
||||
|
{ |
||||
|
public string Id { get; set; } |
||||
|
} |
||||
|
|
||||
|
public GrainState PublicState |
||||
|
{ |
||||
|
get { return State; } |
||||
|
} |
||||
|
|
||||
|
public MyGrain(IStore<string> store) |
||||
|
: base(store) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public Task PublicWriteAsync() |
||||
|
{ |
||||
|
return WriteStateAsync(); |
||||
|
} |
||||
|
|
||||
|
public Task PublicClearAsync() |
||||
|
{ |
||||
|
return ClearStateAsync(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public GrainOfStringTests() |
||||
|
{ |
||||
|
A.CallTo(() => persistence.ReadAsync(EtagVersion.Any)) |
||||
|
.Invokes(_ => |
||||
|
{ |
||||
|
read(new MyGrain.GrainState { Id = id }); |
||||
|
}); |
||||
|
|
||||
|
A.CallTo(() => store.WithSnapshots(typeof(MyGrain), id, A<HandleSnapshot<MyGrain.GrainState>>.Ignored)) |
||||
|
.Invokes(new Action<Type, string, HandleSnapshot<MyGrain.GrainState>>((type, id, callback) => |
||||
|
{ |
||||
|
read = callback; |
||||
|
})) |
||||
|
.Returns(persistence); |
||||
|
|
||||
|
sut = new MyGrain(store); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_read_on_activate() |
||||
|
{ |
||||
|
await sut.ActivateAsync(id); |
||||
|
|
||||
|
Assert.Equal(id, sut.PublicState.Id); |
||||
|
|
||||
|
A.CallTo(() => persistence.ReadAsync(EtagVersion.Any)) |
||||
|
.MustHaveHappened(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_invoke_persistence_on_write() |
||||
|
{ |
||||
|
await sut.ActivateAsync(id); |
||||
|
await sut.PublicWriteAsync(); |
||||
|
|
||||
|
A.CallTo(() => persistence.WriteSnapshotAsync(sut.PublicState)) |
||||
|
.MustHaveHappened(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_invoke_persistence_on_clear() |
||||
|
{ |
||||
|
await sut.ActivateAsync(id); |
||||
|
await sut.PublicClearAsync(); |
||||
|
|
||||
|
A.CallTo(() => persistence.DeleteAsync()) |
||||
|
.MustHaveHappened(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue