Open source PHP extension for Async IO, Coroutines and Fibers

Swoole Logo

lib-openswoole ext-openswoole test-linux Coverity Scan Build Status codecov

Swoole is an event-driven asynchronous & coroutine-based concurrency networking communication engine with high performance written in C++ for PHP.

Open Swoole since release version v4.7.1.

Event-based

The network layer in Swoole is event-based and takes full advantage of the underlying epoll/kqueue implementation, making it really easy to serve millions of requests.

Swoole 4.x uses a brand new engine kernel and now it has a full-time developer team, so we are entering an unprecedented period in PHP history which offers a unique possibility for rapid evolution in performance.

Coroutine

Swoole 4.x or later supports the built-in coroutine with high availability, and you can use fully synchronized code to implement asynchronous performance. PHP code without any additional keywords, the underlying automatic coroutine-scheduling.

Developers can understand coroutines as ultra-lightweight threads, and you can easily create thousands of coroutines in a single process.

MySQL

Concurrency 10K requests to read data from MySQL takes only 0.2s!

$s = microtime(true);
Co\run(function() {
    for ($c = 100; $c--;) {
        go(function () {
            $mysql = new Swoole\Coroutine\MySQL;
            $mysql->connect([
                'host' => '127.0.0.1',
                'user' => 'root',
                'password' => 'root',
                'database' => 'test'
            ]);
            $statement = $mysql->prepare('SELECT * FROM `user`');
            for ($n = 100; $n--;) {
                $result = $statement->execute();
                assert(count($result) > 0);
            }
        });
    }
});
echo 'use ' . (microtime(true) - $s) . ' s';

Mixed server

You can create multiple services on the single event loop: TCP, HTTP, Websocket and HTTP2, and easily handle thousands of requests.

function tcp_pack(string $data): string
{
    return pack('N', strlen($data)) . $data;
}
function tcp_unpack(string $data): string
{
    return substr($data, 4, unpack('N', substr($data, 0, 4))[1]);
}
$tcp_options = [
    'open_length_check' => true,
    'package_length_type' => 'N',
    'package_length_offset' => 0,
    'package_body_offset' => 4
];
$server = new Swoole\WebSocket\Server('127.0.0.1', 9501, SWOOLE_BASE);
$server->set(['open_http2_protocol' => true]);
// http && http2
$server->on('request', function (Swoole\Http\Request $request, Swoole\Http\Response $response) {
    $response->end('Hello ' . $request->rawcontent());
});
// websocket
$server->on('message', function (Swoole\WebSocket\Server $server, Swoole\WebSocket\Frame $frame) {
    $server->push($frame->fd, 'Hello ' . $frame->data);
});
// tcp
$tcp_server = $server->listen('127.0.0.1', 9502, SWOOLE_TCP);
$tcp_server->set($tcp_options);
$tcp_server->on('receive', function (Swoole\Server $server, int $fd, int $reactor_id, string $data) {
    $server->send($fd, tcp_pack('Hello ' . tcp_unpack($data)));
});
$server->start();

Coroutine clients

Whether you DNS query or send requests or receive responses, all of these are scheduled by coroutine automatically.

go(function () {
    // http
    $http_client = new Swoole\Coroutine\Http\Client('127.0.0.1', 9501);
    assert($http_client->post('/', 'Swoole Http'));
    var_dump($http_client->body);
    // websocket
    $http_client->upgrade('/');
    $http_client->push('Swoole Websocket');
    var_dump($http_client->recv()->data);
});
go(function () {
    // http2
    $http2_client = new Swoole\Coroutine\Http2\Client('localhost', 9501);
    $http2_client->connect();
    $http2_request = new Swoole\Http2\Request;
    $http2_request->method = 'POST';
    $http2_request->data = 'Swoole Http2';
    $http2_client->send($http2_request);
    $http2_response = $http2_client->recv();
    var_dump($http2_response->data);
});
go(function () use ($tcp_options) {
    // tcp
    $tcp_client = new Swoole\Coroutine\Client(SWOOLE_TCP);
    $tcp_client->set($tcp_options);
    $tcp_client->connect('127.0.0.1', 9502);
    $tcp_client->send(tcp_pack('Swoole Tcp'));
    var_dump(tcp_unpack($tcp_client->recv()));
});

Channel

Channel is the only way for exchanging data between coroutines, the development combination of the Coroutine + Channel is the famous CSP programming model.

In Swoole development, Channel is usually used for implementing connection pool or scheduling coroutine concurrent.

The simplest example of a connection pool

In the following example, we have a thousand concurrently requests to redis. Normally, this has exceeded the maximum number of Redis connections setting and will throw a connection exception, but the connection pool based on Channel can perfectly schedule requests. We don't have to worry about connection overload.

class RedisPool
{
    /**@var \Swoole\Coroutine\Channel */
    protected $pool;

    /**
     * RedisPool constructor.
     * @param int $size max connections
     */
    public function __construct(int $size = 100)
    {
        $this->pool = new \Swoole\Coroutine\Channel($size);
        for ($i = 0; $i < $size; $i++) {
            $redis = new \Swoole\Coroutine\Redis();
            $res = $redis->connect('127.0.0.1', 6379);
            if ($res == false) {
                throw new \RuntimeException("failed to connect redis server.");
            } else {
                $this->put($redis);
            }
        }
    }

