Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:129420 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 31E091A00BC for ; Sun, 23 Nov 2025 21:53:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1763934813; bh=d+WmPvRPS88MdpZgHPSy9sWYD9Q4FxS3K5BeymVnjX0=; h=Date:Subject:To:References:From:In-Reply-To:From; b=KB9EK8WSVxosR7WZjawc6PAqQTxKRRjeXcuJZXh4hLdx2TCOzZIrzTJzOZZXgdZlX zGH/GL0oyshHcM4oe7tKzIceIhS//cFzBN5pKQYkwRHmZUPfIrTf8Rxqccj0Uu2H5I mqJKb+2M20FrS0E+dZ6p+0Uykpnd3K7nL0xQdkm/QJL1r3iOW4b5cHvaz0ZxkGtuYF n1qiUMKH2Ckspz62z2wXy0aLA/N8U6SD8sbSvdEvLgDEO6KT8tBH/x/b6gChSFJkr8 mO56q3nZerQ5z4ku/ROmqwXeDnll71Hkry+tRvHMsP/HPCwZ0QQOEuxmh8qckOousF iaCx8/Nt76FdA== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id B45051801E8 for ; Sun, 23 Nov 2025 21:53:30 +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.1 required=5.0 tests=BAYES_50,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_MISSING,HTML_MESSAGE, RCVD_IN_DNSWL_LOW,SPF_HELO_PASS,SPF_PASS autolearn=no autolearn_force=no version=4.0.1 X-Spam-Virus: No X-Envelope-From: Received: from fout-b8-smtp.messagingengine.com (fout-b8-smtp.messagingengine.com [202.12.124.151]) (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 ; Sun, 23 Nov 2025 21:53:29 +0000 (UTC) Received: from phl-compute-01.internal (phl-compute-01.internal [10.202.2.41]) by mailfout.stl.internal (Postfix) with ESMTP id CBC011D0003F for ; Sun, 23 Nov 2025 16:53:23 -0500 (EST) Received: from phl-mailfrontend-01 ([10.202.2.162]) by phl-compute-01.internal (MEProxy); Sun, 23 Nov 2025 16:53:23 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=rwec.co.uk; h=cc :content-type:content-type:date:date:from:from:in-reply-to :in-reply-to:message-id:mime-version:references:reply-to:subject :subject:to:to; s=fm3; t=1763934803; x=1764021203; bh=gybwCLdSuY RSOtTIs1jLVYO2hkYUb6B6wnm4yI7Eis0=; b=lljG+KDI5CVwlk9dFHeNQK4Vgg +0J3pAoXwyVdk0pANdcOHL/Z7vUF7OTPREFuVwe/+hu3VXzjftuMrzWS70mEqcC2 /evN6k3OhIhk4MvAe6q2be2isG1lB2FkBtebXjJtgcfd5ttg5Ii3SsioWzohycz6 ZzCrhA1YQgywZpNJwe2d4lriZMyf9JOVqZzWfhSrRNtEl+suZJGx1jgz4Jf31JFj 6R9pXCjQQSXv4wha5cjRPpxLTzDPRKq8NP9wwySzR8ajOBK6cdmEgh7avIIY/G7C D5F6xw0af5rbsD16arALfwPd1p61MexSi/kp30f/n+mmpplEUrRS5AB7VPhw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-type:content-type:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:subject:subject:to :to:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm3; t= 1763934803; x=1764021203; bh=gybwCLdSuYRSOtTIs1jLVYO2hkYUb6B6wnm 4yI7Eis0=; b=REYEekIQywhPb7RcPMztyyAwIYc8bFReTFjvV9wNgEgTlXo/qKK e6ZYwdD6xS5ySQ+3A/S6aMoQJuKigr0Si2tCiVWq7Skc3XX6SPEOlm9pmB+wwx0c /zI/xUmlZLt7C0f6pDIxIT3uRVerpAqvtto1TGcdtMROZ7jhtBuvZSuBs6hnGAuk XK+aazYNU9QK68CAmWj0gquOeT2Nis8k5ZvDuP1JkLrZEe3X2tr68Lwsm2UaO23a SUZuUinGUC1cs9RlZKRfs1umEnumW8ehRCdMhYuUWLHxFJ8PzneWtHHWNOWcep2N qTmMs9AnQ8v6JYM9ag51SX+JuVHC6YBV3Eg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeffedrtdeggddvfeeikeehucetufdoteggodetrf dotffvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfurfetoffkrfgpnffqhgenuceu rghilhhouhhtmecufedttdenucenucfjughrpegtkfffgggfuffvfhfhjgesrgdtreertd dvjeenucfhrhhomhepfdftohifrghnucfvohhmmhhinhhsucglkffoufhorfgnfdcuoehi mhhsohhprdhphhhpsehrfigvtgdrtghordhukheqnecuggftrfgrthhtvghrnhepheetle eiiefgueduieeuieffvdevheduueefkeejuefgffeftdeitdegtedtleetnecuvehluhhs thgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrhhomhepihhmshhophdrphhhph esrhifvggtrdgtohdruhhkpdhnsggprhgtphhtthhopedupdhmohguvgepshhmthhpohhu thdprhgtphhtthhopehinhhtvghrnhgrlhhssehlihhsthhsrdhphhhprdhnvght X-ME-Proxy: Feedback-ID: id5114917:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA for ; Sun, 23 Nov 2025 16:53:22 -0500 (EST) Content-Type: multipart/alternative; boundary="------------Tz04QU8VlHCjMB26NU7JyKXk" Message-ID: <9287c46c-bc63-4dd0-9792-0f9421959589@rwec.co.uk> Date: Sun, 23 Nov 2025 21:53:21 +0000 Precedence: list list-help: list-unsubscribe: list-post: List-Id: x-ms-reactions: disallow MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PHP-DEV] [VOTE] True Async RFC 1.6 To: internals@lists.php.net References: <691963327.399484.1763796022993@email.ionos.de> <1402906904.784903.1763811759896@email.ionos.de> <2015208655.784984.1763811978476@email.ionos.de> <980296152.1071.1763813573083@email.ionos.de> <92865666.4510.1763818506332@email.ionos.de> <329450798.8037.1763822426377@email.ionos.de> Content-Language: en-GB In-Reply-To: From: imsop.php@rwec.co.uk ("Rowan Tommins [IMSoP]") This is a multi-part message in MIME format. --------------Tz04QU8VlHCjMB26NU7JyKXk Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit On 23/11/2025 19:09, Edmond Dantes wrote: >> @Ed Unless something calls `spawn` all I/O is going to be blocking & >> non-concurrent, correct? > Yes. > If no one calls spawn, this is equivalent to the code running inside a > single coroutine. > > At the moment, TrueAsync has an internal flag that allows it to be > enabled or disabled. If Async is disabled, an exception will be > thrown. I think there's a lot of confusion in this thread because different people are talking about different scenarios. Perhaps it would be useful to introduce some User Stories... Async Alice is working on a brand new application written in PHP 9, and is designing it from the ground up to make use of async capabilities wherever possible. She wants third-party libraries to use async I/O so that she can use them in her design. Beginner Bob has a recently built application, and thinks there's an opportunity to improve it with async I/O, but doesn't know anything about it. He wants a simple-to-use API that lets him get the benefits, and clear instructions on what pitfalls to look out for. Legacy Les is maintaining a 20-year-old business back office system, which makes extensive use of global state and does not have good automated testing. He wants to run it under PHP 9, and to use up-to-date third-party libraries for new functionality, without an expensive and risky rewrite of existing code. Finally, SDK Susie is publishing the official PHP library for a popular cloud API. She wants to serve the best version she can for Alice, Bob, and Les, but doesn't want to maintain separate "sync" and "async" branches of the library or its methods. Feel free to create more personas if you want to talk about additional scenarios. The first thing I want to clarify is that SDK Susie doesn't necessarily need to change the public methods of her library; she can still use async I/O internally. For instance, if a method already returns an Iterator to silently fetch a page of results at a time, that can be changed to store Promises internally, and await them when the data is needed. However, she might want to mark it as a breaking change anyway, so that Async Alice and Beginner Bob know they are opting into it. Legacy Les won't get it until he opts in, but at some point he will need a new version of the library for other reasons (e.g. because the cloud API becomes incompatible with the old library version); so he still needs a way to run it safely. If he runs PHP in a mode where any attempt to use async I/O *throws an error*, he still can't use the new version of the library, so this doesn't help him. However, if Legacy Les can run PHP in a mode where any attempt to use async I/O is *automatically run synchronously*, then he will be happy: he can run his legacy application under PHP 9, and use the updated library, without worrying about async code. Beginner Bob doesn't want to run his whole application in "sync only" mode, but might want to switch *parts of it*, so that he doesn't have to think about them yet. So a scoped, rather than global, switch might be useful for him. This is how I picture that mode working: when SDK Susie's library code calls "spawn", a Coroutine is created as normal. However, when it suspends, the Scheduler immediately resumes it, rather than switching to a different Coroutine. The library code will see the Coroutine object it expects, but passing it to "await" will immediately produce its result. However, I might well be misunderstanding something, and this is either impossible or difficult to implement. If so, I think some other solution to Legacy Les's requirements is needed. I hope this description is useful. -- Rowan Tommins [IMSoP] --------------Tz04QU8VlHCjMB26NU7JyKXk Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: 8bit
On 23/11/2025 19:09, Edmond Dantes wrote:
@Ed Unless something calls `spawn` all I/O is going to be blocking &
non-concurrent, correct?
Yes.
If no one calls spawn, this is equivalent to the code running inside a
single coroutine.

