-
Notifications
You must be signed in to change notification settings - Fork 16.4k
fix: don't use blocking property access for async purposes #47326
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
Conversation
The AwsGenericHook provides the `@property` decorated function `async_conn` for building and accessing the async boto3 client. Unfortunately, this is results in blocking calls to the Airflow Db or secrets backends within async contexts. This PR provides an async method `get_async_conn` as an alternative that can be awaited in async contexts. This method will call the underlying sync code in a `sync_to_async` wrapper. The `async_conn` property is now deprecated and will be removed in future versions.
|
I think your analysis is correct (I haven't checked it, but you make a convincing argument) but I wonder if it's possible to solve this without changing the interface 🤔 |
Not changing the interface would be ideal, but I believe we need to return something awaitable in order to avoid blocking and that breaks the interface either way. To put it differently, the interface is part of the problem. 🤔 |
|
Is it possible to do this while keeping the property or cached_property decorator? We're trying to get rid of get_conn() since it's redundant with the conn property, it would be awkward to have two different means of interacting for sync and async like that. |
I don't think |
|
If you really want to keep class AwsGenericHook:
@property
def async_conn(self) -> coroutine[client]:
return sync_to_async(self._get_async_conn)()but you will still need to await it async def run(self):
client = await self.hook.async_connand thus it will be a breaking change for |
|
I really don't have enough background with python's async implementation to make the call. IMHO, I'd prefer to see a breaking implementation change that allows users to use Let's see what others think. I have the opinions but not the practical experience with this particular issue, so I suppose they aren't worth all that much in the end. :P |
I do get your intentions. :) But I fear that this might not be possible. In particular The issue is You can get away with it in normal (sync) code, but in |
|
I think I see where you are going. Thanks for looking into this and for the extra info, what you are saying makes sense. I'm going to step back and let others make the call, but I'll follow along an learn what I can. |
|
Sure! :) Let's see what others think about it. |
o-nikolas
left a comment
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.
Read through the discussion and the changes look reasonable (just one comment) 👍
I'm curious how noticeable the blockage on the async loop was though. Did you have a very noticeable issue that caused you to drill down and find this? Or is this more of an academic PR just to ensure things are fully async?
Thanks for the contribution!
I've been working with a customer. They have a DAG which kicks off up to 500 deferrable appearing 10-19 times per minute with values of 2-11 seconds. In particular the TaskDoneTrigger instantiates 2 clients per run (one each for EcsHook and AwsLogsHook). The triggerer basically was blocked for ten's of minutes while sequentially instantiating those async clients. Based on my findings they implemented changes to a custom version of TaskDoneTrigger and reported improvements upon those changes. |
In providers `AirflowProviderDeprecationWarning` must be used.
) The AwsGenericHook provides the `@property` decorated function `async_conn` for building and accessing the async boto3 client. Unfortunately, this is results in blocking calls to the Airflow Db or secrets backends within async contexts. This PR provides an async method `get_async_conn` as an alternative that can be awaited in async contexts. This method will call the underlying sync code in a `sync_to_async` wrapper. The `async_conn` property is now deprecated and will be removed in future versions.
The AwsGenericHook provides the
@propertydecorated methodasync_connfor building and accessing the async boto3 client. Unfortunately, this is results in blocking calls to the Airflow Db or secrets backends within async contexts.The exact call chain is as follows:
This PR provides an async method
get_async_connas an alternative that can be awaited in async contexts. This method will call the original sync code in async_to_asyncwrapper to avoid any side effects from potentially blocking@propertyor@cached_propertydecorated methods used downstream.The
async_connproperty is now deprecated and will be removed in future versions.closes: #47312