    public function get(): \Swoole\Coroutine\Redis
    {
        return $this->pool->pop();
    }

    public function put(\Swoole\Coroutine\Redis $redis)
    {
        $this->pool->push($redis);
    }

    public function close(): void
    {
        $this->pool->close();
        $this->pool = null;
    }
}

go(function () {
    $pool = new RedisPool();
    // max concurrency num is more than max connections
    // but it's no problem, channel will help you with scheduling
    for ($c = 0; $c < 1000; $c++) {
        go(function () use ($pool, $c) {
            for ($n = 0; $n < 100; $n++) {
                $redis = $pool->get();
                assert($redis->set("awesome-{$c}-{$n}", 'swoole'));
                assert($redis->get("awesome-{$c}-{$n}") === 'swoole');
                assert($redis->delete("awesome-{$c}-{$n}"));
                $pool->put($redis);
            }
        });
    }
});

Producer and consumers

Some Swoole's clients implement the defer mode for concurrency, but you can still implement it flexible with a combination of coroutines and channels.

go(function () {
    // User: I need you to bring me some information back.
    // Channel: OK! I will be responsible for scheduling.
    $channel = new Swoole\Coroutine\Channel;
    go(function () use ($channel) {
        // Coroutine A: Ok! I will show you the github addr info
        $addr_info = Co::getaddrinfo('github.com');
        $channel->push(['A', json_encode($addr_info, JSON_PRETTY_PRINT)]);
    });
    go(function () use ($channel) {
        // Coroutine B: Ok! I will show you what your code look like
        $mirror = Co::readFile(__FILE__);
        $channel->push(['B', $mirror]);
    });
    go(function () use ($channel) {
        // Coroutine C: Ok! I will show you the date
        $channel->push(['C', date(DATE_W3C)]);
    });
    for ($i = 3; $i--;) {
        list($id, $data) = $channel->pop();
        echo "From {$id}:\n {$data}\n";
    }
    // User: Amazing, I got every information at earliest time!
});

Timer

$id = Swoole\Timer::tick(100, function () {
    echo "⚙️ Do something...\n";
});
Swoole\Timer::after(500, function () use ($id) {
    Swoole\Timer::clear($id);
    echo "⏰ Done\n";
});
Swoole\Timer::after(1000, function () use ($id) {
    if (!Swoole\Timer::exists($id)) {
        echo "✅ All right!\n";
    }
});

The way of coroutine

go(function () {
    $i = 0;
    while (true) {
        Co::sleep(0.1);
        echo "📝 Do something...\n";
        if (++$i === 5) {
            echo "🛎 Done\n";
            break;
        }
    }
    echo "🎉 All right!\n";
});

🔥 Amazing runtime hooks

As of Swoole v4.1.0, we added the ability to transform synchronous PHP network libraries into co-routine libraries using a single line of code.

Simply call the Swoole\Runtime::enableCoroutine() method at the top of your script. In the sample below we connect to php-redis and concurrently read 10k requests in 0.1s:

Swoole\Runtime::enableCoroutine();
$s = microtime(true);
Co\run(function() {
    for ($c = 100; $c--;) {
        go(function () {
            ($redis = new Redis)->connect('127.0.0.1', 6379);
            for ($n = 100; $n--;) {
                assert($redis->get('awesome') === 'swoole');
            }
        });
    }
});
echo 'use ' . (microtime(true) - $s) . ' s';

By calling this method, the Swoole kernel replaces ZendVM stream function pointers. If you use php_stream based extensions, all socket operations can be dynamically converted to be asynchronous IO scheduled by coroutine at runtime!

How many things you can do in 1s?

Sleep 10K times, read, write, check and delete files 10K times, use PDO and MySQLi to communicate with the database 10K times, create a TCP server and multiple clients to communicate with each other 10K times, create a UDP server and multiple clients to communicate with each other 10K times... Everything works well in one process!

Just see what the Swoole brings, just imagine...

