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` 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
