workflow

package module
v0.3.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 5, 2026 License: MIT Imports: 8 Imported by: 0

README

workflow

组合式流程编排——四种流 + Hook AOP

🌐 项目主页:https://oekit.github.io/ · 名称由来:Open Easy Kit(开源 · 易用 · 工具集合) 🤖 AI Agent:本仓规范与硬规则见 AGENTS.md;机器可读索引见 llms.txt(接口签名以源码为准)。

安装

go get github.com/oekit/workflow@v0.3.4

这个仓库做什么

workflow 是组合式流程编排框架:串行/并行/异步/条件分支四种模式任意嵌套, Hook AOP 自动向子流程递归传播,context 取消自动传递,panic 全量 recover。

四种流

流 语义
PipeFlow 串行管道:步骤依次执行,任一失败即中止
ParallelFlow 并行:并发执行(可限并发数),聚合错误
AsyncFlow 异步:提交后收集结果,错误经 resultFn 上抛
SwitchFlow 条件分支:按判定选择子流程

快速使用

import "github.com/oekit/workflow"

p := workflow.NewPipe()
p.Add(step1, step2, workflow.NewParallel(4))
err := p.Run(ctx)

Hook AOP

HookManager 注册 Before/After/成功/失败钩子,自动递归传播到所有子流程—— 审计日志、链路打点、熔断注入都不用改业务步骤。

边界

  • 步骤是任意 Runnable(Run(ctx) error);定时触发用 timertask

矩阵总览(24 活跃模块,自动生成)