Swoole\Runtime::enableCoroutine();
$s = microtime(true);
Co\run(function() {
    // i just want to sleep...
    for ($c = 100; $c--;) {
        go(function () {
            for ($n = 100; $n--;) {
                usleep(1000);
            }
        });
    }

    // 10K file read and write
    for ($c = 100; $c--;) {
        go(function () use ($c) {
            $tmp_filename = "/tmp/test-{$c}.php";
            for ($n = 100; $n--;) {
                $self = file_get_contents(__FILE__);
                file_put_contents($tmp_filename, $self);
                assert(file_get_contents($tmp_filename) === $self);
            }
            unlink($tmp_filename);
        });
    }

    // 10K pdo and mysqli read
    for ($c = 50; $c--;) {
        go(function () {
            $pdo = new PDO('mysql:host=127.0.0.1;dbname=test;charset=utf8', 'root', 'root');
            $statement = $pdo->prepare('SELECT * FROM `user`');
            for ($n = 100; $n--;) {
                $statement->execute();
                assert(count($statement->fetchAll()) > 0);
            }
        });
    }
    for ($c = 50; $c--;) {
        go(function () {
            $mysqli = new Mysqli('127.0.0.1', 'root', 'root', 'test');
            $statement = $mysqli->prepare('SELECT `id` FROM `user`');
            for ($n = 100; $n--;) {
                $statement->bind_result($id);
                $statement->execute();
                $statement->fetch();
                assert($id > 0);
            }
        });
    }

    // php_stream tcp server & client with 12.8K requests in single process
    function tcp_pack(string $data): string
    {
        return pack('n', strlen($data)) . $data;
    }

    function tcp_length(string $head): int
    {
        return unpack('n', $head)[1];
    }

    go(function () {
        $ctx = stream_context_create(['socket' => ['so_reuseaddr' => true, 'backlog' => 128]]);
        $socket = stream_socket_server(
            'tcp://0.0.0.0:9502',
            $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $ctx
        );
        if (!$socket) {
            echo "$errstr ($errno)\n";
        } else {
            $i = 0;
            while ($conn = stream_socket_accept($socket, 1)) {
                stream_set_timeout($conn, 5);
                for ($n = 100; $n--;) {
                    $data = fread($conn, tcp_length(fread($conn, 2)));
                    assert($data === "Hello Swoole Server #{$n}!");
                    fwrite($conn, tcp_pack("Hello Swoole Client #{$n}!"));
                }
                if (++$i === 128) {
                    fclose($socket);
                    break;
                }
            }
        }
    });
    for ($c = 128; $c--;) {
        go(function () {
            $fp = stream_socket_client("tcp://127.0.0.1:9502", $errno, $errstr, 1);
            if (!$fp) {
                echo "$errstr ($errno)\n";
            } else {
                stream_set_timeout($fp, 5);
                for ($n = 100; $n--;) {
                    fwrite($fp, tcp_pack("Hello Swoole Server #{$n}!"));
                    $data = fread($fp, tcp_length(fread($fp, 2)));
                    assert($data === "Hello Swoole Client #{$n}!");
                }
                fclose($fp);
            }
        });
    }

    // udp server & client with 12.8K requests in single process
    go(function () {
        $socket = new Swoole\Coroutine\Socket(AF_INET, SOCK_DGRAM, 0);
        $socket->bind('127.0.0.1', 9503);
        $client_map = [];
        for ($c = 128; $c--;) {
            for ($n = 0; $n < 100; $n++) {
                $recv = $socket->recvfrom($peer);
                $client_uid = "{$peer['address']}:{$peer['port']}";
                $id = $client_map[$client_uid] = ($client_map[$client_uid] ?? -1) + 1;
                assert($recv === "Client: Hello #{$id}!");
                $socket->sendto($peer['address'], $peer['port'], "Server: Hello #{$id}!");
            }
        }
        $socket->close();
    });
    for ($c = 128; $c--;) {
        go(function () {
            $fp = stream_socket_client("udp://127.0.0.1:9503", $errno, $errstr, 1);
            if (!$fp) {
                echo "$errstr ($errno)\n";
            } else {
                for ($n = 0; $n < 100; $n++) {
                    fwrite($fp, "Client: Hello #{$n}!");
                    $recv = fread($fp, 1024);
                    list($address, $port) = explode(':', (stream_socket_get_name($fp, true)));
                    assert($address === '127.0.0.1' && (int)$port === 9503);
                    assert($recv === "Server: Hello #{$n}!");
                }
                fclose($fp);
            }
        });
    }
});
echo 'use ' . (microtime(true) - $s) . ' s';

⌛️ Installation

As with any open source project, Swoole always provides the most reliable stability and the most powerful features in the latest released version. Please ensure as much as possible that you are using the latest version.

Compiling requirements

  • Linux, OS X or Cygwin, WSL
  • PHP 7.2.0 or later (The higher the version, the better the performance.)
  • GCC 4.8 or later

1. Install via PECL (beginners)

pecl install openswoole

2. Install from source (recommended)

Please download the source packages from Releases or:

git clone https://github.com/openswoole/swoole-src.git && \
cd swoole-src

Compile and install at the source folder:

phpize && \
./configure && \
make && make install

Enable extension in PHP

After compiling and installing to the system successfully, you have to add a new line extension=openswoole.so to php.ini to enable Swoole extension.

Extra compiler configurations

for example: ./configure --enable-openssl --enable-sockets

  • --enable-openssl or --with-openssl-dir=DIR
  • --enable-sockets
  • --enable-http2
  • --enable-mysqlnd (need mysqlnd, it just for supporting $mysql->escape method)
  • --enable-swoole-json
  • --enable-swoole-curl

Upgrade

⚠️ If you upgrade from source, don't forget to make clean before you upgrade your swoole

  1. pecl upgrade openswoole
  2. cd swoole-src && git pull && make clean && make && sudo make install
  3. if you change your PHP version, please re-run phpize clean && phpize then try to compile

