三个常见场景怎么写
下面三种形状反复出现。每一段都完整到可以贴进项目里再改。
下面的例子省掉了 createOrder、download 这类辅助函数,要看的是流程的形状。
事件和超时赛跑
三十分钟内没付款就关单。难的从来不是定时器,是支付和超时会撞上:拆成两个流程互相取消,这场竞态得你自己赢。这里胜负由一次原子操作定死,29:59.9 落地的那笔钱要么被采纳、要么被拒,不会两边都成立。
tick.Flow("order/close", func(ctx *gotick.Context) { orderId, _ := ctx.MetaData("order_id") gotick.Task(ctx, "create-order", func(c *gotick.TaskContext) error { return orders.Create(c, orderId) }) paid, ok := gotick.WaitForSignal[Payment](ctx, "paid", gotick.WithSignalTimeout(30*time.Minute)) if !ok { gotick.Task(ctx, "close-order", func(c *gotick.TaskContext) error { return orders.Close(c, orderId) }) return } gotick.Task(ctx, "ship", func(c *gotick.TaskContext) error { return shipping.Send(c, orderId, paid.TradeNo) })})散开,再收回来
下载一批文件,最多四个同时进行。Array 记住列表,每一遍对「要遍历什么」的答案都一样。AsyncArray 把列表展开成并行步骤,Wait 等它们做完。每个元素有自己的状态,重启之后只接着做没做完的那些。
tick.Flow("media/convert", func(ctx *gotick.Context) { dir, _ := ctx.MetaData("dir") files := gotick.Array(ctx, "list", func(c *gotick.TaskContext) ([]string, error) { return storage.List(c, dir) }) fs := gotick.AsyncArray(ctx, "convert", files, func(c *gotick.TaskContext, name string, i int) (string, error) { return ffmpeg.Convert(c, name) }) gotick.Wait(ctx, 4, fs...) gotick.Task(ctx, "publish", func(c *gotick.TaskContext) error { out := make([]string, 0, len(fs)) for _, f := range fs { out = append(out, f.(*gotick.FutureT[string]).Value()) } return catalog.Publish(c, dir, out) })})只有最后一次改动算数
用户一分钟内改了同一份文档十次,每次都触发一轮很贵的重新生成,但只有最后一次的结果会被人看到。用文档 ID 给流程做 key,前九次自己就取消了,不用再为没人看的结果付钱。
tick.Flow("doc/preview", func(ctx *gotick.Context) { docId, _ := ctx.MetaData("doc_id") // expensive, and only the newest result will ever be looked at url := gotick.Memo(ctx, "render", func() (string, error) { return renderer.Build(docId) }) gotick.Task(ctx, "attach", func(c *gotick.TaskContext) error { return docs.SetPreview(c, docId, url) })}) // in the save handler — ten edits, nine of them canceled automaticallytick.Trigger(ctx, "doc/preview", gotick.MetaData{"doc_id": docId}, gotick.WithKey(docId))更多能直接跑的例子在仓库的 example 目录里,包括上面这个关单的例子,接上真的 Redis 几秒钟就能看到结果。 example/