-
Notifications
You must be signed in to change notification settings - Fork 3.2k
[Identity] Add async token method concurrency control #43889
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| # ------------------------------------ | ||
| # Copyright (c) Microsoft Corporation. | ||
| # Licensed under the MIT License. | ||
| # ------------------------------------ | ||
| import sys | ||
| from typing import Type | ||
|
|
||
|
|
||
| def get_running_async_lock_class() -> Type: | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we move this into azure-core?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Core does already have a similar function, but it returns a Lock instance instead of a class/type. An instance is fine for most cases where only one lock needs to be instantiated, but in this particular scenario, several locks are instantiated. I only want to check the event loop once to get the class, so I think it's fine to have a separate function here for this purpose. |
||
| """Get a lock class from the async library that the current context is running under. | ||
| :return: The running async library's Lock class. | ||
| :rtype: Type[Lock] | ||
| :raises RuntimeError: if the current context is not running under an async library. | ||
| """ | ||
|
|
||
| try: | ||
| import asyncio # pylint: disable=do-not-import-asyncio | ||
|
|
||
| # Check if we are running in an asyncio event loop. | ||
| asyncio.get_running_loop() | ||
| return asyncio.Lock | ||
| except RuntimeError as err: | ||
| # Otherwise, assume we are running in a trio event loop if it has already been imported. | ||
| if "trio" in sys.modules: | ||
| import trio # pylint: disable=networking-import-outside-azure-core-transport | ||
|
|
||
| return trio.Lock | ||
| raise RuntimeError("An asyncio or trio event loop is required.") from err | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
_last_request_timeupdate should occur before calling_request_token(on success path) as well, not only in the exception handler. Currently, when_request_tokensucceeds,_last_request_timeis never updated, which could bypass the retry delay check in_should_refresh. This inconsistency means the retry delay only applies after failures, not after successful token requests.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I want to modify this logic to only set the
_last_request_timethrottle when a_request_tokencall fails.This still prevents rapid retries on failures, without allowing a successful request for one scope to block a necessary refresh for another (which would be the case if we set this on success as well).