From 4badcf0c4168b26cb18fc95c214d4563c49b9490 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Thu, 29 Aug 2019 14:56:30 +0200 Subject: [PATCH] Make execution timeout for rules configurable. --- .../HandleRules/RuleOptions.cs | 14 ++++++++++++++ .../HandleRules/RuleService.cs | 15 ++++++++++++--- src/Squidex/WebStartup.cs | 3 +++ src/Squidex/appsettings.json | 7 +++++++ .../Operations/HandleRules/RuleServiceTests.cs | 6 +++++- 5 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleOptions.cs diff --git a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleOptions.cs b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleOptions.cs new file mode 100644 index 000000000..8b5926dda --- /dev/null +++ b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleOptions.cs @@ -0,0 +1,14 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +namespace Squidex.Domain.Apps.Core.HandleRules +{ + public sealed class RuleOptions + { + public int ExecutionTimeoutInSeconds { get; set; } = 3; + } +} diff --git a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleService.cs b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleService.cs index 2834315ab..ba8ea2632 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleService.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleService.cs @@ -10,6 +10,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.Options; using NodaTime; using Squidex.Domain.Apps.Core.Rules; using Squidex.Domain.Apps.Events; @@ -23,16 +24,17 @@ namespace Squidex.Domain.Apps.Core.HandleRules { public class RuleService { - private static readonly TimeSpan DefaultTimeout = TimeSpan.FromSeconds(3); private readonly Dictionary ruleActionHandlers; private readonly Dictionary ruleTriggerHandlers; private readonly TypeNameRegistry typeNameRegistry; + private readonly RuleOptions ruleOptions; private readonly IEventEnricher eventEnricher; private readonly IJsonSerializer jsonSerializer; private readonly IClock clock; private readonly ISemanticLog log; public RuleService( + IOptions ruleOptions, IEnumerable ruleTriggerHandlers, IEnumerable ruleActionHandlers, IEventEnricher eventEnricher, @@ -42,6 +44,7 @@ namespace Squidex.Domain.Apps.Core.HandleRules TypeNameRegistry typeNameRegistry) { Guard.NotNull(jsonSerializer, nameof(jsonSerializer)); + Guard.NotNull(ruleOptions, nameof(ruleOptions)); Guard.NotNull(ruleTriggerHandlers, nameof(ruleTriggerHandlers)); Guard.NotNull(ruleActionHandlers, nameof(ruleActionHandlers)); Guard.NotNull(typeNameRegistry, nameof(typeNameRegistry)); @@ -51,14 +54,15 @@ namespace Squidex.Domain.Apps.Core.HandleRules this.typeNameRegistry = typeNameRegistry; + this.ruleOptions = ruleOptions.Value; this.ruleTriggerHandlers = ruleTriggerHandlers.ToDictionary(x => x.TriggerType); this.ruleActionHandlers = ruleActionHandlers.ToDictionary(x => x.ActionType); - this.eventEnricher = eventEnricher; this.jsonSerializer = jsonSerializer; this.clock = clock; + this.log = log; } @@ -171,7 +175,7 @@ namespace Squidex.Domain.Apps.Core.HandleRules var deserialized = jsonSerializer.Deserialize(job, actionHandler.DataType); - using (var cts = new CancellationTokenSource(DefaultTimeout)) + using (var cts = new CancellationTokenSource(GetTimeoutInMs())) { result = await actionHandler.ExecuteJobAsync(deserialized, cts.Token).WithCancellation(cts.Token); } @@ -187,5 +191,10 @@ namespace Squidex.Domain.Apps.Core.HandleRules return (result, elapsed); } + + private int GetTimeoutInMs() + { + return ruleOptions.ExecutionTimeoutInSeconds * 1000; + } } } diff --git a/src/Squidex/WebStartup.cs b/src/Squidex/WebStartup.cs index 12f7c2fdb..b17cb7ea7 100644 --- a/src/Squidex/WebStartup.cs +++ b/src/Squidex/WebStartup.cs @@ -27,6 +27,7 @@ using Squidex.Config.Domain; using Squidex.Config.Orleans; using Squidex.Config.Startup; using Squidex.Config.Web; +using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Domain.Apps.Entities.Assets; using Squidex.Domain.Apps.Entities.Contents; using Squidex.Infrastructure; @@ -100,6 +101,8 @@ namespace Squidex config.GetSection("rebuild")); services.Configure( config.GetSection("exposedConfiguration")); + services.Configure( + config.GetSection("rules")); services.Configure( config.GetSection("contentsController")); diff --git a/src/Squidex/appsettings.json b/src/Squidex/appsettings.json index 2e8254483..b2a8ed119 100644 --- a/src/Squidex/appsettings.json +++ b/src/Squidex/appsettings.json @@ -39,6 +39,13 @@ "custom": "" }, + "rules": { + /* + * The timeout to execute rule actions. + */ + "executionTimeoutInSeconds": 3 + }, + "ui": { /* * Regex suggestions for the UI 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 102fbd85a..7a66e3252 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleServiceTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleServiceTests.cs @@ -9,6 +9,7 @@ using System; using System.Threading; using System.Threading.Tasks; using FakeItEasy; +using Microsoft.Extensions.Options; using NodaTime; using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents; @@ -84,7 +85,10 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules var log = A.Fake(); - sut = new RuleService(new[] { ruleTriggerHandler }, new[] { ruleActionHandler }, eventEnricher, TestUtils.DefaultSerializer, clock, log, typeNameRegistry); + sut = new RuleService(Options.Create(new RuleOptions()), + new[] { ruleTriggerHandler }, + new[] { ruleActionHandler }, + eventEnricher, TestUtils.DefaultSerializer, clock, log, typeNameRegistry); } [Fact]