Help us shape the future of Go! Take the 2026 Go Developer Survey

taskpool

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Nov 3, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

Documentation

Overview

Package taskpool 提供本地异步任务池,依赖 logit 创建独立日志作用域并关联 logId。 导入路径为 github.com/bpcoder16/pixiu/infra/taskpool,支持实例及进程级默认池。

初始化时设置等待队列容量、消费者区间和失败重试次数; MaxRetries 为 0 到 100,表示首次失败后最多再尝试的次数,零值不重试。 消费者会按积压在区间内自动扩缩容;失败重试固定间隔 1 秒, SubmitTimeout 为 0 时默认 1 秒,IdleTimeout 为 0 时默认 5 分钟, DrainTimeout 为 0 时默认 20 秒。

主协程创建独立任务池,并负责在退出时调用 Shutdown:

pool, err := taskpool.New(taskpool.Config{
    MinWorkers:    2,
    MaxWorkers:    8,
    QueueSize:     256,
    SubmitTimeout: time.Second, // 一次提交的超时预算为 1 秒
    MaxRetries:    3,           // 首次执行失败后最多再试 3 次
})
if err != nil {
    return err
}

业务入口直接向该实例提交任务。SubmitTimeout 从参数校验通过后、首次获取锁前开始计时, 获取锁与等待队列空位共享预算;即使队列有空位,检查时已超时也会拒绝提交。 内部锁等待不可中断,函数可能在取得锁后才返回超时;requestCtx 可以更早取消提交。 SubmitTimeout 为 0 时默认 1 秒,正值按配置使用,不设 100ms 下限。 成功接收的任务以 WithoutCancel(requestCtx) 为父 context 创建独立日志作用域, 只复制 meta 中的 logId,缺失或为空时主动生成;任务及重试复用该作用域和 ID。 父级、不同任务的普通与 meta 日志字段互不影响;其他 context 值仍按引用保留。 taskCtx 不继承请求或池的截止时间与取消,Done 为 nil;池自身另用 p.ctx 控制排空和重试。 业务需要执行时限时,在回调内自行派生 WithTimeout: 示例中的 requestCtx 和 sendNotice 由应用提供:

if err := pool.Submit(requestCtx, "send-notice", func(taskCtx context.Context) error {
    workCtx, cancel := context.WithTimeout(taskCtx, 3*time.Second)
    defer cancel()
    return sendNotice(workCtx)
}); err != nil {
    return err
}

使用 logit 时,入口调用一次 logit.WithContextLogID 即可让任务日志沿用链路 ID:

requestCtx = logit.WithContextLogID(requestCtx)
if err := pool.Submit(requestCtx, "send-notice", func(taskCtx context.Context) error {
    logit.Info(taskCtx, "sending notice")
    return sendNotice(taskCtx)
}); err != nil {
    return err
}

任务池直接依赖 logit;入口没有初始化日志字段时也可提交,任务会自行生成 ID。 其他共享值由调用方保证并发安全,并允许其存活到任务结束。

应用自行处理停机信号,先停止上游提交,再调用 Shutdown 获取限时关闭结果。 任务池只通过 Shutdown 发起关闭;宽限倒计时从首次调用开始,不因后续调用而重置。 全部任务提前完成时正常返回,宽限到期仍有任务时中止排空并返回超时错误:

if err := pool.Shutdown(); err != nil {
    return err
}

Shutdown 超时返回时任务可能仍在清理资源。只要求限时尽力关闭时,可直接继续退出。 Wait 是可选操作:需要确认全部任务已退出时,再调用 pool.Wait(); 它没有等待上限,完成后仍返回此前的关闭错误。Wait 只观察完成,不发起关闭; 如果先调用 Wait,需要其他 goroutine 调用 Shutdown。两个方法均允许重复或并发调用。

程序需要全局默认池时,可将上面的 New 调用改为 NewDefault; 它创建并注册默认池,业务代码可直接调用包级 Submit,退出时可调用 包级 Shutdown,并按需调用 Wait。New 仍可同时创建其他独立任务池,分别通过 各自的 Submit、Wait、Shutdown 管理;全局入口只作用于默认池。

if _, err := taskpool.NewDefault(taskpool.Config{
    MinWorkers: 2,
    MaxWorkers: 8,
    QueueSize:  256,
    MaxRetries: 3,
}); err != nil {
    return err
}
if err := taskpool.Submit(requestCtx, "send-notice", sendNotice); err != nil {
    return err
}
return taskpool.Shutdown()

未注册默认池时,全局 Submit、Wait、Shutdown 返回 ErrNoDefault。 Default 返回当前池或 nil;Swap 可替换并返回旧池,传入 nil 可清除注册。 SetDefault 和 Swap 均不会关闭旧池,调用方仍负责旧池的退出。 全局 Wait/Shutdown 与实例方法的语义相同;若可能切换默认池, 应保留实例指针,通过同一个实例执行 Shutdown 和 Wait。

使用 lifecycle.Stack 同时回收任务池和任务依赖的 client 时, client 指应用创建、供任务使用且具有 Close() error 方法的资源, 例如 *sql.DB;它不是 taskpool 或 lifecycle 提供的对象。 先登记 client,再登记任务池。Stack.Close 逆序执行,确保任务结束后才关闭 client。 此时调用 Shutdown 发起排空,随后用 Wait 确认全部 worker 退出:

var stack lifecycle.Stack
if err := stack.Register(client.Close); err != nil {
    return err
}
if err := stack.Register(func() error {
    shutdownErr := pool.Shutdown()
    _ = pool.Wait() // 等待任务清理完毕,再允许 Stack 关闭 client
    return shutdownErr
}); err != nil {
    return err
}
// 停止上游提交任务后:
return stack.Close()