模块 内容 矩阵内依赖
pkg 微工具集 24 合 1(errors/bloomx/contextx/container/stringx/slicex/enumx/convert/encoding/jsonrepair/httpjson/mathx/pathx/pagination/ptrx/shellx/timex/cache/bufiox/strmap/singleflighttest/urlguard/cli/pack;v0.10.0 起 uidgen/validator 拆至 kitx);errors(v0.12.0 起)New/As/Is/Unwrap 与 stdlib 同型透传——下游哨兵/As 判定单 import 即可,类型同一性红线可完整执行;cache(v0.4.0 起)含缓存接口 CacheAside + BatchGetter 批量能力(MGet)+ LocalCache/SingleFlightCache + cachetest 契约(Run 真实时间 + RunWithClock 假时钟确定性 TTL 边界)+ Checker;LocalCache 时钟可注入(LocalConfig.Now——TTL/NullTTL 全路径确定性测试,v0.13.0 起);v0.16.0 起 LocalCache 可选形状——NoBackgroundSweep 关闭后台清扫 goroutine(嵌入式/短命进程,公开 Sweep 手动清扫口)、CloneOnRead 读命中返回副本(调用方可改写不污染缓存)、EvictPolicy 可选 LRU(默认 FIFO 不变)、GetEx 区分未命中与值为 nil(新增能力以可选接口 Sweeper/HitGetter 外置,不破坏其它后端);v0.23.0 起补 Peek 非删除式读(可选接口 PeekGetter 外置——读到过期条目只算不命中、不删除它,stale-if-error 兜底需要那份过期真值留在表内;SingleFlightCache 包装 LocalCache 时曾因前置检查走 Get 惰性删除而静默废掉 StaleIfError,#72);container(v0.9.0 起,收编原 collectionx)泛型容器 Set/Ring/Queue/SafeMap + Map(sync.Map 背书)/Slice(并发安全);mathx/jsonrepair(v0.11.0)Unstable 单边向上抖动 Upward / 宽松解析 UnmarshalLenient / 抽对象与抽数组对称原语 ExtractObject·ExtractArray(v0.18.0 起——多段数组与散文含 '{' 的数组文本不再整段作废,取首个口径与对象面一致);timex/stringx(v0.7.0 起)时间段边界 BeginningOf/EndOf 七对(分/时/日/周/月/季/年,周起始显式参数)+ trie 多模式替换器 Replacer(最长匹配)/ NewMask 敏感词遮罩;stringx Masker(v0.16.0 起)正则脱敏——按形态分类打码(形态标签进掩码供审计读)+ 保留首尾各 ≤4 字符定位线索且不可复原(保留位封顶不随长度变化),规则表由调用方完全提供;singleflighttest(v0.8.0 起)singleflight 共享契约测试套件(internal 与 concurrency 双侧引用);urlguard(v0.15.0 起)出站 SSRF 防护原语——CheckURL 字面量校验(私网/loopback/链路本地含云元数据 169.254.169.254/CGNAT/ULA/组播保留、.internal·.local·localhost 域名、scheme 白名单、IPv4-mapped IPv6 归一)+ DialFunc 拨号层预解析校验与实际 RemoteAddr 端点核对闭合 TOCTOU(Happy-Eyeballs 覆盖),构造态豁免 WithAllowPrivate/WithAllowCIDRs/WithAllowDomains,与 httpx WithDialFunc 一行组合(httpx#11);cli(v0.16.0 起)框架无关可单测的子命令分发原语——App/Command + 退出码 0/1/2 写死在包里、usage 按 Summary 自动生成、不读 os.Args 不调 os.Exit(输出流全由调用方给);pack(v0.16.0 起)迁移包容器原语——zip + manifest(格式版本/条数/每文件 SHA-256)+ JSONL 流式读写 + Inspect 体检一次列全问题并区分包损坏与版本不认识 —
concurrency 并发与流控原语(async/gopool/group/singleflight/progress/syncx/ratelimit/retry)+ window 滑动窗口 / breaker 自适应熔断(规范哨兵 ErrCircuitOpen)/ shedding CPU 自适应降载 / batch 攒批执行器(满条数/满字节/窗口去重)/ timewheel 单级时间轮;v0.5.0 起 retry 指数退避+抖动(MaxDelay 封顶/溢出饱和)、loop 周期原语(忙时丢 tick/单轮 panic 收编/FirstDelay 可打断)、async labeled RunSafe(panic 按任务标签上报)、syncx.FanInErr 逐槽错误(panic 槽显式标记)、KeyedLimiter 增强(容量护栏/RetryAfter/速率热更)并接入 pkg/singleflighttest 契约测试;v0.8.0 起 singleflight DoShared 折叠可观测(Result.Waiters)、async panic 统一收编 typed *PanicError(errors.As 可辨、携带栈)+ 实例级 Runner panic 路由、retry DelayHint(服务端 Retry-After 建议优先)+ JitterRatio 比例抖动 + retry/httpx Retryable 可重试性判定;v0.9.0 起 breaker 显式三态状态机 closed/open/half-open——冷却(WithProbeTimeout 缺省 1m)期满首个放行即半开探测、探测成功关闸清窗/失败重开、失联超时自动回收 + AbandonGen 显式放弃,GenBreaker 代绑定(AllowGen/SuccessGen/FailureGen/AbandonGen:代仅在探测放行自增、陈旧代回报整体作废、开放期失败不后移冷却);v0.10.0 起 WithCooldown 独立业务冷却期(缺省回落 probeTimeout)+ WithConsecutiveFailures 连续失败计数触发(与速率型并联,补低 QPS 信号,对齐 Envoy consecutive_5xx);v0.11.0 起 ratelimit Lockout 防爆破锁(fail2ban 形态:滑窗失败计数→阈值锁定拒绝 LockDuration→成功 Reset 清零/到期自解,CheckLocked 返回剩余时长);v0.12.0 起 retry/httpx RetryableWithHeaders(403 + Retry-After/X-RateLimit-Remaining 头感知可重试判定,HeaderSource 零依赖抽象)、syncx FanInLimit 受限并发扇出(固定 worker 防下游过载)+ FanInLimitCtx(v0.14.0,ctx 感知:ctx 已取消未启动项 fn 一次不调、剩余槽快速排空 Canceled、在飞项照常落槽)、ratelimit WithTokenClock 时钟注入;v0.13.0 起 breaker 熔断期收敛到探测级(forcePass 强制探活 + 冷却期满半开探测,其余拒绝——SRE 公式退役为 closed→open 触发器,WithConsecutiveFailures 触发后流量真停)+ State()/State 枚举可观测出口;v0.16.0 起 ratelimit NewKeyedLimiterByFunc[K]——factory func(K) Limiter 按 key 定配额(一个管理器按接口维度分档位,NewKeyedLimiterOf 零破坏随迁;未登记 key 拿 factory 兜底档的坑已在 doc 点名,#31);v0.17.0 起 KeyedLimiter.Create 护栏内原子登记(表满先回收空闲与 Allow 同路、仍满拒绝计 OverCapHits、已存在不覆盖——热更走 Replace;解决 ByFunc factory 库锁内调用致消费方锁序倒置,#33);v0.18.0 起 retry.DoValue 泛型伴生——带返回值的重试(DoValue[T](ctx, cfg, fn func(attempt int) (T, error));Do 改为委托给 DoValue——退避序列/抖动/MaxDelay 封顶/DelayHint 优先/Retryable 门控/ctx 取消只有一份实现,杜绝「同一个仓里两份实现」;失败返回零值与最后一次错误) pkg
logx 统一日志门面(多后端可替换 + caller 归属;Sink 已迁嵌套模块 logx/sink,根包纯 stdlib);WithFilter 脱敏/丢弃包装(FilterKey 命中键替换 ***/FilterFunc 丢整条,子 logger 保持规则)、Slogger/SlogHandler 正向桥(三方 slog 直接消费 logx 生态)、TraceHandler 任意 slog.Handler 自动注入 trace_id、NewAuditLogger 审计留痕(级别锁 Info,不受 LOG_LEVEL 降级)、LevelEnabler 热路径提前判级、ParseLogLevel 返回 (Level, error) + ParseLogLevelOr 配错退默认(v0.7.0);优雅关停正身在 core/lifecycle.Manager(logx/shutdown 仅余 Deprecated 别名);桥接子包 hlog/hertzlog/kitexlog 为嵌套模块按需引入 core
core 应用基建件——governance 治理 schema、config 配置加载(LoadBootstrap/LoadDotEnv/Get* 系、default/env/range/options tag 校验、OverlaySource 多源叠加热更、ApplyEnvOverlay env 优先 12-factor 形态)、transport 协议无关传输上下文(Transporter/Header/Server·Client ctx 存取,仅标准库)、chain 中间件链(Handler/Middleware/Chain/Recovery/Timeout,与 nns-endpoint.Endpoint 同形)、lifecycle 契约 + Manager 优雅关停(自 logx/shutdown 迁入,日志 *slog.Logger——core 不再依赖 logx)、network IP 工具、version;v0.9.0 起 config FieldSet 显式提供集合(yaml 显式 port:0 不再被 default/env 覆盖——LoadBootstrap 默认接线,免全量指针化)+ require tag(必须 yaml/env 提供,缺失列全并附 env 提示)+ v0.9.1 修 yaml:,inline 字段在 FieldSet 下漏标记(inline 叶子显式零值曾被 default 覆盖);v0.9.2 env 卫生改纯静态(仅格式/重名,移除依赖进程环境的拼写冒烟检查——误报 PATH/HOME、漏无人设置的真拼错,core#8),命名一致性走 LintEnvNaming 诊断 / WithEnvNamingLint 可选 fail-closed / ignorederived="true" 豁免;v0.10.0 起 config 严格模式——LoadBootstrap[T](envFlag string, opts ...LoadOption) 传 config.WithStrict() 开启:未知键拒载(不再静默忽略),错误带嵌套路径 + 该层合法键清单 + 近似拼写建议(UnknownKeyError);默认行为不变,严格模式显式开启;v0.11.0 起 config 加载入口按来源拆开——LoadFile(任意路径:CLI -config 路径、容器内固定挂载位)+ Unmarshal(字节源:API 下发 / 模板渲染 / 测试夹具),与 LoadBootstrap(etc/ 约定)共享同一条解码线,因此严格模式诊断面(嵌套路径 / 合法键清单 / 拼写建议)与来源无关;LoadBootstrap 行为与错误文案逐字不变 —
kitx 标识与校验——uidgen(Snowflake 全局单例+Extract 元数据、手写 RFC 4122 v4 UUID 零第三方依赖、RandomHex/RandomString 拒绝采样随机串)+ validator(go-playground/validator v10 接口化门面:struct tag 校验/自定义规则注册/ValidationError Unwrap 为 BizError 400 对接 middleware.Fail)+ hash(v0.2.0 起非密码学哈希助手 Md5Hex/Md5Bytes——缓存键/幂等键/短唯一 code,格式稳定承诺,pkg 2026-09-15 治理移除弱哈希后 kitx 侧收编 pkg#10),自 pkg v0.10.0 拆出 pkg
metrics Prometheus 门面 + 弹性指标族 core
tracing OpenTelemetry 追踪 + trace_id 真相源(v0.3.0 起 OTLP 双协议导出:gRPC 缺省 / HTTP,Config.Protocol + Headers,切换协议不丢传播器/指标/旧 provider 关闭) logx
registry 注册发现核心(provider 无关 SPI:Registrar/Discoverer/Subscriber/ConfigStore + 实例模型 + netutil)+ sdbridge + registrymocks——根仓零第三方依赖;Nacos 实现与 Nacos 配置源已拆成嵌套模块(v0.5.0 起:registry/nacosimpl、registry/nacos——nacos-sdk-go 重依赖隔离在此,实测单独引入即拖 63 个第三方模块,不隔离时只要 SPI 接口的消费方也会被连带拖入) core
data 数据访问门面——复刻 ekit data/ 能力面:cache/rediscache/crud/distlock/gormx/redisx/timertask/cachetest 八子包 re-export(类型同一,实现住 pkg 与各子仓)+ cached 缓存读写编排(写后失效/事务提交后失效/查询缓存版本号失效/GetByIDs 批量点读 MGet 快路径/bloom 防穿透)+ twolevel 两级缓存与跨实例失效广播(v0.7.0 起本仓唯二非 re-export 实现);v0.15.0 起壳跟随源仓演进——cache 壳补 LocalCache 可选形状(EvictPolicy/Sweeper/HitGetter)、cachetest 壳补 5 个契约套件入口(套件 8 → 13 场景)、v0.18.0 起 cache 壳补 PeekGetter 别名 + cachetest 壳补 2 个 stale-if-error 契约入口(套件 13 → 15 场景)、timertask 壳的 Redis 形态随源仓 v0.2.0 迁至嵌套模块 timertask/redis(壳不再转发 RedisBackend/ShardManager,Redis 形态直接依赖该嵌套模块);all/ 聚合模块已废弃 retract concurrency、gormx、logx、pkg、redisx、timertask
gormx SQL/GORM 全家——连接池增强、框架无关 CRUD Service、仓储(原 oekit/gorm,v0.3.0 更名) logx、pkg
redisx Redis 全家——客户端封装(根包)、分布式缓存 cache/、分布式锁 distlock(Locker 同形可互换;Renew 手动续期(false=锁丢失,不进 Locker 接口保 etcdx 互换)+ WithAutoRenew 覆盖 TryLock 自动续期(v0.8.0 feat!:此前组合不续期);Semaphore ZSET 槽位信号量(v0.8.0:Acquire 同 identifier 幂等刷新 + Lua 内原子清过期槽崩溃自愈、Renew 仅未过期槽可续、Cleanup 返条数、无 Redis 降级 fail-fast))、分布式限流 ratelimit(Lua 三态 + 故障本地兜底);v0.9.0 起 distlock Lockout 分布式防爆破锁(Redis 侧 fail2ban:滑窗失败计数→阈值锁定 Penalty→Reset 清零,与 concurrency/ratelimit.Lockout 进程内孪生——多实例共享计数是存在理由;惩罚只按首次触发计算、nil client fail-fast 不降级,#6) concurrency、logx、pkg
etcdx etcd 全家——客户端封装(根包:生产默认值/Health 探活/Close(ctx) 幂等)、registry 注册发现实现(SPI 对接 registry/nacos 链路:Lease KeepAlive 注册 + 丢约指数退避自动重注册、prefix Watch 订阅推送、ConfigStore KV 配置监听)、distlock 分布式锁(Session+concurrency.Mutex 公平排队,接口与 redisx/distlock.Locker 同形可互换,可选无 etcd 降级放行) concurrency、logx、registry
httpx HTTP 客户端 + 负载均衡——服务发现/熔断(规范哨兵 ErrCircuitOpen)/重试/指标/OTel 透传;loadbalance Selector 形态(RoundRobin/Random/Weighted/一致性哈希权重感知虚拟副本/p2c 自适应——EWMA 经 DoneFunc 回写建立、Err 计 1s 惩罚;WithFilter 按元数据过滤;v0.4.0 起 Balancer 全家族删除无兼容路径);codec 注册制编解码器(json 内置 + form 表单,DoCodec 请求按 codec 序列化、响应按 Content-Type 反查回退请求 codec);v0.6.0 起 net/http 桥接层 NewRoundTripper/StdClient——存量标准库外呼一行 Transport 接入熔断/重试/指标/链路(重试缺省关显式开、非 2xx 非错误、hop-by-hop 隔离,#8);v0.8.0 起 SafeDialFunc/WithSafeDial 出站 SSRF 防护胶水(判定单源 pkg/urlguard v0.15.0:解析 IP 全量预检 + 实际 RemoteAddr 端点核对闭合重解析 TOCTOU、Happy-Eyeballs 覆盖,构造态豁免;v0.7.0 内置的独立 httpx/urlguard 实现收敛删除,#11) concurrency、logx、metrics、pkg、registry、tracing
network 轻量网络客户端——WebSocket/NATS/MQ 抽象、连接与流工具 concurrency、logx、tracing
timertask 分片定时任务(FNV-1a、心跳续约);v0.1.5 起可选可靠投递 DeliveryAtLeastOnce(租约 + Ack + 可见性超时;过期租约回扫重投/死信、停机 best-effort 收租,v0.1.7 接入生命周期真正生效);v0.2.0 起 Redis 后端迁至嵌套模块 timertask/redis(根包不再引 go-redis/logx/concurrency,require 仅 pkg——import timertask 与 import timertask/local 的模块依赖面均无 redis,纯 stdlib 嵌入式场景可用)+ 新增 local 子包 cron 调度器 Scheduler(表达式复用 pkg/timex/cron 不另写一份;并发度/CatchUp 补跑/退出语义明确,FakeClock 假时钟驱动、触发点序列可确定性断言) pkg
middleware Hertz 标准中间件栈(模块根 mw,双层目录已收平)+ contrib 桥接 + hmw + SheddingMiddleware 自适应降载 + chainmw 子包(transport 感知框架无关中间件,基于 core/chain+transport:Recovery 带 panic 隔离上报钩子 WithRecoveryReporter、AccessLog skip+redact+自定义字段、MetadataPropagate——kitex 经 kitex/chainmw.ToKitex 复用同一实现,根包 Recovery/AccessLog 已薄壳化复用 chainmw 内核、下游 handler 可经 transport.FromServerContext 读协议无关传输信息);v0.6.0 起 accesslog 凭证路径脱敏(WithAccessLogRedactPathPrefixes)、ratelimit 默认 KeyFunc 去端口(连接桶→地址桶);v0.11.0 起 WithAccessLogSink 落库 sink(AccessRecord{Method,Path,Status,Latency,ClientIP,UserAgent,TraceID} 与日志同源、c 同传可读业务键、error/panic 只记 Warn 不影响主链路、SkipPaths 命中不触发)+ chainmw.WithSink 内核同构(kitex 随 ToKitex 获得)+ StackConfig.DisableResponseWrap 响应自管一键形态(TraceID→Recovery→AccessLog)与 AccessLogOptions 透传 + doc/README「适用边界」段(响应契约统一 vs handler 自管的推荐组合,#18);v0.12.0 起 AccessLog panic 恢复点产出记录(AccessRecord.Panic 标记 + Err 摘要,Hertz status 按 Recovery 缺省 500)后按原值重抛——panic 请求不再零访问记录,sink/kitex 桥接同步留痕,#20;v0.13.0 起 accesslog 内建日志可关闭/改道(WithAccessLogSilent 只采不写、WithAccessLogLogger 注入宿主 logger 避免双写;静默下 skip/redact/sink/panic 记录照常),内核 chainmw.WithSilent 同构(kitex 随 ToKitex 获得),#38 concurrency、core、logx、metrics、pkg、registry、tracing
k8s Kubernetes 客户端封装——RESTConfig/Clientset/DynamicClient 构建(显式 kubeconfig → in-cluster 自动 → KUBECONFIG/~/.kube/config 逐级回退,QPS/Burst 限流默认 50/100)+ leaderelection 子包 Lease 选主简化封装(OnStartedLeading/OnStoppedLeading/OnNewLeader 回调,主备单活,仅要求 Lease CRUD 权限) logx
nns NNS 服务治理客户端——provider 无关发现/配置/实例缓存 concurrency、core、logx、registry
nns-endpoint NNS 端点工厂——per-service 熔断、换实例重试、gRPC 池 httpx、logx、metrics、nns、registry
bootstrap 应用生命周期引导——New(WithServiceName/WithShutdownTimeout/WithBeforeServe) + Run(fn) + healthz;App.Ready/ReadyChan/IsReady 就绪门(幂等并发安全)——嵌套 bootstrap/nacos 自 v0.3.0 起 NNS 注册延迟到 Ready 之后(server 就绪 → userFn 触发 Ready → 才进注册中心)、关停序 nns 反注册先于 server 关闭;就绪门漏接时可观测——nacos 看门狗超时打 ERROR 点明「服务不会注册到注册中心」(WithReadyTimeout 可调)+ NNSComponent.RegistrationState() 暴露注册阶段(pending/registered/failed/skipped/shutdown);Metrics/Tracing 在嵌套模块 bootstrap/obs concurrency、core、logx
hertz Hertz 运行时集成(模块根扁平化)——日志桥接、生命周期、SSE/health/metrics、适配器、OTel、crudh/validatorh(基于 kitx/validator)/versionh(原 handler 微库收编);RunServer 变参就绪门 WithOnReady(全部 HostPort TCP 探活可建连后回调,探活超时按启动失败优雅关机;缺省超时 5s 经 WithReadyProbeTimeout 调整——探活目标是 server 自动取到的全部 HostPort,无探活地址覆盖选项(kitex 侧才有 WithReadyAddr)),配合 bootstrap Ready 实现 NNS 延迟注册;transportx(hertz→core/transport 同构适配器)+ chainmw 桥接 bootstrap、concurrency、core、gormx、kitx、logx、metrics、middleware、nns、pkg、registry、tracing
kitex Kitex 生态——日志桥接、治理热更、生命周期、BizError 桥接、kitexotel、istio(xDS 动态熔断,原 istio 微库收编);RunServer 变参就绪门(WithOnReady/WithReadyAddr/WithReadyProbeTimeout)+ chainmw.ToKitex(core/chain.Middleware → kitex 中间件,与 hertz 共享 middleware/chainmw 实现)+ transportx bootstrap、concurrency、core、logx、metrics、nns、pkg、registry
workflow 组合式流程编排——串行/并行/异步/条件分支 + Hook AOP concurrency、logx
kitex-examples Kitex echo 示例——client/server + IDL + 治理配置 bootstrap、core、kitex、logx、tracing

依赖严格自底向上;微库已合并为 pkg,旧微库仓已删除。

本仓在矩阵中的位置与依赖见上表「矩阵内依赖」列。历史沿革:源自 ekit 单体库 (git.enjoye.top/enjoydream/ekit v0.34.0,冻结维护),2026-10 拆分为独立 module。

License

MIT — 见 LICENSE

Documentation

Overview

Package workflow 提供组合式流程编排框架。

支持串行、并行、异步、条件分支四种流程模式,可任意嵌套组合。 所有流程节点共享 Runnable 接口,Hook 自动递归传播实现 AOP。

流程类型

  • PipeFlow: 串行流程,按顺序依次执行,任一失败则停止
  • ParallelFlow: 并行流程,并发执行,任一失败则取消其他
  • AsyncFlow: 异步流程,返回 Future,不阻塞调用方
  • SwitchFlow: 条件分支,根据 key 选择执行路径

组合嵌套

pipe := workflow.NewPipe()
pipe.Add(step1, step2)

parallel := workflow.NewParallel(10)
parallel.Add(task1, task2)

// 嵌套:串行流程中包含并行流程
pipe.Add(parallel)

Context 取消传播

所有流程支持 context 取消传播:

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

// 如果 ctx 被取消,所有正在执行的任务会收到取消信号
err := pipe.Run(ctx)

任务错误与 context 取消的语义

ParallelFlow/AsyncFlow 对错误链包含 context.Canceled/DeadlineExceeded 的 任务错误采用统一豁免规则:

  • 流程级 context 确实被取消/超时 → 视为取消的副作用,不上报;
  • 流程级 context 健康 → 视为任务自身的失败(例如任务内部子操作超时 返回 fmt.Errorf("db timeout: %w", context.DeadlineExceeded)),必须 正常上报给调用方,绝不吞错。

Hook AOP

hook := workflow.NewHookManager()
hook.Add(&LogHook{}, &MetricsHook{})

// Hook 会自动递归传播到子流程
pipe.SetHookManager(hook)

异步任务

async := workflow.NewAsync(10)
async.Add(task1, task2, task3)

// 返回 Future,不阻塞
future := async.RunAsync(ctx)

// 等待完成或取消
err := future.Wait(ctx)
future.Cancel()

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AsyncFlow

type AsyncFlow struct {
	// contains filtered or unexported fields
}

AsyncFlow 异步执行多个任务。 返回 Future,不阻塞调用方。 支持 context 取消传播和任务取消。

func NewAsync

func NewAsync(maxProcs int) *AsyncFlow

NewAsync 创建一个异步流程。 maxProcs 为最大并发数,<=0 表示不限制。

func (*AsyncFlow) Add

func (a *AsyncFlow) Add(tasks ...Runnable) *AsyncFlow

Add 添加一个或多个异步任务。 若任务本身是子流程,当前 HookManager 会同步传播给它(与 PipeFlow.Add 对称,2026-09-06 复审修复)。

func (*AsyncFlow) Hooks

func (a *AsyncFlow) Hooks() *HookManager

Hooks 获取 Hook 管理器。

func (*AsyncFlow) Run

func (a *AsyncFlow) Run(ctx context.Context) error

Run 并发执行所有任务,阻塞直到全部完成或 context 取消。 如需非阻塞模式,请使用 RunAsync。

func (*AsyncFlow) RunAsync

func (a *AsyncFlow) RunAsync(ctx context.Context) *Future

RunAsync 异步执行所有任务,返回 Future。 调用方可以通过 Future.Wait() 等待完成,或 Future.Cancel() 取消任务。

func (*AsyncFlow) RunAsyncWithResults

func (a *AsyncFlow) RunAsyncWithResults(ctx context.Context) <-chan AsyncResult

RunAsyncWithResults 异步执行所有任务,返回结果通道。 每个任务完成后会发送结果到通道。

func (*AsyncFlow) SetHookManager

func (a *AsyncFlow) SetHookManager(hm *HookManager)

SetHookManager 设置 HookManager(用于嵌套传播)。

type AsyncResult

type AsyncResult struct {
	Index int
	Error error
}

AsyncResult 异步执行结果

type Flow

type Flow interface {
	Runnable
	Hooks() *HookManager
	SetHookManager(*HookManager)
}

Flow 流程容器接口。 继承 Runnable,支持组合嵌套。 SetHookManager 用于递归传播 HookManager 到子流程。 Hooks 返回当前 manager(传播前据此检测子流程自有 hook 被覆盖并告警)。

type Future

type Future struct {
	// contains filtered or unexported fields
}

Future 异步任务的结果。 支持等待完成、检查状态、取消。

func (*Future) Cancel

func (f *Future) Cancel()

Cancel 取消异步任务。 如果任务已完成,此方法无效。

func (*Future) IsDone

func (f *Future) IsDone() bool

IsDone 检查任务是否已完成。

func (*Future) Wait

func (f *Future) Wait(ctx context.Context) error

Wait 等待任务完成并返回结果。 如果 ctx 被取消,返回 ctx.Err()。 优先读取 channel(结果就绪时立即返回),再检查 context。

type Hook

type Hook interface {
	// Before 在 Runnable 执行前调用。
	// 返回 error 时中止执行(HookManager.Before 短路传播)。
	Before(ctx context.Context, r Runnable) error

	// After 在 Runnable 执行后调用(包括 Run panic 时通过 defer 触发)。
	// err 为 nil 表示执行成功,非 nil 表示执行失败。
	After(ctx context.Context, r Runnable, err error)
}

Hook 生命周期钩子接口。 用于在 Runnable 执行前后插入通用逻辑(如日志、监控、链路追踪、权限校验)。

type HookManager

type HookManager struct {
	// contains filtered or unexported fields
}

HookManager 钩子管理器。 按注册顺序依次执行所有 Hook,支持递归传播到子流程。

并发契约:Add 非 goroutine 安全——所有 Hook 必须在 Run 之前注册完毕 (Run 期间 Add 是数据竞争)。Run 期间同一 Hook 会被并发调用 (Parallel/Async 多 goroutine),Hook 实现必须并发安全且自担幂等; 嵌套流程会逐层各触发一次(非端到端一次)。

func NewHookManager

func NewHookManager() *HookManager

NewHookManager 创建一个新的 HookManager。

func (*HookManager) Add

func (m *HookManager) Add(hooks ...Hook)

Add 添加一个或多个 Hook。

func (*HookManager) After

func (m *HookManager) After(ctx context.Context, r Runnable, err error)

After 按注册顺序依次调用所有 Hook 的 After 方法。

func (*HookManager) Before

func (m *HookManager) Before(ctx context.Context, r Runnable) error

Before 按注册顺序依次调用所有 Hook 的 Before 方法。 遇到第一个返回 error 的 Hook 时短路返回该 error。

func (*HookManager) Len

func (m *HookManager) Len() int

Len 返回 Hook 数量。

type ParallelFlow

type ParallelFlow struct {
	// contains filtered or unexported fields
}

ParallelFlow 并发执行多个任务。 支持并发限制和 context 取消传播。 当任一任务失败时,取消其他正在执行的任务。

func NewParallel

func NewParallel(maxProcs int) *ParallelFlow

NewParallel 创建一个并行流程。 maxProcs 为最大并发数,<=0 表示不限制。

func (*ParallelFlow) Add

func (p *ParallelFlow) Add(tasks ...Runnable) *ParallelFlow

Add 添加一个或多个并发任务。 若任务本身是子流程,当前 HookManager 会同步传播给它(与 PipeFlow.Add 对称,2026-09-06 复审修复)。

func (*ParallelFlow) Hooks

func (p *ParallelFlow) Hooks() *HookManager

Hooks 获取 Hook 管理器。

func (*ParallelFlow) Run

func (p *ParallelFlow) Run(ctx context.Context) error

Run 并发执行所有任务。 返回第一个非 nil error,或 context 取消错误。

错误豁免规则(与 AsyncFlow 一致):仅当流程级 context 确实被取消/超时 时,错误链中的 context.Canceled/DeadlineExceeded 才视为取消的副作用被 豁免;流程 context 健康时,任务自身的超时/取消失败必须上报。

func (*ParallelFlow) SetHookManager

func (p *ParallelFlow) SetHookManager(hm *HookManager)

SetHookManager 设置 HookManager(用于嵌套传播)。

type PipeFlow

type PipeFlow struct {
	// contains filtered or unexported fields
}

PipeFlow 顺序执行多个步骤。 任一步骤失败则停止并返回错误。 支持 context 取消传播。

func NewPipe

func NewPipe() *PipeFlow

NewPipe 创建一个顺序流程。

func (*PipeFlow) Add

func (p *PipeFlow) Add(steps ...Runnable) *PipeFlow

Add 添加一个或多个步骤(按添加顺序执行)。 若步骤本身是子流程,当前 HookManager 会同步传播给它 — "先 SetHookManager 后 Add"与"先 Add 后 SetHookManager"两种顺序下 hook 均生效(2026-09-06 复审修复:原实现只在 SetHookManager 时传播)。

func (*PipeFlow) Hooks

func (p *PipeFlow) Hooks() *HookManager

Hooks 获取 Hook 管理器。

func (*PipeFlow) Run

func (p *PipeFlow) Run(ctx context.Context) error

Run 顺序执行所有步骤。 任一步骤失败或 context 取消则停止并返回错误。 Hook 或 Runnable 的 panic 会被捕获并转为 error 返回。

func (*PipeFlow) SetHookManager

func (p *PipeFlow) SetHookManager(hm *HookManager)

SetHookManager 设置 HookManager(用于嵌套传播)。

type Runnable

type Runnable interface {
	// Run 执行业务逻辑。
	// 返回 error 表示执行失败,会触发流程中断或取消。
	Run(ctx context.Context) error
}

Runnable 可执行单元的基础接口。 所有流程节点(叶子节点和容器 Flow)都必须实现此接口。

type SwitchFlow

type SwitchFlow struct {
	// contains filtered or unexported fields
}

SwitchFlow 条件分支流程。 根据 SwitchFunc 返回的 key 选择执行路径。

func NewSwitch

func NewSwitch(switchFunc SwitchFunc) *SwitchFlow

NewSwitch 创建一个条件分支流程。

func (*SwitchFlow) Case

func (s *SwitchFlow) Case(key string, runnable Runnable) *SwitchFlow

Case 添加一个分支。 重复 key 后者覆盖前者(静默);分支集合应在 Run 前定型。 若分支本身是子流程,当前 HookManager 会同步传播给它(2026-09-06 复审修复)。

func (*SwitchFlow) Hooks

func (s *SwitchFlow) Hooks() *HookManager

Hooks 获取 Hook 管理器。

func (*SwitchFlow) Run

func (s *SwitchFlow) Run(ctx context.Context) error

Run 根据 SwitchFunc 选择并执行分支。 如果 SwitchFunc 返回的 key 不存在,返回错误。 SwitchFunc 自身的 panic 同样被捕获转为 error(与 PipeFlow 的 "Hook 或 Runnable 的 panic 会被捕获"契约对齐,2026-09-06 复审修复: 原实现裸调 switchFunc,分支选择函数 panic 直接炸穿调用方)。

func (*SwitchFlow) SetHookManager

func (s *SwitchFlow) SetHookManager(hm *HookManager)

SetHookManager 设置 HookManager(用于嵌套传播)。

type SwitchFunc

type SwitchFunc func(ctx context.Context) string

SwitchFunc 条件路由函数。 根据 context 返回要执行的分支 key。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL