Coder Social home page Coder Social logo

gengine's People

Contributors

cluas avatar lynnworld avatar rencalo770 avatar terry-mao avatar wangyu122-tal avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gengine's Issues

规则语法中能否支持定义二维数组

rule "rule_decision_matrix_user_level" "" salience 1
begin
rule_decision_matrix_user_level_matrix = map[string]map[string]string{"1": {"1":
"D", "2": "D", "3": "D", "4": "D"}, "2": {"1": "D", "2": "D", "3": "D", "4":
"D"}, "3": {"1": "D", "2": "D", "3": "D", "4": "D"}, "4": {"1": "C", "2": "C",
"3": "C", "4": "C"}, "5": {"1": "C", "2": "C", "3": "C", "4": "B"}, "6": {"1":
"B", "2": "B", "3": "B", "4": "B"}, "7": {"1": "A", "2": "B", "3": "B", "4":
"B"}, "8": {"1": "A", "2": "A", "3": "A", "4": "A"}}
tmp_rule_decision_matrix_user_level_matrix = rule_decision_matrix_user_level_matrix[score_level]
resp["user_level"] = tmp_rule_decision_matrix_user_level_matrix[approve_periods]
return resp
end

IsZero undefined

使用golang版本1.12.17,提示找不到reflect.IsZero
github.com/bilibili/gengine/internal/core/is_nil.go:32:22: value.Field(i).IsZero undefined (type reflect.Value has no field or method IsZero)

翻了下version note发现这个IsZero是1.13才引入的?为什么gengine文档上写支持1.12.x呢?

ruleBuilder 构建后 传入进方法的map 添加的key value 添加不进去

image

image

我吧gloabalMap 作为参数传进方法,在里面新加一个key value ,期待最外层的gloabalMap也会加这样一个key value但是当我用了你们框架的dc := dataContext.NewDataContext() ruleBuilder := builder.NewRuleBuilder(dc) 发现key value没加进去

image

当我把rulebuilder注释

image

key value就添加进去了

image

这是debug模式下的 不知道是我goland原因还是什么?我直接取值能取出来的

map[string]interface{}指针传到dataContext,在做 if 字段判断一直出现panic,求解

