hyperjumptech / grule-rule-engine

Rule engine implementation in Golang
Other
2.22k stars 346 forks source link

Panic During Rule Execution: Reflect Call on Slice Value #446

Open mro95 opened 6 months ago

mro95 commented 6 months ago

When attempting to execute a rule that involves a custom function CheckProductCondition which checks conditions on a slice of Product structs, Grule encounters a panic with an error related to improper use of reflection (reflect: call of reflect.Value.Elem on slice Value). This error suggests that there might be an issue with how Grule handles reflection operations on slices within custom functions.

Steps to Reproduce:

  1. Define a struct Product.
  2. Define a struct ValidationFact containing a slice of Product.
  3. Implement a method CheckProductCondition on ValidationFact to check for a condition across all products using a custom function passed as a parameter.
  4. Attempt to execute a rule that uses CheckProductCondition.
  5. The rule engine panics upon execution.

Expected Behavior:

The rule should execute without errors, correctly using the custom function to evaluate conditions on each element of the product slice.

Actual Behavior:

The rule engine throws a panic error related to reflection operations, specifically when attempting to handle a slice within the rule execution context. Code Snippet:

type Product struct {
    ProductName  string
    ProductType  string
    Valid        int
}

type ValidationFact struct {
    products []Product
}

func (ps *ValidationFact) CheckProductCondition(propName, expectedValue string, conditionFunc func(string, string) bool) bool {
    for _, p := range ps.products {
        switch propName {
        case "ProductName":
            if conditionFunc(p.ProductName, expectedValue) {
                return true
            }
        }
    }
    return false
}

// Function used as argument
func startsWith(input, prefix string) bool {
    return strings.HasPrefix(input, prefix)
}

// Rule definition causing the panic
rule PhoneNeedToStartWithI "Phone name needs to start with I" salience 10 {
    when
        ValidationFact.CheckProductCondition("ProductName", "I", startsWith) == true
    then
        Log("Non-compliant product found.");
}

Environment:

Grule version: 1.15
Go version: 1.21.5
Operating System and version: Ubuntu 20.04

Impact:

This issue prevents the implementation of dynamic condition checking within rules, limiting the flexibility and utility of the rule engine for scenarios involving collections of items.