poggit / libasynql

Asynchronous MySQL access library for PocketMine plugins.
https://poggit.github.io/libasynql
Apache License 2.0
132 stars 44 forks source link

Calling libasynql functions won't execute until we call another one. #90

Closed Aboshxm2 closed 1 year ago

Aboshxm2 commented 1 year ago

Describe the bug When you call any libasynql function, let's say executeSelect, the onSelect function will never executed until another libasynql function called. and the second libasynql function well never get it's results until another function is called...

Something I noticed is that the bug does not exist in older versions. (before DEV-182 https://github.com/poggit/libasynql/commit/f0d668c9699824bb8d2433421c2401d385099a45)

Sample code https://github.com/Aboshxm2/libasyncql_query_bug

sqlite.sql

-- #!sqlite
-- #{ libasyncql_query_bug.init
CREATE TABLE IF NOT EXISTS example_table (playerName TEXT PRIMARY KEY, kills INTEGER);
-- #}
-- #{ libasyncql_query_bug.select
-- # :playerName string
SELECT * FROM example_table WHERE playerName=:playerName;
-- #}
-- #{ libasyncql_query_bug.insert
-- # :playerName string
-- # :kills int
INSERT INTO example_table (playerName, kills) VALUES (:playerName, :kills)
-- #}

Main.php

    private DataConnector $database;

    protected function onEnable(): void
    {
        $this->database = libasynql::create($this, [
            "type" => "sqlite",
            "sqlite" => ["file" => "data.sqlite"],
            "worker-limit" => 1
        ], [
            "sqlite" => "sqlite.sql"
        ]);

        $this->database->executeGeneric("libasyncql_query_bug.init", [], null, function (SqlError $error): void {
            throw new $error;
        });
    }

    public function onCommand(CommandSender $sender, Command $command, string $label, array $args): bool
    {
        if(!isset($args[0])) {
            $sender->sendMessage("/test (insert|select)");
            return true;
        }

        if($args[0] === "insert") {

            if(count($args) < 3) {
                $sender->sendMessage("/test insert (playerName) (kills)");
                return true;
            }

            $this->database->executeInsert("libasyncql_query_bug.insert", ["playerName" => $args[1], "kills" => (int)$args[2]], function (int $_) {
                var_dump("insert query executed successfully.");
            }, function (SqlError $error): void {
                throw new $error;
            });

        }elseif($args[0] === "select") {

            if(count($args) < 2) {
                $sender->sendMessage("/test select (playerName)");
                return true;
            }

            $this->database->executeSelect("libasyncql_query_bug.select", ["playerName" => $args[1]], function (array $rows) {
                var_dump("select query executed successfully.");
                var_dump($rows);
            }, function (SqlError $error): void {
                throw new $error;
            });
        }

Expected behavior When I do /test insert player1 10, It should display "insert query executed successfully." in the console. but it doesn't. until I send another command /test insert player2 10

Tests 1: /test insert player1 10. resaults: nothing.

2: /test insert player1 10 then /test select player1. resaults:

"insert query executed successfully.".

3: /test insert player1 10 then /test select player1 then /test select player2 resaults:

"insert query executed successfully."`
"select query executed successfully."
array(1) {
  [0]=>
  array(2) {
    ["playerName"]=>
    string(2) "player1"
    ["kills"]=>
    int(1)
  }
}

4: /test insert player1 10 then /test select player2 then /test select player1 resaults:

"insert query executed successfully."`
"select query executed successfully."
array(0) {
}

Environment OS: linux PocketMine version: 4.12.2 PHP version: 8.0.17

I am sorry if there any misspelling. English is not my main language.

SOF3 commented 1 year ago

@JavierLeon9966 linked commit is yours, can you have a look?

JavierLeon9966 commented 1 year ago

I debugged it and it looks like it does fetch the result correctly and it says it has called the callback but the callback does nothing until the next query

JavierLeon9966 commented 1 year ago

Ok, so when var dumping the $handler it dumped a correct Closure object but then it crashed when calling it because it says it is null

JustSxm commented 1 year ago

@JavierLeon9966 any update?

JavierLeon9966 commented 1 year ago

It just seems like a PHP (or pthreads) bug to me. The callback is being called but not executed until the next callback gets called, and forget the previous test, I tested it wrong

JustSxm commented 1 year ago

So then, should the commit be reverted to atleast get back to a working state? It causes problems that callbacks are not called at the right time

JavierLeon9966 commented 1 year ago

You can use the build before that commit, but this should be left so we don't forget about it and eventually be fixed

ColinHDev commented 1 year ago

You can use the build before that commit, but this should be left so we don't forget about it and eventually be fixed

Any movement on this? Since using an earlier version won't be an option anymore if the support for PHP 8.0 will be dropped soon and the commit dc8c284171ef2fff82ac78e8650ebe22f545dec6 that made the plugin work with PHP 8.1+ was only made after the talked about change.

JavierLeon9966 commented 1 year ago

Here is an update about the situation: https://github.com/poggit/libasynql/pull/92 and it is also fixed in the PM5 port