Skip to content

Commit acd2581

Browse files
authored
feat: Async refresh dry run in parallel with sync refresh (#2849)
* feat: Add async refresh dry run * add meter provider and attributes * adding error handler instead of metrics * Rename variable and add comment * adding more comments * Updating oauth2adapt
1 parent 2657039 commit acd2581

File tree

5 files changed

+74
-4
lines changed

5 files changed

+74
-4
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ go 1.21
55
require (
66
cloud.google.com/go v0.116.0
77
cloud.google.com/go/auth v0.10.2
8-
cloud.google.com/go/auth/oauth2adapt v0.2.5
8+
cloud.google.com/go/auth/oauth2adapt v0.2.6
99
cloud.google.com/go/compute/metadata v0.5.2
1010
github.com/google/go-cmp v0.6.0
1111
github.com/google/s2a-go v0.1.8

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE=
33
cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U=
44
cloud.google.com/go/auth v0.10.2 h1:oKF7rgBfSHdp/kuhXtqU/tNDr0mZqhYbEh+6SiqzkKo=
55
cloud.google.com/go/auth v0.10.2/go.mod h1:xxA5AqpDrvS+Gkmo9RqrGGRh6WSNKKOXhY3zNOr38tI=
6-
cloud.google.com/go/auth/oauth2adapt v0.2.5 h1:2p29+dePqsCHPP1bqDJcKj4qxRyYCcbzKpFyKGt3MTk=
7-
cloud.google.com/go/auth/oauth2adapt v0.2.5/go.mod h1:AlmsELtlEBnaNTL7jCj8VQFLy6mbZv0s4Q7NGBeQ5E8=
6+
cloud.google.com/go/auth/oauth2adapt v0.2.6 h1:V6a6XDu2lTwPZWOawrAa9HUK+DB2zfJyTuciBG5hFkU=
7+
cloud.google.com/go/auth/oauth2adapt v0.2.6/go.mod h1:AlmsELtlEBnaNTL7jCj8VQFLy6mbZv0s4Q7NGBeQ5E8=
88
cloud.google.com/go/compute/metadata v0.5.2 h1:UxK4uu/Tn+I3p2dYWTfiX4wva7aYlKixAHn3fyqngqo=
99
cloud.google.com/go/compute/metadata v0.5.2/go.mod h1:C66sj2AluDcIqakBq/M8lw8/ybHgOZqin2obFxa/E5k=
1010
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=

internal/settings.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ type DialSettings struct {
7272
// New Auth library Options
7373
AuthCredentials *auth.Credentials
7474
EnableNewAuthLibrary bool
75+
76+
// TODO(b/372244283): Remove after b/358175516 has been fixed
77+
EnableAsyncRefreshDryRun func()
7578
}
7679

7780
// GetScopes returns the user-provided scopes, if set, or else falls back to the

option/internaloption/internaloption.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,33 @@ func (w enableNewAuthLibrary) Apply(o *internal.DialSettings) {
211211
o.EnableNewAuthLibrary = bool(w)
212212
}
213213

214+
// EnableAsyncRefreshDryRun returns a ClientOption that specifies if libraries in this
215+
// module should asynchronously refresh auth token in parallel to sync refresh.
216+
//
217+
// This option can be used to determine whether refreshing the token asymnchronously
218+
// prior to its actual expiry works without any issues in a particular environment.
219+
//
220+
// errHandler function will be called when there is an error while refreshing
221+
// the token asynchronously.
222+
//
223+
// This is an EXPERIMENTAL option and will be removed in the future.
224+
// TODO(b/372244283): Remove after b/358175516 has been fixed
225+
func EnableAsyncRefreshDryRun(errHandler func()) option.ClientOption {
226+
return enableAsyncRefreshDryRun{
227+
errHandler: errHandler,
228+
}
229+
}
230+
231+
// TODO(b/372244283): Remove after b/358175516 has been fixed
232+
type enableAsyncRefreshDryRun struct {
233+
errHandler func()
234+
}
235+
236+
// TODO(b/372244283): Remove after b/358175516 has been fixed
237+
func (w enableAsyncRefreshDryRun) Apply(o *internal.DialSettings) {
238+
o.EnableAsyncRefreshDryRun = w.errHandler
239+
}
240+
214241
// EmbeddableAdapter is a no-op option.ClientOption that allow libraries to
215242
// create their own client options by embedding this type into their own
216243
// client-specific option wrapper. See example for usage.

transport/grpc/dial.go

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,40 @@ func prepareDialOptsNewAuth(ds *internal.DialSettings) []grpc.DialOption {
262262
return append(opts, ds.GRPCDialOpts...)
263263
}
264264

265+
// dryRunAsync is a wrapper for oauth2.TokenSource that performs a sync refresh
266+
// after an async refresh. Token generated by async refresh is not used.
267+
//
268+
// This is an EXPERIMENTAL feature and may be removed or changed in the future.
269+
// It is a temporary struct to determine if the async refresh
270+
// is working properly.
271+
// TODO(b/372244283): Remove after b/358175516 has been fixed
272+
type dryRunAsync struct {
273+
asyncTokenSource oauth2.TokenSource
274+
syncTokenSource oauth2.TokenSource
275+
errHandler func()
276+
}
277+
278+
// TODO(b/372244283): Remove after b/358175516 has been fixed
279+
func newDryRunAsync(ts oauth2.TokenSource, errHandler func()) dryRunAsync {
280+
tp := auth.NewCachedTokenProvider(oauth2adapt.TokenProviderFromTokenSource(ts), nil)
281+
asyncTs := oauth2adapt.TokenSourceFromTokenProvider(tp)
282+
return dryRunAsync{
283+
syncTokenSource: ts,
284+
asyncTokenSource: asyncTs,
285+
errHandler: errHandler,
286+
}
287+
}
288+
289+
// Token returns a token or an error.
290+
// TODO(b/372244283): Remove after b/358175516 has been fixed
291+
func (async dryRunAsync) Token() (*oauth2.Token, error) {
292+
_, err := async.asyncTokenSource.Token()
293+
if err != nil {
294+
async.errHandler()
295+
}
296+
return async.syncTokenSource.Token()
297+
}
298+
265299
func dial(ctx context.Context, insecure bool, o *internal.DialSettings) (*grpc.ClientConn, error) {
266300
if o.HTTPClient != nil {
267301
return nil, errors.New("unsupported HTTP client specified")
@@ -298,8 +332,14 @@ func dial(ctx context.Context, insecure bool, o *internal.DialSettings) (*grpc.C
298332
if err != nil {
299333
return nil, err
300334
}
335+
336+
ts := creds.TokenSource
337+
// TODO(b/372244283): Remove after b/358175516 has been fixed
338+
if o.EnableAsyncRefreshDryRun != nil {
339+
ts = newDryRunAsync(ts, o.EnableAsyncRefreshDryRun)
340+
}
301341
grpcOpts = append(grpcOpts, grpc.WithPerRPCCredentials(grpcTokenSource{
302-
TokenSource: oauth.TokenSource{TokenSource: creds.TokenSource},
342+
TokenSource: oauth.TokenSource{TokenSource: ts},
303343
quotaProject: internal.GetQuotaProject(creds, o.QuotaProject),
304344
requestReason: o.RequestReason,
305345
}))

0 commit comments

Comments
 (0)