> On 3 Mar 2025, at 13:05, Edmond Dantes <[email protected]> wrote:
>
>> As a heavy use of both amphp and go, cancellations (contexts in go) are absolutely needed,
>> as a fiber may spawn further background fibers in order to execute some operation, just cancelling
>> that specific fiber will not cancel the spawned fibers, unless a bunch of boilerplate try-catch
>> blocks are added to propagate CancellationExceptions.
>
> I didn't mean that Cancellation isn't needed at all. I meant that canceling a Fiber
> is sufficient in most scenarios and leads to clean, understandable code.
>
> Other languages have child coroutines (Swoole supports them too), but I'm not sure if
> that's the right approach.
>
> I like context.WithCancel from Go, but it can essentially be implemented directly in PHP land
> since all the necessary tools are available.
>
Note, this is precisely the problem, implement cancellation propagation to child fibers in userland
PHP requires writing a bunch of boilerplate try-catch blocks to propagate CancellationExceptions to
child FutureHandle::cancel()s (spawning multiple fibers to execute subtasks concurrently during an
async method call is pretty common, and the current implicit cancellation mode requires writing a
bunch of try-catch blocks to propagate cancellation, instead of just passing a cancellation object,
or a flag to inherit the cancellation of the current fiber when spawning a new one).
>> A nicer API should use only explicit cancellation objects, as this pattern of preemptive
>> implicit cancellations
>
> The exception mechanism is the standard way to alter the execution flow in PHP. If a programmer
> writes code with lock and unlock outside of a try-finally block but calls functions between these
> methods, they are potentially creating a bad solution—at the very least because someone else might
> later introduce an exception in one of those functions. This is a classic case for languages with
> exceptions.
>
Note the explicit use case I listed is that of an unlock() in a finally block that *requires
spawning a new fiber* in order to execute the actual unlock() RPC call: this is explicitly in
contrast with the RFC, which specifies that
>ATTENTION: A programmer must never attempt to create a new fiber while handling a
>CancellationException, as this behavior may trigger an exception during Graceful Shutdown mode.
While this is *somewhat* understandable in the context of graceful shutdown, it still means that
unlocking in a finally block (the only way of properly handling cancellations with the current
model) isn’t always possible..
> So far, I haven't found a better way to ensure the logical consistency and integrity of
> the execution flow. Maybe someone has a suggestion?
>
>> The main reason given in the RFC
>
> The main reason is that PHP has been around for many years and didn’t just appear yesterday.
>
> If you have an idea on how to start the Scheduler implicitly, let's implement it. So far,
> I have a few ideas:
>
> Using an option in php.ini (downside: if PHP is used for multiple projects).
> Using a CLI option – so far, I like this the most.
I would really prefer it to be always enabled, no fallback at all, because as I said, it will make
absolutely no difference to legacy, non-async projects that do not use fibers, but it will avoid a
split ecosystem scenario.
>> A thing I would love to see, on the other hand, is for Context to become a
>> “provider”
>
> It's hard for me to evaluate this idea. Intuitively, it doesn't seem ideal. In
> general, I'm not very fond of $_GET/$_POST. But on the other hand, why not? This needs some
> consideration.
>
>> allow to very easily to turn i.e. php-fpm into a fully asynchronous application server,
>> where each request is started in the same thread (or in N threads in an M-N M>N
>> execution model) but its global state is entirely isolated between fibers.
> I haven’t thought about this possibility. But wouldn’t this break the FCGI contract?
I see no reason why it should break the contract, if implemented by isolating the global state of
each fiber, it can be treated as a mere implementation detail of the (eventually new) SAPI.
Regards,
Daniil Gentili
—
Daniil Gentili - Senior software engineer
Portfolio: https://daniil.it
<https://daniil.it/>Telegram: https://t.me/danogentili