When PHP Gearman client fails to connect to the server I get the same code as when it fail to get new jobs

StackOverflow https://stackoverflow.com/questions/16815420

  •  30-05-2022
  •  | 
  •  

Question

PHP Gearman worker retrieves tasks from the server. When we don't have any new tasks we do some other work in the background. Please check the implementation below.

$worker = new GearmanWorker();
$worker->addServer('host', 123);
$worker->addFunction('name', array($this, 'function'));
$worker->setTimeout(5000);

while ($worker->work() || GEARMAN_TIMEOUT == $worker->returnCode()) {
    if (GEARMAN_TIMEOUT == $worker->returnCode()) {
        $this->handleTimeout();
    } elseif (GEARMAN_SUCCESS != $worker->returnCode()) {
        $this->handleFail();
        break;
    }
}

The code looks very simple and works normally most of the times. But when for some reason the script fails to connect to the server the $worker->returnCode() is equal to GEARMAN_TIMEOUT.

The $worker->returnCode() value is the same

  • when we don't have any new tasks
  • when script fails to connect to the server

When script fails to connect to the server the error message and code are the following:

  • $worker->error()

    gearman_worker_grab_job(GEARMAN_TIMEOUT) Option timeout return reached -> libgearman/worker.cc:869

  • $worker->getErrno()

    0

How to catch error when client fails to connect to server?

Was it helpful?

Solution

We have added GearmanWorker::echo() call to check if the Gearman server is available.

Look at the code after changes

$worker = new GearmanWorker();
$worker->addServer('host', 123);
$worker->addFunction('name', array($this, 'function'));
$worker->setTimeout(5000);

while ($worker->work() || GEARMAN_TIMEOUT == $worker->returnCode()) {
    if (GEARMAN_TIMEOUT == $worker->returnCode()) {
        $this->handleTimeout();
        $echo = @$worker->echo(1);
        if (!$echo) {
            echo 'Failed to connect to Gearman Gerver.'. PHP_EOL;
            break;
        }
    } elseif (GEARMAN_SUCCESS != $worker->returnCode()) {
        $this->handleFail();
        break;
    }
}

Please note the line $echo = @$worker->echo(1); and checks bellow. If server is unavailable then echo() output PHP warning and returns false.

GearmanException is never thrown in our setup.

OTHER TIPS

For basic solution you can use code like this:

try {
while ($worker->work() || GEARMAN_TIMEOUT == $worker->returnCode()) {
    if (GEARMAN_TIMEOUT == $worker->returnCode()) {
        echo "Timeout...\n";
    } elseif (GEARMAN_SUCCESS != $worker->returnCode()) {
        echo "Fail...\n";
        break;
    }
}
} catch (GearmanException $e) {
  echo "Exception caused!\n";
}

But you can not leave worker alive, because it needs to connect. I suggest to use Supervisord for automatically restart workers.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top