gengine icon indicating copy to clipboard operation
gengine copied to clipboard

execute rules on list of data objects

Open gzhhong opened this issue 5 years ago • 2 comments

Hello, I read the example:

...

type User struct { Name string Age int64 Male bool }

func (u *User)GetNum(i int64) int64 { return i }

func (u *User)Print(s string){ fmt.Println(s) }

func (u *User)Say(){ fmt.Println("hello world") }

const ( base_rule = ... func exe(user *User){ dataContext := context.NewDataContext() //inject struct dataContext.Add("User", user) ... //init rule engine knowledgeContext := base.NewKnowledgeContext() ruleBuilder := builder.NewRuleBuilder(knowledgeContext, dataContext)

//读取规则
start1 := time.Now().UnixNano()
err := ruleBuilder.BuildRuleFromString(base_rule)
end1 := time.Now().UnixNano()

logrus.Infof("rules num:%d, load rules cost time:%d ns", len(knowledgeContext.RuleEntities), end1-start1 )

if err != nil{
	logrus.Errorf("err:%s ", err)
}else{
	eng := engine.NewGengine()

	start := time.Now().UnixNano()
	// true: means when there are many rules, if one rule execute error,continue to execute rules after the occur error rule
	err := eng.Execute(ruleBuilder, true)

... } }

func Test_Base(t *testing.T){ user := &User{ Name: "Calo", Age: 0, Male: true, } exe(user) // HERE: If I have a list of user, for example I have 10 user object, how to run exe(user) efficiently? }

My questions is: if I have a list of user, with 10 user objects. How to run exe(user) 10 times but more efficiently. Because in the exe it will execute the functions in sequence as below: NewDataContext, then NewKnowledgeContext, NewRuleBuilder, NewGengine and eng.Execute(ruleBuilder, true). I think those methods are just duplicated running for 10 times, how can I inject each of the user object in the list by the function dataContext.Add("User",user), but do not execute other function each time I inject a new user object?

gzhhong avatar Dec 23 '20 08:12 gzhhong

If you have a list of data need to checks by rules, you should NEVER DO IT LIKE THIS "NewDataContext, then NewKnowledgeContext, NewRuleBuilder, NewGengine and eng.Execute(ruleBuilder, true) " again and again !


First, I am so sorry for you that we just finished the gengine Chinese doc, not finish the gengine English doc, in future,we will finish it!
We recommend users to use the gengine pool, and the methods are one-to-one between gengine.go and gengine_pool.go


if you have a list of data(users) ,you could do it like this:

import (
	"fmt"
	"gengine/engine"
	"testing"
)


type User struct {
	Name string
	Age int

}

func Test_list_data_check_by_rules(t *testing.T) {

	// there are many rules you add
	var rules = `
rule "1" 
begin
// you want to do 
end

rule "2" 
begin
// you want to do 
end

// rules "n"...
`
	//apis use to inject non-state function or service which will not cause thread-safety bug
	apis := make(map[string]interface{})
	apis["println"] = fmt.Println
	//just init once !
	pool, e := engine.NewGenginePool(10, 20, 1, rules, apis)
	if e != nil {
		//init pool failed
		panic(e)
	}

	// there is your a list of data(users)
	users := make([]*User, 100)

	for _, user := range users  {
		tmpApisOrData := make(map[string]interface{})
		tmpApisOrData["user"] = user
		//execute rules
		//all methods the gengine pool supply is thread-safety
		e, _ := pool.Execute(tmpApisOrData, true)
		if e != nil {
			//log or return the err
			//errors.New(fmt.Sprintf("execute rules err:%+v", e))
		}
		// err== nil to do you want to do
	}


	// or concurrent to execute
	/*
	for _, user := range users  {
		u := user
		go func() {
			tmpApisOrData := make(map[string]interface{})
			tmpApisOrData["user"] = u
			//execute rules
			//all methods the gengine pool supply is thread-safety
			e, _ := pool.Execute(tmpApisOrData, true)
			if e != nil {
				//log or return the err
				//errors.New(fmt.Sprintf("execute rules err:%+v", e))
			}
			// err== nil to do you want to do
		}()
	}
	*/
}

 ```

rencalo770 avatar Dec 23 '20 11:12 rencalo770

Got it, thanks for the quick answer.

gzhhong avatar Dec 23 '20 12:12 gzhhong