任务没有这类依赖时,省略 client.Close 的注册即可。 Shutdown 发起的 DrainTimeout 到期会放弃排队任务并停止重试,不依赖调用 Wait。 正在执行的回调不会被取消;回调一直不返回时,Wait 也会一直等待。 只收到 Shutdown 的超时结果时,不能立即关闭任务仍在使用的 client。 如果还有日志资源,应先登记日志关闭函数,使其最后关闭。

Submit 返回 nil 只表示任务已接收。任务每次执行失败都会写入 stderr; panic 会输出堆栈且不自动重试。可用 Stats 查看队列、消费者及累计结果。 任务只保存在内存中,进程异常退出后不会恢复;需要可靠交付时应使用持久化队列。

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrClosed 表示任务池已开始关闭,不再接收任务。
	ErrClosed = errors.New("taskpool: closed")
	// ErrInvalidConfig 表示任务池配置无效。
	ErrInvalidConfig = errors.New("taskpool: invalid config")
	// ErrInvalidTask 表示提交参数无效。
	ErrInvalidTask = errors.New("taskpool: invalid task")
)
View Source
var ErrNoDefault = errors.New("taskpool: no default pool")

ErrNoDefault 表示尚未注册默认任务池。

Functions

func SetDefault

func SetDefault(p *Pool)

SetDefault 注册默认任务池;传入 nil 可清除注册。旧池仍由调用方关闭。

func Shutdown

func Shutdown() error

Shutdown 关闭当前默认任务池,等待完成或宽限到期;允许重复或并发调用。

func Submit

func Submit(ctx context.Context, name string, fn func(context.Context) error) error

Submit 向当前默认任务池提交任务;未注册时返回 ErrNoDefault。

func Wait

func Wait() error

Wait 可选地等待当前默认任务池的全部 worker 退出,不发起关闭;允许重复或并发调用。

Types

type Config

type Config struct {
	// MinWorkers 和 MaxWorkers 是消费者自动扩缩容的固定区间。
	MinWorkers int
	MaxWorkers int
	// QueueSize 只限制等待执行的任务,不包含执行中的任务。
	QueueSize int
	// SubmitTimeout 是从参数校验通过后开始计算的提交超时预算;零值默认 1 秒。
	SubmitTimeout time.Duration
	// MaxRetries 是首次执行失败后的附加尝试次数,范围为 0 到 100;零值不重试。
	MaxRetries int
	// IdleTimeout 为零时使用默认值。
	IdleTimeout time.Duration
	// DrainTimeout 限制首次 Shutdown 触发后的排空宽限时间;零值默认 20 秒。
	DrainTimeout time.Duration
}

Config 定义任务池的容量、消费者区间与失败重试行为。

type Pool

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

Pool 执行已接收的进程内任务。创建方负责在退出前调用 Shutdown。

func Default

func Default() *Pool

Default 返回当前默认任务池;未注册时返回 nil。

func New

func New(cfg Config) (*Pool, error)

New 创建任务池并启动最少数量的消费者;调用方通过 Shutdown 发起关闭。

func NewDefault

func NewDefault(cfg Config) (*Pool, error)

NewDefault 创建并启动任务池,成功后注册为默认池;失败时默认池保持不变。 其他通过 New 创建的实例不受影响;替换已有默认池时,旧池仍由调用方关闭。

func Swap

func Swap(p *Pool) *Pool

Swap 原子替换默认任务池并返回旧池;传入 nil 可清除注册。

func (*Pool) Shutdown

func (p *Pool) Shutdown() error

Shutdown 开始排空并等待全部 worker 退出或宽限到期;允许重复或并发调用。 超时会放弃排队任务并停止重试,不取消运行中的回调;需要确认收尾时继续调用 Wait。

func (*Pool) Stats

func (p *Pool) Stats() Stats

Stats 返回当前数量与累计结果的快照。

func (*Pool) Submit

func (p *Pool) Submit(ctx context.Context, name string, fn func(context.Context) error) error

Submit 等待队列空位并接收任务;ctx 的取消、截止时间和 SubmitTimeout 只控制提交过程。 任务创建独立日志作用域并复用或补生成 logId;同一任务重试复用该作用域。 回调不继承提交方或池的取消;其他值按引用保留,调用方须保证其并发安全。 获取锁与等待空位共享超时预算;锁等待不可中断,可能在取得锁后才返回超时。

func (*Pool) Wait

func (p *Pool) Wait() error

Wait 可选地等待全部 worker 退出并返回关闭结果,不发起关闭,也不限制等待时间。 允许重复或并发调用;排空曾超时时,即使任务随后退出也仍返回该超时错误。

type Stats

type Stats struct {
	// Pending 是队列中等待执行的任务数,不包含运行中的任务。
	Pending int
	// Running 是正在执行的任务数,重试等待期间仍计入。
	Running int
	// Workers 是尚未退出的消费者数,包含空闲和执行中的消费者。
	Workers int
	// Accepted 是累计接收的任务数,Submit 成功时计入。
	Accepted uint64
	// Succeeded 是累计最终执行成功的任务数。
	Succeeded uint64
	// Failed 是累计执行结束但未成功的任务数。
	Failed uint64
	// Abandoned 是中止排空时累计放弃的未开始任务数。
	Abandoned uint64
}

Stats 是 Pool.Stats 返回的任务池状态快照。

Jump to

Keyboard shortcuts

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