Ошибка при расширении класса GearmanClient

Я пытаюсь создать класс, расширяющий GearmanClient, чтобы я мог централизовать и использовать gearman в своем приложении в соответствии со своими спецификациями. Одна из причин, по которой я занимаюсь своим собственным классом, заключается в том, чтобы легко сохранять невыполненные задачи в базе данных, чтобы впоследствии их можно было снова обработать.

Я получаю основную ошибку

Предупреждение: GearmanClient::runTasks(): _client_run_task(GEARMAN_NO_SERVERS) без добавления серверов -> libgearman/run.cc:66 в /var/www/html/app/forecast/Forecast.php в строке 37

<?php
namespace app\service;
use helpers\Config_helper;
use \GearmanClient;

class Gearman_service extends GearmanClient
{
    public $client;
    private $servers = array();
    private $tasks   = array();

    private $completedTasks = array();
    private $failedTasks    = array();

    private $maxRetryAttempts;

    public function __construct()
    {       
        $this->client = new GearmanClient();            
        $this->servers = Config_helper::get_config_option('gearman_servers');
        $this->maxRetryAttempts = Config_helper::get_config_option('gearman_retry_attempts');

        $this->initialize();
    }

    protected function initialize()
    {
        foreach($this->servers as $key => $value):
            $this->client->addServer($value[0],$value[1]);
        endforeach;
    }

} Я должен предположить, что что-то не так с этой реализацией, но я хотел бы знать, почему.

Config_helper::get_config_option('gearman_servers'); правильно получает мой список серверов.

Это мой прогноз класса

<?php
namespace app\forecast;
use app\service\Gearman_service;
use helpers\Config_helper;
use helpers\Urlrequest_helper;
use app\warehouse\models\Client_time_forecast;

abstract class Forecast
{
    public $coordinates = array(); # set of coordinates
    public $servers     = array();
    public $variables   = array();
    public $url         = array();
    public $prevision;
    public $client;

    public $gearmanclient;

    public function __construct()
    {
        $this->servers   = Config_helper::get_config_option('forecast_servers');
        $this->variables = Config_helper::get_config_option('surface_variables');
        $this->prevision = Config_helper::get_config_option('forecast_prevision');

        $this->gearmanclient = new Gearman_service();       
    }

    public function storeResults()
    {               
        $this->gearmanclient->setCompleteCallback(array($this, 'requestComplete'));

        foreach($this->url as $key => $value):          
            $this->gearmanclient->addTask('request_forecast', serialize($value[0]));
        endforeach;

        $this->gearmanclient->runTasks();       // **line 37**  
    }   

    /**
     * [requestComplete store request results in cassandra db]
     * @param  \GearmanTask $task [description]
     * @return [boolean]          
     */
    public function requestComplete(\GearmanTask $task)
    {
        $persistent = new Client_time_forecast($this->client, unserialize($task->data()));
        $persistent->storeData();
    }
}

Кто-нибудь может поделиться со мной светом на это?

Спасибо!

1 ответ

Решение

Как и предполагалось, причиной проблемы является то, что вы смешиваете наследование и композицию. Вы расширили класс GearmanClient и в то же время создаете новый экземпляр класса GearmanClient в конструкторе и настраиваете этот новый экземпляр в методе initialize.

class Gearman_service extends GearmanClient
{
    public $client;
    // other properties
    public function __construct()
    {       
        $this->client = new GearmanClient();
        // more code
        $this->initialize();
    }

Вы можете изменить строку 37 и все другие вызовы открытых методов GermanClient, чтобы вызвать экземпляр, инициированный в конструкторе, и не расширять класс GearmanClient.

$this->gearmanclient->client->runTasks(); 

Однако было бы лучше изменить видимость свойства Gearman_service::client на private и реализовать открытый интерфейс класса GeamanClient.

class Gearman_service extends GearmanClient
{

    private $client;

    // constructor etc

    public function addTask($name, $workload, $context = null, $unique = "")
    {
        return $this->client->addTask($name, $workload, $context, $unique);
    }

Если вы сделаете это, строка 37 должна остаться без изменений.

В качестве альтернативы вы можете выбрать наследование. В этом случае вам нужно будет удалить клиент открытого свойства, не создавайте новый экземпляр класса GeamanClient в конструкторе и не изменяйте методы инициализации.

protected function initialize()
{
    foreach($this->servers as $key => $value):
        $this->addServer($value[0],$value[1]);
    endforeach;
}

В этом случае вам также не нужно менять строку 37 или другие вызовы открытых методов класса GeamanClient.

Другие вопросы по тегам