-
Notifications
You must be signed in to change notification settings - Fork 137
Support raising cancellation in sync multithreaded activities #217
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
|
Looks like worker shutdown is disconnected from thread raise. I would merge it with cancellation so activity authors have one less thing to worry about. In TS worker shutdown notifications are delivered via cancellation. |
Only slightly disconnected. Just like in TS, worker shutdown in Python is also delivered via cancellation, it's just that we offer a grace period before that where we populate an event. But the grace period by default is 0 anyways and most don't use it. It's only for advanced uses needing to know worker shutdown before the cancel occurs. We don't throw an exception or cancel the async task during this grace period. |
I see, in TS we immediately cancel the activities and wait for the grace period before throwing an exceptions in case activities don't respond to shutdown. Again, not for this PR, it came up because I saw the worker shutdown event while doing the code review. |
The whole reason for the grace period is so that activities can react differently than to cancellation. This concept also is in the Go SDK and people do ask for it and leverage it.
Hrmm, not sure. We simply don't shutdown in Python if activities don't respond to the cancellation. Same for Go (and maybe same for Java too, unsure).
Not true. A user can choose to give up, but we don't have to and don't in multiple SDKs. In multithreaded/async situations in many languages, you can't force a stop from the outside, you can only request it. So we guarantee no leaks after "shutdown" returns. But if we were to return from shutdown without guaranteeing the threads/tasks actually finished (e.g. they catch and swallow cancel/interrupt), you are basically encouraging leaks. |
They can do this with the cancellation approach, it's just a matter of checking the cancellation reason if they need to customize the logic.
I don't know what Java does here either but I'm not convinced this is the right approach.
User can set the shutdown grace period to some very high number if they want to avoid the leak. |
|
From what I've seen in HTTP servers, there's typically a grace period for draining all of the existing connections after which the server will forcefully shut down. |
This confuses libraries with processes I think. If we're talking about a Temporal worker process, yes we should give up and kill the process. But we're talking about a library here. The giving up and killing of the process is the user's choice, not ours. Giving up and returning (or erroring) as though the user can continue on without leaks would be bad. https://pkg.go.dev/net/http#Server.Shutdown for example, the Go HTTP server, would never give up unless the user asks them to. If you have an HTTP handler doing work forever and you don't timeout the call from the caller side, that call will never return. |
I don't think there's any confusion, by giving the user a configurable grace period we make it the user's choice.
From that page:
That's basically the graceful period that we have in TS. |
Why have that graceful period then? Why not let the user just abandon the promise after their own timeout? If you're just abandoning shutdown, the user can too.
Cancellation/abandoning the shutdown call is an option for users too. They can easily |
We do some cleanup but I agree there's probably not that much value there.
In TS SDK you can't wait for shutdown, it doesn't return a promise and I'm not convinced it should. |
|
I understand that in Python there might be less value for implementing the version of graceful shutdown that TS has. |
What was changed
@activity.defndecorator to avoid thisactivity.shield_thread_cancel_exceptioncontext manager to have blocks shielded from this exceptionChecklist