Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:129006 X-Original-To: internals@lists.php.net Delivered-To: internals@lists.php.net Received: from php-smtp4.php.net (php-smtp4.php.net [45.112.84.5]) by lists.php.net (Postfix) with ESMTPS id 74A4D1A00BC for ; Thu, 30 Oct 2025 13:33:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1761831206; bh=vZk4vtGMo3t0bxt3UnJfzB3HQ+rPfc1rUt9glwt72E0=; h=References:In-Reply-To:From:Date:Subject:To:Cc:From; b=d/akgZQi+/MtSDe5p8s0pHP5JyVZvLn7EncSiNIKjZdAH1KjNYXr2TBiXs9IySmR5 WgzcFB782QjkwUVgvM9xSGE7xwe7S0bFP86tx0ZbR4NkkLNLkXdeVdyeqBBIoTRxf2 CuV+wOVjXene2IluHMTjSyVTXmFqCW/IXLAZtIggPJfbfg5uJrpkg+DRsiC2uG9sZ7 8pS7luVJ1rdMx1MW7EK8bHdft881J0N2lDHZLtNfWC9kqBnsBWgHxg7e9BpvUb8F3p U5TA2iOsjr+KHIeWjeHkzyvJN0cVQX0Kcte4tT91LPFDB2xg1UZFUuVptyIIHgXvQE IYutI0c8uVKrw== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id AF7FB180055 for ; Thu, 30 Oct 2025 13:33:25 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=0.6 required=5.0 tests=BAYES_50,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS,FREEMAIL_FROM, HTML_MESSAGE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=4.0.1 X-Spam-Virus: No X-Envelope-From: Received: from mail-yx1-f44.google.com (mail-yx1-f44.google.com [74.125.224.44]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Thu, 30 Oct 2025 13:33:25 +0000 (UTC) Received: by mail-yx1-f44.google.com with SMTP id 956f58d0204a3-636d75f08a3so198447d50.1 for ; Thu, 30 Oct 2025 06:33:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1761831200; x=1762436000; darn=lists.php.net; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=UwAC8M3LiKD8KWr3wU4+OtMpmXmupjgqwCBjcmYL00A=; b=V4Kz+WYd9WfgCThX7l/2QZUl35frGU6vsIToYCZo1wQhvQdaNvYq02uCjSYpzYmbr/ zMFzLmZyEgggwDNnRrwvMYr5/ed39n/qB/ZnoGoOz7d4Xjv7tNGVvrav8nUatJnXHhuT 2M3p33sF9HFGHCMUUyO9KeVp3w8uMfvP02A56YbV2U1KJpZj3Oji1mdxYYOHee0G1bC2 03xb8dpzy74DHxaDwH7jbGR4Sbmwu1gxyrv2hMBacvgnEWHdvrvfDUUoXe5XPJjTf5i9 vTV+wSNt2NsqmYg2Ys8icqBACt57g+Svf9142NciHkPHycpc9fUt9Z5EA0uiTPZ5B+lu Yg1w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1761831200; x=1762436000; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=UwAC8M3LiKD8KWr3wU4+OtMpmXmupjgqwCBjcmYL00A=; b=VhuCJMI+JWAjNJ4CCD7ChFx9KCxxOoEHhM4Lzw027m992vcvD/b65GwHJyXQkyXxvr fSXoqZxREwMbkj1iGuTa5lHa79DCTIroGJjCpzaqhwmxJ5sm9XFNcLe08zb+cRZSbPqZ +8zGahUA4TtUM8x2hsnzkXKaVraLrYTcPMZFU8NATH5Prp5mkFQaCCGPbwY+jvNEkHdL WpmQgG/zVU7n/NplU3/N6m+bLjozhFSeRxBOh5OMOO05hT/Tf/T438pBv0NWeMgTPtHM mhXC62DFNHEs4Uc+BgpW+vZOL6rnQmxNYHf3wx8i4jEFg6XpHYD/Qa2DscTnWPsJyHpJ VuzQ== X-Gm-Message-State: AOJu0YzfmgQxGIqdt01a8vRXmkWNUu9fpROjN+m75vAYcebQAcndKQT1 KZhCkz9AcGvsEbzmpkJcjFRyTJ0oVGOPD5oGbxu4FOtRCKH2WQuaz7ggFb4hxuIQM8w39fuk8qo ea0Wsvd4ulNO+ciejz5QiYdEovp9edT4= X-Gm-Gg: ASbGnctMwKCwZqtVKWGiHzm70awRNHk9Z31ErtZVwwMPDjwTf2PzbbcdVBeunXFB5JR AaeowByDeNu7Nc8DZ6wf9sl8DLRmEeREsjiIL+jrnmh5oq+wHKJ6+11jbQ/tu2hybwLE2jE8ibf +IKTsdN8X1Fn0TtGmiR5wD4GkeihmoPyYh0odiJCLUFj3sr69MFbjONZk0sgno9w9W6NATuj4HK AXxF3Jlq3/CHK/CHA0DBf2UHu0aFQ2CNpaClHzBRd7/09Zp74n97k89I1K0lq3UDHKb8AIo79mB gsQ7r14zPVvmxImO4A== X-Google-Smtp-Source: AGHT+IEU11nRcjtruaiJwUMkmp3vERIUobJfA3c4ybMCnYQUPL8lqDPBM1cm56hiEn5HAbD80Dn1UvEMuauYne8Y1iE= X-Received: by 2002:a05:690c:6282:b0:784:ad94:ac62 with SMTP id 00721157ae682-7862900dfbbmr43849857b3.11.1761831199441; Thu, 30 Oct 2025 06:33:19 -0700 (PDT) Precedence: list list-help: list-unsubscribe: list-post: List-Id: x-ms-reactions: disallow MIME-Version: 1.0 References: In-Reply-To: Date: Thu, 30 Oct 2025 10:32:43 -0300 X-Gm-Features: AWmQ_bnmgrPonUjczuH1HPzRjDaJfUxye29IjDWOvhyVZ1Z0AcGEmUeSJPwYmU8 Message-ID: Subject: Re: [PHP-DEV] PHP True Async RFC Stage 5 To: Edmond Dantes Cc: php internals Content-Type: multipart/alternative; boundary="000000000000cc09d60642604a1e" From: deleugyn@gmail.com (Deleu) --000000000000cc09d60642604a1e Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Hi Edmond! On Thu, Oct 30, 2025 at 5:22=E2=80=AFAM Edmond Dantes = wrote: > Hi > > 1.5 RFC: > https://wiki.php.net/rfc/true_async > > Here=E2=80=99s the fifth version of the RFC with the updates made after t= he > 1.4 discussion. > > Starting from 2025-11-03, there will be a two-week discussion period. > > **Changelog:** > > * Added FutureLike interface methods: cancel(), isCompleted(), > isCancelled() > * Renamed Coroutine::isFinished() to Coroutine::isCompleted() > * Clarified exit/die behavior: always triggers Graceful Shutdown mode > regardless of where called > * Added rationale for =E2=80=9CCancellable by design=E2=80=9D policy: exp= lains why > default cancellability reduces code complexity for read-heavy PHP > workloads > * RFC structure improvements: reorganized Cancellation section with > proper subsections hierarchy > * Moved =E2=80=9CCoroutine lifetime=E2=80=9D as subsection under Coroutin= e section > * Extended glossary with Awaitable, Suspension, Graceful Shutdown, and > Deadlock terms > * Introduced FutureLike interface with single-assignment semantics and > changed await() signature to accept FutureLike instead of Awaitable > for type safety > * Split RFC: Moved Scope and structured concurrency functionality to > separate Scope RFC. Base RFC now focuses on core async primitives > (coroutines, await, cancellation) > > I decided not to wait until Monday and made the changes today. If > anyone has read version 1.4 and has comments on it, they=E2=80=99re still > relevant. > > The Scope API has been moved to a separate RFC: > https://wiki.php.net/rfc/true_async_scope > > ---- > Best Regards, Ed > Thanks for the RFC update! I've been trying to read and understand this RFC since its earlier versions and I can definitely feel it getting easier to digest, which I can only assume it's a good thing for RFC voters - it's easier to vote No because something is too complex / too hard to understand= . One minor question: is this section https://wiki.php.net/rfc/true_async#awaiting_a_result_with_cancellation named wrongly? I'm not sure how this snippet of code relates to cancellation. Onto more important things. In regards to the change of Awaitable vs FutureLike, my understanding of the discussion is that on the implementation side it was asked about whether an Awaitable object should be awaited in a loop (consumed until completion) or if it should be awaited only once, which also raised the question about idempotency and whether an object is awaitable more than once. While the change makes the type-system somewhat more explicit in regards to how await() is meant for a single-shot Awaitable object (named FutureLike), it does mean the implementation of things like awaitAll(Awaitable[] $awaitables) is no longer a simple loop to await every item in the array. My questions are: - What's the difference between Multishot Awaitables and Generators? - If await() is hardened to FutureLike only, doesn't this mean that multishot awaitables are not really capable of being awaited anymore? Doesn't this mean that the Awaitable interface becomes out-of-sync with the await() function and it stops making sense? - Shouldn't FutureLike be Awaitable and what has been described as Multishot awaitables should actually be generators / array of / list of Awaitables? In regards to Cancellable by Design. In the current state of PHP, we can assume that if a function used to throw an Exception and a future version stops throwing said exception it is not considered a BC Break. Of course, throwing a *different exception* not part of the hierarchy is a BC break. But when an exception signals "I cannot handle this" and a future version becomes capable of handling it, that in essence is a feature/enhancement and not treated as a BC break. With "Cancellation by Design" we are expected that every coroutine be cancellable and that we must write try / catch to design for cancellation. This seems to open up a different development flow where catch blocks can be fundamentally part of the BC promise. One possible alternative would be e.g. await(Awaitable $awaitable, Closure $cancellation) where the cancellation of a coroutine would trigger the specified Closure. Now, I don't want to dive too much into the trade-offs of these options, what I want is to spark the idea that there may be multiple ways to design cancellable coroutines. When I consider that, plus the added fact that the RFC is very dense, extensive and hard to digest, wouldn't it be best to postpone coroutine cancellations altogether? The RFC itself states: > [...] read operations (database queries, API calls, file reads) are typically as frequent as=E2=80=94or even more frequent than=E2=80=94write o= perations. Since read operations generally don't modify state, they're inherently safe to cancel without risking data corruption. which not only I agree with, but also want us to focus on this very fact. What if the first version of Async PHP provides userland with the ability to trigger coroutines for reading purposes only? We will not forbid/prevent anybody from shooting themselves if they want to, but we can still clearly state the design principle that Async PHP is meant to spawn coroutines cancellable by design. There will not be any coroutine markers in the future nor there will be assumptions that coroutines written for the 1st version of Async PHP must not be cancellable. The assumption is that the first version of Async PHP should be treated as a way to perform read operations only and a future RFC / enhancement will bring cancellation capabilities (be it Closure, Try / Catch, what have you). My reasoning is that this would further reduce the scope of the RFC while still introducing real life useful async components to PHP, even if at a limited capacity. It gives voters less concepts to understand, digest, agree on and approve and it extends the opportunity to focus on specific deep aspects of Async PHP in chunks and throughout different stages. --=20 Marco Deleu --000000000000cc09d60642604a1e Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Hi Edmond!

On Thu, O= ct 30, 2025 at 5:22=E2=80=AFAM Edmond Dantes <edmond.ht@gmail.com> wrote:
Hi

1.5 RFC:
https://wiki.php.net/rfc/true_async

Here=E2=80=99s the fifth version of the RFC with the updates made after the=
1.4 discussion.

Starting from 2025-11-03, there will be a two-week discussion period.

**Changelog:**

* Added FutureLike interface methods: cancel(), isCompleted(), isCancelled(= )
* Renamed Coroutine::isFinished() to Coroutine::isCompleted()
* Clarified exit/die behavior: always triggers Graceful Shutdown mode
regardless of where called
* Added rationale for =E2=80=9CCancellable by design=E2=80=9D policy: expla= ins why
default cancellability reduces code complexity for read-heavy PHP
workloads
* RFC structure improvements: reorganized Cancellation section with
proper subsections hierarchy
* Moved =E2=80=9CCoroutine lifetime=E2=80=9D as subsection under Coroutine = section
* Extended glossary with Awaitable, Suspension, Graceful Shutdown, and
Deadlock terms
* Introduced FutureLike interface with single-assignment semantics and
changed await() signature to accept FutureLike instead of Awaitable
for type safety
* Split RFC: Moved Scope and structured concurrency functionality to
separate Scope RFC. Base RFC now focuses on core async primitives
(coroutines, await, cancellation)

I decided not to wait until Monday and made the changes today. If
anyone has read version 1.4 and has comments on it, they=E2=80=99re still relevant.

The Scope API has been moved to a separate RFC:
https://wiki.php.net/rfc/true_async_scope

----
Best Regards, Ed

Thanks for the RFC upd= ate! I've been trying to read and understand this RFC since its earlier= versions and I can definitely feel it getting easier to digest, which I ca= n only assume it's a good thing for RFC voters - it's easier to vot= e No because something is too complex / too hard to understand.
<= br>
One minor question: is this section=C2=A0https://wik= i.php.net/rfc/true_async#awaiting_a_result_with_cancellation named wron= gly?=C2=A0I'm not sure how this snippet of code relates to cancellation= .

Onto more important things. In regards to the ch= ange of Awaitable vs FutureLike, my understanding of the discussion is that= on the implementation side it was asked about whether an Awaitable object = should be awaited in a loop (consumed until completion) or if it should be = awaited only once, which also raised the question about idempotency and whe= ther an object is awaitable more than once. While the change makes the type= -system somewhat more explicit in regards to how await() is meant for a sin= gle-shot Awaitable object (named FutureLike), it does mean the implementati= on of things like awaitAll(Awaitable[] $awaitables) is no longer a simple l= oop to await every item in the array.

My questions= are:=C2=A0
- What's the difference between Multishot Awaitab= les and Generators?
- If await() is hardened to FutureLike only, = doesn't this mean that multishot awaitables are not really capable of b= eing awaited anymore? Doesn't this mean that the Awaitable interface be= comes out-of-sync with the await() function and it stops making sense?
- Shouldn't FutureLike be Awaitable and what has been described a= s Multishot awaitables should actually be generators / array of / list of A= waitables?

In regards to Cancellable by Design. In= the current state of PHP, we can assume that if a function used to throw a= n Exception and a future version stops throwing said exception it is not co= nsidered a BC Break. Of course, throwing a different exception=C2=A0= not part of the hierarchy is a BC break. But when an exception signals &quo= t;I cannot handle this" and a future version becomes capable of handli= ng it, that in essence is a feature/enhancement and not treated as a BC bre= ak. With "Cancellation by Design" we are expected that every coro= utine be cancellable and that we must write try / catch to design for cance= llation. This seems to open up a different development flow where catch blo= cks can be fundamentally part of the BC promise. One possible alternative w= ould be e.g. await(Awaitable $awaitable, Closure $cancellation) where the c= ancellation of a coroutine would trigger the specified Closure. Now, I don&= #39;t want to dive too much into the trade-offs of these options, what I wa= nt is to spark the idea that there may be multiple ways to design cancellab= le coroutines. When I consider that, plus the added fact that the RFC is ve= ry dense, extensive and hard to digest, wouldn't it be best to postpone= coroutine cancellations altogether? The RFC itself states:

>=C2= =A0=C2=A0[= ...]=C2=A0read operations (database queries, API calls, file reads) = are typically as frequent as=E2=80=94or even more frequent than=E2=80=94wri= te operations. Since read operations generally don't modify state, they= 're inherently safe to cancel without risking data corruption.

which not only I agree with, but also want us to focus on = this very fact. What if the first version of Async PHP provides userland wi= th the ability to trigger coroutines for reading purposes only? We will not= forbid/prevent anybody from shooting themselves if they want to, but we ca= n still clearly state the design principle that Async PHP is meant to spawn= coroutines cancellable by design. There will not be any coroutine markers = in the future nor there will be assumptions that coroutines written for the= 1st version of Async PHP must not be cancellable. The assumption is that t= he first version of Async PHP should be treated as a way to perform read op= erations only and a future RFC / enhancement will bring cancellation capabi= lities (be it Closure, Try / Catch, what have you). My reasoning is that th= is would further reduce the scope of the RFC while still introducing real l= ife useful async components to PHP, even if at a limited capacity. It gives= voters less concepts to understand, digest, agree on and approve and it ex= tends the opportunity to focus on specific deep aspects of Async PHP in chu= nks and throughout different stages.

--
Marco Deleu
--000000000000cc09d60642604a1e--