ソースを参照

Merge pull request #46458 from vvoland/vendor-resenje-singleflight-4.0.0

vendor: resenje.org/singleflight v0.4.0
Sebastiaan van Stijn 1 年間 前
コミット
9641c90eaf

+ 1 - 1
vendor.mod

@@ -106,7 +106,7 @@ require (
 	google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4
 	google.golang.org/grpc v1.53.0
 	gotest.tools/v3 v3.5.0
-	resenje.org/singleflight v0.3.0
+	resenje.org/singleflight v0.4.0
 )
 
 require (

+ 2 - 2
vendor.sum

@@ -2140,8 +2140,8 @@ mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jC
 mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f/go.mod h1:4G1h5nDURzA3bwVMZIVpwbkw+04kSxk3rAtzlimaUJw=
 mvdan.cc/unparam v0.0.0-20200501210554-b37ab49443f7/go.mod h1:HGC5lll35J70Y5v7vCGb9oLhHoScFwkHDJm/05RdSTc=
 pack.ag/amqp v0.11.2/go.mod h1:4/cbmt4EJXSKlG6LCfWHoqmN0uFdy5i/+YFz+fTfhV4=
-resenje.org/singleflight v0.3.0 h1:USJtsAN6HTUA827ksc+2Kcr7QZ4HBq/z/P8ugVbqKFY=
-resenje.org/singleflight v0.3.0/go.mod h1:lAgQK7VfjG6/pgredbQfmV0RvG/uVhKo6vSuZ0vCWfk=
+resenje.org/singleflight v0.4.0 h1:NdOEhCxEikK2S2WxGjZV9EGSsItolQKslOOi6pE1tJc=
+resenje.org/singleflight v0.4.0/go.mod h1:lAgQK7VfjG6/pgredbQfmV0RvG/uVhKo6vSuZ0vCWfk=
 rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
 rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
 rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=

+ 1 - 1
vendor/modules.txt

@@ -1444,7 +1444,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.3.0
+# resenje.org/singleflight v0.4.0
 ## explicit; go 1.18
 resenje.org/singleflight
 # sigs.k8s.io/yaml v1.3.0

+ 16 - 20
vendor/resenje.org/singleflight/singleflight.go

@@ -5,7 +5,7 @@
 
 // Package singleflight provides a duplicate function call suppression
 // mechanism similar to golang.org/x/sync/singleflight with support
-// for context cancelation.
+// for context cancellation.
 package singleflight
 
 import (
@@ -17,7 +17,7 @@ import (
 // which units of work can be executed with duplicate suppression.
 type Group[K comparable, V any] struct {
 	calls map[K]*call[V] // lazily initialized
-	mu    sync.Mutex       // protects calls
+	mu    sync.Mutex     // protects calls
 }
 
 // Do executes and returns the results of the given function, making sure that
@@ -25,10 +25,12 @@ type Group[K comparable, V any] struct {
 // comes in, the duplicate caller waits for the original to complete and
 // receives the same results.
 //
-// The context passed to the fn function is a new context which is canceled when
-// contexts from all callers are canceled, so that no caller is expecting the
-// result. If there are multiple callers, context passed to one caller does not
-// effect the execution and returned values of others.
+// The context passed to the fn 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 (no caller is awaiting the result).
+// If there are multiple callers, context passed to one caller does not affect
+// the execution and returned values of others except if the function result is
+// dependent on the context values.
 //
 // The return value shared indicates whether v was given to multiple callers.
 func (g *Group[K, V]) Do(ctx context.Context, key K, fn func(ctx context.Context) (V, error)) (v V, shared bool, err error) {
@@ -45,7 +47,9 @@ func (g *Group[K, V]) Do(ctx context.Context, key K, fn func(ctx context.Context
 		return g.wait(ctx, key, c)
 	}
 
-	callCtx, cancel := context.WithCancel(context.Background())
+	// Replace cancellation from the user context with a cancellation
+	// controlled by the singleflight and preserve context values.
+	callCtx, cancel := context.WithCancel(withoutCancel(ctx))
 
 	c := &call[V]{
 		done:    make(chan struct{}),
@@ -76,8 +80,6 @@ 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()
-	}
-	if !c.forgotten {
 		delete(g.calls, key)
 	}
 	g.mu.Unlock()
@@ -89,9 +91,6 @@ 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()
 }
@@ -105,15 +104,12 @@ type call[V any] struct {
 	// done channel signals that the function call is done.
 	done chan struct{}
 
-	// forgotten indicates whether Forget was called with this call's key
-	// while the call was still in flight.
-	forgotten bool
-
-	// shared indicates if results val and err are passed to multiple callers.
-	shared bool
+	// Cancel function for the context passed to the executing function.
+	cancel context.CancelFunc
 
 	// Number of callers that are waiting for the result.
 	counter int
-	// Cancel function for the context passed to the executing function.
-	cancel context.CancelFunc
+
+	// shared indicates if results val and err are passed to multiple callers.
+	shared bool
 }

+ 87 - 0
vendor/resenje.org/singleflight/withoutcancel.go

@@ -0,0 +1,87 @@
+//go:build !go1.21
+
+// Copyright (c) 2009 The Go Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Source: https://cs.opensource.google/go/go/+/refs/tags/go1.21.1:src/context/context.go
+// The only modifications to the original source were:
+// - renaming WithoutCancel to withoutCancel
+// - replacing the usage of internal reflectlite with reflect
+// - replacing the usage of private value function with Value method call
+package singleflight
+
+import (
+	"context"
+	"reflect"
+	"time"
+)
+
+// withoutCancel returns a copy of parent that is not canceled when parent is canceled.
+// The returned context returns no Deadline or Err, and its Done channel is nil.
+// Calling [Cause] on the returned context returns nil.
+func withoutCancel(parent context.Context) context.Context {
+	if parent == nil {
+		panic("cannot create context from nil parent")
+	}
+	return withoutCancelCtx{parent}
+}
+
+type withoutCancelCtx struct {
+	c context.Context
+}
+
+func (withoutCancelCtx) Deadline() (deadline time.Time, ok bool) {
+	return
+}
+
+func (withoutCancelCtx) Done() <-chan struct{} {
+	return nil
+}
+
+func (withoutCancelCtx) Err() error {
+	return nil
+}
+
+func (c withoutCancelCtx) Value(key any) any {
+	return c.c.Value(key)
+}
+
+func (c withoutCancelCtx) String() string {
+	return contextName(c.c) + ".WithoutCancel"
+}
+
+type stringer interface {
+	String() string
+}
+
+func contextName(c context.Context) string {
+	if s, ok := c.(stringer); ok {
+		return s.String()
+	}
+	return reflect.TypeOf(c).String()
+}

+ 12 - 0
vendor/resenje.org/singleflight/withoutcancel_go121.go

@@ -0,0 +1,12 @@
+//go:build go1.21
+
+package singleflight
+
+import "context"
+
+// withoutCancel returns a copy of parent that is not canceled when parent is canceled.
+// The returned context returns no Deadline or Err, and its Done channel is nil.
+// Calling [Cause] on the returned context returns nil.
+func withoutCancel(ctx context.Context) context.Context {
+	return context.WithoutCancel(ctx)
+}