Выход из цикла Gearman

У меня есть приложение php, которое получает запросы на номера деталей с нашего сервера. В этот момент мы обращаемся к стороннему API для сбора информации о ценах, чтобы убедиться, что у нас самая последняя цена для этого конкретного запроса. Иногда сторонний API работает медленно или может быть недоступен, поэтому у нас есть база данных, в которой хранятся последние запросы цен для каждого конкретного номера детали, которые мы можем использовать в качестве запасного. Я бы хотел выполнить запрос к стороннему API и базе данных параллельно, используя Gearman. Вот идея:

  1. Получить запрос
  2. С помощью gearman создайте две рабочие места:
    • Запрос стороннего API
    • Поиск в базе данных MySQL
  3. Подождите в цикле и верните результаты на основе следующих условий:
    • Если сторонний API завершил, верните этот результат, немедленно верните этот результат
    • Если истекшее время прошло (например, 2 секунды) и сторонний API не ответил, верните данные поиска MySQL

Используя gearman, я думал о том, чтобы либо запустить две задачи на переднем плане и выйти из runTasks () в вызове setCompleteCallback (), либо запустить их в фоновом режиме и проверить две задачи в отдельном цикле и выполнить на задачах, используя jobStatus ().

К сожалению, я не могу заставить ни один маршрут работать для меня, все еще получая доступ к полученным данным. Есть ли лучший способ, или есть некоторые примеры того, как кто-то сделал эту работу?

2

Решение

Я думаю, что вы описали одну проблему блокировки, а именно результаты поиска стороннего API. С моей точки зрения, вы можете справиться с этим двумя способами: либо вы можете полностью прервать попытку, если решите, что у вас закончилось время, либо вы можете сообщить клиенту, что у вас закончилось время, но продолжить с в любом случае, просто обновите свой локальный кеш на тот случай, если он отреагирует медленнее, чем хотелось бы. Я опишу, как бы я справился с первой проблемой, потому что это было бы проще.

Со стороны клиента:

$request = array(
'productId' => 5,
);
$client = new GearmanClient( );
$client->addServer( '127.0.0.1', 4730 );
$results = json_decode($client->doNormal('apiPriceLookup', json_encode( $request )));

if($results && property_exists($results->success) && $results->success) {
// Use local data
} else {
// Use fresh data
}

Это создаст задание на сервере заданий с именем функции 'apiPriceLookup' и передать ему данные рабочей нагрузки, содержащие идентификатор продукта 5, Он будет ждать результатов, чтобы вернуться, и проверить наличие success имущество. Если он существует и является истинным, то поиск API был успешным.

Идея состоит в том, чтобы установить условие времени ожидания в рабочей задаче, что полностью зависит от того, как вы реализуете поиск API. Если вы используете cURL (или какую-то оболочку вокруг cURL), вы можете увидеть ответ, как определить время ожидания Вот.

Со стороны рабочих:

$worker= new GearmanWorker();
$worker->addServer();
$worker->addFunction("apiPriceLookup", "apiPriceLookup", $count);

while ($worker->work());

function apiPriceLookup($job) {
$payload = json_decode($job->workload());

try {
$results = [
'data' => PerformApiLookupForProductId($payload->productId),
'success' => true,
];
} catch(Exception $e) {
$results = ['success' => false];
}

return json_encode($results);
}

Это просто создает GearmanWorker объект и подписывает его функцию apiPriceLookup, Будет вызывать функцию apiPriceLookup всякий раз, когда клиент отправляет задачу на сервер заданий. Эта функция вызывает другую функцию, PerformApiLookupForProductId, который должен быть написан так, чтобы генерировать исключение при возникновении условия тайм-аута.

Я не думаю, что это будет рассматриваться с использованием исключений для управления логическим потоком, я думаю, что условия таймаута обычно являются исключительными (или должны быть) событиями. Например, Guzzle бросит GuzzleHttp\Exception\RequestException когда он решил тайм-аут.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]