microsoft / RulesEngine

A Json based Rules Engine with extensive Dynamic expression support
https://microsoft.github.io/RulesEngine/
MIT License
3.61k stars 543 forks source link

AddOrUpdateWorkflow has a problem with delayed effect of rules #366

Closed BianYuan1995 closed 1 year ago

BianYuan1995 commented 2 years ago

I have a program that is used in a production environment. His working principle is to first get the item information to do rule matching, if the match fails, automatically generate a new rule, and then update the rule by AddOrUpdateWorkflow(workflow). Now the problem is that Task 4 generates AutoRule-6, Task 6 has the same model name information as Task 4, but Task 6 fails to match and creates AutoRule-7 with the same expression as AutoRule-6, but the other tasks after it can match AutoRule-6 correctly.

Task4 log info

2022-06-16 15:28:51.635 +08:00 [INF] task4-request info:{"actionResult":1,"goodsBaseInfo":{"brand":"Apple","model":"A1984","modelName":"iPhone XR","capacity":"64GB","color":"Coral","deviceStatus":"Power up","service":"Pass","mdm":"Pass","carrier":"Pass","esn":"unknown","bio":"Yes","display":"Yes","camera":"Yes","cdt":"K3","modelNumber":"MRYW2LL/A","gpeMc":null,"fpiMc":null,"dpeMc":null,"abbreviation":null},"readText":null}
2022-06-16 15:28:51.635 +08:00 [INF] 规则引擎匹配失败 开始自动生成该通道号:6 对应匹配规则
2022-06-16 15:28:51.635 +08:00 [INF] 自动生成通道号:6 对应的匹配规则:{"RuleName":"AutoRule-6","Properties":null,"Operator":null,"ErrorMessage":"This Rule is not match!!!","Enabled":true,"ErrorType":0,"RuleExpressionType":0,"WorkflowRulesToInject":null,"WorkflowsToInject":null,"Rules":null,"LocalParams":null,"Expression":"input1.ModelName== \u0022iPhone XR\u0022 ","Actions":null,"SuccessEvent":"6"}

take6 log info

2022-06-16 15:28:58.433 +08:00 [INF] task6-request info:{"actionResult":1,"goodsBaseInfo":{"brand":"Apple","model":"A1984","modelName":"iPhone XR","capacity":"64GB","color":"Red","deviceStatus":"Power up","service":"Pass","mdm":"Pass","carrier":"Pass","esn":"unknown","bio":"Yes","display":"Yes","camera":"Yes","cdt":"K3","modelNumber":"MRYU2LL/A","gpeMc":null,"fpiMc":null,"dpeMc":null,"abbreviation":null},"readText":null}
2022-06-16 15:28:58.433 +08:00 [INF] 规则引擎匹配失败 开始自动生成该通道号:7 对应匹配规则
2022-06-16 15:28:58.433 +08:00 [INF] 自动生成通道号:7 对应的匹配规则:{"RuleName":"AutoRule-7","Properties":null,"Operator":null,"ErrorMessage":"This Rule is not match!!!","Enabled":true,"ErrorType":0,"RuleExpressionType":0,"WorkflowRulesToInject":null,"WorkflowsToInject":null,"Rules":null,"LocalParams":null,"Expression":"input1.ModelName== \u0022iPhone XR\u0022 ","Actions":null,"SuccessEvent":"7"}

method BulidRule

