У меня есть приложение php, которое получает запросы на номера деталей с нашего сервера. В этот момент мы обращаемся к стороннему API для сбора информации о ценах, чтобы убедиться, что у нас самая последняя цена для этого конкретного запроса. Иногда сторонний API работает медленно или может быть недоступен, поэтому у нас есть база данных, в которой хранятся последние запросы цен для каждого конкретного номера детали, которые мы можем использовать в качестве запасного. Я бы хотел выполнить запрос к стороннему API и базе данных параллельно, используя Gearman. Вот идея:
Используя gearman, я думал о том, чтобы либо запустить две задачи на переднем плане и выйти из runTasks () в вызове setCompleteCallback (), либо запустить их в фоновом режиме и проверить две задачи в отдельном цикле и выполнить на задачах, используя jobStatus ().
К сожалению, я не могу заставить ни один маршрут работать для меня, все еще получая доступ к полученным данным. Есть ли лучший способ, или есть некоторые примеры того, как кто-то сделал эту работу?
Я думаю, что вы описали одну проблему блокировки, а именно результаты поиска стороннего 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
когда он решил тайм-аут.
Других решений пока нет …