Skip to content

Commit

Permalink
Singleflight token retrieval (#9)
Browse files Browse the repository at this point in the history
  • Loading branch information
holowinski authored Sep 5, 2023
1 parent e3afa87 commit 82e1fc7
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 0 deletions.
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,7 @@ require (

require (
github.com/golang/protobuf v1.5.2 // indirect
github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect
golang.org/x/sync v0.3.0 // indirect
google.golang.org/protobuf v1.28.0 // indirect
)
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4=
github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
Expand All @@ -23,6 +25,8 @@ golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0=
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
Expand Down
39 changes: 39 additions & 0 deletions internal/token.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ import (
"sync"
"time"

"github.com/mitchellh/hashstructure/v2"
"golang.org/x/net/context/ctxhttp"
"golang.org/x/sync/singleflight"
)

// Token represents the credentials used to authorize
Expand Down Expand Up @@ -185,7 +187,44 @@ func cloneURLValues(v url.Values) url.Values {
return v2
}

var tokenFetchGroup singleflight.Group

func RetrieveToken(ctx context.Context, clientID, clientSecret, tokenURL string, v url.Values, authStyle AuthStyle) (*Token, error) {
// singleflight wrapper over the actual implementation `doRetrieveToken`
// this function makes sure that token endpoint is called only once at the same time with
// the same credentials and params
var (
hashStr = struct {
clientID string
clientSecret string
tokenURL string
v url.Values
authStyle AuthStyle
}{
clientID: clientID,
clientSecret: clientSecret,
tokenURL: tokenURL,
v: v,
authStyle: authStyle,
}
hash uint64
token interface{}
err error
)

if hash, err = hashstructure.Hash(hashStr, hashstructure.FormatV2, nil); err != nil {
return nil, err
}

if token, err, _ = tokenFetchGroup.Do(strconv.FormatUint(hash, 10), func() (interface{}, error) {
return doRetrieveToken(ctx, clientID, clientSecret, tokenURL, v, authStyle)
}); err != nil {
return nil, err
}
return token.(*Token), nil
}

func doRetrieveToken(ctx context.Context, clientID, clientSecret, tokenURL string, v url.Values, authStyle AuthStyle) (*Token, error) {
needsAuthStyleProbe := authStyle == 0
if needsAuthStyleProbe {
if style, ok := lookupAuthStyle(tokenURL); ok {
Expand Down

0 comments on commit 82e1fc7

Please sign in to comment.