vendor: resenje.org/singleflight v0.4.3

full diff: https://resenje.org/singleflight/compare/v0.4.1...v0.4.3

Changes:
- Fix incorrect `Forget` behavior
- Make panic behavior consistent with x/sync package

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
This commit is contained in:
Paweł Gronowski
2024-11-22 11:40:51 +01:00
parent 1832afcf69
commit 1551d95727
6 changed files with 99 additions and 9 deletions

View File

@@ -113,7 +113,7 @@ require (
google.golang.org/grpc v1.66.3
google.golang.org/protobuf v1.35.1
gotest.tools/v3 v3.5.1
resenje.org/singleflight v0.4.1
resenje.org/singleflight v0.4.3
tags.cncf.io/container-device-interface v0.8.0
)

View File

@@ -801,8 +801,8 @@ kernel.org/pub/linux/libs/security/libcap/cap v1.2.70 h1:QnLPkuDWWbD5C+3DUA2IUXa
kernel.org/pub/linux/libs/security/libcap/cap v1.2.70/go.mod h1:/iBwcj9nbLejQitYvUm9caurITQ6WyNHibJk6Q9fiS4=
kernel.org/pub/linux/libs/security/libcap/psx v1.2.70 h1:HsB2G/rEQiYyo1bGoQqHZ/Bvd6x1rERQTNdPr1FyWjI=
kernel.org/pub/linux/libs/security/libcap/psx v1.2.70/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24=
resenje.org/singleflight v0.4.1 h1:ryGHRaOBwhnZLyf34LMDf4AsTSHrs4hdGPdG/I4Hmac=
resenje.org/singleflight v0.4.1/go.mod h1:lAgQK7VfjG6/pgredbQfmV0RvG/uVhKo6vSuZ0vCWfk=
resenje.org/singleflight v0.4.3 h1:l7foFYg8X/VEHPxWs1K/Pw77807RMVzvXgWGb0J1sdM=
resenje.org/singleflight v0.4.3/go.mod h1:lAgQK7VfjG6/pgredbQfmV0RvG/uVhKo6vSuZ0vCWfk=
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=

2
vendor/modules.txt vendored
View File

@@ -1597,7 +1597,7 @@ k8s.io/klog/v2/internal/clock
k8s.io/klog/v2/internal/dbg
k8s.io/klog/v2/internal/serialize
k8s.io/klog/v2/internal/severity
# resenje.org/singleflight v0.4.1
# resenje.org/singleflight v0.4.3
## explicit; go 1.18
resenje.org/singleflight
# sigs.k8s.io/yaml v1.4.0

36
vendor/resenje.org/singleflight/.golangci.yaml generated vendored Normal file
View File

@@ -0,0 +1,36 @@
run:
timeout: 10m
allow-parallel-runners: true
linters:
enable:
- errname
- stylecheck
- importas
- errcheck
- gosimple
- govet
- ineffassign
- mirror
- staticcheck
- tagalign
- testifylint
- typecheck
- unused
- unconvert
- wastedassign
- whitespace
- gocritic
- exhaustive
- noctx
- promlinter
# TODO these fail on windows
# - gofmt
# - goimports
linters-settings:
govet:
enable-all: true
disable:
- shadow
- fieldalignment

View File

@@ -3,9 +3,12 @@
[![GoDoc](https://godoc.org/resenje.org/singleflight?status.svg)](https://godoc.org/resenje.org/singleflight)
[![Go](https://github.com/janos/singleflight/workflows/Go/badge.svg)](https://github.com/janos/singleflight/actions?query=workflow%3AGo)
Package singleflight provides a duplicate function call suppression
mechanism similar to golang.org/x/sync/singleflight but with support
for context cancelation.
Package singleflight provides a duplicate function call suppression
mechanism similar to [golang.org/x/sync/singleflight](https://pkg.go.dev/golang.org/x/sync/singleflight) but with:
- support for context cancelation. The context passed to the callback function is a context that preserves all values
from the passed context but is cancelled by the singleflight only when all awaiting caller's contexts are cancelled.
- support for generics.
## Installation

View File

@@ -10,11 +10,36 @@ package singleflight
import (
"context"
"fmt"
"runtime/debug"
"sync"
)
// A panicError is an arbitrary value recovered from a panic
// with the stack trace during the execution of given function.
type panicError struct {
value interface{}
stack []byte
}
// Error implements error interface.
func (p *panicError) Error() string {
return fmt.Sprintf("%v\n\n%s", p.value, p.stack)
}
func (p *panicError) Unwrap() error {
err, ok := p.value.(error)
if !ok {
return nil
}
return err
}
// Group represents a class of work and forms a namespace in
// which units of work can be executed with duplicate suppression.
// K is the type of the key used for deduplication, and V is
// the return value of the work function.
type Group[K comparable, V any] struct {
calls map[K]*call[V] // lazily initialized
mu sync.Mutex // protects calls
@@ -60,8 +85,14 @@ func (g *Group[K, V]) Do(ctx context.Context, key K, fn func(ctx context.Context
g.mu.Unlock()
go func() {
defer func() {
if v := recover(); v != nil {
c.panicErr = &panicError{value: v, stack: debug.Stack()}
}
close(c.done)
}()
c.val, c.err = fn(callCtx)
close(c.done)
}()
return g.wait(ctx, key, c)
@@ -69,10 +100,12 @@ func (g *Group[K, V]) Do(ctx context.Context, key K, fn func(ctx context.Context
// wait for function passed to Do to finish or context to be done.
func (g *Group[K, V]) wait(ctx context.Context, key K, c *call[V]) (v V, shared bool, err error) {
var panicErr *panicError
select {
case <-c.done:
v = c.val
err = c.err
panicErr = c.panicErr
case <-ctx.Done():
err = ctx.Err()
}
@@ -80,10 +113,17 @@ func (g *Group[K, V]) wait(ctx context.Context, key K, c *call[V]) (v V, shared
c.counter--
if c.counter == 0 {
c.cancel()
delete(g.calls, key)
if !c.forgotten {
delete(g.calls, key)
}
}
shared = c.shared
g.mu.Unlock()
if panicErr != nil {
panic(panicErr)
}
return v, shared, err
}
@@ -92,6 +132,9 @@ func (g *Group[K, V]) wait(ctx context.Context, key K, c *call[V]) (v V, shared
// an earlier call to complete.
func (g *Group[K, V]) Forget(key K) {
g.mu.Lock()
if c, ok := g.calls[key]; ok {
c.forgotten = true
}
delete(g.calls, key)
g.mu.Unlock()
}
@@ -102,6 +145,10 @@ type call[V any] struct {
val V
err error
// panicError wraps the value passed to panic() if the function call panicked.
// val and err should be ignored if this is non-nil.
panicErr *panicError
// done channel signals that the function call is done.
done chan struct{}
@@ -113,4 +160,8 @@ type call[V any] struct {
// shared indicates if results val and err are passed to multiple callers.
shared bool
// forgotten indicates whether Forget was called with this call's key
// while the call was still in flight.
forgotten bool
}