💎 Frameworks & Components

  • Hyperf is a coroutine framework that focuses on hyperspeed and flexibility, specifically used for build microservices or middlewares.
  • Swoft is a modern, high-performance AOP and coroutine PHP framework.
  • Easyswoole is a simple, high-performance PHP framework, based on Swoole, which makes using Swoole as easy as echo "hello world".
  • MixPHP is a powerful single-threaded coroutine framework with a very small footprint, simple and elegant.
  • imi is a high-performance coroutine application development framework based on PHP Swoole, which supports the development of HttpApi, WebSocket, TCP, UDP services.
  • Saber is a human-friendly, high-performance HTTP client component that has almost everything you can imagine.
  • One is a minimalist, high-performance PHP framework that supports the [swoole | php-fpm] environment

🛠 Develop & Discussion

🍭 Benchmark

  • On the open source Techempower Web Framework benchmarks Swoole used MySQL database benchmark to rank first, and all performance tests ranked in the first echelon.
  • You can just run Benchmark Script to quickly test the maximum QPS of Swoole-HTTP-Server on your machine.

🔰️ Security issues

Security issues should be reported privately, via email, to the Swoole develop team [email protected]. You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message.

🖊️ Contribution

Your contribution to Swoole development is very welcome!

You may contribute in the following ways:

❤️ Contributors

This project exists thanks to all the people who contribute. [Contributors].

🎙️ Official Evangelist

Demin has been playing with PHP since 2000, focusing on building high-performance, secure web services. He is an occasional conference speaker on PHP and Swoole, and has been working for companies in the states like eBay, Visa and Glu Mobile for years. You may find Demin on Twitter or GitHub.

📃 License

Apache License Version 2.0 see http://www.apache.org/licenses/LICENSE-2.0.html

