From 404acb31adb14ff67dea9fd46efe687baa945a18 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Fri, 11 Jan 2019 22:15:34 +0100 Subject: [PATCH] Grain improved. --- .../HandleRules/IRuleTriggerHandler.cs | 2 +- .../HandleRules/RuleService.cs | 4 +- .../HandleRules/RuleTriggerHandler.cs | 7 +- .../Triggers/AssetChangedTriggerHandler.cs | 1 - .../Triggers/ContentChangedTriggerHandler.cs | 2 +- .../Triggers/UsageTriggerHandler.cs | 4 +- .../Apps/InviteUserCommandMiddleware.cs | 2 +- .../Rules/EventEnricher.cs | 2 +- .../Rules/RuleEnqueuer.cs | 2 +- .../Rules/UsageTracking/IUsageTrackerGrain.cs | 10 +-- .../Rules/UsageTracking/UsageTrackerGrain.cs | 54 ++++++++++----- .../UsageTracking/UsageTriggerHandler.cs | 69 ------------------- .../AppUsageExceeded.cs | 7 +- .../Commands/CommandContext.cs | 5 ++ .../Apps/AppContributorsController.cs | 5 +- .../Controllers/Plans/AppPlansController.cs | 2 +- .../ETagCommandMiddleware.cs | 2 +- .../HandleRules/RuleServiceTests.cs | 69 ++++++++++--------- .../Triggers/AssetChangedTriggerTests.cs | 4 +- .../Triggers/ContentChangedTriggerTests.cs | 11 +-- .../Triggers/UsageTriggerHandlerTests.cs | 20 +++--- .../Rules/RuleEnqueuerTests.cs | 18 ++--- .../Commands/CommandContextTests.cs | 19 ++++- 23 files changed, 144 insertions(+), 177 deletions(-) delete mode 100644 src/Squidex.Domain.Apps.Entities/Rules/UsageTracking/UsageTriggerHandler.cs diff --git a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/IRuleTriggerHandler.cs b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/IRuleTriggerHandler.cs index 023d0908d..5b27a05b9 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/IRuleTriggerHandler.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/IRuleTriggerHandler.cs @@ -18,6 +18,6 @@ namespace Squidex.Domain.Apps.Core.HandleRules bool Trigger(EnrichedEvent @event, RuleTrigger trigger); - bool Trigger(IEvent @event, RuleTrigger trigger); + bool Trigger(IEvent @event, RuleTrigger trigger, Guid ruleId); } } diff --git a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleService.cs b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleService.cs index 14db51bf2..b7a0050b7 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleService.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleService.cs @@ -56,7 +56,7 @@ namespace Squidex.Domain.Apps.Core.HandleRules this.clock = clock; } - public virtual async Task CreateJobAsync(Rule rule, Envelope @event) + public virtual async Task CreateJobAsync(Rule rule, Guid ruleId, Envelope @event) { Guard.NotNull(rule, nameof(rule)); Guard.NotNull(@event, nameof(@event)); @@ -83,7 +83,7 @@ namespace Squidex.Domain.Apps.Core.HandleRules return null; } - if (!triggerHandler.Trigger(@event.Payload, rule.Trigger)) + if (!triggerHandler.Trigger(@event.Payload, rule.Trigger, ruleId)) { return null; } diff --git a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleTriggerHandler.cs b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleTriggerHandler.cs index 334e759d1..7e62cad86 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleTriggerHandler.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleTriggerHandler.cs @@ -6,7 +6,6 @@ // ========================================================================== using System; -using System.Threading.Tasks; using Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents; using Squidex.Domain.Apps.Core.Rules; using Squidex.Infrastructure.EventSourcing; @@ -28,14 +27,14 @@ namespace Squidex.Domain.Apps.Core.HandleRules return @event is TEnrichedEvent e && Trigger(e, (TTrigger)trigger); } - bool IRuleTriggerHandler.Trigger(IEvent @event, RuleTrigger trigger) + bool IRuleTriggerHandler.Trigger(IEvent @event, RuleTrigger trigger, Guid ruleId) { - return @event is TEvent e && Trigger(e, (TTrigger)trigger); + return @event is TEvent e && Trigger(e, (TTrigger)trigger, ruleId); } protected abstract bool Trigger(TEnrichedEvent @event, TTrigger trigger); - protected virtual bool Trigger(TEvent @event, TTrigger trigger) + protected virtual bool Trigger(TEvent @event, TTrigger trigger, Guid ruleId) { return true; } diff --git a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/Triggers/AssetChangedTriggerHandler.cs b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/Triggers/AssetChangedTriggerHandler.cs index 8daa7db20..e75e41b8a 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/Triggers/AssetChangedTriggerHandler.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/Triggers/AssetChangedTriggerHandler.cs @@ -5,7 +5,6 @@ // 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.Core.Scripting; diff --git a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/Triggers/ContentChangedTriggerHandler.cs b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/Triggers/ContentChangedTriggerHandler.cs index 21bc4124c..1c95e6734 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/Triggers/ContentChangedTriggerHandler.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/Triggers/ContentChangedTriggerHandler.cs @@ -25,7 +25,7 @@ namespace Squidex.Domain.Apps.Core.HandleRules.Triggers this.scriptEngine = scriptEngine; } - protected override bool Trigger(ContentEvent @event, ContentChangedTriggerV2 trigger) + protected override bool Trigger(ContentEvent @event, ContentChangedTriggerV2 trigger, Guid ruleId) { if (trigger.HandleAll) { diff --git a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/Triggers/UsageTriggerHandler.cs b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/Triggers/UsageTriggerHandler.cs index f3bb0965f..71ed317f4 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/Triggers/UsageTriggerHandler.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/Triggers/UsageTriggerHandler.cs @@ -5,11 +5,9 @@ // 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 { @@ -17,7 +15,7 @@ namespace Squidex.Domain.Apps.Core.HandleRules.Triggers { protected override bool Trigger(EnrichedUsageExceededEvent @event, UsageTrigger trigger) { - return true; + return @event.Limit == trigger.Limit; } } } diff --git a/src/Squidex.Domain.Apps.Entities/Apps/InviteUserCommandMiddleware.cs b/src/Squidex.Domain.Apps.Entities/Apps/InviteUserCommandMiddleware.cs index 9372b80b5..a82031519 100644 --- a/src/Squidex.Domain.Apps.Entities/Apps/InviteUserCommandMiddleware.cs +++ b/src/Squidex.Domain.Apps.Entities/Apps/InviteUserCommandMiddleware.cs @@ -35,7 +35,7 @@ namespace Squidex.Domain.Apps.Entities.Apps await next(); - if (isInvited && context.Result() is EntityCreatedResult id) + if (isInvited && context.PlainResult is EntityCreatedResult id) { context.Complete(new InvitedResult { Id = id }); } diff --git a/src/Squidex.Domain.Apps.Entities/Rules/EventEnricher.cs b/src/Squidex.Domain.Apps.Entities/Rules/EventEnricher.cs index 99e915073..803d90884 100644 --- a/src/Squidex.Domain.Apps.Entities/Rules/EventEnricher.cs +++ b/src/Squidex.Domain.Apps.Entities/Rules/EventEnricher.cs @@ -72,7 +72,7 @@ namespace Squidex.Domain.Apps.Entities.Rules case AppUsageExceeded usageExceeded: { - var result = new EnrichedUsageExceededEvent { Current = usageExceeded.Current, Limit = usageExceeded.Limit }; + var result = new EnrichedUsageExceededEvent { Current = usageExceeded.CallsCurrent, Limit = usageExceeded.CallsLimit }; await EnrichDefaultAsync(result, @event); diff --git a/src/Squidex.Domain.Apps.Entities/Rules/RuleEnqueuer.cs b/src/Squidex.Domain.Apps.Entities/Rules/RuleEnqueuer.cs index e1710013e..e485d324e 100644 --- a/src/Squidex.Domain.Apps.Entities/Rules/RuleEnqueuer.cs +++ b/src/Squidex.Domain.Apps.Entities/Rules/RuleEnqueuer.cs @@ -65,7 +65,7 @@ namespace Squidex.Domain.Apps.Entities.Rules foreach (var ruleEntity in rules) { - var job = await ruleService.CreateJobAsync(ruleEntity.RuleDef, @event); + var job = await ruleService.CreateJobAsync(ruleEntity.RuleDef, ruleEntity.Id, @event); if (job != null) { diff --git a/src/Squidex.Domain.Apps.Entities/Rules/UsageTracking/IUsageTrackerGrain.cs b/src/Squidex.Domain.Apps.Entities/Rules/UsageTracking/IUsageTrackerGrain.cs index 19deb0be8..812b2862b 100644 --- a/src/Squidex.Domain.Apps.Entities/Rules/UsageTracking/IUsageTrackerGrain.cs +++ b/src/Squidex.Domain.Apps.Entities/Rules/UsageTracking/IUsageTrackerGrain.cs @@ -14,12 +14,14 @@ namespace Squidex.Domain.Apps.Entities.Rules.UsageTracking { public interface IUsageTrackerGrain : IGrainWithStringKey { - Task AddTargetAsync(NamedId appId, int limits); + Task AddTargetAsync(Guid ruleId, NamedId appId, int limits); - Task ActivateTargetAsync(NamedId appId); + Task ActivateTargetAsync(Guid ruleId); - Task DeactivateTargetAsync(NamedId appId); + Task DeactivateTargetAsync(Guid ruleId); - Task RemoveTargetAsync(NamedId appId); + Task RemoveTargetAsync(Guid ruleId); + + Task UpdateTargetAsync(Guid ruleId, int limits); } } \ No newline at end of file diff --git a/src/Squidex.Domain.Apps.Entities/Rules/UsageTracking/UsageTrackerGrain.cs b/src/Squidex.Domain.Apps.Entities/Rules/UsageTracking/UsageTrackerGrain.cs index d1607d097..1ebc89e37 100644 --- a/src/Squidex.Domain.Apps.Entities/Rules/UsageTracking/UsageTrackerGrain.cs +++ b/src/Squidex.Domain.Apps.Entities/Rules/UsageTracking/UsageTrackerGrain.cs @@ -24,17 +24,19 @@ namespace Squidex.Domain.Apps.Entities.Rules.UsageTracking public sealed class Target { - public int Limit { get; set; } + public int Limits { get; set; } - public bool Enabled { get; set; } + public bool Disabled { get; set; } public DateTime Triggered { get; set; } + + public NamedId AppId { get; set; } } [CollectionName("UsageTracker")] public sealed class GrainState { - public Dictionary, Target> Targets { get; set; } = new Dictionary, Target>(); + public Dictionary Targets { get; set; } = new Dictionary(); } public UsageTrackerGrain(IStore store, IUsageTracker usageTracker) @@ -60,19 +62,25 @@ namespace Squidex.Domain.Apps.Entities.Rules.UsageTracking foreach (var kvp in State.Targets) { - var appId = kvp.Key; + var appId = kvp.Value.AppId; if (!IsSameMonth(today, kvp.Value.Triggered)) { var usage = await usageTracker.GetMonthlyCallsAsync(appId.Id.ToString(), today); - var limit = kvp.Value.Limit; + var limit = kvp.Value.Limits; if (usage > limit) { kvp.Value.Triggered = today; - var @event = new AppUsageExceeded { AppId = appId, Current = usage, Limit = limit }; + var @event = new AppUsageExceeded + { + AppId = appId, + CallsCurrent = usage, + CallsLimit = limit, + RuleId = kvp.Key + }; await Persistence.WriteEventAsync(@event); } @@ -87,37 +95,51 @@ namespace Squidex.Domain.Apps.Entities.Rules.UsageTracking return lhs.Year == rhs.Year && lhs.Month == rhs.Month; } - public Task ActivateTargetAsync(NamedId appId) + public Task AddTargetAsync(Guid ruleId, NamedId appId, int limits) + { + UpdateTarget(ruleId, t => { t.Limits = limits; t.AppId = appId; }); + + return WriteStateAsync(); + } + + public Task UpdateTargetAsync(Guid ruleId, int limits) + { + UpdateTarget(ruleId, t => t.Limits = limits); + + return WriteStateAsync(); + } + + public Task ActivateTargetAsync(Guid ruleId) { - UpdateTarget(appId, t => t.Enabled = true); + UpdateTarget(ruleId, t => t.Disabled = false); return WriteStateAsync(); } - public Task DeactivateTargetAsync(NamedId appId) + public Task DeactivateTargetAsync(Guid ruleId) { - UpdateTarget(appId, t => t.Enabled = false); + UpdateTarget(ruleId, t => t.Disabled = true); return WriteStateAsync(); } - public Task AddTargetAsync(NamedId appId, int limits) + public Task AddTargetAsync(Guid ruleId, int limits) { - UpdateTarget(appId, t => t.Limit = limits); + UpdateTarget(ruleId, t => t.Limits = limits); return WriteStateAsync(); } - public Task RemoveTargetAsync(NamedId appId) + public Task RemoveTargetAsync(Guid ruleId) { - State.Targets.Remove(appId); + State.Targets.Remove(ruleId); return WriteStateAsync(); } - private void UpdateTarget(NamedId appId, Action updater) + private void UpdateTarget(Guid ruleId, Action updater) { - updater(State.Targets.GetOrAddNew(appId));; + updater(State.Targets.GetOrAddNew(ruleId)); } } } diff --git a/src/Squidex.Domain.Apps.Entities/Rules/UsageTracking/UsageTriggerHandler.cs b/src/Squidex.Domain.Apps.Entities/Rules/UsageTracking/UsageTriggerHandler.cs deleted file mode 100644 index c33e903a8..000000000 --- a/src/Squidex.Domain.Apps.Entities/Rules/UsageTracking/UsageTriggerHandler.cs +++ /dev/null @@ -1,69 +0,0 @@ -//// ========================================================================== -//// Squidex Headless CMS -//// ========================================================================== -//// Copyright (c) Squidex UG (haftungsbeschraenkt) -//// All rights reserved. Licensed under the MIT license. -//// ========================================================================== - -//using System.Threading.Tasks; -//using Orleans; -//using Squidex.Domain.Apps.Core.HandleRules; -//using Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents; -//using Squidex.Domain.Apps.Core.Rules.Triggers; -//using Squidex.Domain.Apps.Events; -//using Squidex.Domain.Apps.Events.Rules; -//using Squidex.Infrastructure; -//using Squidex.Infrastructure.Orleans; -//using Squidex.Infrastructure.Tasks; - -//namespace Squidex.Domain.Apps.Entities.Rules.UsageTracking -//{ -// public sealed class UsageTriggerHandler : RuleTriggerHandler -// { -// private readonly IUsageTrackerGrain usageTrackerGrain; - -// public UsageTriggerHandler(IGrainFactory grainFactory) -// { -// Guard.NotNull(grainFactory, nameof(grainFactory)); - -// usageTrackerGrain = grainFactory.GetGrain(SingleGrain.Id); -// } - -// protected override async Task Trigger(AppEvent @event, UsageTrigger trigger) -// { -// switch (@event) -// { -// case RuleDeleted _: -// await usageTrackerGrain.RemoveTargetAsync(@event.AppId); -// break; -// case RuleEnabled _: -// await usageTrackerGrain.ActivateTargetAsync(@event.AppId); -// break; -// case RuleDisabled _: -// await usageTrackerGrain.DeactivateTargetAsync(@event.AppId); -// break; -// case RuleCreated ruleCreated: -// if (ruleCreated.Trigger is UsageTrigger createdTrigger) -// { -// await usageTrackerGrain.AddTargetAsync(ruleCreated.AppId, createdTrigger.Limit); -// } - -// break; -// case RuleUpdated ruleUpdated: -// if (ruleUpdated.Trigger is UsageTrigger updatedTrigger) -// { -// await usageTrackerGrain.AddTargetAsync(ruleUpdated.AppId, updatedTrigger.Limit); -// } - -// break; -// } - -// return @event is AppUsageExceeded; -// } - -// protected override Task Trigger(EnrichedUsageExceededEvent @event, UsageTrigger trigger) -// { -// return TaskHelper.True; -// } -// } -//} diff --git a/src/Squidex.Domain.Apps.Events/AppUsageExceeded.cs b/src/Squidex.Domain.Apps.Events/AppUsageExceeded.cs index dc1313ee6..c7b6c6d8d 100644 --- a/src/Squidex.Domain.Apps.Events/AppUsageExceeded.cs +++ b/src/Squidex.Domain.Apps.Events/AppUsageExceeded.cs @@ -5,6 +5,7 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System; using Squidex.Infrastructure.EventSourcing; namespace Squidex.Domain.Apps.Events @@ -12,8 +13,10 @@ namespace Squidex.Domain.Apps.Events [EventType(nameof(AppUsageExceeded))] public sealed class AppUsageExceeded : AppEvent { - public long Current { get; set; } + public long CallsCurrent { get; set; } - public long Limit { get; set; } + public long CallsLimit { get; set; } + + public Guid RuleId { get; set; } } } diff --git a/src/Squidex.Infrastructure/Commands/CommandContext.cs b/src/Squidex.Infrastructure/Commands/CommandContext.cs index 22cea0840..0b50bb495 100644 --- a/src/Squidex.Infrastructure/Commands/CommandContext.cs +++ b/src/Squidex.Infrastructure/Commands/CommandContext.cs @@ -19,6 +19,11 @@ namespace Squidex.Infrastructure.Commands public ICommandBus CommandBus { get; } + public object PlainResult + { + get { return result?.Item1; } + } + public bool IsCompleted { get { return result != null; } diff --git a/src/Squidex/Areas/Api/Controllers/Apps/AppContributorsController.cs b/src/Squidex/Areas/Api/Controllers/Apps/AppContributorsController.cs index 30baf7b0b..571d9be66 100644 --- a/src/Squidex/Areas/Api/Controllers/Apps/AppContributorsController.cs +++ b/src/Squidex/Areas/Api/Controllers/Apps/AppContributorsController.cs @@ -75,14 +75,13 @@ namespace Squidex.Areas.Api.Controllers.Apps var command = request.ToCommand(); var context = await CommandBus.PublishAsync(command); - var result = context.Result(); var response = (ContributorAssignedDto)null; - if (result is EntityCreatedResult idOrValue) + if (context.PlainResult is EntityCreatedResult idOrValue) { response = ContributorAssignedDto.FromId(idOrValue.IdOrValue, false); } - else if (result is InvitedResult invited) + else if (context.PlainResult is InvitedResult invited) { response = ContributorAssignedDto.FromId(invited.Id.IdOrValue, true); } diff --git a/src/Squidex/Areas/Api/Controllers/Plans/AppPlansController.cs b/src/Squidex/Areas/Api/Controllers/Plans/AppPlansController.cs index caf36e07a..5b5a8fe65 100644 --- a/src/Squidex/Areas/Api/Controllers/Plans/AppPlansController.cs +++ b/src/Squidex/Areas/Api/Controllers/Plans/AppPlansController.cs @@ -80,7 +80,7 @@ namespace Squidex.Areas.Api.Controllers.Plans string redirectUri = null; - if (context.Result() is RedirectToCheckoutResult result) + if (context.PlainResult is RedirectToCheckoutResult result) { redirectUri = result.Url.ToString(); } diff --git a/src/Squidex/Pipeline/CommandMiddlewares/ETagCommandMiddleware.cs b/src/Squidex/Pipeline/CommandMiddlewares/ETagCommandMiddleware.cs index fb4c74dfa..ef14a8bb0 100644 --- a/src/Squidex/Pipeline/CommandMiddlewares/ETagCommandMiddleware.cs +++ b/src/Squidex/Pipeline/CommandMiddlewares/ETagCommandMiddleware.cs @@ -54,7 +54,7 @@ namespace Squidex.Pipeline.CommandMiddlewares await next(); - if (context.Result() is EntitySavedResult result) + if (context.PlainResult is EntitySavedResult result) { httpContextAccessor.HttpContext.Response.Headers[HeaderNames.ETag] = result.Version.ToString(); } diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleServiceTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleServiceTests.cs index d69dddfcc..537de9762 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleServiceTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleServiceTests.cs @@ -33,6 +33,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules private readonly string actionDump = "MyDump"; private readonly string actionName = "ValidAction"; private readonly string actionDescription = "MyDescription"; + private readonly Guid ruleId = Guid.NewGuid(); private readonly NamedId appId = NamedId.Of(Guid.NewGuid(), "my-app"); private readonly NamedId schemaId = NamedId.Of(Guid.NewGuid(), "my-schema"); private readonly TypeNameRegistry typeNameRegistry = new TypeNameRegistry(); @@ -87,10 +88,10 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules [Fact] public async Task Should_not_create_if_rule_disabled() { - var ruleConfig = ValidRule().Disable(); - var ruleEnvelope = Envelope.Create(new ContentCreated()); + var rule = ValidRule().Disable(); + var ruleEvent = Envelope.Create(new ContentCreated()); - var job = await sut.CreateJobAsync(ruleConfig, ruleEnvelope); + var job = await sut.CreateJobAsync(rule, ruleId, ruleEvent); Assert.Null(job); @@ -101,10 +102,10 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules [Fact] public async Task Should_not_create_job_for_invalid_event() { - var ruleConfig = ValidRule(); - var ruleEnvelope = Envelope.Create(new InvalidEvent()); + var rule = ValidRule(); + var ruleEvent = Envelope.Create(new InvalidEvent()); - var job = await sut.CreateJobAsync(ruleConfig, ruleEnvelope); + var job = await sut.CreateJobAsync(rule, ruleId, ruleEvent); Assert.Null(job); @@ -115,10 +116,10 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules [Fact] public async Task Should_not_create_job_if_no_trigger_handler_registered() { - var ruleConfig = new Rule(new InvalidTrigger(), new ValidAction()); - var ruleEnvelope = Envelope.Create(new ContentCreated()); + var rule = new Rule(new InvalidTrigger(), new ValidAction()); + var ruleEvent = Envelope.Create(new ContentCreated()); - var job = await sut.CreateJobAsync(ruleConfig, ruleEnvelope); + var job = await sut.CreateJobAsync(rule, ruleId, ruleEvent); Assert.Null(job); @@ -129,10 +130,10 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules [Fact] public async Task Should_not_create_job_if_no_action_handler_registered() { - var ruleConfig = new Rule(new ContentChangedTriggerV2(), new InvalidAction()); - var ruleEnvelope = Envelope.Create(new ContentCreated()); + var rule = new Rule(new ContentChangedTriggerV2(), new InvalidAction()); + var ruleEvent = Envelope.Create(new ContentCreated()); - var job = await sut.CreateJobAsync(ruleConfig, ruleEnvelope); + var job = await sut.CreateJobAsync(rule, ruleId, ruleEvent); Assert.Null(job); @@ -143,13 +144,13 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules [Fact] public async Task Should_not_create_job_if_not_triggered_with_precheck() { - var ruleConfig = ValidRule(); - var ruleEnvelope = Envelope.Create(new ContentCreated()); + var rule = ValidRule(); + var ruleEvent = Envelope.Create(new ContentCreated()); - A.CallTo(() => ruleTriggerHandler.Trigger(A.Ignored, ruleConfig.Trigger)) + A.CallTo(() => ruleTriggerHandler.Trigger(A.Ignored, rule.Trigger, ruleId)) .Returns(false); - var job = await sut.CreateJobAsync(ruleConfig, ruleEnvelope); + var job = await sut.CreateJobAsync(rule, ruleId, ruleEvent); Assert.Null(job); @@ -160,16 +161,16 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules [Fact] public async Task Should_not_create_job_if_not_triggered() { - var ruleConfig = ValidRule(); - var ruleEnvelope = Envelope.Create(new ContentCreated()); + var rule = ValidRule(); + var ruleEvent = Envelope.Create(new ContentCreated()); - A.CallTo(() => ruleTriggerHandler.Trigger(A.Ignored, ruleConfig.Trigger)) + A.CallTo(() => ruleTriggerHandler.Trigger(A.Ignored, rule.Trigger, ruleId)) .Returns(true); - A.CallTo(() => ruleTriggerHandler.Trigger(A.Ignored, ruleConfig.Trigger)) + A.CallTo(() => ruleTriggerHandler.Trigger(A.Ignored, rule.Trigger)) .Returns(false); - var job = await sut.CreateJobAsync(ruleConfig, ruleEnvelope); + var job = await sut.CreateJobAsync(rule, ruleId, ruleEvent); Assert.Null(job); } @@ -177,22 +178,22 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules [Fact] public async Task Should_not_create_job_if_too_old() { - var @event = new ContentCreated { SchemaId = schemaId, AppId = appId }; + var ruleEvent = new ContentCreated { SchemaId = schemaId, AppId = appId }; var now = SystemClock.Instance.GetCurrentInstant(); - var ruleConfig = ValidRule(); - var ruleEnvelope = Envelope.Create(@event); + var rule = ValidRule(); + var ruleEnvelope = Envelope.Create(ruleEvent); ruleEnvelope.SetTimestamp(now.Minus(Duration.FromDays(3))); A.CallTo(() => clock.GetCurrentInstant()) .Returns(now); - A.CallTo(() => ruleActionHandler.CreateJobAsync(A.Ignored, ruleConfig.Action)) + A.CallTo(() => ruleActionHandler.CreateJobAsync(A.Ignored, rule.Action)) .Returns((actionDescription, actionData)); - var job = await sut.CreateJobAsync(ruleConfig, ruleEnvelope); + var job = await sut.CreateJobAsync(rule, ruleId, ruleEnvelope); Assert.Null(job); @@ -203,28 +204,28 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules [Fact] public async Task Should_create_job_if_triggered() { - var @event = new ContentCreated { SchemaId = schemaId, AppId = appId }; + var ruleEvent = new ContentCreated { SchemaId = schemaId, AppId = appId }; var now = Instant.FromUnixTimeSeconds(SystemClock.Instance.GetCurrentInstant().ToUnixTimeSeconds()); - var ruleConfig = ValidRule(); - var ruleEnvelope = Envelope.Create(@event); + var rule = ValidRule(); + var ruleEnvelope = Envelope.Create(ruleEvent); ruleEnvelope.SetTimestamp(now); A.CallTo(() => clock.GetCurrentInstant()) .Returns(now); - A.CallTo(() => ruleTriggerHandler.Trigger(A.Ignored, ruleConfig.Trigger)) + A.CallTo(() => ruleTriggerHandler.Trigger(A.Ignored, rule.Trigger)) .Returns(true); - A.CallTo(() => ruleTriggerHandler.Trigger(A.Ignored, ruleConfig.Trigger)) + A.CallTo(() => ruleTriggerHandler.Trigger(A.Ignored, rule.Trigger, ruleId)) .Returns(true); - A.CallTo(() => ruleActionHandler.CreateJobAsync(A.Ignored, ruleConfig.Action)) + A.CallTo(() => ruleActionHandler.CreateJobAsync(A.Ignored, rule.Action)) .Returns((actionDescription, new ValidData { Value = 10 })); - var job = await sut.CreateJobAsync(ruleConfig, ruleEnvelope); + var job = await sut.CreateJobAsync(rule, ruleId, ruleEnvelope); Assert.Equal(actionData, job.ActionData); Assert.Equal(actionName, job.ActionName); @@ -233,7 +234,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules Assert.Equal(now, job.Created); Assert.Equal(now.Plus(Duration.FromDays(2)), job.Expires); - Assert.Equal(@event.AppId.Id, job.AppId); + Assert.Equal(ruleEvent.AppId.Id, job.AppId); Assert.NotEqual(Guid.Empty, job.JobId); } diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/Triggers/AssetChangedTriggerTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/Triggers/AssetChangedTriggerTests.cs index 4bc0ff28f..3ea7cdeb2 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/Triggers/AssetChangedTriggerTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/Triggers/AssetChangedTriggerTests.cs @@ -39,7 +39,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules.Triggers { TestForCondition(string.Empty, trigger => { - var result = sut.Trigger(new ContentCreated(), trigger); + var result = sut.Trigger(new ContentCreated(), trigger, Guid.NewGuid()); Assert.False(result); }); @@ -50,7 +50,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules.Triggers { TestForCondition(string.Empty, trigger => { - var result = sut.Trigger(new AssetCreated(), trigger); + var result = sut.Trigger(new AssetCreated(), trigger, Guid.NewGuid()); Assert.True(result); }); diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/Triggers/ContentChangedTriggerTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/Triggers/ContentChangedTriggerTests.cs index a9e5bc937..467cb9378 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/Triggers/ContentChangedTriggerTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/Triggers/ContentChangedTriggerTests.cs @@ -28,6 +28,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules.Triggers { private readonly IScriptEngine scriptEngine = A.Fake(); private readonly IRuleTriggerHandler sut; + private readonly Guid ruleId = Guid.NewGuid(); private static readonly NamedId SchemaMatch = NamedId.Of(Guid.NewGuid(), "my-schema1"); private static readonly NamedId SchemaNonMatch = NamedId.Of(Guid.NewGuid(), "my-schema2"); @@ -47,7 +48,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules.Triggers { TestForTrigger(handleAll: true, schemaId: null, condition: null, action: trigger => { - var result = sut.Trigger(new AssetCreated(), trigger); + var result = sut.Trigger(new AssetCreated(), trigger, ruleId); Assert.False(result); }); @@ -58,7 +59,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules.Triggers { TestForTrigger(handleAll: false, schemaId: null, condition: null, action: trigger => { - var result = sut.Trigger(new ContentCreated { SchemaId = SchemaMatch }, trigger); + var result = sut.Trigger(new ContentCreated { SchemaId = SchemaMatch }, trigger, ruleId); Assert.False(result); }); @@ -69,7 +70,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules.Triggers { TestForTrigger(handleAll: true, schemaId: SchemaMatch, condition: null, action: trigger => { - var result = sut.Trigger(new ContentCreated { SchemaId = SchemaMatch }, trigger); + var result = sut.Trigger(new ContentCreated { SchemaId = SchemaMatch }, trigger, ruleId); Assert.True(result); }); @@ -80,7 +81,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules.Triggers { TestForTrigger(handleAll: false, schemaId: SchemaMatch, condition: string.Empty, action: trigger => { - var result = sut.Trigger(new ContentCreated { SchemaId = SchemaMatch }, trigger); + var result = sut.Trigger(new ContentCreated { SchemaId = SchemaMatch }, trigger, ruleId); Assert.True(result); }); @@ -91,7 +92,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules.Triggers { TestForTrigger(handleAll: false, schemaId: SchemaNonMatch, condition: null, action: trigger => { - var result = sut.Trigger(new ContentCreated { SchemaId = SchemaMatch }, trigger); + var result = sut.Trigger(new ContentCreated { SchemaId = SchemaMatch }, trigger, ruleId); Assert.False(result); }); diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/Triggers/UsageTriggerHandlerTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/Triggers/UsageTriggerHandlerTests.cs index b3eb86013..def006016 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/Triggers/UsageTriggerHandlerTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/Triggers/UsageTriggerHandlerTests.cs @@ -5,6 +5,7 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System; using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents; using Squidex.Domain.Apps.Core.HandleRules.Triggers; @@ -17,38 +18,39 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules.Triggers { public class UsageTriggerHandlerTests { + private readonly Guid ruleId = Guid.NewGuid(); 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()); + var result = sut.Trigger(new ContentCreated(), new UsageTrigger(), ruleId); Assert.False(result); } [Fact] - public void Should_trigger_precheck_when_event_type_correct() + public void Should_not_trigger_precheck_when_rule_id_not_matchs() { - var result = sut.Trigger(new AppUsageExceeded(), new UsageTrigger()); + var result = sut.Trigger(new AppUsageExceeded { RuleId = Guid.NewGuid() }, new UsageTrigger(), ruleId); Assert.True(result); } [Fact] - public void Should_not_trigger_check_when_event_type_not_correct() + public void Should_trigger_precheck_when_event_type_correct_and_rule_id_matchs() { - var result = sut.Trigger(new EnrichedContentEvent(), new UsageTrigger()); + var result = sut.Trigger(new AppUsageExceeded { RuleId = ruleId }, new UsageTrigger(), ruleId); - Assert.False(result); + Assert.True(result); } [Fact] - public void Should_trigger_check_when_type_correct() + public void Should_not_trigger_check_when_event_type_not_correct() { - var result = sut.Trigger(new AppUsageExceeded(), new UsageTrigger()); + var result = sut.Trigger(new EnrichedContentEvent(), new UsageTrigger()); - Assert.True(result); + Assert.False(result); } } } diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Rules/RuleEnqueuerTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Rules/RuleEnqueuerTests.cs index 0822d1b77..a38e3a2da 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Rules/RuleEnqueuerTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Rules/RuleEnqueuerTests.cs @@ -28,9 +28,9 @@ namespace Squidex.Domain.Apps.Entities.Rules private readonly IAppProvider appProvider = A.Fake(); private readonly IMemoryCache cache = new MemoryCache(Options.Create(new MemoryCacheOptions())); private readonly IRuleEventRepository ruleEventRepository = A.Fake(); - private readonly RuleService ruleService = A.Fake(); private readonly Instant now = SystemClock.Instance.GetCurrentInstant(); private readonly NamedId appId = NamedId.Of(Guid.NewGuid(), "my-app"); + private readonly RuleService ruleService = A.Fake(); private readonly RuleEnqueuer sut; public sealed class TestAction : RuleAction @@ -72,38 +72,28 @@ namespace Squidex.Domain.Apps.Entities.Rules var rule1 = new Rule(new ContentChangedTriggerV2(), new TestAction { Url = new Uri("https://squidex.io") }); var rule2 = new Rule(new ContentChangedTriggerV2(), new TestAction { Url = new Uri("https://squidex.io") }); - var rule3 = new Rule(new ContentChangedTriggerV2(), new TestAction { Url = new Uri("https://squidex.io") }); var job1 = new RuleJob { Created = now }; - var job2 = new RuleJob { Created = now }; var ruleEntity1 = A.Fake(); var ruleEntity2 = A.Fake(); - var ruleEntity3 = A.Fake(); A.CallTo(() => ruleEntity1.RuleDef).Returns(rule1); A.CallTo(() => ruleEntity2.RuleDef).Returns(rule2); - A.CallTo(() => ruleEntity3.RuleDef).Returns(rule3); A.CallTo(() => appProvider.GetRulesAsync(appId.Id)) - .Returns(new List { ruleEntity1, ruleEntity2, ruleEntity3 }); + .Returns(new List { ruleEntity1, ruleEntity2 }); - A.CallTo(() => ruleService.CreateJobAsync(rule1, @event)) + A.CallTo(() => ruleService.CreateJobAsync(rule1, ruleEntity1.Id, @event)) .Returns(job1); - A.CallTo(() => ruleService.CreateJobAsync(rule2, @event)) - .Returns(job2); - - A.CallTo(() => ruleService.CreateJobAsync(rule3, @event)) + A.CallTo(() => ruleService.CreateJobAsync(rule2, ruleEntity2.Id, @event)) .Returns(Task.FromResult(null)); await sut.On(@event); A.CallTo(() => ruleEventRepository.EnqueueAsync(job1, now)) .MustHaveHappened(); - - A.CallTo(() => ruleEventRepository.EnqueueAsync(job2, now)) - .MustHaveHappened(); } } } \ No newline at end of file diff --git a/tests/Squidex.Infrastructure.Tests/Commands/CommandContextTests.cs b/tests/Squidex.Infrastructure.Tests/Commands/CommandContextTests.cs index 3d97d2a33..8d8793984 100644 --- a/tests/Squidex.Infrastructure.Tests/Commands/CommandContextTests.cs +++ b/tests/Squidex.Infrastructure.Tests/Commands/CommandContextTests.cs @@ -26,8 +26,13 @@ namespace Squidex.Infrastructure.Commands public void Should_instantiate_and_provide_command() { Assert.Equal(command, sut.Command); - Assert.False(sut.IsCompleted); + + Assert.Null(sut.PlainResult); + Assert.Null(sut.Result()); + Assert.NotEqual(Guid.Empty, sut.ContextId); + + Assert.False(sut.IsCompleted); } [Fact] @@ -39,9 +44,19 @@ namespace Squidex.Infrastructure.Commands } [Fact] - public void Should_provide_result_valid_when_succeeded_with_value() + public void Should_provide_result_when_succeeded_with_value() + { + sut.Complete("RESULT"); + + Assert.Equal("RESULT", sut.Result()); + } + + [Fact] + public void Should_provide_plain_result_when_succeeded_with_value() { sut.Complete("RESULT"); + + Assert.Equal("RESULT", sut.PlainResult); } } }