afterwork

package
v0.3.6 Latest Latest
Warning

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

Go to latest
Published: Aug 6, 2026 License: Apache-2.0 Imports: 6 Imported by: 0

Documentation

Overview

Package afterwork 提供请求级后台任务延寿(waitUntil 语义)。

响应可以立即返回,但被 waitUntil 注册的后台任务会继续跑完—— 运行时不会在响应后立刻杀掉它。这是"请求级后台任务延寿"。

与 pkg/safe.Go 的区别:safe.Go 是全局 fire-and-forget,无生命周期绑定; afterwork 把任务绑定到请求 ctx,响应返回后由框架调用 Wait() 等待 全部延寿任务跑完(带上限,超时则放弃),常用于"响应后副作用":

  • 响应后发邮件 / 写审计日志;
  • 响应后触发 webhook / 消息推送;
  • 响应后异步更新统计指标。

用法:

func (h *Handler) Create(w http.ResponseWriter, r *http.Request) {
    // ... 处理请求 ...
    afterwork.Defer(r.Context(), func(ctx context.Context) {
        _ = h.webhook.Notify(ctx, event)
    })
    w.Write(resp) // 响应立即返回,webhook 在响应后继续跑完
}

框架在 handler 返回后调用 afterwork.Wait(ctx) 等待延寿任务。 任务 panic 不会崩进程(复用 pkg/safe),panic 转为 error 记录。

零值不可用,用 WithRegistry 装入 ctx,或用 New 创建独立 Registry。

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Defer

func Defer(ctx context.Context, fn func(ctx context.Context))

Defer 投递一个延寿任务到 ctx 关联的 Registry。 任务在 Wait 时被等待(不阻塞当前 handler);响应可立即返回。 若 ctx 没有 Registry,任务被丢弃(不 panic)。 任务接收派生自 ctx 的子 ctx:请求 ctx 取消时任务应主动退出。

func Middleware

func Middleware(opts ...Option) func(http.Handler) http.Handler

Middleware 返回一个 http 中间件:为每个请求创建独立 Registry 并装入 ctx, 调用下游 handler 后调用 Wait() 等待延寿任务跑完(带 drain timeout)。

这就是 waitUntil 语义在 beauty 的接入点:handler 里 afterwork.Defer(...) 投递的响应后副作用,在响应返回后由本中间件统一等待完成。

h := afterwork.Middleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    // ... 处理 ...
    afterwork.Defer(r.Context(), func(ctx context.Context) {
        _ = webhook.Notify(ctx, event)
    })
    w.Write([]byte("ok")) // 响应立即返回
    // ← 本中间件在此之后调用 reg.Wait(),webhook 跑完才放行下一个环节
}))

注意:本中间件在 handler 返回后才 Wait,因此 handler 写完响应体后 不能再持有 w/r。延寿任务通过 Defer 接收的 taskCtx 工作,不应触碰 w。

func WithRegistry

func WithRegistry(ctx context.Context, reg *Registry) context.Context

WithRegistry 把 reg 装入 ctx,返回新 ctx。 通常在中间件里包裹每个请求:ctx = afterwork.WithRegistry(ctx, reg), 处理完后 afterwork.Wait(ctx) 等待延寿任务。

Types

type Option

type Option func(*config)

Option 配置 Registry。

func WithDrainTimeout

func WithDrainTimeout(d time.Duration) Option

WithDrainTimeout 设置 Wait 的最大等待时长。<=0 表示无上限(慎用)。

func WithPanicHandler

func WithPanicHandler(fn func(error)) Option

WithPanicHandler 设置任务 panic 回调。默认忽略(panic 已被 safe.Go 恢复)。

type Registry

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

Registry 一个请求级延寿任务注册表。 一个 Registry 对应一次请求:Defer 投递任务,Wait 等待全部完成。 并发安全;Wait 幂等(可重复调用,第二次起立即返回)。

func FromContext

func FromContext(ctx context.Context) *Registry

FromContext 从 ctx 取出 Registry。没有则返回 nil(此时 Defer 为空操作)。

func New

func New(opts ...Option) *Registry

New 创建一个独立 Registry。 通常不需要手动创建——用 WithRegistry 把全局 Registry 装入 ctx, 再用 FromContext 在 handler 内取出投递任务。New 用于测试或非 HTTP 场景。

func (*Registry) Defer

func (r *Registry) Defer(ctx context.Context, fn func(ctx context.Context))

Defer 把任务投递到本 Registry(无论 ctx 是否有 Registry)。 任务 panic 被恢复,转交 WithPanicHandler 回调。

func (*Registry) Pending

func (r *Registry) Pending() int

Pending 返回当前已投递但未完成的任务数(诊断用)。

func (*Registry) Stop

func (r *Registry) Stop()

Stop 等同于 Wait,提供与 beauty 其他包(Stop 命名惯例)一致的退出语义。

func (*Registry) Wait

func (r *Registry) Wait()

Wait 阻塞直到所有已投递的延寿任务完成,或到达 drain timeout。 幂等:可重复调用,第二次起立即返回。 在 HTTP 场景下由框架/中间件在 handler 返回后调用。

Jump to

Keyboard shortcuts

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