Owner
Open Swoole
Open source PHP extension for Async IO, Coroutines and Fibers
Open Swoole
Comments
  • Random got WARNING ProcessPool::wait(): worker#1 abnormal exit, status=0, signal=13

    Random got WARNING ProcessPool::wait(): worker#1 abnormal exit, status=0, signal=13

    1. What did you do? If possible, provide a simple script for reproducing the error.

    I made local server based on standart alpine docker images https://hub.docker.com/r/shlinkio/shlink and https://hub.docker.com/r/shlinkio/shlink-web-client

    When setting and starting up with docker-compose.yml absolutely randomly I gеt errors "connection refused" when try API/redirect requests or "502 bad gateway" when use nginx proxy_pass to shlink docker container.

    I tried several configs with docker compose with mysql/maria, rabbit, geolite, web_worker_num, task_worker_num, domain, base path - but nothing does matters.

    I check logs in shlinks docker container, when get the error: WARNING ProcessPool::wait(): worker#1 abnormal exit, status=0, signal=13

    I dont understand what happens. I think OpenSwoole breaks the requests.

    1. What did you expect to see? no errors and correctly working docker container

    2. What did you see instead? failed requests with error in logs, that I describe earlier

    3. What version of OpenSwoole are you using (show your php --ri openswoole)?

    /etc/shlink # php --ri openswoole
    
    openswoole
    Open Swoole => enabled
    Author => Open Swoole Group <[email protected]>
    Version => 4.11.1
    Built => Oct 18 2022 17:12:42
    coroutine => enabled with boost asm context
    epoll => enabled
    eventfd => enabled
    signalfd => enabled
    spinlock => enabled
    rwlock => enabled
    mutex_timedlock => enabled
    pthread_barrier => enabled
    async_redis => enabled
    
    Directive => Local Value => Master Value
    swoole.enable_coroutine => On => On
    swoole.enable_library => On => On
    swoole.enable_preemptive_scheduler => Off => Off
    swoole.display_errors => On => On
    swoole.use_shortname => On => On
    swoole.unixsock_buffer_size => 8388608 => 8388608
    
    1. What is your machine environment used (show your uname -a & php -v & gcc -v) ?

    DOCKER CONTAINER SHLINK

    /etc/shlink # uname -a
    Linux f0e141b14fed 5.10.16.3-microsoft-standard-WSL2 #1 SMP Fri Apr 2 22:23:49 UTC 2021 x86_64 Linux
    
    /etc/shlink # php -v
    PHP 8.1.9 (cli) (built: Aug  9 2022 21:47:49) (NTS)
    Copyright (c) The PHP Group
    Zend Engine v4.1.9, Copyright (c) Zend Technologies
    
    /etc/shlink # gcc -v
    /bin/sh: gcc: not found
    

    MY HOST MACHINE

    Windows 10 Pro 21H1 64bit, DDR4 48GB, Xeon E5-2678 3.3GHz
    Docker Desktop v4.13.1 with WSL2 (config VM memory=32GB processors=20) 
    on Ubuntu 20.04.5 LTS (GNU/Linux 5.10.16.3-microsoft-standard-WSL2 x86_64)
    
    [email protected]:~# uname -a
    Linux slava-pc 5.10.16.3-microsoft-standard-WSL2 #1 SMP Fri Apr 2 22:23:49 UTC 2021 x86_64 GNU/Linux
    

    DOCKER-COMPOSE.YML

    db:
    	container_name: my-db
    	image: mariadb:10.3.34
    	restart: always
    	ports:
    		- '127.0.0.1:3306:3306'
    	command: [
    		'--default-authentication-plugin=mysql_native_password',
    		'--character-set-server=utf8',
    		'--collation-server=utf8_unicode_ci'
    	]
    	environment:
    		MYSQL_ROOT_PASSWORD: password
    		TZ: Europe/Berlin
    	volumes:
    		- my-db-data:/var/lib/mysql
    
    shlink:
    	container_name: my-shlink
    	image: shlinkio/shlink:3.3.2
    	restart: always
    	environment:
    		DEFAULT_DOMAIN: shlink.local
    		PORT: 8080
    		BASE_PATH: /shlink
    		IS_HTTPS_ENABLED: false
    		WEB_WORKER_NUM: 8
    		TASK_WORKER_NUM: 8
    		INITIAL_API_KEY: shlinkapikey
    		DB_DRIVER: maria
    		DB_NAME: shlink
    		DB_USER: root
    		DB_PASSWORD: password
    		DB_HOST: my-db
    		GEOLITE_LICENSE_KEY: ${SHLINK_GEOLITE_LICENSE_KEY}
    		SKIP_INITIAL_GEOLITE_DOWNLOAD: false
    		ENABLE_PERIODIC_VISIT_LOCATE: false
    	links:
    		- db
    	depends_on:
    		- db
    	ports:
    		- '127.0.0.1:8080:8080'
    
    shlinkweb:
    	container_name: my-shlinkweb
    	image: shlinkio/shlink-web-client
    	restart: always
    	volumes:
    		- ./docker/dev/shlink/servers.json:/usr/share/nginx/html/servers.json
    	links:
    		- shlink
    	depends_on:
    		- shlink
    	ports:
    		- '127.0.0.1:8000:80'
    

    SERVER.JSON file

    [
        {
            "name": "Localhost",
            "url": "http://shlink.local/shlink",
            "apiKey": "shlinkapikey"
        }
    ]
    
  • PDO Connection Pool for Postgres Not able to create connection ...

    PDO Connection Pool for Postgres Not able to create connection ...

    1. What did you do? If possible, provide a simple script for reproducing the error.
    // db_connection_pool.php
    
    //const POSTGRES_SERVER_DRIVER = 'pgsql'; // I get warning "Already defined" if i uncomment it
    const POSTGRES_SERVER_HOST = 'localhost';
    const POSTGRES_SERVER_PORT = 5432;
    const POSTGRES_SERVER_DB = 'swooledb';
    const POSTGRES_SERVER_USER = 'postgres';
    const POSTGRES_SERVER_PWD = 'passwd123';
    
    function create_db_connection_pool() {
        return new PDOPool(
                (new PDOConfig())
                    ->withDriver(POSTGRES_SERVER_DRIVER)
                    ->withHost(POSTGRES_SERVER_HOST)
                    ->withPort(POSTGRES_SERVER_PORT)
                    // ->withUnixSocket('/tmp/mysql.sock')
                    ->withDbName(POSTGRES_SERVER_DB)
                    //->withCharset('utf8mb4')
                    ->withUsername(POSTGRES_SERVER_USER)
                    ->withPassword(POSTGRES_SERVER_PWD)
            );
    }
    

    Also, tried ...

    ->withCharset('utf8mb4')

    And, from inside a class:

    include(db_connection_pool.php);
    
    protected $conn_pool_swoole;
    
    $this->conn_pool_swoole = create_db_connection_pool();
    $pgsql_conn_swoole = $this->conn_pool_swoole->get();
    
    1. What did you expect to see?
    Creation of connection pool without any Fatal Error
    
    
    1. What did you see instead?
    PHP Fatal error:  Uncaught PDOException: SQLSTATE[HY000] [1698] Access denied for user 'postgres'@'localhost' in @swoole-src/library/core/Database/PDOPool.php:44
    Stack trace:
    #0 @swoole-src/library/core/Database/PDOPool.php(44): PDO->__construct()
    #1 @swoole-src/library/core/Database/PDOProxy.php(41): Swoole\Database\PDOPool->Swoole\Database\{closure}()
    #2 @swoole-src/library/core/ConnectionPool.php(89): Swoole\Database\PDOProxy->__construct()
    #3 @swoole-src/library/core/ConnectionPool.php(58): Swoole\ConnectionPool->make()
    #4 /var/www/html/swoole-prac/sw_service.php(160): Swoole\ConnectionPool->get()
    #5 [internal function]: sw_service->{closure}()
    #6 {main}
      thrown in @swoole-src/library/core/Database/PDOPool.php on line 44
    
    

    And when used ->withCharset(''), the error became:

    PHP Fatal error:  Uncaught PDOException: SQLSTATE[08006] [7] invalid connection option "charset" in @swoole-src/library/core/Database/PDOPool.php:44
    Stack trace:
    #0 @swoole-src/library/core/Database/PDOPool.php(44): PDO->__construct()
    #1 @swoole-src/library/core/Database/PDOProxy.php(41): Swoole\Database\PDOPool->Swoole\Database\{closure}()
    #2 @swoole-src/library/core/ConnectionPool.php(89): Swoole\Database\PDOProxy->__construct()
    #3 @swoole-src/library/core/ConnectionPool.php(58): Swoole\ConnectionPool->make()
    #4 /var/www/html/swoole-prac/sw_service.php(160): Swoole\ConnectionPool->get()
    #5 [internal function]: sw_service->{closure}()
    #6 {main}
      thrown in @swoole-src/library/core/Database/PDOPool.php on line 44
    

    I can connect postgres using same credentials and using open-smf package for connection pool for swoole.

    I suspect that the issue is in the definition of dsn string in constructor of PDO() which is returned from inside the constructor of PDOPool class.

    Unlike mysql, "postgres" does not take charset='something' as part of dsn string therefore it should not be concatenated if database driver is set as "pgsql" instead of "mysql".

    For postgres, charset can be set using "options" key of dsn string, as below:

    options='--client_encoding=UTF8'

    1. What version of OpenSwoole are you using (show your php --ri openswoole)?
    version 4.11.1
    
    
    1. What is your machine environment used (show your uname -a & php -v & gcc -v) ?
    **uname -a:**
    Linux fakhar-HP-Laptop 5.17.5-76051705-generic #202204271406~1651504840~20.04~63e51bd-Ubuntu SMP PREEMPT Wed Ma x86_64 x86_64 x86_64 GNU/Linux
    
    **php -v:**
    PHP 8.1.12 (cli) (built: Oct 28 2022 17:39:57) (NTS)
    Copyright (c) The PHP Group
    Zend Engine v4.1.12, Copyright (c) Zend Technologies
        with Zend OPcache v8.1.12, Copyright (c), by Zend Technologies
    
    **gcc -v :**
    Using built-in specs.
    COLLECT_GCC=gcc
    COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/11/lto-wrapper
    OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa
    OFFLOAD_TARGET_DEFAULT=1
    Target: x86_64-linux-gnu
    Configured with: ../src/configure -v --with-pkgversion='Ubuntu 11.3.0-1ubuntu1~22.04' --with-bugurl=file:///usr/share/doc/gcc-11/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-11 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --enable-cet --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-11-xKiWfi/gcc-11-11.3.0/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-11-xKiWfi/gcc-11-11.3.0/debian/tmp-gcn/usr --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-serialization=2
    Thread model: posix
    Supported LTO compression algorithms: zlib zstd
    gcc version 11.3.0 (Ubuntu 11.3.0-1ubuntu1~22.04) 
    
    

    You can also try the following OpenSwoole support channels:

  • HTTP client fails to make request when data contains empty array

    HTTP client fails to make request when data contains empty array

    1. What did you do? If possible, provide a simple script for reproducing the error.
    go(function () {
        $client = new Co\Http\Client('some.domain.com');
        $client->setData('');
        var_dump($client->execute('/first')); //true - getBody() returns response content
    
        $client->setData([]);
        var_dump($client->execute('/second')); //true - getBody() returns response content
    
        $client->setData(['data' => []]);
        var_dump($client->execute('/third')); //false - getBody() DOES NOT return response content
        //the request also fails with other methods than GET
    });
    
    
    1. What did you expect to see?
    No warning, a successful ->execute() and getBody() returning response content. The same behaviour as the /second request.
    
    1. What did you see instead?
    PHP Warning:  Swoole\Coroutine\Http\Client::execute(): http_build_query failed in ... on line with execute('/third') statement
    
    
    1. What version of OpenSwoole are you using (show your php --ri openswoole)?
    openswoole
    
    Open Swoole => enabled
    Author => Open Swoole Group <[email protected]>
    Version => 4.11.1
    Built => Sep 22 2022 10:58:22
    coroutine => enabled with boost asm context
    epoll => enabled
    eventfd => enabled
    signalfd => enabled
    cpu_affinity => enabled
    spinlock => enabled
    rwlock => enabled
    openssl => OpenSSL 1.1.1f  31 Mar 2020
    dtls => enabled
    http2 => enabled
    zlib => 1.2.11
    mutex_timedlock => enabled
    pthread_barrier => enabled
    futex => enabled
    async_redis => enabled
    
    Directive => Local Value => Master Value
    swoole.enable_coroutine => On => On
    swoole.enable_library => On => On
    swoole.enable_preemptive_scheduler => Off => Off
    swoole.display_errors => On => On
    swoole.use_shortname => On => On
    swoole.unixsock_buffer_size => 8388608 => 8388608
    
    1. What is your machine environment used (show your uname -a & php -v & gcc -v) ?
    Linux 5.15.0-48-generic #54~20.04.1-Ubuntu SMP Thu Sep 1 16:17:26 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
    PHP 8.1.11 (cli) (built: Sep 29 2022 22:28:49) (NTS)
    Copyright (c) The PHP Group
    Zend Engine v4.1.11, Copyright (c) Zend Technologies
    Using built-in specs.
    COLLECT_GCC=gcc
    COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper
    OFFLOAD_TARGET_NAMES=nvptx-none:hsa
    OFFLOAD_TARGET_DEFAULT=1
    Target: x86_64-linux-gnu
    Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.4.0-1ubuntu1~20.04.1' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-Av3uEd/gcc-9-9.4.0/debian/tmp-nvptx/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
    Thread model: posix
    gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.1) 
    
  • task() is mapping wrongly">

    "task_id (destination Task Worker Id") in $server->task() is mapping wrongly

    Please answer these questions before submitting your issue.

    1. What did you do? If possible, provide a simple script for reproducing the error.

    In Swoole configuration, i configured two Worker processes and four Task Worker processes. So ids of Worker processes is 0 and 1, and Task Worker processes is from 2 to 5. I called $server->task($data, 2, callback() {})

    1. What did you expect to see? I expect that the argument 2 in the $server->task() should map to Task Worker Process with Id 2; the first Task Worker Process.

    2. What did you see instead? The argument 2 in the $server->task() is actually map to Task Worker Process with Id 3; the second Task Worker Process.

    In other words, if i pass argument 2 in the call $server->task(), it means second Task Worker having Id as 3, not 'the first Task Worker having Id as 2)

    I think the $server->task() should take the actual ID number of the Task Worker, not the number of order of the Task Worker in the list of Task Workers.

    1. What version of Swoole are you using (show your php --ri swoole)? OpenSwoole 4.11.1

    2. What is your machine environment used (show your uname -a & php -v & gcc -v) ? Linux (Ubuntu 22.04), PHP version 8.1.10

    GCC -V Output;

    Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/11/lto-wrapper OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa OFFLOAD_TARGET_DEFAULT=1 Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Ubuntu 11.2.0-19ubuntu1' --with-bugurl=file:///usr/share/doc/gcc-11/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-11 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --enable-cet --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-11-gBFGDP/gcc-11-11.2.0/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-11-gBFGDP/gcc-11-11.2.0/debian/tmp-gcn/usr --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-serialization=2 Thread model: posix Supported LTO compression algorithms: zlib zstd gcc version 11.2.0 (Ubuntu 11.2.0-19ubuntu1)

  • Swoole\Table::[someMethod]() table is not created or has been destroyed

    Swoole\Table::[someMethod]() table is not created or has been destroyed

    1. What did you do? If possible, provide a simple script for reproducing the error.
    Use Swoole\Table in a connection tracking object property.
    
    
    1. What did you expect to see?
    Swoole table should not go away
    
    
    1. What did you see instead?
    **MOST** time it does work. But from time to time I see the following error:
    
    PHP Fatal error:  Swoole\Table::get(): table is not created or has been destroyed in /var/www/apps/frontend/websocket/WsConnections.php on line 164
    Symfony\Component\ErrorHandler\Error\FatalError^ {#117
      #message: "Error: Swoole\Table::get(): table is not created or has been destroyed"
      #code: 0
      #file: "/var/www/apps/frontend/websocket/WsConnections.php"
      #line: 164
      -error: array:4 [
        "type" => 1
        "message" => "Swoole\Table::get(): table is not created or has been destroyed"
        "file" => "/var/www/apps/frontend/websocket/WsConnections.php"
        "line" => 164
      ]
    }
    
    or
    
    PHP Fatal error:  Swoole\Table::rewind(): table is not created or has been destroyed in /var/www/apps/frontend/websocket/WsConnections.php on line 404
    
    
    
    1. What version of OpenSwoole are you using (show your php --ri openswoole)?
    
    openswoole
    
    Open Swoole => enabled
    Author => Open Swoole Group <[email protected]>
    Version => 4.11.1
    Built => Sep 21 2022 11:26:35
    coroutine => enabled with boost asm context
    epoll => enabled
    eventfd => enabled
    signalfd => enabled
    cpu_affinity => enabled
    spinlock => enabled
    rwlock => enabled
    openssl => OpenSSL 1.1.1n  15 Mar 2022
    dtls => enabled
    zlib => 1.2.11
    mutex_timedlock => enabled
    pthread_barrier => enabled
    futex => enabled
    async_redis => enabled
    
    Directive => Local Value => Master Value
    swoole.enable_coroutine => On => On
    swoole.enable_library => On => On
    swoole.enable_preemptive_scheduler => Off => Off
    swoole.display_errors => On => On
    swoole.use_shortname => On => On
    swoole.unixsock_buffer_size => 8388608 => 8388608
    
    
    1. What is your machine environment used (show your uname -a & php -v & gcc -v) ?
    Linux dev01 5.10.0-18-amd64 #1 SMP Debian 5.10.140-1 (2022-09-02) x86_64 GNU/Linux
    PHP 8.1.10 (cli) (built: Sep 18 2022 12:52:19) (NTS)
    Copyright (c) The PHP Group
    Zend Engine v4.1.10, Copyright (c) Zend Technologies
    Using built-in specs.
    COLLECT_GCC=gcc
    COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/10/lto-wrapper
    OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa:hsa
    OFFLOAD_TARGET_DEFAULT=1
    Target: x86_64-linux-gnu
    Configured with: ../src/configure -v --with-pkgversion='Debian 10.2.1-6' --with-bugurl=file:///usr/share/doc/gcc-10/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-10 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-gcn/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-mutex
    Thread model: posix
    Supported LTO compression algorithms: zlib zstd
    gcc version 10.2.1 20210110 (Debian 10.2.1-6) 
    
    
  • configure: error: Cannot find libpq.so. Please specify correct PostgreSQL installation path

    configure: error: Cannot find libpq.so. Please specify correct PostgreSQL installation path

    I want to install from source and when I run the following command:

    ./configure --with-php-config=/usr/bin/php-config --enable-sockets=yes --enable-openssl=yes --enable-http2=yes --enable-mysqlnd=yes --enable-swoole-json=yes --enable-swoole-curl=yes --with-postgres

    I get the following error

    configure: error: Cannot find libpq.so. Please specify correct PostgreSQL installation path

    my OS:

    image

    This is while libpq.so exists

