Preface
gengine is a rule engine developed based on golang and AST (abstract syntax tree). The syntax supported by gengine is a custom DSL
gengine was authorized by Bilibili() in July 2020 to open source
gengine has been used in B station risk control system, traffic delivery system, AB testing, recommendation platform system and other business scenarios.
You can also apply genine to any business scenario in golang application that requires rules or metrics to support
Advantages
contrast | drools | gengine |
---|---|---|
Execution mode | Only sequential mode is supported | Supports sequential mode, concurrent mode, mixed mode, and other subdivided execution modes |
Difficulty in writing rules | High, strongly related to Java | Low, custom simple syntax, weakly related to golang |
Rule execution performance | Low, whether between rules or within rules, they are executed sequentially | High, whether it is between rules or within rules, it supports concurrent execution. Users choose the appropriate execution mode based on their needs. |
Open source code address
/bilibili/gengine
/bilibili/gengine
grammar
DSL syntax
const rule = ` rule "rulename" "rule-describtion" salience 10 begin //Rulesend`
As mentioned above, the complete syntax block of gengine DSL consists of the following components:
The keyword rule is followed by "rule name" and "rule description". The rule name is necessary, but the rule description is not necessary. When there are multiple rules in a gengine instance, the "rule name" must be unique. Otherwise, when there are multiple rules with the same rule name, only one will exist after compilation.
The keyword sales, followed by an integer, represents the priority of the rules, which are not necessary. The larger the number, the higher the priority of the rules; when the user does not explicitly specify the priority, the priority of the rules is unknown. If the priority of multiple rules is the same, then the execution order of the rules with the same priority is unknown when executed.
The keywords begin and end are wrapped in the rule body, that is, the specific logic of the rule.
Rule-body grammar
The syntax support or execution order of rule bodies is consistent with mainstream computing languages (such as golang, java, C/C++, etc.)
Operations supported by rules
Supports four operations between complete values (+), subtraction (-), multiplication (*), and division (/), as well as addition between strings
Complete logical operations (&&, ||, !)
Comparison operators are supported: equal to (==), not equal to (!=), greater than (>), less than (<), greater than or equal to (>=), less than or equal to (<=)
Support +=, -=, *=, /=
Support brackets
Priority: brackets, non, multiplication and division, addition and subtraction, logical operations (&&,||) are reduced in turn
Basic data types supported by rules
string
bool
int, int8, int16, int32, int64
uint, uint8, uint16,uint32, uint64
float32, float64
Unsupported special cases
It does not support direct processing of nil, but users can define a variable in rule to accept nil, and then define a function to process nil
For the convenience of users, the latest version of gengine has built-in isNil() function, which users can use directly to determine whether the data is nil
Syntax supported by rules
Complete if .. else if .. else syntax structure, and its nested structure
If you have any other syntax, you can check it in the official document:
/bilibili/gengine/wiki/%E8%AF%AD%E6%B3%95
Use Cases
package test import ( "bytes" "fmt" "/bilibili/gengine/builder" "/bilibili/gengine/context" "/bilibili/gengine/engine" "/sirupsen/logrus" "io/ioutil" "strconv" "strings" "testing" "time" ) //Define the structure you want to injecttype User struct { Name string Age int64 Male bool } func (u *User)GetNum(i int64) int64 { return i } func (u *User)Print(s string){ (s) } func (u *User)Say(){ ("hello world") } //Define the rulesconst rule1 = ` rule "name test" "i can" salience 0 begin if 7 == (7){ = (89767) + 10000000 ("6666") }else{ = "yyyy" } end ` func Test_Multi(t *){ user := &User{ Name: "Calo", Age: 0, Male: true, } dataContext := () //Inject the initialized structure ("User", user) //init rule engine ruleBuilder := (dataContext) start1 := ().UnixNano() //Build rules err := (rule1) //string(bs) end1 := ().UnixNano() ("rules num:%d, load rules cost time:%d", len(), end1-start1 ) if err != nil{ ("err:%s ", err) }else{ eng := () start := ().UnixNano() //Execute the rules err := (ruleBuilder,true) println() end := ().UnixNano() if err != nil{ ("execute rule error: %v", err) } ("execute rule cost %d ns",end-start) ("=%d,Name=%s,Male=%t", , , ) } }
Example explanation
User is a structure that needs to be injected into the gengine; the structure needs to be initialized before injection; the structure needs to be injected as a pointer, otherwise its attribute value cannot be changed in the rule.
rule1 is a specific rule defined by a string
dataContext is used to accept injected data (structure, method, etc.)
ruleBuilder is used to compile rules in string form
Engine accepts ruleBuilder and executes the loaded rules in the execution mode selected by the user.
Tips
Through the example, we can find that the compilation, construction and execution of rules are asynchronous. Therefore, users can use this feature to update rules without stopping service.
It should be noted that compiling and building rules is a CPU-intensive matter. Usually, the compiled and building updates are only compiled and updated when the rules are updated by the user;
Gengine has made a lot of optimizations for rule loading and removal internally. All related APIs provided by Gengine pool are thread-safe and high-performance, so we recommend that you use Gengine pool directly.
In addition, users can also perform asynchronous syntax detection through ruleBuilder.
If you are interested in design implementation, you can check it through the following address:
///jiaoben/
The above is the detailed content of the basic grammar of the new generation of golang rules engine gengine on B.com. For more information about golang rules engine gengine on B.com, please follow my other related articles!