swoole / swoole-src

🚀 Coroutine-based concurrency library for PHP
https://www.swoole.com
Apache License 2.0
18.47k stars 3.16k forks source link

Worker exit on PostgreSQL statement #4542

Closed factormaarten closed 2 years ago

factormaarten commented 2 years ago

Please answer these questions before submitting your issue. Thanks!

  1. What did you do? If possible, provide a simple script for reproducing the error. I have a GraphQL mutation (running on siler] and the mutation entry point here:
    return array(
        'saveUser' => new Save(repository())
    );

Save looks like this:

class Save
{
    private Users $users;

    public function __construct(Users $users)
    {
        $this->users = $users;
    }

    public function __invoke(array $root, array $args)
    {
        // ... validations

        $args['input'] = $input;

        try {
            return ($this->users->save($args))->serialize();
        } catch (\Throwable $e) {
            throw new Error(\json_encode(array('email' => EMAIL_TAKEN)));
        }
    }
}

The save function looks like this

public function save(array $data): User
    {
        $id = isset($data['id']) ? (string)$data['id'] : '';

        if (! $id) {
            return $this->create($data);
        }

        return $this->update($id, $data);
    }

In the create function it goes wrong on these lines:

            $persist = $this->persist;
            $persist($user);

Which invokes:

    public function __invoke(User $user)
    {
        $connection = (persistence())->getConnection(); // Fetching Persistence class from the container
        $statement = 'insert into users (id, email, data, created_at, updated_at)
                        values ($1, $2, $3, $4, $5) on conflict (id) do update set data = $3, updated_at = $5';
        $arguments = array(
            $user->getId(),
            $user->getEmail(),
            \json_encode($user->serialize()),
            now(),
            now()
        );

        $key = md5($statement);

        $connection->query('BEGIN');
        $connection->prepare($key, $statement);
        $result = $connection->execute($key, $arguments);
        $array = $connection->fetchAll($result, SW_PGSQL_ASSOC);
        $connection->query('COMMIT');
    }

This goes wrong upon actually saving in the persistence.

Persistence class

<?php

declare(strict_types=1);

namespace App\Core\Store;

use Swoole\Coroutine\Channel;
use Swoole\Coroutine\PostgreSQL;
use function Siler\Env\env_int;
use function Siler\Env\env_var;

class Persistence
{
    private Channel $pool;

    public function __construct()
    {
        $config = [
            'host' => env_var('DB_HOST', 'localhost'),
            'port' => env_int('DB_PORT', 3306),
            'dbname' => env_var('DB_NAME', 'default'),
            'user' => env_var('DB_USER', 'default'),
            'password' => env_var('DB_PASSWORD', 'default'),
            'poolSize' => env_int('DB_POOL_SIZE', 64)
        ];

        $dsn = implode(';', [
            "host={$config['host']}",
            "port={$config['port']}",
            "dbname={$config['dbname']}",
            "user={$config['user']}",
            "password={$config['password']}",
        ]);

        $size = $config['poolSize'];
        $this->pool = new Channel($size);
        for ($i = 0; $i < $size; $i++) {
            $postgres = new PostgreSQL();
            $connection = $postgres->connect($dsn);

            if (! $connection) {
                throw new \RuntimeException('PSQL connection fails');
            }

            $this->put($postgres);
        }
    }

    public function getConnection(): PostgreSQL
    {
        return $this->pool->pop();
    }

    public function put($connection): void
    {
        $this->pool->push($connection);
    }
}
  1. What did you expect to see? The record being stored in the database and giving back a result

  2. What did you see instead? WARNING Server::check_worker_exit_status(): worker(pid=58, id=0) abnormal exit, status=0, signal=11 A bug occurred in OpenSwoole-v4.8.1, please report it.

  3. What version of Swoole are you using (show your php --ri swoole)? OpenSwoole-v4.8.1

  4. What is your machine environment used (show your uname -a & php -v & gcc -v) ? OS: Linux 5.10.76-linuxkit #1 SMP PREEMPT Mon Nov 8 11:22:26 UTC 2021 aarch64 GCC_VERSION: 10.2.1 20201203 OPENSSL_VERSION: OpenSSL 1.1.1l 24 Aug 2021 PHP_VERSION : 7.4.22

NathanFreeman commented 2 years ago

Hi. Can you provide some other information? https://github.com/swoole/swoole-src/blob/master/.github/ISSUE.md#coredump

or use valgrind to track memory exception information.

USE_ZEND_ALLOC=0 valgrind --log-file=/tmp/valgrind.log php your_file.php
deminy commented 2 years ago

Starting from Swoole v5.0.0, the swoole_postgresql extension is part of Swoole. Besides that, there are more and more differences between Swoole and OpenSwoole.

I'm closing the issue since no feedback for months. Please feel free to create new issues if needed.