Go运行Grule引擎实现计费规则管理

Go运行Grule引擎实现计费规则管理

  • github位置: https://github.com/hyperjumptech/grule-rule-engine
shell 复制代码
# 安装grule模块
go get -u github.com/hyperjumptech/grule-rule-engine

Grule的示例代码

  • 示例位置: https://github.com/hyperjumptech/grule-rule-engine/tree/master/examples

    • 使用 go test 运行
    shell 复制代码
    cd examples
    $ go test NumberExponentExample_test.go 
    ok      command-line-arguments  0.011s
  • Grule规则

    • rule {} 表示规则
    • salience 10 表示优先级为10
      • 优先级高的先执行
go 复制代码
type ExponentData struct {
	Check float64
	Set   float64
}

/*
    条件部分 (when):
    当ExponentData 结构体中的 Check 等于 6.67428e-11 时,规则会触发
    动作部分 (then):
    当条件满足时,将 ExponentData 结构体中的 Set 设置为 .12345E+5
    然後,使用 Retract("ExponentCheck") 將這個规则從工作记忆中移除,
    以防止它再次被觸發。
*/

const ExponentRule = `
rule  ExponentCheck  "User Related Rule"  salience 10 {
	when 
		ExponentData.Check == 6.67428e-11
	Then
		ExponentData.Set = .12345E+5;
		Retract("ExponentCheck");
}
`
// 往下是 运行"github.com/stretchr/testify/assert"的测试代码, 忽略
func TestEvaluateAndAssignExponentNumber(t *testing.T) {
	exponent := &ExponentData{
		Check: 6.67428e-11,
		Set:   0,
	}
	...
}
  • 总结:Grule规则使用 when 判断条件, 当条件满足时执行 then

编写计费规则代码

  • 仿照示例代码,编写计费规则代码

    • 对云服务器 cpu 计费, 每小时 0.05元 * 核数
    • 对云服务器 内存 计费, 每小时 0.01元 * GB
    go 复制代码
    const (
      rule = `
      rule CalculateCost "Calculate the total cost based on CPU and Memory usage" {
        when 
            CloudResource.CPU > 0 &&
            CloudResource.Memory > 0
        then
            costPerCPUHour = 0.05;
            costPerGBMemoryHour = 0.01;
            cpuCost = CloudResource.CPU * costPerCPUHour;
            memoryCost = CloudResource.Memory * costPerGBMemoryHour;
            CloudResource.TotalCost = cpuCost + memoryCost;
            Retract("CalculateCost");
      }
      `
    )
    • cpu 内存 总费用 封装为结构体
    go 复制代码
    type CloudResource struct {
        CPU       float64
        Memory    float64
        TotalCost float64
    }
  • 使用 go test 执行完整代码

go 复制代码
package example

import (
    "testing"

    "github.com/hyperjumptech/grule-rule-engine/ast"
    "github.com/hyperjumptech/grule-rule-engine/builder"
    "github.com/hyperjumptech/grule-rule-engine/engine"
    "github.com/hyperjumptech/grule-rule-engine/pkg"
    "github.com/stretchr/testify/assert"
)

const (
    rule = `
rule CalculateCost "Calculate the total cost based on CPU and Memory usage" {
    when 
        CloudResource.CPU > 0 &&
        CloudResource.Memory > 0
    then
        costPerCPUHour = 0.05;
        costPerGBMemoryHour = 0.01;
        cpuCost = CloudResource.CPU * costPerCPUHour;
        memoryCost = CloudResource.Memory * costPerGBMemoryHour;
        CloudResource.TotalCost = cpuCost + memoryCost;
        Retract("CalculateCost");
}
`
)

type CloudResource struct {
    CPU       float64
    Memory    float64
    TotalCost float64
}

func TestCloudResource(t *testing.T) {
    myResource := &CloudResource{
        CPU:    2,
        Memory: 4,
    }
    dataContext := ast.NewDataContext()
    err := dataContext.Add("CloudResource", myResource)
    if err != nil {
        t.Fatal(err)
    }
    lib := ast.NewKnowledgeLibrary()
    ruleBuilder := builder.NewRuleBuilder(lib)
    err = ruleBuilder.BuildRuleFromResource("Test", "0.1.1", pkg.NewBytesResource([]byte(rule)))
    assert.NoError(t, err)
    kb, err := lib.NewKnowledgeBaseInstance("Test", "0.1.1")
    assert.NoError(t, err)
    eng1 := &engine.GruleEngine{MaxCycle: 1}
    err = eng1.Execute(dataContext, kb)
    assert.NoError(t, err)

    // 檢查計算出的總成本
    expectedTotalCost := (2 * 0.05) + (4 * 0.01)
    assert.Equal(t, expectedTotalCost, myResource.TotalCost)
}
  • 总结: 使用 assert.Equal 校验 expectedTotalCost ,最后得出结果
shell 复制代码
$ go test
PASS
ok      grule_study/example/test        0.007s
相关推荐
星火开发设计2 分钟前
命名空间 namespace:解决命名冲突的利器
c语言·开发语言·c++·学习·算法·知识
小北方城市网3 分钟前
RabbitMQ 生产级实战:可靠性投递、高并发优化与问题排查
开发语言·分布式·python·缓存·性能优化·rabbitmq·ruby
爱学习的阿磊8 分钟前
C++中的策略模式应用
开发语言·c++·算法
郝学胜-神的一滴9 分钟前
Python中的bisect模块:优雅处理有序序列的艺术
开发语言·数据结构·python·程序人生·算法
Remember_99312 分钟前
Spring 事务深度解析:实现方式、隔离级别与传播机制全攻略
java·开发语言·数据库·后端·spring·leetcode·oracle
看得见的风14 分钟前
Claude Code + CCR配置(含OpenRouter、GLM、Kimi Coding Plan)
开发语言
L_090716 分钟前
【Linux】进程状态
linux·开发语言·c++
roman_日积跬步-终至千里16 分钟前
【Java并发】用 JMM 与 Happens-Before 解决多线程可见性与有序性问题
java·开发语言·spring
2401_8384725117 分钟前
C++异常处理最佳实践
开发语言·c++·算法
m0_7369191021 分钟前
C++中的类型标签分发
开发语言·c++·算法