Files
smartmate/backend/services/agent/shared/retry.go
Losita d7184b776b Version: 0.9.75.dev.260505
后端:
1.收口阶段 6 agent 结构迁移,将 newAgent 内核与 agentsvc 编排层迁入 services/agent
- 切换 Agent 启动装配与 HTTP handler 直连 agent sv,移除旧 service agent bridge
- 补齐 Agent 对 memory、task、task-class、schedule 的 RPC 适配与契约字段
- 扩展 schedule、task、task-class RPC/contract 支撑 Agent 查询、写入与 provider 切流
- 更新迁移文档、README 与相关注释,明确 agent 当前切流点和剩余 memory 迁移面
2026-05-05 16:00:57 +08:00

86 lines
2.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package agentshared
import (
"context"
"time"
)
// RetryOptions 描述公共重试策略。
//
// 职责边界:
// 1. 这里只定义“是否重试、最多几次、间隔多久”;
// 2. 不关心具体业务是工具调用失败、模型 JSON 失败还是 DB 暂时不可用;
// 3. 真正的业务兜底文案仍应由上层 node 决定。
type RetryOptions struct {
MaxAttempts int
Interval time.Duration
ShouldRetry func(err error) bool
OnRetry func(attempt int, err error)
}
// Do 执行一个只返回 error 的重试任务。
//
// 执行规则:
// 1. 第一次执行也算一次 attempt
// 2. 任意一次成功即立即返回;
// 3. 上下文取消、达到最大次数、或 ShouldRetry=false 时立即停止。
func Do(ctx context.Context, options RetryOptions, fn func(attempt int) error) error {
_, err := DoValue[struct{}](ctx, options, func(attempt int) (struct{}, error) {
return struct{}{}, fn(attempt)
})
return err
}
// DoValue 执行一个带返回值的通用重试任务。
//
// 设计说明:
// 1. 旧 agent 里后续很多地方都会出现“失败重试 2~3 次”的模式;
// 2. 这里先把循环骨架统一,避免每个 skill 自己写 for + sleep + ctx.Done
// 3. 上层只需关心“本轮失败要不要继续”,而不是重复造轮子。
func DoValue[T any](ctx context.Context, options RetryOptions, fn func(attempt int) (T, error)) (T, error) {
var zero T
maxAttempts := options.MaxAttempts
if maxAttempts <= 0 {
maxAttempts = 1
}
for attempt := 1; attempt <= maxAttempts; attempt++ {
if err := ctx.Err(); err != nil {
return zero, err
}
value, err := fn(attempt)
if err == nil {
return value, nil
}
// 1. 到最后一次了,直接返回原错误,避免无意义等待。
if attempt >= maxAttempts {
return zero, err
}
// 2. 业务显式声明“不值得重试”时,立刻停止。
if options.ShouldRetry != nil && !options.ShouldRetry(err) {
return zero, err
}
// 3. 把重试钩子留给上层,用于打点或阶段提示。
if options.OnRetry != nil {
options.OnRetry(attempt, err)
}
// 4. 没有配置间隔则马上下一轮;配置了则等待,同时尊重 ctx 取消。
if options.Interval <= 0 {
continue
}
timer := time.NewTimer(options.Interval)
select {
case <-ctx.Done():
timer.Stop()
return zero, ctx.Err()
case <-timer.C:
}
}
return zero, nil
}