We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

DB connection on a forked CLI script

Hello,

I am not sure on which category should I ask this question becasue it involves a few, I think DB is the best fit.

I am running a CLI script which do some processes, the thing is that some of these processes could take seconds, and some could take minutes, so I thought of forking these processes and to not wait for the response on the parent.

The problem is that when the parent finishes, the child processes loss their connection to the DB. According to some comments in the PHP documentation:

The reason for the MySQL "Lost Connection during query" issue when forking is the fact that the child process inherits the parent's database connection. When the child exits, the connection is closed. If the parent is performing a query at this very moment, it is doing it on an already closed connection, hence the error.

Option 1

It is recommended to close the connection before forking, and open a new connection after forking. So I thought of clonning the connection and use the cloned instead.

On the child process I am using stuff like this:

$categoryModel = Category::findFirst($id);

$categoryModel->setStatus($status);
$categoryModel->save();

My first question is, if I clone the db connection, how do I discard the DB connection from the DI and how do I assign the new connection? is it even possible?

$db = $this->di->getShared('db');
$db->close();

$dbClone = clone($db);
$dbClone->connect();

$categoryModel = Category::findFirst($id);

Option 2

The second option is to run the processes in another CLI script, each script will have their own DB connection and 'everything'... how can I run a CLI script from another CLI or controller?

$command = "php cli.php {$pluginName} start {$categoryId}";
exec($command);

This simple script is not running the my Task class on the tasks directory, seems that is not even getting to the cli.php file.

Any thoughts? Thanks.

Hugo.

Seems that this is working:

$db = $this->di->getShared('db');
if ($processID == 0) {
            $dbClone = clone $db;
            $this->di->setShared('db', function ($dbClone) { return $dbClone; });

            $db = $this->di->getShared('db');
            $db->connect();
            ...

Not sure if it has a side effect though, what I know is that the parent process needs to reconnect to the DB after the forking.

Regards.

There are a few options to tackle this. In short, you should call connect() db service method after you fork a process from a parent.

But, with your code - where do you get process ID from? After pcntl_fork()?