C++14 asynchronous allocation aware futures (supporting then, exception handling, coroutines and connections)
C++14 asynchronous allocation aware futures (supporting then, exception handling, coroutines and connections)

Continuable is a C++14 library that provides full support for: lazy async continuation chaining based on callbacks (then) and expression templates, ca

Nov 27, 2022
C++20 coroutines-based cooperative multitasking library

?? Coop Coop is a C++20 coroutines-based library to support cooperative multitasking in the context of a multithreaded application. The syntax will be

Dec 3, 2022
Discrete-event simulation in C++20 using coroutines

SimCpp20 SimCpp20 is a discrete-event simulation framework for C++20. It is similar to SimPy and aims to be easy to set up and use. Processes are defi

Nov 15, 2022
Header-Only C++20 Coroutines library

CPP20Coroutines Header-Only C++20 Coroutines library This repository aims to demonstrate the capabilities of C++20 coroutines. generator Generates val

Aug 15, 2022
Cppcoro - A library of C++ coroutine abstractions for the coroutines TS

CppCoro - A coroutine library for C++ The 'cppcoro' library provides a large set of general-purpose primitives for making use of the coroutines TS pro

Nov 29, 2022
Coro - Single-header library facilities for C++2a Coroutines

coro This is a collection of single-header library facilities for C++2a Coroutines. coro/include/ co_future.h Provides co_future<T>, which is like std

