Documentation
¶
Overview ¶
Package job 提供长时间运行作业(Job)的状态机与执行能力。
与 queue 包(无状态消息投递)不同,job 包关注作业的完整生命周期: 提交(pending)→ 执行(running)→ 失败重试(pending + 调度时间)→ 终态(success/failed/cancelled), 并提供进度上报、心跳保活、失联恢复与重试退避等长任务必需的能力。
重要语义:作业采用「至少一次执行」投递,即作业可能被重复执行, 处理器(Handler)必须实现幂等或显式容忍重复,并且尊重 ctx 的取消 (作业超时、取消或执行器停止时 ctx 会被关闭),否则会造成 goroutine 泄漏且作业无法及时终止。
取消延迟:对 running 作业调用 Cancel 只是更新库中状态,处理器要等到 下一次心跳(默认 HeartbeatInterval 10s)发现状态变化后才会收到 ctx 取消, 因此取消生效存在最多约一个心跳间隔的延迟。
处理器分发:Executor 支持按作业类型注册处理器(Register),未注册的 类型回退到 NewExecutor 传入的默认处理器;两者都没有时会按重试策略 重新入队,超过 MaxAttempts 后标记失败。
存储仅支持 MySQL 5.7+:PopPending 使用「无锁 SELECT + 原子 UPDATE 抢占」 (UPDATE 携带 status/attempts 条件 + RowsAffected 判定),锁等待/死锁自动重试; 数据库与连接需使用 utf8mb4 字符集(避免中文/emoji 乱码)。 Payload/Result 存储在 MySQL JSON 列中,写入时校验 JSON 合法性, 提交作业时应传入合法 JSON(如 []byte(`{"key":"value"}`)), 便于在数据库中通过 JSON_EXTRACT 等函数查询任务内容。
Index ¶
- Constants
- Variables
- func ReportProgress(ctx context.Context, progress int)
- type AttemptError
- type Config
- func (c Config) Validate() error
- func (c Config) WithCleanupInterval(interval time.Duration) Config
- func (c Config) WithConcurrency(n int) Config
- func (c Config) WithHeartbeatInterval(interval time.Duration) Config
- func (c Config) WithJobTimeout(timeout time.Duration) Config
- func (c Config) WithProgressInterval(interval time.Duration) Config
- func (c Config) WithQueues(queues ...string) Config
- func (c Config) WithRecoverInterval(interval time.Duration) Config
- func (c Config) WithRetention(d time.Duration) Config
- func (c Config) WithRetryDelay(delay time.Duration) Config
- func (c Config) WithRetryJitter(jitter bool) Config
- func (c Config) WithRetryMaxDelay(delay time.Duration) Config
- func (c Config) WithRetryStrategy(strategy RetryStrategy) Config
- func (c Config) WithShutdownTimeout(timeout time.Duration) Config
- func (c Config) WithStaleTimeout(timeout time.Duration) Config
- type Executor
- type Failure
- type Handler
- type HandlerFunc
- type Job
- func (j *Job) IsTerminal() bool
- func (j *Job) WithDelay(delay time.Duration) *Job
- func (j *Job) WithMaxAttempts(maxAttempts int) *Job
- func (j *Job) WithMetadata(key, value string) *Job
- func (j *Job) WithPayload(payload []byte) *Job
- func (j *Job) WithQueue(queue string) *Job
- func (j *Job) WithScheduleAt(t time.Time) *Job
- type JobFilter
- type RetryStrategy
- type SQLStore
- func (s *SQLStore) Cancel(ctx context.Context, queue, jobID string) error
- func (s *SQLStore) Cleanup(ctx context.Context, retainFor time.Duration) (int64, error)
- func (s *SQLStore) Complete(ctx context.Context, queue, jobID string, attempt int, result []byte) error
- func (s *SQLStore) Delete(ctx context.Context, jobID string) error
- func (s *SQLStore) Fail(ctx context.Context, queue, jobID string, attempt int, failure Failure) error
- func (s *SQLStore) Get(ctx context.Context, jobID string) (*Job, error)
- func (s *SQLStore) GetStats(ctx context.Context, queue string) (*Stats, error)
- func (s *SQLStore) Heartbeat(ctx context.Context, queue, jobID string, attempt, progress int) (bool, error)
- func (s *SQLStore) List(ctx context.Context, filter JobFilter) ([]*Job, error)
- func (s *SQLStore) ListStaleRunning(ctx context.Context, queue string, since time.Time, limit int64) ([]*Job, error)
- func (s *SQLStore) PopPending(ctx context.Context, queue string) (*Job, error)
- func (s *SQLStore) Requeue(ctx context.Context, queue, jobID string) error
- func (s *SQLStore) Retry(ctx context.Context, queue, jobID string, attempt int, retryAt time.Time, ...) error
- func (s *SQLStore) Save(ctx context.Context, job *Job) error
- type SQLStoreOption
- type Stats
- type Status
- type Store
Constants ¶
const DefaultQueue = "default"
DefaultQueue 默认队列名
Variables ¶
var ( // ErrJobNotFound 作业不存在 ErrJobNotFound = errors.New("job not found") // ErrNilJob 作业为空 ErrNilJob = errors.New("job cannot be nil") // ErrEmptyJobType 作业类型为空 ErrEmptyJobType = errors.New("job type cannot be empty") // ErrJobStateConflict 作业状态与预期不符,状态转移未生效 ErrJobStateConflict = errors.New("job state conflict") )
作业相关公共错误
var ErrExecutorRunning = errors.New("job: executor is already running")
ErrExecutorRunning 执行器已启动
var ErrStopTimeout = errors.New("job: executor stop timed out")
ErrStopTimeout 执行器停止超时,仍有处理器未退出
Functions ¶
func ReportProgress ¶
ReportProgress 从上下文中上报作业执行进度(0-100),超出范围会被截断。 只有在执行器创建的上下文中调用才生效,否则为无操作。
Types ¶
type AttemptError ¶
type AttemptError struct {
Attempt int `json:"attempt"` // 尝试次数(1-based)
At int64 `json:"at"` // 失败时间(Unix 毫秒)
Error string `json:"error"` // 错误信息
}
AttemptError 记录单次执行尝试的错误信息
type Config ¶
type Config struct {
Queues []string // 要消费的队列名
Concurrency int // 每队列并发执行数
HeartbeatInterval time.Duration // 心跳间隔
StaleTimeout time.Duration // 心跳超时判定(超过则视为失联,重新入队)
RecoverInterval time.Duration // 失联作业扫描间隔
JobTimeout time.Duration // 单个作业执行超时(0 表示不限制)
RetryDelay time.Duration // 重试退避基础延迟
RetryMaxDelay time.Duration // 重试退避最大延迟
RetryStrategy RetryStrategy // 重试退避策略
RetryJitter bool // 重试延迟加入随机抖动(默认开启,避免惊群)
Retention time.Duration // 终态作业保留时长(0 表示永久保留,不自动清理)
CleanupInterval time.Duration // 终态作业清理间隔(Retention > 0 时生效)
ShutdownTimeout time.Duration // 优雅停止等待处理器退出的超时(0 使用默认 30s)
ProgressInterval time.Duration // 进度上报节流间隔(合并高频上报,0 表示不节流)
}
Config 作业执行器配置
func (Config) Validate ¶
Validate 校验配置合法性,返回首个不合法的配置项错误。 零值或负值的周期配置会导致 ticker panic 或失联判定失效,因此必须在启动前校验。
func (Config) WithCleanupInterval ¶
WithCleanupInterval 设置终态作业清理间隔
func (Config) WithConcurrency ¶
WithConcurrency 设置每队列并发执行数
func (Config) WithHeartbeatInterval ¶
WithHeartbeatInterval 设置心跳间隔
func (Config) WithJobTimeout ¶
WithJobTimeout 设置单个作业执行超时(0 表示不限制)
func (Config) WithProgressInterval ¶
WithProgressInterval 设置进度上报节流间隔(0 表示不节流,每次上报立即落库)
func (Config) WithRecoverInterval ¶
WithRecoverInterval 设置失联扫描间隔
func (Config) WithRetention ¶
WithRetention 设置终态作业保留时长(0 表示永久保留)
func (Config) WithRetryDelay ¶
WithRetryDelay 设置重试退避基础延迟
func (Config) WithRetryJitter ¶
WithRetryJitter 设置重试延迟是否加入随机抖动(默认开启,避免惊群)
func (Config) WithRetryMaxDelay ¶
WithRetryMaxDelay 设置重试退避最大延迟
func (Config) WithRetryStrategy ¶
func (c Config) WithRetryStrategy(strategy RetryStrategy) Config
WithRetryStrategy 设置重试退避策略
func (Config) WithShutdownTimeout ¶
WithShutdownTimeout 设置优雅停止等待处理器退出的超时(0 使用默认 30s)
type Executor ¶
type Executor struct {
// contains filtered or unexported fields
}
Executor 消费 pending 作业并执行,负责心跳保活、进度上报、失败重试与失联恢复。
func NewExecutor ¶
NewExecutor 创建作业执行器。 handler 作为默认处理器:未通过 Register 注册的类型会回退到它; 若所有类型都通过 Register 注册,handler 可传 nil。
func (*Executor) Register ¶
Register 为指定作业类型注册处理器,需在 Start 之前调用。 空类型或 nil 处理器会被忽略。未注册的类型回退到 NewExecutor 传入的默认处理器。
type Failure ¶
type Failure struct {
Error string // 最近一次错误信息
Errors []AttemptError // 完整错误历史
}
Failure 作业执行失败信息
type Handler ¶
type Handler interface {
// Execute 执行作业,返回 error 表示执行失败。
//
// 执行结果通过修改 job.Result 返回;
// 执行进度通过 ReportProgress(ctx, progress) 上报。
// ctx 在作业被取消、超时或执行器停止时会被关闭,处理器应尊重 ctx 的取消。
Execute(ctx context.Context, job *Job) error
}
Handler 作业处理器接口
type HandlerFunc ¶
HandlerFunc 函数类型适配 Handler 接口
type Job ¶
type Job struct {
ID string `json:"id"` // 作业ID
Queue string `json:"queue"` // 队列名
Type string `json:"type"` // 作业类型
Payload []byte `json:"payload"` // 作业输入数据(JSON)
Status Status `json:"status"` // 作业状态
Progress int `json:"progress"` // 执行进度(0-100)
Result []byte `json:"result"` // 作业输出数据(JSON)
Error string `json:"error"` // 最近一次错误信息
Attempts int `json:"attempts"` // 已执行次数(1-based,首次执行为 1)
MaxAttempts int `json:"max_attempts"` // 最大执行次数(默认 1,即不重试)
ScheduledAt int64 `json:"scheduled_at"` // 下次可执行时间(Unix 毫秒,0 表示立即)
CreatedAt int64 `json:"created_at"` // 创建时间(Unix 毫秒)
StartedAt int64 `json:"started_at"` // 最近开始执行时间(Unix 毫秒)
CompletedAt int64 `json:"completed_at"` // 完成时间(Unix 毫秒)
HeartbeatAt int64 `json:"heartbeat_at"` // 最近心跳时间(Unix 毫秒)
Metadata map[string]string `json:"metadata"` // 元数据
Errors []AttemptError `json:"errors"` // 错误历史
}
Job 表示一个长时间运行的作业
func (*Job) WithMaxAttempts ¶
WithMaxAttempts 设置最大执行次数(含首次,默认 1 表示不重试)
type JobFilter ¶
type JobFilter struct {
Queue string // 队列过滤(空表示全部)
Type string // 类型过滤(空表示全部)
Status Status // 状态过滤(空表示全部)
Since time.Time // 创建时间下限(零值表示不限)
Until time.Time // 创建时间上限(零值表示不限)
Limit int // 返回数量上限(<=0 使用默认值 100)
Offset int // 偏移量
}
JobFilter 作业查询过滤条件,零值字段表示不限制
type RetryStrategy ¶
type RetryStrategy string
RetryStrategy 重试退避策略
const ( // RetryStrategyFixed 固定延迟 RetryStrategyFixed RetryStrategy = "fixed" // RetryStrategyExponential 指数退避 RetryStrategyExponential RetryStrategy = "exponential" )
type SQLStore ¶
type SQLStore struct {
// contains filtered or unexported fields
}
SQLStore 基于 MySQL 的作业存储实现,通过 gorm 适配。 仅支持 MySQL 5.7+,库与连接需使用 utf8mb4 字符集。
func NewSQLStore ¶
func NewSQLStore(db *gorm.DB, opts ...SQLStoreOption) (*SQLStore, error)
NewSQLStore 创建 MySQL 作业存储实例并自动迁移表结构。 db 由调用方通过项目的 mysql 包创建并管理生命周期,需保证数据库字符集为 utf8mb4。 可通过 WithTableName 等选项自定义表名。
func (*SQLStore) Cancel ¶
Cancel 取消作业(pending/running → cancelled)。 幂等:作业已处于终态(success/failed/cancelled)时返回 nil;作业不存在时返回 ErrJobNotFound。
func (*SQLStore) Complete ¶
func (s *SQLStore) Complete(ctx context.Context, queue, jobID string, attempt int, result []byte) error
Complete 标记作业成功
func (*SQLStore) Fail ¶
func (s *SQLStore) Fail(ctx context.Context, queue, jobID string, attempt int, failure Failure) error
Fail 标记作业最终失败
func (*SQLStore) Heartbeat ¶
func (s *SQLStore) Heartbeat(ctx context.Context, queue, jobID string, attempt, progress int) (bool, error)
Heartbeat 更新心跳与进度,返回是否仍处于 running 状态
func (*SQLStore) ListStaleRunning ¶
func (s *SQLStore) ListStaleRunning(ctx context.Context, queue string, since time.Time, limit int64) ([]*Job, error)
ListStaleRunning 列出心跳早于 since 的 running 作业
func (*SQLStore) PopPending ¶
PopPending 原子取出最早的一个 pending 作业并标记 running
type SQLStoreOption ¶
type SQLStoreOption func(*SQLStore)
SQLStoreOption 配置 SQLStore 的选项
func WithTableName ¶
func WithTableName(name string) SQLStoreOption
WithTableName 设置作业表名(默认 "jobs"),用于多服务共库或表名前缀等场景
type Stats ¶
type Stats struct {
Pending int64 `json:"pending"` // 等待执行数(含延迟/重试等待)
Running int64 `json:"running"` // 执行中数
Success int64 `json:"success"` // 成功状态数
Failed int64 `json:"failed"` // 失败状态数
Cancelled int64 `json:"cancelled"` // 取消状态数
}
Stats 队列统计信息(各状态当前存在的作业数)
type Status ¶
type Status string
Status 作业状态
const ( // StatusPending 等待执行(含延迟/重试等待,由 ScheduledAt 控制实际可执行时间) StatusPending Status = "pending" // StatusRunning 执行中 StatusRunning Status = "running" // StatusSuccess 执行成功 StatusSuccess Status = "success" // StatusFailed 执行失败 StatusFailed Status = "failed" // StatusCancelled 已取消 StatusCancelled Status = "cancelled" )
type Store ¶
type Store interface {
// Save 保存(创建)作业,按 job.Queue 与 job.ScheduledAt 决定入队位置
Save(ctx context.Context, job *Job) error
// Get 获取作业
Get(ctx context.Context, jobID string) (*Job, error)
// Delete 删除作业及其索引
Delete(ctx context.Context, jobID string) error
// PopPending 原子取出队列中最早到期的一个 pending 作业(scheduled_at <= now)并标记 running,
// 无到期作业时返回 (nil, nil)。
PopPending(ctx context.Context, queue string) (*Job, error)
// Heartbeat 更新 running 作业的心跳与进度,返回作业是否仍处于 running 状态。
// progress < 0 表示不更新进度,仅刷新心跳。
// attempt 为当前执行尝试(乐观锁版本号),与库中不匹配时返回 running=false。
Heartbeat(ctx context.Context, queue, jobID string, attempt, progress int) (bool, error)
// Complete 标记 running 作业为 success 并写入结果。
// 作业不在 running 状态或 attempt 不匹配(已被重新调度)时返回 ErrJobStateConflict。
Complete(ctx context.Context, queue, jobID string, attempt int, result []byte) error
// Fail 标记 running 作业为 failed(最终失败),并记录错误信息。
// 作业不在 running 状态或 attempt 不匹配时返回 ErrJobStateConflict。
Fail(ctx context.Context, queue, jobID string, attempt int, failure Failure) error
// Retry 将失败的 running 作业重新入队为 pending,并将下次可执行时间设为 retryAt。
// 作业不在 running 状态或 attempt 不匹配时返回 ErrJobStateConflict。
Retry(ctx context.Context, queue, jobID string, attempt int, retryAt time.Time, failure Failure) error
// Cancel 取消作业(pending/running → cancelled)。
// 幂等:作业已处于终态时返回 nil;作业不存在时返回 ErrJobNotFound。
Cancel(ctx context.Context, queue, jobID string) error
// Requeue 将失联的 running 作业重新入队(running → pending,立即可执行)。
// 作业不在 running 状态时返回 ErrJobStateConflict。
Requeue(ctx context.Context, queue, jobID string) error
// ListStaleRunning 列出心跳早于 since 的 running 作业(用于失联恢复)
ListStaleRunning(ctx context.Context, queue string, since time.Time, limit int64) ([]*Job, error)
// GetStats 获取队列统计信息
GetStats(ctx context.Context, queue string) (*Stats, error)
// List 按过滤条件查询作业,结果按创建时间降序排列
List(ctx context.Context, filter JobFilter) ([]*Job, error)
// Cleanup 清理超过 retainFor 时长的终态作业(success/failed/cancelled),返回清理数量
Cleanup(ctx context.Context, retainFor time.Duration) (int64, error)
}
Store 作业存储接口,负责作业状态的持久化与原子状态转移。
实现必须保证状态转移(如 PopPending、Complete、Fail、Retry)的原子性, 以避免并发执行器重复消费同一作业。
作业详情按全局唯一 ID 存储,队列索引按 queue 维度隔离。