phasync
Blocking calls and the extension / MySQLiAwaiter

Class

MySQLiAwaiter

Waits for a mysqli asynchronous query without blocking other coroutines.

Introduction#

Start the query with MYSQLI_ASYNC, then MySQLiAwaiter::await($mysqli) suspends the calling coroutine until the result is ready, which the caller takes with reap_async_query(). Use it where the phasync extension is not loaded, or to be independent of it; with the extension, an ordinary blocking query waits the same way and this class is not needed.

One coroutine may await a connection at a time, because mysqli keeps one result per connection: a second waiter gets a LogicException rather than the first one's result. Connections are pooled one coroutine at a time by Pool, which is how a query that failed should be handed back.

mysqli offers no sockets for the loop to wait on, so a service coroutine - one for the process, not one per connection - asks mysqli::poll() with a zero timeout, never holding up the process: again at once while queries are landing, backing off from 0.5 ms to 10 ms while they are not. A finished query is therefore waited for no longer than that delay, and one that lands in a busy moment is noticed on the spot.

Must be called from a coroutine: unlike CurlAwaiter::await, which starts one when it has to, there is nothing to start a query with here.

When the wait is cut short - TimeoutException, or the coroutine being cancelled - the query is still in flight on the connection, and mysqli takes no second query before the first result is reaped. This is left as mysqli put it rather than discarded, so the caller may still wait that result out and reap it; otherwise the connection is spent, and should be closed or given to Pool::discard. Reaping it is enough to use the connection again.

Class synopsis#

final class MySQLiAwaiter {
    /* Methods */
    public static MySQLiAwaiter::await(mysqli $connection, ?float $timeout = null): mysqli
}

Methods#

MethodDescription
awaitSuspends the calling coroutine until the connection's asynchronous query has finished.

Examples#

Example 1
phasync::run(function () use ($mysqli) {
    $mysqli->query('SELECT SLEEP(1)', MYSQLI_ASYNC);
    MySQLiAwaiter::await($mysqli);
    $result = $mysqli->reap_async_query();
});

See also#

  • phasync::goStart the coroutines that query side by side