Skip to content
This repository has been archived by the owner on Oct 28, 2022. It is now read-only.

Commit

Permalink
Better exception handling
Browse files Browse the repository at this point in the history
  • Loading branch information
mnapoli committed Apr 17, 2019
1 parent 9080bf1 commit d17fc82
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 9 deletions.
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
},
"require": {
"php": "^7.2",
"ext-json": "*",
"aws/aws-sdk-php": "^3.91",
"symfony/property-info": "^4.2"
},
Expand Down
31 changes: 23 additions & 8 deletions src/Dynamap.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
namespace Dynamap;

use Aws\DynamoDb\DynamoDbClient;
use Aws\DynamoDb\Exception\DynamoDbException;
use Dynamap\Exception\ItemNotFound;
use Dynamap\Exception\TableNotFound;

class Dynamap
{
Expand Down Expand Up @@ -38,16 +41,28 @@ public function getAll(string $table): array
* Get item by primary key.
*
* @param int|string|array $key
* @throws \Exception
* @throws \InvalidArgumentException If the key is invalid.
* @throws ItemNotFound If the item cannot be found.
*/
public function get(string $table, $key): object
{
$tableMapping = $this->mappingObj->getTableMapping($table);

$item = $this->dynamoDb->getItem([
'TableName' => $table,
'Key' => $this->buildKeyQuery($key, $tableMapping),
])['Item'];
try {
$item = $this->dynamoDb->getItem([
'TableName' => $table,
'Key' => $this->buildKeyQuery($key, $tableMapping),
])['Item'];
} catch (DynamoDbException $e) {
if ($e->getAwsErrorCode() === 'ResourceNotFoundException') {
throw TableNotFound::tableMissingInDynamoDb($table, $e);
}
throw $e;
}

if ($item === null) {
throw ItemNotFound::fromKey($tableMapping->getClassName(), $key);
}

return $this->map($item, $table);
}
Expand Down Expand Up @@ -148,14 +163,14 @@ private function map(array $item, string $table): object

/**
* @param int|string|array $key
* @throws \Exception
* @throws \InvalidArgumentException
*/
private function buildKeyQuery($key, TableMapping $tableMapping): array
{
$keyQuery = [];
if (! is_array($key)) {
if ($tableMapping->isCompositeKey()) {
throw new \Exception('The key is a composite key and only a single value was provided');
throw new \InvalidArgumentException('The key is a composite key and only a single value was provided');
}
foreach ($tableMapping->getKeyMapping() as $fieldMapping) {
$keyQuery[$fieldMapping->name()] = $fieldMapping->dynamoDbQueryValue($key);
Expand All @@ -164,7 +179,7 @@ private function buildKeyQuery($key, TableMapping $tableMapping): array
foreach ($tableMapping->getKeyMapping() as $fieldMapping) {
$fieldName = $fieldMapping->name();
if (! isset($key[$fieldName])) {
throw new \Exception('The key is incomplete');
throw new \InvalidArgumentException('The key is incomplete');
}
$keyQuery[$fieldName] = $fieldMapping->dynamoDbQueryValue($key[$fieldName]);
}
Expand Down
14 changes: 14 additions & 0 deletions src/Exception/ItemNotFound.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php declare(strict_types=1);

namespace Dynamap\Exception;

class ItemNotFound extends \Exception
{
/**
* @param int|string|array $key
*/
public static function fromKey(string $className, $key): self
{
return new self("Item `$className` not found for key " . json_encode($key));
}
}
19 changes: 19 additions & 0 deletions src/Exception/TableNotFound.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php declare(strict_types=1);

namespace Dynamap\Exception;

use Aws\DynamoDb\Exception\DynamoDbException;

/**
* The table was not found.
*/
class TableNotFound extends \Exception
{
public static function tableMissingInDynamoDb(string $table, DynamoDbException $previous): self
{
$message = "Cannot find the table `$table` in DynamoDB: make sure it exists and that the code has permissions to access it. "
. $previous->getAwsErrorMessage();

return new self($message, 0, $previous);
}
}
7 changes: 6 additions & 1 deletion src/Mapping.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Dynamap;

use Dynamap\Exception\TableNotFound;
use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
use Symfony\Component\PropertyInfo\PropertyInfoExtractor;
Expand Down Expand Up @@ -35,6 +36,10 @@ public function __construct(array $mappingConfig)

public function getTableMapping(string $table): TableMapping
{
if (! isset($this->tables[$table])) {
throw new TableNotFound("The table `$table` is not configured in Dynamap");
}

return $this->tables[$table];
}

Expand All @@ -46,6 +51,6 @@ public function getTableFromClassName(string $className): TableMapping
}
}

throw new \Exception("No table mapping for for class $className");
throw new TableNotFound("No table mapping found for class `$className`");
}
}
32 changes: 32 additions & 0 deletions tests/DynamapTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
use Aws\DynamoDb\DynamoDbClient;
use Aws\DynamoDb\Exception\DynamoDbException;
use Dynamap\Dynamap;
use Dynamap\Exception\ItemNotFound;
use Dynamap\Exception\TableNotFound;
use Dynamap\Test\Fixture\Article;
use PHPUnit\Framework\TestCase;

Expand Down Expand Up @@ -61,6 +63,12 @@ public function setUp(): void
'id',
],
],
'foo' => [ // This is a table that doesn't exist
'class' => Article::class,
'keys' => [
'id',
],
],
];
$this->dynamap = new Dynamap($dynamoDb, $mapping);
}
Expand Down Expand Up @@ -89,6 +97,30 @@ public function test get all(): void
$this->assertCount(3, $this->dynamap->getAll('articles'));
}

public function test get unknown object(): void
{
$this->expectException(ItemNotFound::class);
$this->expectExceptionMessage('Item `Dynamap\Test\Fixture\Article` not found for key 123');

$this->dynamap->get('articles', 123);
}

public function test get table that is mapped but doesnt exist in DynamoDB(): void
{
$this->expectException(TableNotFound::class);
$this->expectExceptionMessage('Cannot find the table `foo` in DynamoDB: make sure it exists and that the code has permissions to access it');

$this->dynamap->get('foo', 123);
}

public function test get unknown table(): void
{
$this->expectException(TableNotFound::class);
$this->expectExceptionMessage('The table `bar` is not configured in Dynamap');

$this->dynamap->get('bar', 123);
}

public function test string attribute(): void
{
$article = new Article(123);
Expand Down

0 comments on commit d17fc82

Please sign in to comment.