swoole / library

📚 Swoole Library
https://wiki.swoole.com/#/library
Apache License 2.0
242 stars 57 forks source link

Is it possible to create a PDOProxy object from an existing PDO connection? #168

Closed tricarte closed 9 months ago

tricarte commented 10 months ago

As you can guess, I am trying to integrate an existing db framework into some Swoole based framework in a very lazy and hacky way. I tried new PDOProxy($existingPDO) in a hurry but of course it didn't work. It says it needs a callable but I couldn't figure out what kind callable it's talking about.

That existing PDO was already pulled from the connection pool and I got the real PDO object using the __getObject() method of the PDOProxy class. What I'm trying to do is to put that real pdo back to the pool converting to a PDOProxy object in some separate place of the code.

deminy commented 9 months ago

yep,

<?php

use Swoole\ConnectionPool;
use Swoole\Coroutine;
use Swoole\Runtime;

Runtime::enableCoroutine();
Coroutine\run(function () {
    $pool = new ConnectionPool(function (): \PDO {
        return new PDO('mysql:host=mysql;port=3306;dbname=test', 'username', 'password');
    });

    Coroutine::create(function () use ($pool) {
        $pdo       = $pool->get();
        $statement = $pdo->prepare('SELECT 1');
        $statement->execute();
        $statement->fetchAll();
        $pool->put($pdo);
    });
});

You can replace the return new PDO(); statement with a PDO object for a list of available PDO objects. In this case we don't need to use a Proxy class in between.

Note that the size of the pool and the number of available PDO objects should match, otherwise the pool won't work as expected. Saying that you only have one PDO connection (one PDO object) but the size of the pool is set to two, and there are two concurrent queries using connections from the pool. In this case, the result probably won't be what you expected.

tricarte commented 9 months ago

I couldn't think of using ConnectionPool instead of a PDOPool. Ok, I applied your example. Now I got rid of PDOProxy and achieved what I was trying to do. But my code only works with a pool size of 1. And I think this is what you have warned me about.

At the moment, I don't know what I should be returning from that callback if the pool size is greater than 1. I hope I'm not misunderstanding the concepts.

If I set the pool size to 2, this is what I get:

Fatal error: Uncaught PDOException: SQLSTATE[HY000]: General error: 2014 Cannot
execute queries while other unbuffered queries are active.  Consider using
PDOStatement::fetchAll().

I know, you can't help much without seeing the code but the working pool size of 1 hopefully gives a clue about the situation.

Thanks.