Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/RulesEngine/Models/ReSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ internal ReSettings(ReSettings reSettings)
UseFastExpressionCompiler = reSettings.UseFastExpressionCompiler;
EnableExceptionAsErrorMessageForRuleExpressionParsing = reSettings.EnableExceptionAsErrorMessageForRuleExpressionParsing;
AutoExecuteActions = reSettings.AutoExecuteActions;
EnableParallelRuleCompilation = reSettings.EnableParallelRuleCompilation;
}


Expand Down Expand Up @@ -98,6 +99,13 @@ internal ReSettings(ReSettings reSettings)
/// run actions yourself (e.g. via ExecuteActionWorkflowAsync) for selective control. See #596.
/// </summary>
public bool AutoExecuteActions { get; set; } = true;

/// <summary>
/// When true, rules within a workflow are compiled in parallel during registration.
/// Significantly reduces warmup time for workflows with many rules.
/// Default: false
/// </summary>
public bool EnableParallelRuleCompilation { get; set; } = false;
}

public enum NestedRuleExecutionMode
Expand Down
28 changes: 26 additions & 2 deletions src/RulesEngine/RulesEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -399,9 +399,33 @@ private bool RegisterRule(string workflowName, params RuleParameter[] ruleParams
_rulesCache.AddOrUpdateGlobalParamsDelegate(compileRulesKey, globalParamsDelegate);
}

foreach (var rule in workflow.Rules.Where(c => c.Enabled))
var enabledRules = workflow.Rules.Where(c => c.Enabled).ToArray();
var compiledFuncs = new RuleFunc<RuleResultTree>[enabledRules.Length];
if (_reSettings.EnableParallelRuleCompilation)
{
dictFunc.Add(rule.RuleName, CompileRule(rule,workflow.RuleExpressionType, ruleParams, globalParamExp));
try
{
System.Threading.Tasks.Parallel.For(0, enabledRules.Length, i => {
compiledFuncs[i] = CompileRule(enabledRules[i], workflow.RuleExpressionType, ruleParams, globalParamExp);
});
}
catch (AggregateException ae)
{
// Preserve the serial-compilation contract: the first rule that fails
// to compile surfaces its own exception, not an AggregateException.
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(ae.InnerExceptions[0]).Throw();
}
}
else
{
for (var i = 0; i < enabledRules.Length; i++)
{
compiledFuncs[i] = CompileRule(enabledRules[i], workflow.RuleExpressionType, ruleParams, globalParamExp);
}
}
for (var i = 0; i < enabledRules.Length; i++)
{
dictFunc.Add(enabledRules[i].RuleName, compiledFuncs[i]);
}

_rulesCache.AddOrUpdateCompiledRule(compileRulesKey, dictFunc);
Expand Down