Hi Edmond!

On Wed, Apr 16, 2025 at 7:02 AM Edmond Dantes <edmond...@gmail.com> wrote:

> Good day, everyone. I hope you're doing well.
>
> I’d like to introduce the RFC for the True Async component.
>
> https://wiki.php.net/rfc/true_async
>
> This time the work took longer because I was exploring different
> architectural options and paid more attention to how it works in other
> languages.
>
> I was trying to find a balance between developer freedom and code safety,
> and I believe I managed to find it.
>
>   This RFC will go to a vote in about two weeks.
>
> Wishing you all a great day, and thank you for your feedback!
>
> --
>
> Ed.
>
Thank you so much for such a comprehensive RFC in such a complex domain!
The amount of care and work that went into this is quite visible. I want to
preface that I have no voting rights, so take my feedback with a grain of
salt.

https://wiki.php.net/rfc/true_async#scope

What happens if the coroutine didn't finish execution? does
`disposeSafely()` means that it will wait until completion to safely clear
it up or does it mean it will attempt to dispose and throw an exception if
it fails to do so?

------------------------

https://wiki.php.net/rfc/true_async#taskgroup

My first impression here was a little odd. Wouldn't it make more sense to
hide the syntax behind the TaskGroup class?

$taskGroup = new Async\TaskGroup(captureResults: true);
$taskGroup->spawn(task1(...));

$taskGroup->spawn(task2(...));
[$result1, $result2] = $taskGroup->await()

------------------------

https://wiki.php.net/rfc/true_async#cooperative_cancellation

Is there a time-limit imposed on the catch block?

------------------------

https://wiki.php.net/rfc/true_async#context

Could this example be moved to a later block *after `*spawn use ()` has
been introduced? Would it be possible to elaborate further an example that
could not be easily replaced by `spawn use()`? In other words, what is
unique about Context that makes it indispensable as opposed to `spawn
use()`?

------------------------

https://wiki.php.net/rfc/true_async#combinators

I may be misunderstanding, but it *feels* like `any()` is another way of
`$taskGroup->race()`? and `all()` is another way of `$taskGroup->await()`?
Would it make sense to elaborate further their difference in this example?
Do you think the first RFC perhaps could propose one or the other and keep
one of them for future scope?

------------------------

https://wiki.php.net/rfc/true_async#waiting_for_coroutine_results

isn't this just standard PHP with extra steps? I'm assuming `await` here
blocks and `spawn` creates a coroutine. Wouldn't every use of `await spawn`
be effectively the same as just using PHP as-is today in blocking mode?

------------------------

https://wiki.php.net/rfc/true_async#awaiting_a_result_with_cancellation

What is the output of this statement? Assuming it takes longer than 2
seconds, do we get null back? an exception?

Additionally, this brings another syntax change with the `until` keyword
that initially _feels like_ it could be a future scope to make the RFC
shorter and more digestive? If users need to limit the duration of a
coroutine maybe they can either cancel it or safely dispose?

------------------------

https://wiki.php.net/rfc/true_async#working_with_a_group_of_concurrent_tasks

This feels like it reinforces my previous point.

function mergeFiles(string ...$files): string{
    $taskGroup = new Async\TaskGroup(captureResults: true);

    foreach ($files as $file) {
       $taskGroup->spawn(fn () => file_get_contents
<http://www.php.net/file_get_contents>($file));
    }

    return array_merge <http://www.php.net/array_merge>("\n",
$taskGroup->await());}

Note: I *think* you wanted to use `implode` instead of `array_merge` here.

------------------------

https://wiki.php.net/rfc/true_async#await_all_child_tasks

I want to make a side comment that this example reinforces my initial
sentiment that `until` syntax is not required on the first version?
However, it's relevant to mention I didn't fully understand this example.
It feels to me that the inner function `processJob` is supposed to await
only its own set of coroutines while the `processBackgroundJobs` is
awaiting on all hierarchy as the comments says. However, if the scope is
being
inherited, wouldn't that make the inner `processJob` await basically be
awaiting the entire scope? Effectively the inner await and the outer await
mean
the same thing?

------------------------

https://wiki.php.net/rfc/true_async#binding_coroutines_to_a_php_object

I'm not trying to be pedantic, but it is a rather complex RFC. This seems
to be the first time it uses `stop` a coroutine. Is it different from
`cancel()` and `disposeSafely()`? How so?

------------------------

https://wiki.php.net/rfc/true_async#namespace

This seems like a void statement. Whether the namespace gets used in a way
that respects this statement or not, it doesn't mean that PHP won't break
BC in future versions when the language itself defines a symbol that has
been defined in userland.

------------------------

https://wiki.php.net/rfc/true_async#hipriority_strategy

Seems like a good candidate for future scope and/or left for userland since
the SpawnStrategy interface already exposes the necessary capabilities?

------------------------

https://wiki.php.net/rfc/true_async#suspension

This explains a bit more the "Cooperative cancellation" example early in
the RFC, but it does seem rather awkward to suspend the main in order to
start a coroutine. Shouldn't await be used for that instead? Would making
`suspend` a fatal error inside the main flow somehow worse for
implementation?


------------------------

Sorry for not reading the entire RFC before replying. I hope to get through
it all in the following days.

Thanks!


-- 
Marco Deleu

Reply via email to