Skip to content

Commit

Permalink
change error codes for proxy errors
Browse files Browse the repository at this point in the history
  • Loading branch information
Nemo64 committed Mar 15, 2020
1 parent 3aa914a commit e7e52f8
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 14 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -221,9 +221,9 @@ If an [Aurora Serverless] is paused, you'll get this error message:
> Communications link failure The last packet sent successfully to the server was 0 milliseconds ago.
> The driver has not received any packets from the server.

I mapped this error message to [error code `2002`] which is normally a socket connection error
but this will cause the dbal's `Doctrine\DBAL\Driver\AbstractMySQLDriver::convertException` to map this error
to an `Doctrine\DBAL\Exception\ConnectionException` which existing application might already handle gracefully.
I mapped this error message to error code `6000` (server errors are 1xxx and client errors 2xxx).
It'll also be converted to dbal's `Doctrine\DBAL\Exception\ConnectionException`
which existing application might already handle gracefully.
But the most important thing is that you can catch and handle it in your application
to better tell your user that the database is paused and will probably be available soon.

Expand All @@ -243,4 +243,4 @@ to better tell your user that the database is paused and will probably be availa
[timeout setting of guzzle]: http://docs.guzzlephp.org/en/stable/request-options.html#timeout
[mysql error documentation]: https://dev.mysql.com/doc/refman/5.6/en/server-error-reference.html
[amazon developer forum]: https://forums.aws.amazon.com/thread.jspa?threadID=317595
[error code `2002`]: https://dev.mysql.com/doc/refman/5.6/en/client-error-reference.html#error_cr_connection_error
[error code `2002`]: https://dv.mysql.com/doc/refman/5.6/en/client-error-reference.html#error_cr_connection_error
14 changes: 14 additions & 0 deletions src/RdsDataDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
use Aws\Handler\GuzzleV6\GuzzleHandler;
use Aws\RDSDataService\RDSDataServiceClient;
use Doctrine\DBAL\Driver;
use Doctrine\DBAL\Driver\DriverException;
use Doctrine\DBAL\Exception AS DBALException;
use GuzzleHttp\Client;

class RdsDataDriver extends Driver\AbstractMySQLDriver
Expand Down Expand Up @@ -49,4 +51,16 @@ public function getName(): string
{
return 'rds-data';
}

public function convertException($message, DriverException $exception)
{
switch ($exception->getErrorCode()) {
case '6000':
return new DBALException\ConnectionException($message, $exception);

default:
return parent::convertException($message, $exception);
}
}

}
4 changes: 2 additions & 2 deletions src/RdsDataException.php
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ class RdsDataException extends AbstractDriverException
. "|(*:1701,ER_TRUNCATE_ILLEGAL_FK)Cannot truncate a table referenced in a foreign key constraint \\(.*\\)"

// this error is custom and specific to aurora serverless proxies
// i fake it to indicate a socket connection error so implementations will correctly identify a connection error
. "|(*:2002,CR_CONNECTION_ERROR)Communications link failure.*"
// I decided to use 6xxx error codes for proxy errors since server errors are 1xxx and client errors 2xxx
. "|(*:6000,PR_CONNECTION_ERROR)Communications link failure.*"

. ")$#s"; // note the PCRE_DOTALL modifier

Expand Down
56 changes: 48 additions & 8 deletions tests/RdsDataExceptionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@
namespace Nemo64\DbalRdsData\Tests;


use Doctrine\DBAL\Exception\ConnectionException;
use Doctrine\DBAL\Exception\DriverException;
use Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException;
use Doctrine\DBAL\Exception\SyntaxErrorException;
use Doctrine\DBAL\Exception\TableNotFoundException;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
use Nemo64\DbalRdsData\RdsDataDriver;
use Nemo64\DbalRdsData\RdsDataException;
use PHPUnit\Framework\TestCase;

Expand All @@ -11,23 +18,56 @@ class RdsDataExceptionTest extends TestCase
public static function messages()
{
return [
["Table 'foo.bar' doesn't exist", 1146, 'ER_NO_SUCH_TABLE'],
["Duplicate entry 'foo' for key bar", 1062, 'ER_DUP_ENTRY'],
["You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use", 1149, 'ER_SYNTAX_ERROR'],
["Cannot truncate a table referenced in a foreign key constraint (foobar)", 1701, 'ER_TRUNCATE_ILLEGAL_FK'],
// this is a specific rds proxy error
["Communications link failure\n\nThe last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.", 2002, 'CR_CONNECTION_ERROR'],
["Some never before seen of error", null, null],
[
"Table 'foo.bar' doesn't exist",
1146,
'ER_NO_SUCH_TABLE',
TableNotFoundException::class,
],
[
"Duplicate entry 'foo' for key bar",
1062,
'ER_DUP_ENTRY',
UniqueConstraintViolationException::class,
],
[
"You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use",
1149,
'ER_SYNTAX_ERROR',
SyntaxErrorException::class,
],
[
"Cannot truncate a table referenced in a foreign key constraint (foobar)",
1701,
'ER_TRUNCATE_ILLEGAL_FK',
ForeignKeyConstraintViolationException::class,
],
[
"Communications link failure\n\n"
. "The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.",
6000,
'PR_CONNECTION_ERROR',
ConnectionException::class,
],
[
"Some never before seen of error",
null,
null,
DriverException::class,
],
];
}

/**
* @dataProvider messages
*/
public function testMessageParsing($message, $expectedCode, $expectedState)
public function testMessageParsing($message, $expectedCode, $expectedState, $convertedExceptionInstance)
{
$exception = new RdsDataException($message);
$this->assertEquals($expectedCode, $exception->getErrorCode());
$this->assertEquals($expectedState, $exception->getSQLState());

$driver = new RdsDataDriver();
$this->assertInstanceOf($convertedExceptionInstance, $driver->convertException($exception->getMessage(), $exception));
}
}

0 comments on commit e7e52f8

Please sign in to comment.