> On 3 Mar 2025, at 13:05, Edmond Dantes <edmond...@gmail.com> 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

Reply via email to