OpenSwoole Runtime Hook Flags

Latest version: pecl install openswoole-22.1.2 | composer require openswoole/core:22.1.5

What are coroutine hooks?

Runtime Hooks allow OpenSwoole to listen for internal PHP API calls, take control and execute your code in a non-blocking way, allowing us to use well known and tested libraries like the PDO extension or the CURL library. The benefit of using hooks is it allows us to use existing PHP ecosystem tools and libraries and not force us to use any coroutine specific clients, instead OpenSwoole aims to support the existing ecosystem. Even native blocking PHP functions like sleep or file_get_contents are supported, so it is easy to adopt coroutines throughout your application without much alteration to your existing codebase.

When hooks are enabled, OpenSwoole will take care of the coroutine scheduling for you under the hood, you don't need to write any additional logic with runtime hooks once they are setup and enabled. Hooks are required to run inside a coroutine context, this means you must use enabled hook functionality within a Co::run or inside a OpenSwoole Server request where the coroutine context is created for you for each request.

Coroutine hooks were first supported since OpenSwoole v4.1.0


Coroutine Hooks vs. Coroutine Clients

Before coroutine hooks, the alternative was to write a client for each use case, this included MySQL, Redis and even file operations etc. There would have to be a new client in order to support coroutines and make sure all IO operations are asynchronous. This task of managing multiple clients was a huge workload and it meant that a lot of duplicated API had to be done, so this became complex and even harder to scale when those clients needed updates or API changes. Coroutine clients were not native, they sat in front of native clients like PHP PDO or phpredis, meaning developers had to use an additional client.

The solution to all this complexity and confusion with additional coroutine specific clients is coroutine hooks. By enabling OpenSwoole runtime hooks, we can forget about using additional clients and use our existing PHP ecosystem libraries and extensions, while still having full support for coroutines and improved functionality support, adding hooks which work at the low level, meant that OpenSwoole could provider better support for coroutines in libraries like phpredis and CURL. Developers only have to understand what hooks do and how to set them up, then they can continue developing as they would have done, rather than using an additional coroutine client.

Since the breakthrough with coroutine hooks, the old OpenSwoole coroutine clients are no longer recommended and it is suggested that you migrate to use coroutine hooks if you are still using the old coroutine client API objects.


Supported Libraries

Since OpenSwoole v4.1.0, you can use any IO libraries based on php_stream within a coroutine context.

Libraries with coroutine support:

  • Redis (phpredis) or (predis)
  • MySQL (mysqlnd) PDO and MySQLi
  • PHP SOAP
  • file_get_contents, fopen and many more file I/O operations
  • stream_socket_client functions
  • fsockopen
  • CURL with libcurl

Libraries without coroutine support:

  • MySQL with libmysqlclient
  • MongoDB with mongo-c-client
  • pdo_pgsql, pdo_ori, pdo_odbc, pdo_firebird, php-amqp

OpenSwoole Runtime Hook Flags

You can enable coroutine support with hook Flags:


Enabling and using OpenSwoole Runtime Hooks

<?php
OpenSwoole\Runtime::enableCoroutine(bool $enable = true, int $flags = OpenSwoole\Runtime::HOOK_ALL);

// Or

Co::set(['hook_flags'=> OpenSwoole\Runtime::HOOK_ALL]);

The code above will enable coroutine support for all OpenSwoole Hooks, you can change which hooks you want to enable but it is likely better for performance to enable them all and take advantage of coroutines.

The enableCoroutine call should be placed at the start of your script or at least before any Co::run or server is used, this so that you can obtain 100% coverage. When calling enableCoroutine it will take effect globally for the current process.

To enable multiple flags you must separate them using the pipe | symbol:

<?php
Co::set(['hook_flags'=> OpenSwoole\Runtime::HOOK_TCP | OpenSwoole\Runtime::HOOK_SLEEP]);

Remember that enabling any hooks means you have to perform any operations inside a coroutine container for coroutine support


Set Coroutine Runtime flags

<?php

// Before v4.5.4
OpenSwoole\Runtime::enableCoroutine(true, OpenSwoole\Runtime::HOOK_ALL | OpenSwoole\Runtime::HOOK_CURL);

OpenSwoole\Runtime::HOOK_ALL contains OpenSwoole\Runtime::HOOK_CURL from version v4.5.4

<?php

// All flags but not the sleep flag
OpenSwoole\Runtime::enableCoroutine(true, OpenSwoole\Runtime::HOOK_ALL ^ OpenSwoole\Runtime::HOOK_SLEEP);

Set Coroutine Scheduler Flags

The coroutine scheduler is what OpenSwoole uses at a low level to manage different coroutine context containers and switch between other coroutines when one is waiting or blocking. Read more about the coroutine scheduler API to understand when it should be used. Most of the time you will never need to use it directly because OpenSwoole does it for you already.

<?php

$sch = new OpenSwoole\Coroutine\Scheduler();
$sch->set(['hook_flags' => OpenSwoole\Runtime::HOOK_ALL]);

Dynamic Coroutine Flags

If you are inside a coroutine context or a OpenSwoole server, you can change hooks dynamically once they have been enabled:

<?php

// Enable all OpenSwoole hooks at the beginning
OpenSwoole\Runtime::enableCoroutine(true, OpenSwoole\Runtime::HOOK_ALL);

// Only use the TCP hook from now on...
OpenSwoole\Runtime::enableCoroutine(true, OpenSwoole\Runtime::HOOK_TCP);

Hooks can be changed throughout the application, just take note that once any hooks are changed this will take affect globally for the current process, make sure other operations are not ongoing as this may affect them, removing or adding hooks. It is more recommended to enable hooks at the start of a PHP script so you get full coverage.


Get the OpenSwoole Coroutine Runtime flags

<?php

OpenSwoole\Runtime::getHookFlags();

Returns the currently set hook flags.


Set the OpenSwoole Coroutine Runtime flags

<?php

// Enable all hooks
OpenSwoole\Runtime::setHookFlags(OpenSwoole\Runtime::HOOK_ALL);

// Disable all hooks
OpenSwoole\Runtime::setHookFlags(0);

Disable all coroutine hooks

<?php

OpenSwoole\Runtime::enableCoroutine(false);
Last updated on August 31, 2022