Skip to content

Commit

Permalink
Merge pull request #20 from keboola/roman-fix-exception-handler
Browse files Browse the repository at this point in the history
Fix parsing exception
  • Loading branch information
romanbracinik authored Jun 24, 2019
2 parents ba46f00 + 4a35aab commit 9ea9a64
Show file tree
Hide file tree
Showing 3 changed files with 291 additions and 32 deletions.
87 changes: 87 additions & 0 deletions src/Keboola/GoogleDriveExtractor/Extractor/ExceptionHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<?php

namespace Keboola\GoogleDriveExtractor\Extractor;

use GuzzleHttp\Exception\RequestException;
use Keboola\GoogleDriveExtractor\Exception\ApplicationException;
use Keboola\GoogleDriveExtractor\Exception\UserException;

class ExceptionHandler
{
public function handleGetSpreadsheetException(\Exception $e, array $sheet)
{
if (($e instanceof RequestException) && ($e->getResponse() !== null)) {
if ($e->getResponse()->getStatusCode() === 404) {
throw new UserException(sprintf('File "%s" not found in Google Drive', $sheet['sheetTitle']), 404, $e);
}

$errorSpec = json_decode($e->getResponse()->getBody(), true);

if (array_key_exists('error', $errorSpec)) {
if ($errorSpec['error'] === 'invalid_grant') {
throw new UserException(sprintf(
'Invalid OAuth grant when fetching "%s", try reauthenticating the extractor',
$sheet['fileTitle']
), 0, $e);
}

if (count($errorSpec['error']) > 1 && !isset($errorSpec['error_description'])) {
throw new UserException(sprintf(
'"%s" (%s) for "%s"',
$errorSpec['error']['message'],
$errorSpec['error']['status'],
$sheet['sheetTitle']
), 0, $e);
}

if (isset($errorSpec['error_description'])) {
throw new UserException(sprintf(
'"%s" (%s)',
$errorSpec['error_description'],
$errorSpec['error']
), 0, $e);
}
}

$userException = new UserException("Google Drive Error: " . $e->getMessage(), 400, $e);
$userException->setData([
'message' => $e->getMessage(),
'reason' => $e->getResponse()->getReasonPhrase(),
'sheet' => $sheet,
]);
throw $userException;
}
throw new ApplicationException(
$e->getMessage(),
$e->getCode(),
$e
);
}

public function handleExportException(\Exception $e, $sheet)
{
if (($e instanceof RequestException) && ($e->getResponse() !== null)) {
$userException = new UserException(
sprintf(
"Error importing file - sheet: '%s - %s'",
$sheet['fileTitle'],
$sheet['sheetTitle']
),
400,
$e
);
$userException->setData(array(
'message' => $e->getMessage(),
'reason' => $e->getResponse()->getReasonPhrase(),
'body' => substr($e->getResponse()->getBody()->getContents(), 0, 300),
'sheet' => $sheet
));
throw $userException;
}
throw new ApplicationException(
$e->getMessage(),
$e->getCode(),
$e
);
}
}
38 changes: 6 additions & 32 deletions src/Keboola/GoogleDriveExtractor/Extractor/Extractor.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@

namespace Keboola\GoogleDriveExtractor\Extractor;

