namespace AppHelpersMySQL;
use Closure;
use Exception;
use IlluminateDatabaseMySqlConnection;
use IlluminateDatabaseQueryException;
use Log;
use PDOException;
/**
* Class DeadlockReadyMySqlConnection
*
* @package AppHelpers
*/
class DeadlockReadyMySqlConnection extends MySqlConnection
{
/**
* Error code of deadlock exception
*/
const DEADLOCK_ERROR_CODE = 40001;
/**
* Number of attempts to retry
*/
const ATTEMPTS_COUNT = 3;
/**
* Run a SQL statement.
*
* @param string $query
* @param array $bindings
* @param Closure $callback
* @return mixed
*
* @throws IlluminateDatabaseQueryException
*/
protected function runQueryCallback($query, $bindings, Closure $callback)
{
$attempts_count = self::ATTEMPTS_COUNT;
for ($attempt = 1; $attempt <= $attempts_count; $attempt++) {
try {
return $callback($this, $query, $bindings);
} catch (Exception $e) {
if (((int)$e->getCode() !== self::DEADLOCK_ERROR_CODE) || ($attempt >= $attempts_count)) {
throw new QueryException(
$query, $this->prepareBindings($bindings), $e
);
} else {
$sql = str_replace_array('?', $this->prepareBindings($bindings), $query);
Log::warning("Transaction has been restarted. Attempt {$attempt}/{$attempts_count}. SQL: {$sql}");
}
}
}
}
}
namespace AppHelpersMySQL;
use Config;
use IlluminateDatabaseConnectorsConnectionFactory;
use IlluminateDatabaseMySqlConnection;
use IlluminateDatabasePostgresConnection;
use IlluminateDatabaseSQLiteConnection;
use IlluminateDatabaseSqlServerConnection;
use InvalidArgumentException;
use PDO;
/**
* Class YourAppConnectionFactory
*
* @package AppHelpersMySQL
*/
class YourAppConnectionFactory extends ConnectionFactory
{
/**
* Create a new connection instance.
*
* @param string $driver
* @param PDO $connection
* @param string $database
* @param string $prefix
* @param array $config
* @return IlluminateDatabaseConnection
*
* @throws InvalidArgumentException
*/
protected function createConnection($driver, PDO $connection, $database, $prefix = '', array $config = [])
{
if ($this->container->bound($key = "db.connection.{$driver}")) {
return $this->container->make($key, [$connection, $database, $prefix, $config]);
}
switch ($driver) {
case 'mysql':
if ($config['database'] === Config::get('database.connections.mysql.database')) {
return new DeadlockReadyMySqlConnection($connection, $database, $prefix, $config);
} else {
return new MySqlConnection($connection, $database, $prefix, $config);
}
case 'pgsql':
return new PostgresConnection($connection, $database, $prefix, $config);
case 'sqlite':
return new SQLiteConnection($connection, $database, $prefix, $config);
case 'sqlsrv':
return new SqlServerConnection($connection, $database, $prefix, $config);
}
throw new InvalidArgumentException("Unsupported driver [$driver]");
}
}