-
Notifications
You must be signed in to change notification settings - Fork 77
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
Investigate issues with gevent.monkey.patch_all() #59
Comments
Does this mean gevent with Temporal is meant to be a supported configuration? Do you need to use synchronous Activities to use gevent code? Is there any documentation on the usage together? I tried looking for some earlier and couldn’t find it. |
No, the SDK does not use gevent in any way nor depend on it in any way. This is just a case where a user had an old gevent library in their existing code and it clashed with Temporal due to some bug in gevent's global side-effecting code that may have since been fixed. This issue is simply me acknowledging it so I can test and if necessary add a warning to the README for users of older gevent libraries.
You may have to and there is no Temporal documentation here (nor is there with any Python async library integration beyond builtin |
Thanks for the context. I am planning on testing our gevent setup with Temporal. I will report back the results w/gevent version once I have done so |
As a follow-up, we use gevent 1.3.7 and ran into a number of issues. We haven't done a full investigation but here are some of the things we did:
When things worked, it was awesome! Unfortunately, in general we experienced unpredictable behavior in our code where it would mysteriously hang indefinitely (usually around monkeypatched IO calls). We haven't had time to dig in and identify exactly where the incompatibility is. We have a general sense of uneasiness of using gevent monkeypatched code with asyncio code. If I have time, I'm going to try an experiment where I run Temporal in a process forked off before gevent monkeypatching and using a cross-process executor. I don't expect it to work, but it is a fun exercise! |
This is still failing on latest gevent (21.12.0) and temporalio (0.1b2). Minimal code to reproduce:
Error
ExplanationNOTE that only threading needs to be patched I believe there is something funky with how gevent patches thread locals and how thread locals are used to store the current event loop. The code here that calls Similar to @alecgorge I tried to pass in a Potential fixUse I will add an example with this soon. |
After a deep dive into the asyncio code I found that a running loop always sets the c specific thread local and there is no (easy) way around that. That said, I was able to get the gevent
|
@reallistic - Thanks for this deep dive. I have this on my schedule to dig into and even write an integration test for (if isolatable, i.e. can "unpatch" afterwards).
I think this is the right approach and we should do this if it in fact fixes it. Who knows who else is setting default event loops on threads somehow. I just set to |
This is 100% sane and reasonable. The issue is that gevent monkey patches pure python threading but not the c implementation. Also, changing However, using those apis does not help out with gevent. This is because the main loop used to connect the client and run the The only approach I can think of to allow gevent to work would be to use regular asyncio calls instead of a custom event loop. I recognize though that doing such an implementation would require a decent amount of work and you would lose the safeguards of preventing multi-threading etc. |
Completely agree, but there was something w/ the default event loop policy on some platform I think was causing me problems. But I forget what and I didn't document it, so will definitely try to move back to all public API.
We really have to keep our custom event loop. It's the underpinning of what makes workflows work well. Maybe we can have a similar monkey patch that overrides gevent for the life of the run_once and then puts it back after. I'll have to check gevent, but surely we're not the first that have wanted to do advanced asyncio loop management in a gevent-enabled process. I'll have to dig into what they really do. I only need a short synchronous window to own the loop on a thread run. |
I am happy to report I have succeeded combining gevent and Temporal: temporalio/samples-python#84. @reallistic - I basically took your approach but I created a separate executor for running the asyncio event loop in a native gevent thread (separate from the executor that is used to execute workflow/activity tasks). I will have to update the README in this repo with the update and then I'll be able to close this out I think unless I'm missing something. |
Fixes temporalio#59 Fixes temporalio#379
Is your feature request related to a problem? Please describe.
Users on an older version of gevent (1.5.0) reported that running
gevent.monkey.patch_all()
breaks workflow asyncio.Describe the solution you'd like
The text was updated successfully, but these errors were encountered: