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

Reply via email to