Re: PHP True Async RFC Stage 4

From: Date: Thu, 16 Oct 2025 14:42:39 +0000
Subject: Re: PHP True Async RFC Stage 4
References: 1 2 3 4 5 6 7 8 9  Groups: php.internals 
Request: Send a blank email to internals+get-128855@lists.php.net to get a copy of this message
On Thu, Oct 16, 2025, at 15:19, Edmond Dantes wrote: > > Would it be better to instead of having ->awaitCompletion (which feels like an implicit > > implementation of Awaitable without an explicit implmentation -- which is the part that was > > bothering me), maybe having something like ->joinAll() or ->joinOnCancellation()? > > That way someone like me won't come along and wrap them in an Awaitable because it > > looks Awaitable. > > For example, you have an interface DataBaseAdmin with a > removeDB() > method and a class that implements it. > You need to be able to delete the database, but with an additional > condition. So you create a decorator class with a method > ContextualDBAdmin::removeDBWhen($extraRules). > > As a result, the decorator class is logically associated with the > DataBaseAdmin interface. > > The question is: **so what?** I think we might be talking past each other a little. You said earlier that one of the goals here is to prevent misuse (e.g. unbounded or foreign awaits). I completely agree and that’s exactly why I’m suggesting a rename. From the outside, a method called awaitCompletion() looks and behaves like an Awaitable, even though the type explicitly isn’t one. That contradiction encourages people to wrap it to “make it awaitable,” which re-introduces the very problem you’re trying to avoid. Renaming it to something like joinAll() or joinAfterCancellation() keeps the semantics intact while communicating the intent: this isn’t a future; it’s a container join. That small change would make the interface self-documenting and harder to misuse. > > > It also might be a good idea to make specifying a timeout in ms mandatory, instead of a > > taking an Awaitable/Cancellation. > > The idea is correct, but there will definitely be someone who says > they need more flexibility. > And it's true you can create a DeferredCancellation and > forget to > finish it. :) > > There are a lot of such subtle points, and they can be discussed endlessly. > But I wouldn’t spend time on them. That's what we are here to do, no? Discussion is useful if it makes things better than the sum of their parts. > > It also might be good to provide a realistic looking example showing a "bad > > case" of how this is dangerous instead of simply saying that it is, showing how a scope is not > > a 'future', > > but a container, and preemptively mention TaskGroups, linking to the future scope (which > > it should also probably be listed there as well). > > 1. It’s very difficult to write a realistic example that’s still small. I'll give it a go: $scope = new Scope(); // Library code spawns in my scope (transitively) $scope->spawn(fn() => thirdPartyOperation()); // may spawn more // Looks innocent, but this can wait on foreign work: $scope->awaitCompletion(Async\timeout(60000)); // rename -> joinAll(...)? > 2. The TaskGroup or CoroutineGroupҔV > �`ÔÆÑÕE class is left for future > discussion. In the final documentation, it will be exactly as you > suggested. My point is that it wasn't listed in "future scope" of the RFC, though they're mentioned throughout the document, in passing. — Rob

« previous php.internals (#128855) next »