Browse Source

Grain improved.

pull/342/head
Sebastian Stehle 7 years ago
parent
commit
404acb31ad
  1. 2
      src/Squidex.Domain.Apps.Core.Operations/HandleRules/IRuleTriggerHandler.cs
  2. 4
      src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleService.cs
  3. 7
      src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleTriggerHandler.cs
  4. 1
      src/Squidex.Domain.Apps.Core.Operations/HandleRules/Triggers/AssetChangedTriggerHandler.cs
  5. 2
      src/Squidex.Domain.Apps.Core.Operations/HandleRules/Triggers/ContentChangedTriggerHandler.cs
  6. 4
      src/Squidex.Domain.Apps.Core.Operations/HandleRules/Triggers/UsageTriggerHandler.cs
  7. 2
      src/Squidex.Domain.Apps.Entities/Apps/InviteUserCommandMiddleware.cs
  8. 2
      src/Squidex.Domain.Apps.Entities/Rules/EventEnricher.cs
  9. 2
      src/Squidex.Domain.Apps.Entities/Rules/RuleEnqueuer.cs
  10. 10
      src/Squidex.Domain.Apps.Entities/Rules/UsageTracking/IUsageTrackerGrain.cs
  11. 54
      src/Squidex.Domain.Apps.Entities/Rules/UsageTracking/UsageTrackerGrain.cs
  12. 69
      src/Squidex.Domain.Apps.Entities/Rules/UsageTracking/UsageTriggerHandler.cs
  13. 7
      src/Squidex.Domain.Apps.Events/AppUsageExceeded.cs
  14. 5
      src/Squidex.Infrastructure/Commands/CommandContext.cs
  15. 5
      src/Squidex/Areas/Api/Controllers/Apps/AppContributorsController.cs
  16. 2
      src/Squidex/Areas/Api/Controllers/Plans/AppPlansController.cs
  17. 2
      src/Squidex/Pipeline/CommandMiddlewares/ETagCommandMiddleware.cs
  18. 69
      tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleServiceTests.cs
  19. 4
      tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/Triggers/AssetChangedTriggerTests.cs
  20. 11
      tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/Triggers/ContentChangedTriggerTests.cs
  21. 20
      tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/Triggers/UsageTriggerHandlerTests.cs
  22. 18
      tests/Squidex.Domain.Apps.Entities.Tests/Rules/RuleEnqueuerTests.cs
  23. 19
      tests/Squidex.Infrastructure.Tests/Commands/CommandContextTests.cs

2
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);
}
}

4
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<RuleJob> CreateJobAsync(Rule rule, Envelope<IEvent> @event)
public virtual async Task<RuleJob> CreateJobAsync(Rule rule, Guid ruleId, Envelope<IEvent> @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;
}

7
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;
}

1
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;

2
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)
{

4
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;
}
}
}

2
src/Squidex.Domain.Apps.Entities/Apps/InviteUserCommandMiddleware.cs

@ -35,7 +35,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
await next();
if (isInvited && context.Result<object>() is EntityCreatedResult<string> id)
if (isInvited && context.PlainResult is EntityCreatedResult<string> id)
{
context.Complete(new InvitedResult { Id = id });
}

2
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);

2
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)
{

10
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<Guid> appId, int limits);
Task AddTargetAsync(Guid ruleId, NamedId<Guid> appId, int limits);
Task ActivateTargetAsync(NamedId<Guid> appId);
Task ActivateTargetAsync(Guid ruleId);
Task DeactivateTargetAsync(NamedId<Guid> appId);
Task DeactivateTargetAsync(Guid ruleId);
Task RemoveTargetAsync(NamedId<Guid> appId);
Task RemoveTargetAsync(Guid ruleId);
Task UpdateTargetAsync(Guid ruleId, int limits);
}
}

54
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<Guid> AppId { get; set; }
}
[CollectionName("UsageTracker")]
public sealed class GrainState
{
public Dictionary<NamedId<Guid>, Target> Targets { get; set; } = new Dictionary<NamedId<Guid>, Target>();
public Dictionary<Guid, Target> Targets { get; set; } = new Dictionary<Guid, Target>();
}
public UsageTrackerGrain(IStore<string> 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<Guid> appId)
public Task AddTargetAsync(Guid ruleId, NamedId<Guid> 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<Guid> appId)
public Task DeactivateTargetAsync(Guid ruleId)
{
UpdateTarget(appId, t => t.Enabled = false);
UpdateTarget(ruleId, t => t.Disabled = true);
return WriteStateAsync();
}
public Task AddTargetAsync(NamedId<Guid> 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<Guid> appId)
public Task RemoveTargetAsync(Guid ruleId)
{
State.Targets.Remove(appId);
State.Targets.Remove(ruleId);
return WriteStateAsync();
}
private void UpdateTarget(NamedId<Guid> appId, Action<Target> updater)
private void UpdateTarget(Guid ruleId, Action<Target> updater)
{
updater(State.Targets.GetOrAddNew(appId));;
updater(State.Targets.GetOrAddNew(ruleId));
}
}
}

