You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用singleflight.Group.Do实现失败请求重试遇阻问题

使用singleflight时,错误后调用Forget(key)仍无法触发重试的问题

我用singleflight实现请求缓存,功能本身正常。现在想实现:相同key的请求失败时,后续请求能触发重试。我调用了group.Forget(Key),但后续调用还是复用之前的错误结果,没有触发重试。

代码如下:

type Result struct {
    v int
    k string
}

var group singleflight.Group

func main() {
    if true {
        for k := 0; k <= 2; k++ {
            go doGroup(context.Background(), "sameKey")
        }

        <-time.Tick(5 * time.Second)

        for k := 0; k <= 3; k++ {
            go doGroup(context.Background(), "sameKey")
        }

        <-time.Tick(30 * time.Second)
    }
}

func doGroup(ctx context.Context, key string) (*Result, error) {
    log.Println("Inside normal call")

    results, err, shared := group.Do(key, func() (interface{}, error) {
        r, e := doExpensive(ctx, key)

        // 尝试在出错时移除key,让后续请求重试,但未生效
        if e != nil {
            group.Forget(key)
        }

        return r, e
    })

    fmt.Printf("Call to multiple callers: %v\n", shared)

    if err != nil {
        wrapped := fmt.Errorf("error bruh %s: %w", key, err)
        fmt.Printf("%s\n", wrapped.Error())
        return nil, wrapped
    }

    fmt.Printf("Results: %v\n", results)
    return results.(*Result), err
}

func doExpensive(ctx context.Context, key string) (*Result, error) {
    log.Printf("Inside Expensive function with key %s\n", key)
    <-time.Tick(time.Second * 10)

    dice := rand.Int31n(10)

    // 强制返回错误,模拟请求失败场景
    if true {
        return nil, errors.New("operation failed")
    }

    <-time.Tick(time.Second * time.Duration(dice))
    return &Result{
        v: int(dice),
        k: key,
    }, nil
}

我已经在两次doGroup调用之间模拟了等待,确保第二次调用时key已被遗忘,但doExpensive函数仅执行了一次。

内容的提问来源于stack exchange,提问作者IdiakosE Sunday

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 11:15:42