顺带清理 go.mod:condition/contracts/db/reflux/req 之前都靠指向本地兄弟 目录的 replace 绕开版本解析,现在锁定成各自 master 最新的真实 commit, 去掉 replace——本地多仓库协同开发改用父目录的 go.work。 Example_userApprovalFlow 这个例子测试目前会失败(预期输出跟实际 SQL 生成 对不上),验证过跟这次改动无关(改动前后表现一致),是已经存在的问题, 不在这次改动范围内。
2.5 KiB
2.5 KiB
git.fsdpf.net/go/condflow
条件流引擎:把一串"条件 -> 动作"的分支(CondCase)按优先级串成一个决策流(CondFlow),
输入一份数据,按顺序求值每个分支的条件(复用 git.fsdpf.net/go/condition 的 Condition
DSL),命中的分支执行对应动作,支持分支之间链式跳转到下一个流。典型场景:审批流程(金额分档
审批、信用分拒绝)、营销规则(分群发券)等需要"按条件走不同处理逻辑"的业务。
核心概念
CondFlow:一个决策流,New(name string)创建,AddCase(c *CondCase)按优先级加入 分支,Run(app do.Injector, input reflux.R, user req.User) error执行——按getSortedCases()排好的顺序对每个分支求值,命中就执行Action,WithNextCaseOnSuccess(true)控制命中后要不 要继续尝试后面的分支(默认命中一个就停)。CondCase:单个分支,NewCondCase(name, cond *condition.Condition, action string)构造,绑定一个condition.Condition和一个 action 的名字(通过ActionInvoker按名字查 实际实现)。WithPriority/WithActionParams/WithActionConfig配置优先级和动作参数;WithNextFlowOnSuccess(flow *CondFlow, params fieldx.Schema)支持分支命中后跳转到另一个CondFlow继续执行,串成更复杂的决策树。Action/ActionInvoker:实际执行的业务逻辑,type Action func(ctx Context, cfg valuex.Accessor) (reflux.R, error),ActionInvoker按名字查找、调用具体的Action实现(Executor接口 + 反射,NewActionInvokerWithValue支持从一个结构体值上按方法名找 对应的 action)。Context/FlowContext:执行上下文,带当前用户(req.User)、输入数据的按路径取值 (Get/GetParam,基于valuex.Accessor)、Fork(input)派生一个新上下文(分支跳转时 用)、Res() req.Resource拿到动作关联的资源。- 条件求值:
CondFlow.makeTable/makeCTE把输入数据(reflux.R)包装成一张虚拟的Flow表(用db-v2的CTE),每个分支的condition.Condition.ToSql(...)渲染成IF(条件, 1, 0)列,一次查询同时算出所有分支是否命中,不用逐个分支单独跑判断逻辑。
已知问题
tests/example_test.go 里的 Example_userApprovalFlow 目前会失败(预期输出跟实际生成的 SQL
对不上,具体差异待排查),其它测试和例子都正常。