Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Core HTTP] Bug Fix - TokenRefresher shouldn't be recreated for each request #10728

Merged

Conversation

HarshaNalluru
Copy link
Member

@HarshaNalluru HarshaNalluru commented Aug 20, 2020

Summary of the investigation

History

I was trying to fix the CI for the schema-registry PR(#10602) which was failing because the recordings were not generated using the latest master. Upon digging deeper #10683, the failure was caused because the tests weren't recorded using the latest core-http(on master) which had a new change #10085 related to the token refreshing logic that made more requests to refresh the tokens that weren't saved in the older recordings.

Bug 1 (Core HTTP)

New requests mentioned above led to a discussion with @sadasant and upon investigating further, we realized that the tokens weren't cached which caused more requests. Daniel made a PR #10692 to fix the issue to update core-http with caching the tokens that would remove the unnecessary additional requests.

Bug 2 (Core HTTP)

After fixing Bug 1, we generated the recordings, played them back, and have observed one more issue where there was a refresh request that was happening after the test ends. #10694
Another question at this point is that the refresh request is supposed to ping after or at about 30s, why does it ping again after the test when it had just elapsed a couple of seconds(milliseconds if in playback)?
Upon investigating with Daniel to answer the above, the issue turned out to be that a new token refresher was being created for each of the requests that are made to the service.
This PR attempts to fix that by reusing the token refresher.

Many thanks to @sadasant for his help with investigating the issues.

Resolves #10694

'Tue, 18 Aug 2020 23:52:08 GMT'
]);

nock('https://login.microsoftonline.com:443', {"encodedQueryParams":true})
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This deletion is an example of the request that was saved because the token refresher wasn't shared.

Copy link
Member

@xirzec xirzec left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

// @public
export class AccessTokenRefresher {
constructor(credential: TokenCredential, scopes: string | string[], requiredMillisecondsBeforeNewRefresh?: number);
// (undocumented)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing doc comment

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Fixed!

I see more
image

I'll log an issue for this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -100,7 +108,7 @@ export class BasicAuthenticationCredentials implements ServiceClientCredentials

// @public
export class BearerTokenAuthenticationPolicy extends BaseRequestPolicy {
constructor(nextPolicy: RequestPolicy, options: RequestPolicyOptions, credential: TokenCredential, scopes: string | string[], tokenCache: AccessTokenCache);
constructor(nextPolicy: RequestPolicy, options: RequestPolicyOptions, tokenCache: AccessTokenCache, tokenRefresher: AccessTokenRefresher);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this be a breaking change?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might be fine because the libraries depend on BearerTokenAuthenticationPolicy indirectly through bearerTokenAuthenticationPolicy which is not being changed.

Copy link
Contributor

@daviwil daviwil left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks fine, might be worth mentioning this change in the CHANGELOG before the next release just in case anyone happens to be using it directly (which they shouldn't). @xirzec feel free to say otherwise, I don't feel strongly about it

sdk/core/core-http/src/credentials/accessTokenRefresher.ts Outdated Show resolved Hide resolved
Copy link
Contributor

@sadasant sadasant left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yayyy thank you

Comment on lines 8 to 10
- `BearerTokenAuthenticationPolicy` constructor signature has been updated to accommodate the token refresher appropriately. The signature for `bearerTokenAuthenticationPolicy` method doesn't change.
[PR 10728](https://github.com/Azure/azure-sdk-for-js/pull/10728)
Note: It is expected that the users depending on `BearerTokenAuthenticationPolicy` do so indirectly through `bearerTokenAuthenticationPolicy` method that is exported.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sadasant, feel free to update the changelog with more details spanning #10085 and #10692

@daviwil @xirzec - Is this fine?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds reasonable to me, thanks!

Comment on lines 8 to 10
- `BearerTokenAuthenticationPolicy` constructor signature has been updated to accommodate the token refresher appropriately. The signature for `bearerTokenAuthenticationPolicy` method doesn't change.
[PR 10728](https://github.com/Azure/azure-sdk-for-js/pull/10728)
Note: It is expected that the users depending on `BearerTokenAuthenticationPolicy` do so indirectly through `bearerTokenAuthenticationPolicy` method that is exported.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels like a lot of context/details for a change to what is effectively an internal type.

Suggested change
- `BearerTokenAuthenticationPolicy` constructor signature has been updated to accommodate the token refresher appropriately. The signature for `bearerTokenAuthenticationPolicy` method doesn't change.
[PR 10728](https://github.com/Azure/azure-sdk-for-js/pull/10728)
Note: It is expected that the users depending on `BearerTokenAuthenticationPolicy` do so indirectly through `bearerTokenAuthenticationPolicy` method that is exported.
- Fixed a bug in `BearerTokenAuthenticationPolicy` where a helper class was being instantiated on each request. [PR 10728](https://github.com/Azure/azure-sdk-for-js/pull/10728)

I think this is enough honestly. Nobody should have a reason to grab the per-instance class and mess with it. Alternatively we could call this out as 'BREAKING' but honestly BearerTokenAuthenticationPolicy should be private.

I don't really understand why we exported that type, since it's not used as the return type of bearerTokenAuthenticationPolicy -- other policy classes aren't exported e.g.

export { LogPolicyOptions, logPolicy } from "./policies/logPolicy";

But some recent ones like DisableResponseDecompressionPolicy are, which just feels like a bug. Maybe this was done to make tests easier to write?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really understand why we exported that type, since it's not used as the return type of bearerTokenAuthenticationPolicy -- other policy classes aren't exported

Hmmm, they shouldn't have been exported.

But some recent ones like DisableResponseDecompressionPolicy are, which just feels like a bug.

Looks like KeepAlivePolicy is being exported too.
export { keepAlivePolicy, KeepAlivePolicy, KeepAliveOptions } from "./policies/keepAlivePolicy";

Maybe this was done to make tests easier to write?

We import the src code directly inside the tests, no need to export it through index.ts(or coreHttp.ts) just for the sake of tests.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Opened a PR #10738 to un-export these classes.

Co-authored-by: Jeff Fisher <xirzec@xirzec.com>
@sadasant
Copy link
Contributor

This solves the problem and it's neatly done. Ship it!

@HarshaNalluru HarshaNalluru merged commit d752581 into Azure:master Aug 21, 2020
@HarshaNalluru
Copy link
Member Author

This solves the problem and it's neatly done. Ship it!

Couldn't have done it without you!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Core HTTP] Token refresher is not shared among multiple requests
4 participants