use GuzzleHttp\Exception\RequestException;
use Keboola\GoogleDriveExtractor\Exception\ApplicationException;
use Keboola\GoogleDriveExtractor\Exception\UserException;
use Keboola\GoogleDriveExtractor\GoogleDrive\Client;
use Monolog\Logger;
use Psr\Http\Message\ResponseInterface;
Expand Down Expand Up @@ -52,6 +49,8 @@ public function run(array $sheets)
{
$status = [];

$exceptionHandler = new ExceptionHandler();

foreach ($sheets as $sheet) {
if (!$sheet['enabled']) {
continue;
Expand All @@ -61,39 +60,14 @@ public function run(array $sheets)

try {
$spreadsheet = $this->driveApi->getSpreadsheet($sheet['fileId']);
} catch (RequestException $e) {
if ($e->getResponse()->getStatusCode() == 404) {
throw new UserException(sprintf("File '%s' not found in Google Drive", $sheet['sheetTitle']), 404, $e);
} else {
$userException = new UserException("Google Drive Error: " . $e->getMessage(), 400, $e);
$userException->setData(array(
'message' => $e->getMessage(),
'reason' => $e->getResponse()->getReasonPhrase(),
'sheet' => $sheet
));
throw $userException;
}
} catch (\Exception $e) {
$exceptionHandler->handleGetSpreadsheetException($e, $sheet);
}

try {
$this->export($spreadsheet, $sheet);
} catch (RequestException $e) {
$userException = new UserException(
sprintf(
"Error importing file - sheet: '%s - %s'",
$sheet['fileTitle'],
$sheet['sheetTitle']
),
400,
$e
);
$userException->setData(array(
'message' => $e->getMessage(),
'reason' => $e->getResponse()->getReasonPhrase(),
'body' => substr($e->getResponse()->getBody()->getContents(), 0, 300),
'sheet' => $sheet
));
throw $userException;
} catch (\Exception $e) {
$exceptionHandler->handleExportException($e, $sheet);
}

$status[$sheet['fileTitle']][$sheet['sheetTitle']] = 'success';
Expand Down
198 changes: 198 additions & 0 deletions tests/Extractor/ExceptionHandleTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
<?php

namespace Keboola\GoogleDriveExtractor\Tests\Extractor;

use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Psr7\Request;
use GuzzleHttp\Psr7\Response;
use Keboola\GoogleDriveExtractor\Exception\ApplicationException;
use Keboola\GoogleDriveExtractor\Exception\UserException;
use Keboola\GoogleDriveExtractor\Extractor\ExceptionHandler;
use PHPUnit\Framework\TestCase;

class ExceptionHandleTest extends TestCase
{
/**
* @dataProvider provideExceptionsForGetSpreadsheet
*/
public function testHandlingOfExceptions(
$expectedExceptionClass,
$expectedExceptionMessage,
\Exception $caughtException,
array $sheet
) {
$handler = new ExceptionHandler();
$this->expectException($expectedExceptionClass);
$this->expectExceptionMessage($expectedExceptionMessage);
$handler->handleGetSpreadsheetException($caughtException, $sheet);
}
/**
* @return mixed[][]
*/
public function provideExceptionsForGetSpreadsheet()
{
return [
'invalid grant' => [
UserException::class,
'Invalid OAuth grant when fetching "File title", try reauthenticating the extractor',
new RequestException(
'Client error: `POST https://www.googleapis.com/oauth2/v3/token` resulted in a `400 Bad Request` response: { "error": "invalid_grant", "error_description": "Bad Request" }',
new Request('whatever', 'git'),
new Response(400, [], '{ "error": "invalid_grant", "error_description": "Bad Request" }')
),
[
"id" => 2,
"fileId" => "1y_XXXXXXXXXXX",
"fileTitle" => "File title",
"sheetId" => "SheetIdXxxxx",
"sheetTitle" => "Title XXXXXX",
"outputTable" => "table",
"header" => ["rows" => 1, "columns" => []],
"enabled" => true,
],
],
'http404' => [
UserException::class,
'File "Title XXXXXX" not found in Google Drive',
new RequestException(
'Client error: `POST https://www.googleapis.com/oauth2/v3/token` resulted in a `400 Bad Request` response: { "error": "invalid_grant", "error_description": "Bad Request" }',
new Request('whatever', 'git'),
new Response(404, [], '{}')
),
[
"id" => 2,
"fileId" => "1y_XXXXXXXXXXX",
"fileTitle" => "FileIdXxxxxx",
"sheetId" => "SheetIdXxxxx",
"sheetTitle" => "Title XXXXXX",
"outputTable" => "table",
"header" => ["rows" => 1, "columns" => []],
"enabled" => true,
],
],
'other request exception without description' => [
UserException::class,
'Google Drive Error: Client error: `POST https://www.googleapis.com/oauth2/v3/token` resulted in a `400 Bad Request` response: { "error": "invalid_grant", "error_description": "Bad Request" }',
new RequestException(
'Client error: `POST https://www.googleapis.com/oauth2/v3/token` resulted in a `400 Bad Request` response: { "error": "invalid_grant", "error_description": "Bad Request" }',
new Request('whatever', 'git'),
new Response(403, [], '{}')
),
[
"id" => 2,
"fileId" => "1y_XXXXXXXXXXX",
"fileTitle" => "FileIdXxxxxx",
"sheetId" => "SheetIdXxxxx",
"sheetTitle" => "Title XXXXXX",
"outputTable" => "table",
"header" => ["rows" => 1, "columns" => []],
"enabled" => true,
],
],
'other request exception with description' => [
UserException::class,
'"The column AX is not in the sheet" (out_of_range)',
new RequestException(
'Client error: `POST
https://www.googleapis.com/oauth2/v3/token` resulted in a `400 Bad Request` response: { "error":
"out_of_range", "error_description": "The column AX is not in the sheet" }',
new Request('whatever', 'git'),
new Response(403, [], '{ "error": "out_of_range", "error_description": "The column AX is not in the sheet" }')
),
[
"id" => 2,
"fileId" => "1y_XXXXXXXXXXX",
"fileTitle" => "FileIdXxxxxx",
"sheetId" => "SheetIdXxxxx",
"sheetTitle" => "Title XXXXXX",
"outputTable" => "table",
"header" => ["rows" => 1, "columns" => []],
"enabled" => true,
],
],
'other random exception' => [
ApplicationException::class,
'Timeout',
new \Exception(
'Timeout'
),
[
"id" => 2,
"fileId" => "1y_XXXXXXXXXXX",
"fileTitle" => "FileIdXxxxxx",
"sheetId" => "SheetIdXxxxx",
"sheetTitle" => "Title XXXXXX",
"outputTable" => "table",
"header" => ["rows" => 1, "columns" => []],
"enabled" => true,
],
],
'exception with another response array ' => [
UserException::class,
'"The caller does not have permission" (PERMISSION_DENIED) for "Title XXXXXX"',
new RequestException(
'Client error: `POST
https://sheets.googleapis.com/v4/spreadsheets/123` resulted in a `403 Forbidden` response: { "error": {
"code": 403,
"message": "The caller does not have permission",
"status": "PERMISSION_DENIED"
}}',
new Request('whatever', 'git'),
new Response(400, [], '{ "error": { "code": 403, "message": "The caller does not have permission", "status": "PERMISSION_DENIED" } }')
),
[
"id" => 2,
"fileId" => "1y_XXXXXXXXXXX",
"fileTitle" => "File title",
"sheetId" => "SheetIdXxxxx",
"sheetTitle" => "Title XXXXXX",
"outputTable" => "table",
"header" => ["rows" => 1, "columns" => []],
"enabled" => true,
],
],
];
}
/**
* @dataProvider provideExceptionsForExport
*/
public function testExportExceptionHandling(
$expectedExceptionClass,
$expectedExceptionMessage,
\Exception $caughtException,
array $sheet
) {
$handler = new ExceptionHandler();
$this->expectException($expectedExceptionClass);
$this->expectExceptionMessage($expectedExceptionMessage);
$handler->handleExportException($caughtException, $sheet);
}
/**
* @return mixed[][]
*/
public function provideExceptionsForExport()
{
return [
'Rate limit exceeded' => [
UserException::class,
"Error importing file - sheet: 'FileIdXxxxxx - Title XXXXXX'",
new RequestException(
'Some eeror message... Resulted in HTTP 429',
new Request('whatever', 'git'),
// phpcs:disable Generic.Files.LineLength
new Response(429, [], '{"error": {"errors": [{"domain": "usageLimits","reason": "rateLimitExceeded","message": "Rate Limit Exceeded"}],"code": 429,"message": "Rate Limit Exceeded"}}')
),
[
"id" => 2,
"fileId" => "1y_XXXXXXXXXXX",
"fileTitle" => "FileIdXxxxxx",
"sheetId" => "SheetIdXxxxx",
"sheetTitle" => "Title XXXXXX",
"outputTable" => "table",
"header" => ["rows" => 1, "columns" => []],
"enabled" => true,
],
],
];
}
}

0 comments on commit 9ea9a64

Please sign in to comment.