Событийный цикл и таймеры

Каждый worker обслуживает сокеты и таймеры через реализацию EventInterface. Выбор backend-а выполняет EventLoopFactory; имена и требования перечислены в матрице совместимости.

На Unix автоматический выбор: event, затем ev, затем Revolt, иначе встроенный Select. На Windows используется Windows. Swoole и Swow выбираются только явно, чтобы автоматический режим не менял глобальную семантику I/O приложения. Посмотреть доступность можно так:

php server.php capabilities --json
use localzet\Server\Events\EventLoopFactory;

$loop = EventLoopFactory::create('revolt'); // бросает RuntimeException, если backend недоступен

Таймеры

localzet\Timer — фасад таймеров текущего процесса. repeat() повторяет callback, delay() вызывает его один раз, del() отменяет таймер.

use localzet\Timer;

$timerId = Timer::repeat(5.0, static function (): void {
    // Короткая неблокирующая работа.
});

Timer::delay(30.0, static function (): void {
    // Одноразовый callback.
});

Timer::del($timerId);

Интервалы задаются в секундах. Не рассчитывайте на realtime-гарантию срока: callback выполняется в event loop и может задержаться, пока worker занят синхронной операцией.

Timer::sleep() не всегда асинхронный: он приостанавливает текущую Fiber/coroutine только для backend-а с SuspensionCapableInterface (например, Revolt). На обычном backend-е он использует блокирующий usleep(). Не вызывайте его без понимания выбранного backend-а внутри обработчика соединения.

Очищайте периодические таймеры при завершении принадлежащей им задачи. Таймеры и PHP-память не общие между worker-процессами.