Dec 6, 2022
Async++ concurrency framework for C++11

Async++ Async++ is a lightweight concurrency framework for C++11. The concept was inspired by the Microsoft PPL library and the N3428 C++ standard pro

Dec 1, 2022
Async GRPC with C++20 coroutine support

agrpc Build an elegant GRPC async interface with C++20 coroutine and libunifex (target for C++23 executor). Get started mkdir build && cd build conan

Nov 15, 2022
Open source re-creation of the copenheimer project.

openheimer Open source re-creation of the copenheimer project. Stage 1: Completed! - Make a extremely fast minecraft server scanner that does the hand

Nov 6, 2022
Open MPI main development repository

Open MPI The Open MPI Project is an open source Message Passing Interface (MPI) implementation that is developed and maintained by a consortium of aca

Dec 5, 2022
Kernel source code of EZ-FLASH OMEGA Definitive Edition

#EZ-FLASH Omega Definitive Edition Kernel How to build 1.We use devkitARM_r53, you can use the current version or newer. 2.Set the following environme

Nov 29, 2022
Nov 30, 2022
An implementation of Actor, Publish-Subscribe, and CSP models in one rather small C++ framework. With performance, quality, and stability proved by years in the production.
An implementation of Actor, Publish-Subscribe, and CSP models in one rather small C++ framework. With performance, quality, and stability proved by years in the production.

