Skip to content

Instantly share code, notes, and snippets.

@kocoten1992
Last active February 22, 2019 17:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kocoten1992/59090767351716a6e1321a003819826f to your computer and use it in GitHub Desktop.
Save kocoten1992/59090767351716a6e1321a003819826f to your computer and use it in GitHub Desktop.
auto retry database connection to different node laravel
<?php
namespace App\Providers;
use DB;
use App\Setting;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
protected $pdo = null;
public function boot()
{
// Note: getPdo() dont actually make database call
// so it is efficient enough
$this->setUpDBConnection();
if ($this->pdo) {
DB::select('SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED');
}
if (config('database.connections.'.config('database.default'))['host'] == env('DB_HOST') &&
env('DB_HOST_ORIGIN') == env('DB_HOST'))
{
return; // everything good
}
if (config('database.connections.'.config('database.default'))['host'] != env('DB_HOST')) {
try {
$this->pdo = DB::connection()->getPdo();
} catch (\Exception $e) {
return;
}
app('dotenvchanger')
->change('DB_HOST',
config('database.connections.'.config('database.default'))['host']
);
app('dotenvchanger')
->change('DB_LAST_CHANGE', now()->format('Y-m-d H:i:sO'));
return;
}
}
protected function setUpDBConnection()
{
try {
$this->pdo = DB::connection()->getPdo();
$this->shouldRepickDBConn();
} catch (\Exception $e) {
$failed_connections = [config('database.connections.'.config('database.default').'.host')];
$backup_connections = json_decode(config('app.db_host_backup'));
// random it
shuffle($backup_connections);
while ($backup_connection = array_pop($backup_connections)) {
$conn_name = str_replace('.', '', $backup_connection);
// create connection on the fly
app('config')
->set('database.connections.'.$conn_name,
[
'driver' => 'pgsql',
'host' => $backup_connection,
'port' => env('DB_PORT', '5432'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'prefix' => '',
'prefix_indexes' => true,
'schema' => 'public',
'sslmode' => 'prefer',
]
);
app('config')->set('database.default', $conn_name);
try {
$this->pdo = DB::connection()->getPdo();
$this->shouldRepickDBConn();
$this->reportFailedConnections($failed_connections);
break;
} catch (\Exception $e2) {
$failed_connections[] = $backup_connection;
continue;
}
}
}
}
protected function shouldRepickDBConn()
{
// repick database if this is plan restart/shutdown
$host = config('database.connections.'.config('database.default'))['host'];
$should_repick = ! Setting::whereK("db.{$host}")->whereV('up')->exists();
if ($should_repick) {
throw new \Exception("DB at {$host} shouldn't be pick, repicking..");
}
}
protected function reportFailedConnections(Array $failed_connections)
{
$message = "Failed DB Connections on:";
foreach ($failed_connections as $idx => $fc) {
if ($idx != 0) {
$message .= ",";
}
$message .= " $fc";
}
$default_conn = app('config')->get('database.default');
app('sysnoti')->error($message);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment