Hi,
> Any Fiber can be canceled at any time, and there is no need to use explicit Cancellation, which
> I personally find an inconvenient pattern.
>
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.
A nicer API should use only explicit cancellation objects, as this pattern of preemptive implicit
cancellations (i.e. a fiber may be cancelled at any point via cancel()) is super dangerous IMO, as
it can lead to all sorts of nasty behaviour: what if we cancel execution of a fiber in the middle of
a critical section (i.e. between a lock() and an unlock() of a file or a database? What if
unlocking() in the catch (CancelledException) block requires spawning a new fiber as part of the
interaction with the database?).
Consider also the huge amount of CancelledException blocks that would have to be added to handle
state cleanup in case of premature implicit cancellations, as opposed to explicit cancellations that
only throw when we ask them to: there’s a reason why golang, amphp & others use explicit
cancellations.
Another thing I’m not happy with is how unless the scheduler is launched, all code executes in
blocking mode: this seems like a super bad idea, as it will hold back the ecosystem again, and
create a split in the project similar to JIT (i.e. a separate “execution mode” with its own
bugs, that get fixed slowly because few people are using it, and few people are using it because of
its bugs).
The main reason given in the RFC (Code written without using the Scheduler should not experience any
side effects) makes no sense, because legacy code not spawning fibers will not experience
concurrency side effects anyway, regardless of whether the scheduler is started or not.
A thing I would love to see, on the other hand, is for Context to become a “provider” for
superglobals such as $_REQUEST, $_POST, $_GET, and all globals in general (and perhaps all other
global state such as static properties): this would 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.
Regards,
Daniil Gentili - Senior software engineer
Portfolio: https://daniil.it <https://daniil.it/>
Telegram: https://t.me/danogentili