/** * @param TaskResult $taskResult * @return TaskLogger */ public function getLogger(TaskResult $taskResult) { $taskExists = false; foreach ($this->phase->getTasks() as $task) { if ($task->getId() !== $taskResult->getId()) { continue; } $taskExists = true; } if (!$taskExists) { throw new \InvalidArgumentException('Non existing task given'); } if (!array_key_exists($taskResult->getId(), $this->loggers)) { $this->loggers[$taskResult->getId()] = new TaskLogger($this->phase->getJob(), $taskResult->getTask(), $this->storageApi); } return $this->loggers[$taskResult->getId()]; }
/** * @param Phase $phase * @param PhaseLogger $logger * @param Client $httpClient * @param Response[] $jobResponses * @return array|bool */ public function pollPhase(Phase $phase, PhaseLogger $logger, Client $httpClient, $jobResponses = array()) { /** * @var Response[] $pollResponses */ $pollResponses = array(); /** * @var TaskResult[] $taskResults */ $taskResults = array(); foreach ($phase->getTasks() as $taskResult) { $taskResults[$taskResult->getId()] = $taskResult; } // all jobs polling $retriesCount = 1; $errorsCount = 0; do { $waitSeconds = min(pow(2, $retriesCount), 20); sleep($waitSeconds); foreach ($jobResponses as $key => $jobResponse) { $taskResult = $taskResults[$key]; $startTime = $taskResult->getStartTime()->getTimestamp(); try { $pollResponse = null; $timeout = $taskResult->getTimeoutMinutes() ? $taskResult->getTimeoutMinutes() : KeboolaOrchestratorBundle::TIMEOUT_MINUTES; $data = array('status' => 'unknown'); if (time() >= $startTime + $timeout * 60) { throw new Exception\JobRuntimeException(sprintf('Asynchronous task processing timeout after %d minutes', $timeout)); } try { $pollResponse = $httpClient->sendOrchestratorPollRequest($phase->getJob(), $jobResponse, $this->encryptor, $retriesCount); if ($pollResponse) { $pollResponses[$key] = $pollResponse; $data = ResponseDecoder::decode($pollResponse); } } catch (GuzzleException\RequestException $e) { if ($e instanceof Exception\CurlException) { } else { $prevE = $e->getPrevious(); if (!$prevE || !$prevE instanceof Exception\JobRuntimeException) { throw $e; } } } catch (\Exception $e) { // maybe json decode error, do nothing } if (!array_key_exists('status', $data)) { continue; } if (!StatusConverter::isFinishedStatus($data['status'])) { continue; } if ($pollResponse) { $response = $pollResponse; if (empty($data) || !in_array($data['status'], array('success', 'ok'))) { //@TODO logovat odpovedi, ktere vraci nesmyslne OK status $fakeRequest = new Request('GET', $response->getHeaderLine(Client::EFFECTIVE_URL_HEADER_NAME)); $clientExc = new GuzzleException\ClientException('Error response from component', $fakeRequest, $response); throw $clientExc; } } if (!ResponseValidator::isSuccessfulResponse($pollResponse) && !ResponseValidator::isInformationalResponse($pollResponse)) { $fakeRequest = new Request('GET', $pollResponse->getHeaderLine(Client::EFFECTIVE_URL_HEADER_NAME)); $clientExc = new GuzzleException\ClientException('Response with error HTTP code', $fakeRequest, $pollResponse); throw $clientExc; } $endEvent = $logger->getLogger($taskResult)->end(); } catch (GuzzleException\ClientException $e) { $endEvent = $logger->getLogger($taskResult)->clientError($e); if ($e->getResponse()) { $response = $e->getResponse(); } } catch (GuzzleException\BadResponseException $e) { $endEvent = $logger->getLogger($taskResult)->responseError($e); if ($e->getResponse()) { $response = $e->getResponse(); } } catch (\Exception $e) { $endEvent = $logger->getLogger($taskResult)->someError($e, $this->logger); $response = null; } $taskResult->setResult($endEvent, empty($response) ? null : $response); if ($taskResult->getError() && !$taskResult->getTask()->getContinueOnFailure()) { $errorsCount++; } unset($jobResponses[$key]); } $this->saveJobResult($this->jobResult); $retriesCount++; } while (count($jobResponses)); if ($errorsCount) { return false; } return array(); }