What is SObjectizer? What distinguishes SObjectizer? SObjectizer is not like TBB, taskflow or HPX Show me the code! HelloWorld example Ping-Pong examp

Nov 15, 2022
Simple and fast C library implementing a thread-safe API to manage hash-tables, linked lists, lock-free ring buffers and queues

libhl C library implementing a set of APIs to efficiently manage some basic data structures such as : hashtables, linked lists, queues, trees, ringbuf

Nov 19, 2022
Sqrt OS is a simulation of an OS scheduler and memory manager using different scheduling algorithms including Highest Priority First (non-preemptive), Shortest Remaining Time Next, and Round Robin
Sqrt OS is a simulation of an OS scheduler and memory manager using different scheduling algorithms including Highest Priority First (non-preemptive), Shortest Remaining Time Next, and Round Robin

A CPU scheduler determines an order for the execution of its scheduled processes; it decides which process will run according to a certain data structure that keeps track of the processes in the system and their status.

Sep 7, 2022
RocketOS is a Unix based OS that uses legacy BIOS and GRUB and is written in C17. It is being developed for educational purposes primarily, but it still is a serious project. It is currently in its infancy.

RocketOS What is RocketOS? RocketOS is a Unix based OS that uses legacy BIOS and GRUB and is written in C17. It is being developed for educational pur

Sep 19, 2022
Nov 24, 2021
OOX: Out-of-Order Executor library. Yet another approach to efficient and scalable tasking API and task scheduling.

OOX Out-of-Order Executor library. Yet another approach to efficient and scalable tasking API and task scheduling. Try it Requirements: Install cmake,

Oct 25, 2022