Skip to content
Merged
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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

All notable changes to this project will be documented in this file.

## [3.0.2]
- Fixed LocalParams cache not getting cleaned up when RemoveWorkflow and ClearWorkflows are called

## [3.0.1]
- Moved ActionResult and ActionRuleResult under RulesEngine.Models namespace

Expand Down
14 changes: 13 additions & 1 deletion src/RulesEngine/RulesEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public class RulesEngine : IRulesEngine
private readonly ILogger _logger;
private readonly ReSettings _reSettings;
private readonly RulesCache _rulesCache = new RulesCache();
private readonly MemoryCache _compiledParamsCache = new MemoryCache(new MemoryCacheOptions());
private MemoryCache _compiledParamsCache = new MemoryCache(new MemoryCacheOptions());
private readonly ParamCompiler _ruleParamCompiler;
private readonly RuleExpressionParser _ruleExpressionParser;
private readonly RuleCompiler _ruleCompiler;
Expand Down Expand Up @@ -179,6 +179,7 @@ public void AddWorkflow(params WorkflowRules[] workflowRules)
public void ClearWorkflows()
{
_rulesCache.Clear();
ClearCompiledParamCache();
}

/// <summary>
Expand All @@ -191,6 +192,7 @@ public void RemoveWorkflow(params string[] workflowNames)
{
_rulesCache.Remove(workflowName);
}
ClearCompiledParamCache();
}

/// <summary>
Expand Down Expand Up @@ -404,6 +406,16 @@ private static string UpdateErrorMessage(string errorMessage, IDictionary<string

return errorMessage;
}

/// <summary>
/// Clears all compiledParams
/// </summary>
private void ClearCompiledParamCache()
{
_compiledParamsCache.Dispose();
_compiledParamsCache = new MemoryCache(new MemoryCacheOptions());
}

#endregion
}
}
4 changes: 2 additions & 2 deletions src/RulesEngine/RulesEngine.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<Version>3.0.1</Version>
<Version>3.0.2</Version>
<Copyright>Copyright (c) Microsoft Corporation.</Copyright>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<PackageProjectUrl>https://github.com/microsoft/RulesEngine</PackageProjectUrl>
<Authors>Abbas Cyclewala, Dishant Munjal, Yogesh Prajapati</Authors>
<Description>Rules Engine is a package for abstracting business logic/rules/policies out of the system. This works in a very simple way by giving you an ability to put your rules in a store outside the core logic of the system thus ensuring that any change in rules doesn't affect the core system.</Description>
<PackageReleaseNotes>https://github.com/microsoft/RulesEngine/blob/master/CHANGELOG.md</PackageReleaseNotes>
<PackageReleaseNotes>https://github.com/microsoft/RulesEngine/blob/main/CHANGELOG.md</PackageReleaseNotes>
<PackageTags>BRE, Rules Engine, Abstraction</PackageTags>
</PropertyGroup>

Expand Down
70 changes: 69 additions & 1 deletion test/RulesEngine.UnitTest/BusinessRuleEngineTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,6 @@ public async Task ClearWorkflow_RemovesAllWorkflow(string ruleFileName)
await Assert.ThrowsAsync<ArgumentException>(async () => await re.ExecuteAllRulesAsync("inputWorkflowReference", input1, input2, input3));
}


[Theory]
[InlineData("rules1.json")]
[InlineData("rules2.json")]
Expand Down Expand Up @@ -416,6 +415,75 @@ public async Task ExecuteRule_MissingMethodInExpression_DefaultParameter(string
Assert.IsType<List<RuleResultTree>>(result);
Assert.All(result, c => Assert.False(c.IsSuccess));
}

[Fact]
public async Task RemoveWorkFlow_ShouldRemoveAllCompiledCache()
{
var workflow = new WorkflowRules {
WorkflowName = "Test",
Rules = new Rule[]{
new Rule {
RuleName = "RuleWithLocalParam",
LocalParams = new LocalParam[] {
new LocalParam {
Name = "lp1",
Expression = "true"
}
},
RuleExpressionType = RuleExpressionType.LambdaExpression,
Expression = "lp1 == true"
}
}
};

var re = new RulesEngine();
re.AddWorkflow(workflow);

var result1 = await re.ExecuteAllRulesAsync("Test","hello");
Assert.True(result1.All(c => c.IsSuccess));

re.RemoveWorkflow("Test");
workflow.Rules.First().LocalParams.First().Expression = "false";

re.AddWorkflow(workflow);
var result2 = await re.ExecuteAllRulesAsync("Test", "hello");
Assert.True(result2.All(c => c.IsSuccess == false));
}

[Fact]
public async Task ClearWorkFlow_ShouldRemoveAllCompiledCache()
{
var workflow = new WorkflowRules {
WorkflowName = "Test",
Rules = new Rule[]{
new Rule {
RuleName = "RuleWithLocalParam",
LocalParams = new LocalParam[] {
new LocalParam {
Name = "lp1",
Expression = "true"
}
},
RuleExpressionType = RuleExpressionType.LambdaExpression,
Expression = "lp1 == true"
}
}
};

var re = new RulesEngine();
re.AddWorkflow(workflow);

var result1 = await re.ExecuteAllRulesAsync("Test", "hello");
Assert.True(result1.All(c => c.IsSuccess));

re.ClearWorkflows();
workflow.Rules.First().LocalParams.First().Expression = "false";

re.AddWorkflow(workflow);
var result2 = await re.ExecuteAllRulesAsync("Test", "hello");
Assert.True(result2.All(c => c.IsSuccess == false));
}

private RulesEngine CreateRulesEngine(WorkflowRules workflow)
{
var json = JsonConvert.SerializeObject(workflow);
Expand Down