walkor / mqtt

Asynchronous MQTT client for PHP based on workerman.
207 stars 46 forks source link

Deamon mode not working in codeigniter framework #5

Closed TOPSinfo closed 5 years ago

TOPSinfo commented 5 years ago

I have integrated workerman mqtt in the CodeIgniter framework.

I am running the code from the terminal as following: php index.php controller function start

In the function, I have added the workerman mqtt code. I have to change the argument key for command in "Worker.php" file as following:

$command  = trim($argv[3]);
$command2 = isset($argv[4]) ? $argv[4] : '';

Replaced $argv[1] with $argv[3] and $argv[2] with $argv[4]. It is working fine.

When I run php index.php controller function start -d, The code that I put into onMessage function is not working. Which is working fine in DEBUG mode.

Following is the output when I run in DEAMON mode

Workerman[index.php] start in DAEMON mode ------------------------------------- WORKERMAN -------------------------------------- Workerman version:3.5.19 PHP version:7.1.25 -------------------------------------- WORKERS --------------------------------------- proto user worker listen processes status
tcp bitnami none none 1 [OK]

Input "php index.php stop" to stop. Start success.

walkor commented 5 years ago

Can you give me a simple example to produce the problem?

TOPSinfo commented 5 years ago

Here is my code:

`require(APPPATH.'libraries/mqtt/vendor/autoload.php'); use Workerman\Worker;

class Welcome extends CI_Controller {

function __construct()
{
    parent::__construct();
    $this->load->model('Mqtt_model');
}

public function index()
{
    try 
    {
        $worker = new Worker();
        $worker->onWorkerStart = function()  
        {   
            $mqtt = new Workerman\Mqtt\Client('<broker_url>', array(
                'ssl' => array(
                    'local_cert'  => APPPATH . 'libraries/mqtt/ssl/certificate.pem.crt',
                    'local_pk'    => APPPATH . 'libraries/mqtt/ssl/private.pem.key',
                    'verify_peer' => false,
                ),
                'debug' => true
            ));

            $mqtt->onConnect = function($mqtt)
            {
                $mqtt->subscribe('<topic_name>');
            };

            $mqtt->onMessage = function($topic, $content) {
                //echo "topic:$topic content:$content\n";

                $content = json_decode($content);

                foreach($content as $k => $v) 
                {
                    $data['mac_address'] = $v->mac;
                    $data['rssi'] = isset($v->rssi) ? $v->rssi : 0;

                    $this->Mqtt_model->insert('gateway_log',$data);
                }
            };
            $mqtt->connect();
        };
        Worker::runAll();
    } 
    catch (Exception $e) 
    {
        writeException($e);
        print_r($e);
    }
}

}`

TOPSinfo commented 5 years ago

It is working fine if I remove the database from autoload of codeigniter.

$autoload['libraries'] = array('database'); to $autoload['libraries'] = array('');

But that is not the solution for me.

Still curious, why it is working in DEBUG mode and not in DEAMON mode?

walkor commented 5 years ago

You can not connect mysql(memcache/redis..) in master process. If you do that every child process will inherit the same mysql connection. If any one close the mysql connection (master process will exit in daemon mode and will close it) the other process can not use it any more.

Remember all the codes in onXXX callback run in child process. Another way of saying all the codes run before Worker::runAll(); will run in master process.

This is wrong way to use mysql(memcache/redis..) in workerman.

$worker = new Worker();
$worker->onMessage = ...;
your_connect_databse_code....
Worker::runAll();

This is a recommend way to use mysql in workerman.

$worker = new Worker();
$worker->onWorkerStart = function() {
     your_connect_databse...
};
Worker::runAll();
TOPSinfo commented 5 years ago

Sounds good. Working fine now. Thank you for your support.