我正在尝试使用开箱即用的 singleflight 来缓存请求。
我想更进一步,随后对同一密钥重试失败(错误请求)。为此,我正在调用 group.Forget(Key)。但是后续调用似乎只是重用先前的结果而不是重试。
type Result struct {
v int
k string
}
var group singleflight.Group
// see https://encore.dev/blog/advanced-go-concurrency
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)
// Do this; so if it encountered an error;
// subsequent calls will retry
// didnt work
// perhaps because of timing
if e != nil {
group.Forget(key)
}
return r, e
})
fmt.Printf("Call to multiple callers: %v\n", shared)
// does not retry if error occured
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 {
// <-time.Tick(time.Millisecond * time.Duration(dice*100))
return nil, errors.New("operation failed")
}
<-time.Tick(time.Second * time.Duration(dice))
return &Result{
v: int(dice),
k: key,
}, nil
}
我已经模拟了调用 doGroup 之间的等待,所以第二次调用实际上忘记了密钥。但是 doExpensive 函数似乎只被调用过一次。
可以在此处找到我的代码的复制品
https://go.dev/play/p/psGjFTypU6C
守候你守候我
相关分类