private void BulidRule(GoodsInfo response, List<FieldItem> fields, int channelNo)
        {
            bool IsFieId = true;
            if (response is null)
            {
                Serilog.Log.Information("没有可以供生成规则的数据源 提前返回");
                return;
            }
            //生成规则
            if (rules is null)
            {
                rules = new List<Rule>();
            }
            if (fields.Count == 0)
            {
                IsFieId = false;
            }
            var rule = new Rule
            {
                RuleName = "AutoRule-" + channelNo.ToString(),
                RuleExpressionType = RuleExpressionType.LambdaExpression,
                SuccessEvent = channelNo.ToString(),
                ErrorMessage = "This Rule is not match!!!"
            };
            string expression = string.Empty;
            if (IsFieId)
            {
                List<PropertyInfo> properties = new List<PropertyInfo>();
                foreach (var item in fields)
                {
                    PropertyInfo propertyInfo = response.GetType().GetProperties().SingleOrDefault(x => x.Name == item.Name);
                    if (propertyInfo is null)
                    {
                        break;
                    }
                    properties.Add(propertyInfo);
                }
                if (properties.Count <= 0)
                {
                    Serilog.Log.Warning("异常情况 规则生成 属性字段不匹配 无法生成规则   失败!!!");
                    return;
                }
                for (int i = 0; i < properties.Count; i++)
                {
                    string value = properties[i].GetValue(response, null)?.ToString();
                    if (value is null)
                    {
                        value = string.Empty;
                    }
                    expression += string.Format("input1.{0}== \"{1}\" ", properties[i].Name, value);
                    if (i != properties.Count - 1)
                    {
                        expression += " And ";
                    }
                }
            }
            if (IsEableGrade)
            {
                if (GradeGroup.ContainsKey(response.Condition))
                {
                    GradeGroup.TryGetValue(response.Condition, out int value);
                    //等级分组 规则表达式用||联起来
                    if (Grades.TryGetValue(value, out List<CellPhoneGrade> cdtList))
                    {
                        if (!string.IsNullOrEmpty(expression))
                        {
                            expression += " And ";
                        }
                        foreach (var item in cdtList)
                        {
                            expression += string.Format("input1.Condition == \"{0}\" ||", item.Condition);
                        }
                        expression = expression.TrimEnd("||".ToCharArray());
                    }
                    else
                    {
                        Serilog.Log.Warning("没有从Grades找到对应的等级信息");
                    }
                }
                else
                {
                    if (!string.IsNullOrEmpty(expression))
                    {
                        expression += " And ";
                    }
                    expression += string.Format("input1.{0}== \"{1}\" ", "Condition", response.Condition);
                }
            }

            rule.Expression = expression;
            Serilog.Log.Information("自动生成通道号:{0} 对应的匹配规则:{1}", channelNo, JsonSerializer.Serialize(rule));
            rules.Add(rule);
            var workflow = new Workflow()
            {
                WorkflowName = "Automatic Sorting",
                Rules = rules
            };
            if (engine is null)
            {
                engine = new RulesEngine.RulesEngine();
            }
            engine.AddOrUpdateWorkflow(workflow);
        }

method RunEnginseAsync

private async Task<int> RunEnginseAsync(GoodsInfo response)
        {
            int result = 0;
            try
            {
                List<RuleResultTree> resultList = await engine.ExecuteAllRulesAsync("Automatic Sorting", response);
                resultList.OnSuccess((eventName) =>
                {
                    bool IsSuccess = int.TryParse(eventName, out result);
                    result = IsSuccess ? result : 0;
                    if (!IsSuccess)
                    {
                        Serilog.Log.Information("转换失败 将采用失败通道号0 源数据:{0}", eventName);
                    }
                    Serilog.Log.Information("{0} 匹配到通道号:{1}", "规则引擎匹配成功", result);
                });
                resultList.OnFail(() =>
                {
                    result = GetEmptyChannel();
                    if (result != 0)
                    {
                        Serilog.Log.Information("{0} 开始自动生成该通道号:{1} 对应匹配规则", "规则引擎匹配失败", result);
                        BulidRule(response, FieldItemList, result);
                    }
                });
            }
            catch (Exception ex)
            {
                Serilog.Log.Information("匹配规则异常{0}", ex.ToString());
                result = 0;
            }
            return result;
        }

So, is it possible that AddOrUpdateWorkflow has a problem with delayed effect of rules?

abbasc52 commented 2 years ago

@BianYuan1995 I think to better debug it, you need to add a log after addOrUpdateWorkflow. Also does these tasks run in parallel ? If yes, what is the parallelism used?

BianYuan1995 commented 2 years ago

Thanks for your reply, now I have added the log after addOrUpdateWorkflow, but I wasn't able to reproduce the issue again. I think the tasks are not parallel, but sequential, I have a thread that will generate the tasks, write the task information to the channel, and another thread will read the tasks in the channel to perform the actions related to the rule engine.

image

abbasc52 commented 1 year ago

Hi @BianYuan1995 , I will be closing this issue since we are not able to reproduce it. Feel free to reopen this in case you face this issue again.