### Initialize Data Context and Inject APIs in Go Source: https://context7.com/bilibili/gengine/llms.txt This example demonstrates creating a data context and injecting custom structs, functions, and helpers for rule engine interaction. It relies on the gengine/context package for reflection-based data management. Inputs include user-defined structs and functions; outputs are modified data contexts ready for rule building. Limitations may include reflection overhead in high-performance scenarios. ```go package main import ( "fmt" "github.com/bilibili/gengine/context" ) type User struct { Name string Age int64 Male bool } func (u *User) GetNum(i int64) int64 { return i } func (u *User) Say() { fmt.Println("Hello from", u.Name) } func main() { // Create new data context dataContext := context.NewDataContext() // Inject structs user := &User{Name: "Alice", Age: 25, Male: false} dataContext.Add("User", user) // Inject functions with aliases dataContext.Add("Sout", fmt.Println) dataContext.Add("PrintReal", func(f float64) { fmt.Println(f) }) // Inject helper structs dataContext.Add("strconv", &StrconvWrapper{}) // Later: remove injected data dataContext.Del("PrintReal", "strconv") } ``` -------------------------------- ### Create High-Concurrency Gengine Pool in Go Source: https://context7.com/bilibili/gengine/llms.txt Demonstrates creating a thread-safe pool of rule engines for high-concurrency scenarios supporting 200K+ QPS. Shows API injection, rule compilation, data context setup, execution with request/response objects, and thread-safe rule updates including full replacement and incremental additions. Uses SortModel execution with min/max pool sizing. ```go package main import ( "fmt" "github.com/bilibili/gengine/engine" ) type Request struct { UserID int64 Amount float64 Approved bool } type Response struct { Status string Message string Code int } func validateRequest(req *Request) bool { return req.Amount > 0 && req.UserID > 0 } func approveRequest(req *Request) { req.Approved = true } func main() { // Define APIs to inject apis := make(map[string]interface{}) apis["validate"] = validateRequest apis["approve"] = approveRequest apis["Sout"] = fmt.Println rules := ` rule "validate_request" "Validate request data" salience 100 begin if validate(Request) { Sout("Request validated") Response.Status = "valid" Response.Code = 200 } else { Sout("Invalid request") Response.Status = "invalid" Response.Code = 400 return false } end rule "approve_request" "Approve valid request" salience 50 begin if Response.Code == 200 { approve(Request) Response.Message = "Request approved" Sout("Request approved") return true } end ` // Create pool with min=10, max=50 engines // Pool supports 200K+ QPS for high-concurrency scenarios pool, err := engine.NewGenginePool( 10, // minPoolLen 50, // maxPoolLen engine.SortModel, // execution model rules, // pre-compiled rules apis, // injected APIs ) if err != nil { panic(err) } // Execute with request/response data request := &Request{UserID: 12345, Amount: 100.50} response := &Response{} data := map[string]interface{}{ "Request": request, "Response": response, } err, resultMap := pool.ExecuteRulesWithMultiInputWithSpecifiedEM(data) if err != nil { panic(err) } fmt.Printf("Response: Status=%s, Code=%d, Message=%s\n", response.Status, response.Code, response.Message) fmt.Printf("Request approved: %v\n", request.Approved) fmt.Printf("Rule results: %v\n", resultMap) // Update pool rules (thread-safe) newRules := ` rule "validate_request" "Updated validation" salience 100 begin if validate(Request) && Request.Amount <= 1000.0 { Response.Status = "valid" Response.Code = 200 } else { Response.Status = "invalid" Response.Code = 400 } end ` err = pool.UpdatePooledRules(newRules) if err != nil { panic(err) } // Or use incremental update incrementalRule := ` rule "fraud_check" "New fraud detection rule" salience 75 begin if Request.Amount > 10000 { Response.Status = "flagged" Response.Code = 403 Response.Message = "Fraud check required" } end ` err = pool.UpdatePooledRulesIncremental(incrementalRule) if err != nil { panic(err) } // Get pool information execModel := pool.GetExecModel() rulesCount := pool.GetRulesNumber() fmt.Printf("Pool exec model: %d, rules count: %d\n", execModel, rulesCount) } ``` -------------------------------- ### Build Rules from String in Go Source: https://context7.com/bilibili/gengine/llms.txt This code shows how to define and parse business rules from a string using the rule builder. It depends on gengine/builder and gengine/context for parsing and context setup. Inputs are rule strings with salience and logic; outputs include loaded rule entities in the builder. Note that rule syntax must follow Gengine's format, and errors in parsing can prevent execution. ```go package main import ( "github.com/bilibili/gengine/builder" "github.com/bilibili/gengine/context" "fmt" ) func main() { dataContext := context.NewDataContext() dataContext.Add("User", &User{Name: "Bob", Age: 30, Male: true}) dataContext.Add("Sout", fmt.Println) // Create rule builder ruleBuilder := builder.NewRuleBuilder(dataContext) // Define rules as string rules := ` rule "check_adult" "Verify user age" salience 100 begin if User.Age >= 18 { Sout("User is an adult") User.Name = "Adult_" + User.Name return true } else { Sout("User is a minor") return false } end rule "check_senior" "Check senior citizen" salience 50 begin if User.Age >= 65 { Sout("User is a senior citizen") discount = 0.20 return discount } end ` // Parse and load rules (full replacement) err := ruleBuilder.BuildRuleFromString(rules) if err != nil { panic(fmt.Sprintf("Rule parsing error: %v", err)) } fmt.Printf("Loaded %d rules\n", len(ruleBuilder.Kc.RuleEntities)) } ``` -------------------------------- ### Installing Gengine via Go Modules Source: https://github.com/bilibili/gengine/blob/main/README.md This snippet adds the Gengine dependency to a Go project's go.mod file. It specifies version v1.5.7 and requires Go 1.12 or later. No runtime inputs or outputs; it enables importing and using the engine in Golang applications. Limitations include compatibility only with supported Go versions. ```go require github.com/bilibili/gengine v1.5.7 ``` -------------------------------- ### Mixed Model Rule Execution (Go) Source: https://context7.com/bilibili/gengine/llms.txt Demonstrates a mixed execution model where the highest priority rule is executed first sequentially, followed by the remaining rules executed concurrently. This is useful for scenarios requiring an initialization step before parallel processing. It requires the 'gengine/builder', 'gengine/context', and 'gengine/engine' packages. ```go package main import ( "fmt" "github.com/bilibili/gengine/builder" "github.com/bilibili/gengine/context" "github.com/bilibili/gengine/engine" ) func main() { dataContext := context.NewDataContext() dataContext.Add("Sout", fmt.Println) var initialized bool dataContext.Add("setInit", func() { initialized = true }) dataContext.Add("getInit", func() bool { return initialized }) ruleBuilder := builder.NewRuleBuilder(dataContext) rules := ` rule "initialize" "Must run first" salience 1000 begin Sout("Initializing system...") setInit() end rule "process_a" "Independent processing A" salience 50 begin if getInit() { Sout("Processing A") } end rule "process_b" "Independent processing B" salience 40 begin if getInit() { Sout("Processing B") } end rule "process_c" "Independent processing C" salience 30 begin if getInit() { Sout("Processing C") } end ` err := ruleBuilder.BuildRuleFromString(rules) if err != nil { panic(err) } gengine := engine.NewGengine() // Execute highest priority rule first (sequentially) // Then execute remaining rules concurrently err = gengine.ExecuteMixModel(ruleBuilder) if err != nil { panic(err) } fmt.Printf("Initialization complete: %v\n", initialized) } ``` -------------------------------- ### Go: Process Orders with Complex Data in Gengine Rules Source: https://context7.com/bilibili/gengine/llms.txt This Go code defines `Product` and `Order` structs and uses them within gengine rules to calculate order totals, apply discounts, and check inventory. It demonstrates adding custom data types to the context and executing rules defined as strings. Dependencies include the gengine library. Input is the `Order` struct and an `Inventory` map, output is the updated `Order` total and discount. ```go package main import ( "fmt" "github.com/bilibili/gengine/builder" "github.com/bilibili/gengine/context" "github.com/bilibili/gengine/engine" ) type Product struct { ID int64 Name string Price float64 Stock int } type Order struct { Products []*Product Total float64 Discount float64 } func main() { // Create sample data products := []*Product{ {ID: 1, Name: "Laptop", Price: 1200.0, Stock: 5}, {ID: 2, Name: "Mouse", Price: 25.0, Stock: 50}, {ID: 3, Name: "Keyboard", Price: 75.0, Stock: 30}, } order := &Order{Products: products} inventory := make(map[string]int) inventory["Laptop"] = 5 inventory["Mouse"] = 50 dataContext := context.NewDataContext() dataContext.Add("Order", order) dataContext.Add("Inventory", &inventory) dataContext.Add("Sout", fmt.Println) ruleBuilder := builder.NewRuleBuilder(dataContext) rules := ` rule "calculate_total" "Calculate order total" salience 100 begin total = 0.0 for product in Order.Products { Sout("Processing: " + product.Name) total = total + product.Price } Order.Total = total Sout("Order total calculated") end rule "apply_discount" "Apply discount for large orders" salience 50 begin if Order.Total > 1000.0 { Order.Discount = Order.Total * 0.10 Order.Total = Order.Total - Order.Discount Sout("10% discount applied") } end rule "check_inventory" "Verify inventory" salience 75 begin Sout("Checking inventory...") laptopStock = Inventory["Laptop"] mouseStock = Inventory["Mouse"] Sout("Laptop stock: " + laptopStock) Sout("Mouse stock: " + mouseStock) end ` err := ruleBuilder.BuildRuleFromString(rules) if err != nil { panic(err) } gengine := engine.NewGengine() err = gengine.Execute(ruleBuilder, true) if err != nil { panic(err) } fmt.Printf("Final Order Total: $%.2f\n", order.Total) fmt.Printf("Discount Applied: $%.2f\n", order.Discount) } ``` -------------------------------- ### Execute Rules with Sort Model in Go Source: https://context7.com/bilibili/gengine/llms.txt Demonstrates rule execution in sequential order by priority using the Sort model. Requires gengine/engine for execution alongside builder and context packages. Inputs are built rules and data context; outputs include execution results and modified data. Supports error handling options but is limited to predefined models for concurrency patterns. ```go package main import ( "fmt" "github.com/bilibili/gengine/builder" "github.com/bilibili/gengine/context" "github.com/bilibili/gengine/engine" ) func main() { // Setup user := &User{Name: "Charlie", Age: 45, Male: true} dataContext := context.NewDataContext() dataContext.Add("User", user) dataContext.Add("Sout", fmt.Println) ruleBuilder := builder.NewRuleBuilder(dataContext) rules := ` rule "high_priority" "Execute first" salience 100 begin Sout("Rule 1: High priority executed") User.Age = User.Age + 1 end rule "medium_priority" "Execute second" salience 50 begin Sout("Rule 2: Medium priority executed") User.Name = User.Name + "_processed" end rule "low_priority" "Execute last" salience 10 begin Sout("Rule 3: Low priority executed") return "completed" end ` err := ruleBuilder.BuildRuleFromString(rules) if err != nil { panic(err) } // Create engine and execute gengine := engine.NewGengine() // Execute rules in order of priority (salience) // true = continue on error, false = stop on first error err = gengine.Execute(ruleBuilder, true) if err != nil { panic(err) } // Get return values from rules resultMap, _ := gengine.GetRulesResultMap() fmt.Printf("Result from low_priority rule: %v\n", resultMap["low_priority"]) fmt.Printf("Final user state: Name=%s, Age=%d\n", user.Name, user.Age) } ``` -------------------------------- ### Implement N-M Hybrid Execution Models in Go Source: https://context7.com/bilibili/gengine/llms.txt Demonstrates hybrid execution models for rule processing combining sequential and concurrent execution. Shows three patterns: N-sort-then-M-concurrent, N-concurrent-then-M-sort, and N-concurrent-then-M-concurrent. Each pattern divides rule sets into two groups executed with different concurrency strategies using salience-based sorting. ```go package main import ( "fmt" "github.com/bilibili/gengine/builder" "github.com/bilibili/gengine/context" "github.com/bilibili/gengine/engine" ) func main() { dataContext := context.NewDataContext() dataContext.Add("Sout", fmt.Println) ruleBuilder := builder.NewRuleBuilder(dataContext) rules := ` rule "rule_1" "Rule 1" salience 100 begin Sout("Rule 1") end rule "rule_2" "Rule 2" salience 90 begin Sout("Rule 2") end rule "rule_3" "Rule 3" salience 80 begin Sout("Rule 3") end rule "rule_4" "Rule 4" salience 70 begin Sout("Rule 4") end rule "rule_5" "Rule 5" salience 60 begin Sout("Rule 5") end ` err := ruleBuilder.BuildRuleFromString(rules) if err != nil { panic(err) } gengine := engine.NewGengine() // Execute first 2 rules sequentially (sorted), then next 3 concurrently err = gengine.ExecuteNSortMConcurrent(2, 3, ruleBuilder, true) if err != nil { panic(err) } fmt.Println("---") // Execute first 3 rules concurrently, then next 2 sequentially (sorted) gengine2 := engine.NewGengine() err = gengine2.ExecuteNConcurrentMSort(3, 2, ruleBuilder, true) if err != nil { panic(err) } fmt.Println("---") // Execute first 2 rules concurrently, then next 3 concurrently gengine3 := engine.NewGengine() err = gengine3.ExecuteNConcurrentMConcurrent(2, 3, ruleBuilder, true) if err != nil { panic(err) } } ``` -------------------------------- ### Execute Specific Rules in gengine (Go) Source: https://context7.com/bilibili/gengine/llms.txt Demonstrates how to execute only a selected set of rules by their names, with options for natural salience-based sorting or a custom execution order. This allows for fine-grained control over which rules are triggered. ```go package main import ( "fmt" "github.com/bilibili/gengine/builder" "github.com/bilibili/gengine/context" "github.com/bilibili/gengine/engine" ) func main() { dataContext := context.NewDataContext() dataContext.Add("Sout", fmt.Println) ruleBuilder := builder.NewRuleBuilder(dataContext) rules := ` rule "step_1" "First step" salience 100 begin Sout("Step 1") return 1 end rule "step_2" "Second step" salience 90 begin Sout("Step 2") return 2 end rule "step_3" "Third step" salience 80 begin Sout("Step 3") return 3 end rule "step_4" "Fourth step" salience 70 begin Sout("Step 4") return 4 end ` err := ruleBuilder.BuildRuleFromString(rules) if err != nil { panic(err) } gengine := engine.NewGengine() // Execute only selected rules by name (sorted by salience) selectedRules := []string{"step_2", "step_4", "step_1"} err = gengine.ExecuteSelectedRules(ruleBuilder, selectedRules) if err != nil { panic(err) } resultMap, _ := gengine.GetRulesResultMap() fmt.Printf("Results: step_1=%v, step_2=%v, step_4=%v\n", resultMap["step_1"], resultMap["step_2"], resultMap["step_4"]) // Execute with custom order (ignoring salience) customOrder := []string{"step_4", "step_2", "step_1"} err = gengine.ExecuteSelectedRulesWithControlAsGivenSortedName(ruleBuilder, true, customOrder) if err != nil { panic(err) } } ``` -------------------------------- ### Concurrent Rule Execution (Go) Source: https://context7.com/bilibili/gengine/llms.txt Illustrates how to execute multiple rules concurrently using Gengine. This method ignores rule priorities and runs all rules in parallel using goroutines. It requires the 'gengine/builder', 'gengine/context', and 'gengine/engine' packages, along with the 'sync' package for thread safety. ```go package main import ( "fmt" "github.com/bilibili/gengine/builder" "github.com/bilibili/gengine/context" "github.com/bilibili/gengine/engine" "sync" ) var mutex sync.Mutex var counter int func incrementCounter() { mutex.Lock() counter++ mutex.Unlock() } func main() { dataContext := context.NewDataContext() dataContext.Add("increment", incrementCounter) dataContext.Add("Sout", fmt.Println) ruleBuilder := builder.NewRuleBuilder(dataContext) rules := ` rule "task_1" "Independent task 1" salience 100 begin Sout("Task 1 executing") increment() end rule "task_2" "Independent task 2" salience 50 begin Sout("Task 2 executing") increment() end rule "task_3" "Independent task 3" salience 10 begin Sout("Task 3 executing") increment() end ` err := ruleBuilder.BuildRuleFromString(rules) if err != nil { panic(err) } gengine := engine.NewGengine() // Execute all rules concurrently (ignores priority) // All rules run in parallel using goroutines err = gengine.ExecuteConcurrent(ruleBuilder) if err != nil { panic(err) } fmt.Printf("Counter value: %d\n", counter) // Should be 3 } ``` -------------------------------- ### Execute Rules with Stop Tag for Early Termination (Go) Source: https://context7.com/bilibili/gengine/llms.txt Demonstrates how to use a stop tag to terminate rule execution early. This is useful when a condition is met and subsequent rules do not need to be evaluated. It requires the 'gengine/builder', 'gengine/context', and 'gengine/engine' packages. ```go package main import ( "fmt" "github.com/bilibili/gengine/builder" "github.com/bilibili/gengine/context" "github.com/bilibili/gengine/engine" ) func main() { user := &User{Name: "Dave", Age: 20, Male: true} dataContext := context.NewDataContext() dataContext.Add("User", user) dataContext.Add("Sout", fmt.Println) // Create stop tag and inject it stag := &engine.Stag{StopTag: false} dataContext.Add("stag", stag) ruleBuilder := builder.NewRuleBuilder(dataContext) rules := ` rule "whitelist_check" "Check if user is whitelisted" salience 100 begin if User.Name == "Dave" { Sout("User is whitelisted, stopping further execution") stag.StopTag = true return "whitelisted" } end rule "blacklist_check" "Check if user is blacklisted" salience 50 begin Sout("This will NOT execute if stopTag was set to true") return "checked" end rule "regular_processing" "Normal processing" salience 10 begin Sout("This will also NOT execute if stopTag was set") end ` err := ruleBuilder.BuildRuleFromString(rules) if err != nil { panic(err) } gengine := engine.NewGengine() // Execute with stop tag control err = gengine.ExecuteWithStopTagDirect(ruleBuilder, true, stag) if err != nil { panic(err) } resultMap, _ := gengine.GetRulesResultMap() fmt.Printf("Whitelist result: %v\n", resultMap["whitelist_check"]) fmt.Printf("Blacklist result: %v\n", resultMap["blacklist_check"]) // nil because not executed } ``` -------------------------------- ### DAG Model Execution in gengine (Go) Source: https://context7.com/bilibili/gengine/llms.txt Implements rule execution using a Directed Acyclic Graph (DAG) model. This allows for defining layers of rules where rules within a layer can execute concurrently, and layers execute sequentially, enabling complex dependency management. ```go package main import ( "fmt" "github.com/bilibili/gengine/builder" "github.com/bilibili/gengine/context" "github.com/bilibili/gengine/engine" ) func main() { dataContext := context.NewDataContext() dataContext.Add("Sout", fmt.Println) ruleBuilder := builder.NewRuleBuilder(dataContext) rules := ` rule "fetch_user" "Fetch user data" salience 100 begin Sout("Layer 1: Fetching user data") end rule "fetch_orders" "Fetch order data" salience 90 begin Sout("Layer 1: Fetching order data") end rule "process_user" "Process user" salience 80 begin Sout("Layer 2: Processing user (after layer 1)") end rule "calculate_total" "Calculate totals" salience 70 begin Sout("Layer 3: Calculating totals") end rule "send_notification" "Send notification" salience 60 begin Sout("Layer 3: Sending notification") end ` err := ruleBuilder.BuildRuleFromString(rules) if err != nil { panic(err) } gengine := engine.NewGengine() // Define DAG structure: each row executes concurrently, rows execute sequentially dag := [][]string{ {}, // Layer 0: empty {"fetch_user", "fetch_orders"}, // Layer 1: concurrent {"process_user"}, // Layer 2: after layer 1 completes {"calculate_total", "send_notification"}, // Layer 3: concurrent, after layer 2 } err = gengine.ExecuteDAGModel(ruleBuilder, dag) if err != nil { panic(err) } fmt.Println("DAG execution completed") } ``` -------------------------------- ### Incremental Rule Updates in gengine (Go) Source: https://context7.com/bilibili/gengine/llms.txt Shows how to perform incremental updates to rule sets, allowing for modification of existing rules, addition of new rules, and removal of specific rules without reloading the entire rule base. This is useful for dynamic rule management. ```go package main import ( "fmt" "github.com/bilibili/gengine/builder" "github.com/bilibili/gengine/context" ) func main() { dataContext := context.NewDataContext() dataContext.Add("Sout", fmt.Println) ruleBuilder := builder.NewRuleBuilder(dataContext) // Initial rules initialRules := ` rule "rule_1" "First rule" salience 100 begin Sout("Rule 1 original") end rule "rule_2" "Second rule" salience 50 begin Sout("Rule 2") end ` err := ruleBuilder.BuildRuleFromString(initialRules) if err != nil { panic(err) } fmt.Printf("Initial rules count: %d\n", len(ruleBuilder.Kc.RuleEntities)) // Incremental update: replace rule_1 and add rule_3 updateRules := ` rule "rule_1" "First rule updated" salience 100 begin Sout("Rule 1 UPDATED") end rule "rule_3" "Third rule" salience 25 begin Sout("Rule 3 NEW") end ` // This will replace rule_1 and add rule_3, rule_2 remains unchanged err = ruleBuilder.BuildRuleWithIncremental(updateRules) if err != nil { panic(err) } fmt.Printf("After incremental update: %d rules\n", len(ruleBuilder.Kc.RuleEntities)) // Check if rules exist exists := ruleBuilder.IsExist([]string{"rule_1", "rule_2", "rule_3", "rule_4"}) fmt.Printf("Rule existence: rule_1=%v, rule_2=%v, rule_3=%v, rule_4=%v\n", exists[0], exists[1], exists[2], exists[3]) // Remove specific rules err = ruleBuilder.RemoveRules([]string{"rule_3"}) if err != nil { panic(err) } fmt.Printf("After removal: %d rules\n", len(ruleBuilder.Kc.RuleEntities)) } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.