Skip to content
This repository was archived by the owner on Jan 1, 2021. It is now read-only.

Commit d2db9a6

Browse files
committed
Added Database Maintenance Mode.
1 parent 6b4536b commit d2db9a6

19 files changed

Lines changed: 590 additions & 19 deletions

app/Console/Commands/DBDown.php

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
<?php
2+
3+
namespace App\Console\Commands;
4+
5+
use Illuminate\Console\Command;
6+
use Illuminate\Support\Facades\DB;
7+
use Illuminate\Support\Facades\Storage;
8+
use Illuminate\Support\Facades\Config;
9+
10+
class DBDown extends Command
11+
{
12+
/**
13+
* The name and signature of the console command.
14+
*
15+
* @var string
16+
*/
17+
protected $signature = 'db:down {maintenance_to_use?}';
18+
19+
/**
20+
* The console command description.
21+
*
22+
* @var string
23+
*/
24+
protected $description = 'Start Database Maintenance mode';
25+
26+
/**
27+
* Create a new command instance.
28+
*
29+
* @return void
30+
*/
31+
public function __construct()
32+
{
33+
parent::__construct();
34+
}
35+
36+
/**
37+
* Execute the console command.
38+
*
39+
* @return mixed
40+
*/
41+
public function handle()
42+
{
43+
//
44+
$info = $this->get_maintenance_info();
45+
if ($info === false)
46+
{
47+
$this->info("Starting maintenance mode!");
48+
$config = $this->argument('maintenance_to_use');
49+
if ($config == "")
50+
{
51+
$config = "maintenance";
52+
}
53+
$this->start_maintenance_mode($config);
54+
}
55+
else
56+
{
57+
$this->error("Maintenance mode already on the way. Currently on stage: {$info['stage_name']}");
58+
}
59+
}
60+
61+
protected function get_maintenance_info()
62+
{
63+
if (Storage::disk()->exists("db.down"))
64+
{
65+
$contents = Storage::get("db.down");
66+
return json_decode($contents, true);
67+
}
68+
69+
return false;
70+
}
71+
72+
protected function start_maintenance_mode($config = "tmdb_maintenance")
73+
{
74+
$this->replicate_tables($config);
75+
76+
$this->finish_preparations();
77+
}
78+
79+
protected function replicate_tables($config)
80+
{
81+
$info = array(
82+
"stage" => "db.replication",
83+
"stage_name" => "Database Replication",
84+
"progress" => 0.0
85+
);
86+
87+
$this->set_maintenance_info($info);
88+
//Replicating database
89+
$from_db = Config::get("database.$config.from_database");
90+
$to_db = Config::get("database.$config.to_database");
91+
$connection = Config::get("database.$config.db_connection");
92+
if ($from_db == "" || $to_db == "")
93+
{
94+
$this->error("Please check your configuration!");
95+
$this->free_maintenance_info();
96+
return;
97+
}
98+
99+
$this->info("Replicating database from $from_db to $to_db");
100+
101+
$conf_tables = Config::get("database.$config.tables");
102+
$tables = $conf_tables;
103+
if ($conf_tables == "all" || $conf_tables == "")
104+
{
105+
$tables = DB::select("SHOW TABLES FROM $from_db");
106+
$real_tables = array();
107+
foreach ($tables as $dict) {
108+
foreach ($dict as $key => $value) {
109+
$real_tables[] = $value;
110+
}
111+
}
112+
$tables = $real_tables;
113+
}
114+
115+
$this->info("Replicating tables ".join(", ", $tables));
116+
117+
$first_tables = Config::get("database.$config.tables_before");
118+
119+
if (is_array($first_tables) && count($first_tables) > 0)
120+
{
121+
$this->info("Starting with table(s) ".join(",", $first_tables));
122+
123+
foreach ($first_tables as $value) {
124+
if (($key = array_search($value, $tables)) !== false) {
125+
unset($tables[$key]);
126+
}
127+
}
128+
129+
foreach ($first_tables as $value) {
130+
array_unshift($tables, $value);
131+
}
132+
133+
$this->info("Order of replication: ".join(", ", $tables));
134+
}
135+
136+
$current = 0;
137+
$total = count($tables);
138+
139+
DB::connection($connection)->statement("SET foreign_key_checks = 0;");
140+
foreach ($tables as $value) {
141+
try {
142+
DB::connection($connection)->statement("DROP TABLE $to_db.$value");
143+
} catch (Exception $e) {
144+
//Ignore since maybe table does not exist yet.
145+
}
146+
147+
$create_syntax = DB::select("SHOW CREATE TABLE $from_db.$value");
148+
$actual_syntax = "";
149+
foreach ($create_syntax as $syntax) {
150+
//dd($syntax);
151+
foreach ($syntax as $key => $val) {
152+
if ($key == "Create Table")
153+
{
154+
$actual_syntax = $val;
155+
}
156+
}
157+
158+
}
159+
160+
$actual_syntax = str_replace("`$value`", "`$to_db`.`$value`", $actual_syntax);
161+
DB::connection($connection)->statement($actual_syntax);
162+
//DB::connection($connection)->getPdo()->query($actual_syntax);
163+
DB::connection($connection)->statement("INSERT INTO $to_db.$value SELECT * FROM $from_db.$value");
164+
$current += 1;
165+
$this->info("Replicated table $value. ($current/$total)");
166+
$info = array(
167+
"stage" => "db.replication",
168+
"stage_name" => "Database Replication",
169+
"progress" => $current / (float)$total
170+
);
171+
172+
$this->set_maintenance_info($info);
173+
}
174+
DB::connection($connection)->statement("SET foreign_key_checks = 1;");
175+
176+
$this->info("Finished Replicating Database.");
177+
}
178+
179+
protected function finish_preparations()
180+
{
181+
$info = array(
182+
"stage" => "finished",
183+
"stage_name" => "Database Maintenance!",
184+
"progress" => 1.0
185+
);
186+
187+
$this->set_maintenance_info($info);
188+
$this->info("Finished preparing Database Maintenance. You can now safely manipulate production database!");
189+
}
190+
191+
protected function set_maintenance_info($info)
192+
{
193+
Storage::put("db.down", json_encode($info));
194+
}
195+
196+
protected function free_maintenance_info()
197+
{
198+
Storage::delete("db.down");
199+
}
200+
}

0 commit comments

Comments
 (0)