const ( data_rule = \
rule "data rule" "a test" salience 10
begin
println(up["status"])
if up["status"] == 1{
return true
}else{
return false
}
end `
)
func Test_check(t *testing.T) {
upDataMap := make(map[string]interface{})
busiz1 := []byte({"reference_id":2073666894,"status":1})
decoder1 := json.NewDecoder(bytes.NewReader(busiz1))
err := decoder1.Decode(&upDataMap)
if err != nil {
fmt.Printf("Unmarshal error, err: %+v", err)
return
}
dataContext := context.NewDataContext()
dataContext.Add("up", &upDataMap)
ruleBuilder := builder.NewRuleBuilder(dataContext)
err1 := ruleBuilder.BuildRuleFromString(data_rule)
if err1 != nil {
panic(err1)
}
eng := engine.NewGengine()
err2 := eng.Execute(ruleBuilder, true)
if err2 != nil {
panic(err2)
}
fmt.Printf("Finish")
}`

规则语法里面是否支持for循环?

请问gengine的规则里面,不支持for循环吗?只能通过下标一个个单独去访问吗?目前来看,我们只能遍历调用了,效率可能是个问题,多谢了哈

文件命名拼写问题

阅读源码时看到一些文件命名,我理解应该是手误敲错了吧,强迫症患者看着有点难受,所以提一下
internal/gengine_paser_vistior.go => gengine_parser_visitor.go
test/mutli_rules_test.go => multi_rules_test.go

engine pool data race

WARNING: DATA RACE
Read at 0x00c038a220b8 by goroutine 61:
github.com/bilibili/gengine/engine.(*GenginePool).getGengine()
/Users/liupengtao/go/pkg/mod/github.com/bilibili/[email protected]/engine/gengine_pool.go:160 +0x77
github.com/bilibili/gengine/engine.(*GenginePool).prepareWithMultiInput()
/Users/liupengtao/go/pkg/mod/github.com/bilibili/[email protected]/engine/gengine_pool.go:522 +0x50
github.com/bilibili/gengine/engine.(*GenginePool).Execute()
/Users/liupengtao/go/pkg/mod/github.com/bilibili/[email protected]/engine/gengine_pool.go:706 +0xa3

Previous write at 0x00c038a220b8 by goroutine 67:
github.com/bilibili/gengine/engine.(*GenginePool).putGengineLocked.func1()
/Users/liupengtao/go/pkg/mod/github.com/bilibili/[email protected]/engine/gengine_pool.go:195 +0x269

strings.Split 不能使用换行符切割字符串?

`package main

import (
"fmt"
"github.com/bilibili/gengine/builder"
"github.com/bilibili/gengine/context"
"github.com/bilibili/gengine/engine"
"github.com/sirupsen/logrus"
"strings"
"time"
)
const rule1 = rule "name test" "i can" salience 0 begin if FreeData == ""{ println("Error:data is null") }else{ rows = split(FreeData,"\n") println(rows[1]) } end
func main() {
dataContext := context.NewDataContext()
freeData := total used free shared buff/cache available Mem: 131910844 41687584 24113760 4251248 66109500 84970700 Swap: 0 0 0
//这里可以成功切割出来
fmt.Println(strings.Split(freeData,"\n")[1])
//注入初始化的结构体
dataContext.Add("FreeData", freeData)
dataContext.Add("split", strings.Split)
dataContext.Add("println", fmt.Println)

//init rule engine
ruleBuilder := builder.NewRuleBuilder(dataContext)


start1 := time.Now().UnixNano()
//构建规则
err := ruleBuilder.BuildRuleFromString(rule1) //string(bs)
end1 := time.Now().UnixNano()

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

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

	start := time.Now().UnixNano()
	//执行规则
	err := eng.Execute(ruleBuilder,true)

	end := time.Now().UnixNano()
	if err != nil{
		logrus.Errorf("execute rule error: %v", err)
	}
	logrus.Infof("execute rule cost %d ns",end-start)
}

}
`

第19行会报错:
ERRO[0000] execute rule error: [rule: "name test" executed, error:
line 8, column 3, code: println(rows[1]), reflect: slice index out of range

输出:
Mem: 131910844 41687584 24113760 4251248 66109500 84970700
INFO[0000] rules num:1, load rules cost time:16206000
ERRO[0000] execute rule error: [rule: "name test" executed, error:
line 8, column 3, code: println(rows[1]), reflect: slice index out of range
goroutine 1 [running]:

规则是否可以动态修改

var serviceRules string = rule "single" "test" begin resp.At = room.GetAttention() if room.Element == "%s" && room.Value %s{ resp.Judge = true }else{ resp.Judge = false } println("rule 1...") end

实现一个简单的巡检,每个巡检项和巡检值都不一样,是否可以这样使用

测试样例错误反馈1

.\increment_update_test.go:212:13: undefined: Reqest
.\increment_update_test.go:280:13: undefined: Reqest

是否有计划集成图形拖拽界面

是否有计划集成图形拖拽界面,例如像 drools 集成的 JBPM ? 虽然引擎语言比golang稍微好理解些,但是还不具备让业务方直接拖拽配置

concurrent map writes

debug模式下

context/data_context.go:371 ==> Vars[variable] = newValue.
限制同时10个50个goroutinue并发请求,均出现过concurrent map writes,map读写问题。

请求场景:
func API(ctx context.Context, req *Request) error {
data := make(map[string]interface{})
data["req"] = req
data["stg_name"] = &stgName

err, _ = engine.EngPool.ExecuteSelectedRules(data, stgRule)
    // do sth ...

}

release并未发现。

规则构建耗时异常

我有一个规则,规则的字符串如下:
code := rule "weight_rule" "weight_rule" salience 0 begin return ((1 * (1 + data.UpvoteNum) / (5.19 + data.CardShow)) + 10*(1+data.UpvoteNum)/(317.65+data.CardShow) + 5*(1+data.CollectNum)/(797.57+data.CardShow) + 0*(1+data.ShareNum)/(4790.89+data.CardShow) + 10*(1+data.ThankNum)/(1585.75+data.CardShow) + 25*(1+data.CommentNum)/(3465.75+data.CardShow) + 60*(1+data.AnswerNum)/(11097.10+data.CardShow) + -40*(1+data.VoteDownNum)/(9400.99+data.CardShow) + 35*(1+data.FollowNum)/(2986.13+data.CardShow)) * Sigmoid(Log10N(data.CardShow/50)) end
然后我通过引擎池去执行这个规则
enginePool, err := engine.NewGenginePool(1, 10, 2, code, map[string]interface{}{
"Sigmoid": Sigmoid,
"Log10N": Log10N,
})
if err != nil {
panic(err)
}
err, resultMap := enginePool.Execute(map[string]interface{}{
"data": contentAggregateData,
}, false)
if err != nil {
panic(err)
}
我发现,在第一步解析规则字符串的时候耗时非常高,大约要3min以上才能完成

在引入了gengine的package下面 无法使用gomonkey

必复现
--- FAIL: TestShakeEngine_DoShake (0.00s)
panic: permission denied [recovered]
panic: permission denied

goroutine 11 [running]:
testing.tRunner.func1.1(0x494b2c0, 0xc00003f448)
/usr/local/go/src/testing/testing.go:940 +0x2f5
testing.tRunner.func1(0xc0001fd680)
/usr/local/go/src/testing/testing.go:943 +0x3f9
panic(0x494b2c0, 0xc00003f448)
/usr/local/go/src/runtime/panic.go:969 +0x166
git.code.oa.com/NGTest/gomonkey.modifyBinary(0x46f5b90, 0xc0001185c4, 0xc, 0xc)
/Users/jingqiyu/dev/go/pkg/mod/git.code.oa.com/!n!g!test/[email protected]/modify_binary_darwin.go:11 +0x190
git.code.oa.com/NGTest/gomonkey.replace(0x46f5b90, 0x4a64ab0, 0x0, 0x0, 0x1)
/Users/jingqiyu/dev/go/pkg/mod/git.code.oa.com/!n!g!test/[email protected]/patch.go:197 +0xef
git.code.oa.com/NGTest/gomonkey.(*Patches).ApplyCore(0xc0000e1f38, 0x4914360, 0x4a64ad8, 0x13, 0x4914360, 0x4a64ab0, 0x13, 0x404da2c)
/Users/jingqiyu/dev/go/pkg/mod/git.code.oa.com/!n!g!test/[email protected]/patch.go:154 +0x14a
git.code.oa.com/NGTest/gomonkey.(*Patches).ApplyFunc(0xc000118738, 0x4914360, 0x4a64ad8, 0x4914360, 0x4a64ab0, 0xc000118748)
/Users/jingqiyu/dev/go/pkg/mod/git.code.oa.com/!n!g!test/[email protected]/patch.go:65 +0x130
git.code.oa.com/NGTest/gomonkey.ApplyFunc(...)
/Users/jingqiyu/dev/go/pkg/mod/git.code.oa.com/!n!g!test/[email protected]/patch.go:23
git.code.oa.com/submarine/activity/logic/monopoly_logic.TestShakeEngine_DoShake(0xc0001fd680)
/Users/jingqiyu/dev/trpc/submarine/activity/logic/monopoly_logic/shake_test.go:23 +0xdc
testing.tRunner(0xc0001fd680, 0x4a64ab8)
/usr/local/go/src/testing/testing.go:991 +0xdc
created by testing.(*T).Run
/usr/local/go/src/testing/testing.go:1042 +0x357

arm32位系统编译报错

github.com/bilibili/gengine/internal/iantlr/alr

../../../../../../go/pkg/mod/github.com/bilibili/[email protected]/internal/iantlr/alr/gengine_parser.go:5415:221: constant 4227858432 overflows int

wiki中的typo

语法 中开始的 DSL语法 展示中

rule "rulename" "rule-describtion" salience 10

中"描述"的英文写错了

求支持自定义函数

背景:我们的项目中用流程画图的方式在写业务逻辑,把逻辑落地成gengine的 rule运行
问题:某些业务场景较为复杂,生成的规则代码超过几万行、里面大量的重复代码(例如一个流程图很多节点都会汇聚到一个最终处理结果的节点,做一些计算工作然后返回给上层业务,造成了很多重复代码)
需求:希望gengine可以支持在rule里面可以自定义函数。

isNil() 问题

const rule2 = `

rule "bot_ask_name" "" salience 12
begin

    println("conversation_list")
   
	if ( isNil( BaseData.UserProfile)  ||  BaseData.UserProfile.Name == "") && lastConversationTime(Base, "", "", "10", "70", "") {
		return true
	}
	return false

end
`
base := BaseStartConversation{
ConversationBaseData: ConversationBaseData{
ConversationLogic: *logicObj,
UserId: 9819,
NodeId: 9818,
Node: &httpparams.GetOneRobotNodeResp{
NodeId: 9818,
RobotNodeGeneralProperties: &robotnodedao.RobotNodeGeneralProperties{NickName: "node nick name"},
RobotNodeCharacterProperties: nil,
},
},
}
apis := make(map[string]interface{})
apis["println"] = fmt.Println
apis["index"] = strings.Index
pool, err := engine.NewGenginePool(10, 20, 1, rule1, apis)

data := make(map[string]interface{})

data["BaseData"] = base.ConversationBaseData
data["Base"] = &base
data["println"] = fmt.Println
data["lastConversationTime"] = lastConversationTime
err = pool.UpdatePooledRulesIncremental(rule2)
//lastConversationTime()
t.Log(err)
assert.Assert(t, err == nil)
err, result := pool.ExecuteSelectedRules(data, []string{"bot_ask_name"})
t.Log(err)
assert.Assert(t, err == nil)
t.Log(result)

其中UserProfile是BaseData的一个结构体指针成员, 报错信息如下
conversation_list
--- FAIL: Test_gengine_pool_bot_inform_city_bot_ask_weather (0.08s)
panic: reflect: call of reflect.Value.FieldByName on zero Value [recovered]
panic: reflect: call of reflect.Value.FieldByName on zero Value

这个 我测试了,就是isNil执行完后,虽然命中了条件(BaseData.UserProfile==nil),但是还会继续 || 后面的那个BaseData.UserProfile.Name,访问了空指针,想问下这个执行逻辑是什么?isNil 不能搭配 || && 使用吗

构建规则后,怎么获取该规则内所需的变量列表?

例如:核心DSL代码为:AND(age > 25, lengthOfService > 5, LEN(name) > 1),AND是内置函数。
执行 ruleBuilder.BuildRuleFromString(rule)后,怎么获取规则所需变量?期望可以拿到变量列表,如果内提供变量类型更好。比如:{age: int, lengthOfService: int, name: string}

是否支持timeout机制?

规则对用户暴露,如果用户创建了长时运行的规则,是否有超时机制直接停止该条规则执行,从而防止引擎被阻塞。

ambiguous import

../../../../pkg/mod/github.com/bilibili/[email protected]/builder/rule_builder.go:6:2: ambiguous import: found package github.com/antlr/antlr4/runtime/Go/antlr in multiple modules:

rule执行go的function时,支持返回多个值吗?

比如go的一个函数myFunc,在入rule映射为MyFunc:

func myFunc()(int, string){
}

在rule中应用:

rule "ruleId"
begin
    a, str := MyFunc()
    Print(str)
end

实际在执行rule的过程中,只能拿到a的值,str的值是拿不到的吗,后续能支持吗

无法准确验证规则脚本是否正确

目前测试发现如下的规则 BuildRuleFromString 无法验证规则的有效性,日志有错误信息输出,但是返回 errnil

规则脚本

rule "test" salience 1
begin
	规则脚本
end

验证逻辑

dataContext := context.NewDataContext()
rb := builder.NewRuleBuilder(dataContext)
if err := rb.BuildRuleFromString(tpl.String()); err != nil {
return err
}

日志输出

line 3:5 token recognition error at: '规'
line 3:6 token recognition error at: '则'
line 3:7 token recognition error at: '脚'
line 3:8 token recognition error at: '本'

isNil() 内置方法不支持多层级的map

rule1 = rule "rule_1" "rule_1" begin return isNil(MyMap["123456789"]["123"]) end

myMap := make(map[string]map[string][]string)

if myMap["123456789"] == nil {
myMap["123456789"] = make(map[string][]string)
}

myMap["123456789"]["123"] = []string{"123"}

dtx := context.NewDataContext()
dtx.Add("MyMap", myMap)

rb := builder.NewRuleBuilder(dtx)
err := rb.BuildRuleFromString(rule1)
if err != nil {
panic(err)
}

eg := engine.NewGengine()
err = eg.Execute(rb, false)
if err != nil {
panic(err)
}

执行返回:
panic: [line 2:33 no viable alternative at input 'isNil(MyMap["123456789"][']

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.