At the moment, TrueAsync has an internal flag that allows it to be
enabled or disabled. If Async is disabled, an exception will be
thrown.


I think there's a lot of confusion in this thread because different people are talking about different scenarios. Perhaps it would be useful to introduce some User Stories...


Async Alice is working on a brand new application written in PHP 9, and is designing it from the ground up to make use of async capabilities wherever possible. She wants third-party libraries to use async I/O so that she can use them in her design.

Beginner Bob has a recently built application, and thinks there's an opportunity to improve it with async I/O, but doesn't know anything about it. He wants a simple-to-use API that lets him get the benefits, and clear instructions on what pitfalls to look out for.

Legacy Les is maintaining a 20-year-old business back office system, which makes extensive use of global state and does not have good automated testing. He wants to run it under PHP 9, and to use up-to-date third-party libraries for new functionality, without an expensive and risky rewrite of existing code.

Finally, SDK Susie is publishing the official PHP library for a popular cloud API. She wants to serve the best version she can for Alice, Bob, and Les, but doesn't want to maintain separate "sync" and "async" branches of the library or its methods.

Feel free to create more personas if you want to talk about additional scenarios.


The first thing I want to clarify is that SDK Susie doesn't necessarily need to change the public methods of her library; she can still use async I/O internally. For instance, if a method already returns an Iterator to silently fetch a page of results at a time, that can be changed to store Promises internally, and await them when the data is needed.