69
src/Squidex.Domain.Apps.Entities/Rules/UsageTracking/UsageTriggerHandler.cs

@ -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<UsageTrigger, AppEvent, EnrichedUsageExceededEvent>
// {
// private readonly IUsageTrackerGrain usageTrackerGrain;
// public UsageTriggerHandler(IGrainFactory grainFactory)
// {
// Guard.NotNull(grainFactory, nameof(grainFactory));
// usageTrackerGrain = grainFactory.GetGrain<IUsageTrackerGrain>(SingleGrain.Id);
// }
// protected override async Task<bool> 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<bool> Trigger(EnrichedUsageExceededEvent @event, UsageTrigger trigger)
// {
// return TaskHelper.True;
// }
// }
//}

7
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; }
}
}

5
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; }

5
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<object>();
var response = (ContributorAssignedDto)null;
if (result is EntityCreatedResult<string> idOrValue)
if (context.PlainResult is EntityCreatedResult<string> 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);
}

2
src/Squidex/Areas/Api/Controllers/Plans/AppPlansController.cs

@ -80,7 +80,7 @@ namespace Squidex.Areas.Api.Controllers.Plans
string redirectUri = null;
if (context.Result<object>() is RedirectToCheckoutResult result)
if (context.PlainResult is RedirectToCheckoutResult result)
{
redirectUri = result.Url.ToString();
}

2
src/Squidex/Pipeline/CommandMiddlewares/ETagCommandMiddleware.cs

@ -54,7 +54,7 @@ namespace Squidex.Pipeline.CommandMiddlewares
await next();
if (context.Result<object>() is EntitySavedResult result)
if (context.PlainResult is EntitySavedResult result)
{
httpContextAccessor.HttpContext.Response.Headers[HeaderNames.ETag] = result.Version.ToString();
}

69
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<Guid> appId = NamedId.Of(Guid.NewGuid(), "my-app");
private readonly NamedId<Guid> 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<IEvent>.Ignored, ruleConfig.Trigger))
A.CallTo(() => ruleTriggerHandler.Trigger(A<IEvent>.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<IEvent>.Ignored, ruleConfig.Trigger))
A.CallTo(() => ruleTriggerHandler.Trigger(A<IEvent>.Ignored, rule.Trigger, ruleId))
.Returns(true);
A.CallTo(() => ruleTriggerHandler.Trigger(A<EnrichedEvent>.Ignored, ruleConfig.Trigger))
A.CallTo(() => ruleTriggerHandler.Trigger(A<EnrichedEvent>.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<EnrichedEvent>.Ignored, ruleConfig.Action))
A.CallTo(() => ruleActionHandler.CreateJobAsync(A<EnrichedEvent>.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<EnrichedEvent>.Ignored, ruleConfig.Trigger))
A.CallTo(() => ruleTriggerHandler.Trigger(A<EnrichedEvent>.Ignored, rule.Trigger))
.Returns(true);
A.CallTo(() => ruleTriggerHandler.Trigger(A<IEvent>.Ignored, ruleConfig.Trigger))
A.CallTo(() => ruleTriggerHandler.Trigger(A<IEvent>.Ignored, rule.Trigger, ruleId))
.Returns(true);
A.CallTo(() => ruleActionHandler.CreateJobAsync(A<EnrichedEvent>.Ignored, ruleConfig.Action))
A.CallTo(() => ruleActionHandler.CreateJobAsync(A<EnrichedEvent>.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);
}

4
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);
});

11
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<IScriptEngine>();
private readonly IRuleTriggerHandler sut;
private readonly Guid ruleId = Guid.NewGuid();
private static readonly NamedId<Guid> SchemaMatch = NamedId.Of(Guid.NewGuid(), "my-schema1");
private static readonly NamedId<Guid> 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);
});

20
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);
}
}
}

18
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<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();
private readonly NamedId<Guid> appId = NamedId.Of(Guid.NewGuid(), "my-app");
private readonly RuleService ruleService = A.Fake<RuleService>();
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<IRuleEntity>();
var ruleEntity2 = A.Fake<IRuleEntity>();
var ruleEntity3 = A.Fake<IRuleEntity>();
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<IRuleEntity> { ruleEntity1, ruleEntity2, ruleEntity3 });
.Returns(new List<IRuleEntity> { 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<RuleJob>(null));
await sut.On(@event);
A.CallTo(() => ruleEventRepository.EnqueueAsync(job1, now))
.MustHaveHappened();
A.CallTo(() => ruleEventRepository.EnqueueAsync(job2, now))
.MustHaveHappened();
}
}
}

19
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<string>());
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<string>());
}
[Fact]
public void Should_provide_plain_result_when_succeeded_with_value()
{
sut.Complete("RESULT");
Assert.Equal("RESULT", sut.PlainResult);
}
}
}

Loading…
Cancel
Save