However, she might want to mark it as a breaking change anyway, so that Async Alice and Beginner Bob know they are opting into it.


Legacy Les won't get it until he opts in, but at some point he will need a new version of the library for other reasons (e.g. because the cloud API becomes incompatible with the old library version); so he still needs a way to run it safely.

If he runs PHP in a mode where any attempt to use async I/O *throws an error*, he still can't use the new version of the library, so this doesn't help him.


However, if Legacy Les can run PHP in a mode where any attempt to use async I/O is *automatically run synchronously*, then he will be happy: he can run his legacy application under PHP 9, and use the updated library, without worrying about async code.

Beginner Bob doesn't want to run his whole application in "sync only" mode, but might want to switch *parts of it*, so that he doesn't have to think about them yet. So a scoped, rather than global, switch might be useful for him.


This is how I picture that mode working: when SDK Susie's library code calls "spawn", a Coroutine is created as normal. However, when it suspends, the Scheduler immediately resumes it, rather than switching to a different Coroutine. The library code will see the Coroutine object it expects, but passing it to "await" will immediately produce its result.

However, I might well be misunderstanding something, and this is either impossible or difficult to implement. If so, I think some other solution to Legacy Les's requirements is needed.


I hope this description is useful.


-- 
Rowan Tommins
[IMSoP]
--------------Tz04QU8VlHCjMB26NU7JyKXk--