親サーバーの特定テーブルを子サーバーにコピーする仕組みを作ってみた
親サーバーの特定テーブルを子サーバーにコピーする仕組みを作ってみた
サーバーを中央と子という関係に分割したら結構な頻度でコピーしたいと思う事が出てきました。
具体的に1例挙げると『モールイベント情報』のコピーです。
このモールのイベント企画って「自社が参加するか否かの判断」が反映されないといけないので、中央に置いた情報だけでは足りません。かといって、全てのクライアントで自書してもらうと言うのも効率が悪い。
だったらmysqldumpして、cronでコピー反映すればいいんじゃね?と思ったのですが問題がありました。
- Docker化したMySQLコンテナにはcronが入っていない。
- Laravelを入れたコンテナにはcronを入れてあるがMySQLコンテナへのコマンドが処理されない(よくわからない)。
と言う事で「調べるの時間かかかりそうだからLaravelからなんかできないかな」と思案し構築してみました。
条件や概要などなど
やりたいことは以下の通りです。
- 親サーバーのeventlists テーブルをCLIENT側のeventlistsにコピーする。
- 親サーバー側でeventlCop の中身を変える事がある。(更新/削除)
- 親サーバーで行った変更はCLIENT側で一部を除き受け取る。
- CLIENT側での変更は基本的にコピーを受けない一部のカラムのみとする。
- 親からのPUSHはせずCLIENT側から取りに来るようにする。
具体的には、モールのイベントがあってこの基礎情報(開始/終了日とか)を親サーバーに書き込んでいます。
このデータをクライアント側で取得して、自店舗に関係ないイベントはマーカーをOFFにします。
※なのでOFFったマーカーを変更されると困ります。
で、出来れば1週間に1回程度のペースで自動的に取りに行きたい訳です。
自動処理はLaravelのスケジュールに入れればよいので無問題。
だったらコピー用のページ用意すればいいんじゃね?
はい、こんな感じにしました。
use App\Models\Mastereventlist;
use App\Models\Carteventlist;
public function EventReplicate(Request $request)
{
$tasks = Mastereventlist::get();
foreach($tasks as $task){
$localTask = Carteventlist::find($task->id);
if(!empty($localTask)){
#必要なものだけ上書き
$item->cart_id = $task->cart_id;
$item->announcedatetime = $task->announcedatetime;
$item->startdatetime = $task->startdatetime;
$item->enddatetime = $task->enddatetime;
$item->carturl = $task->carturl;
$localTask->save();
}else{
#新規追加
$item = new Carteventlist;
$item->cart_id = $task->id;
$item->cart_id = $task->cart_id;
$item->eventname = $task->eventname;
$item->announcedatetime = $task->announcedatetime;
$item->startdatetime = $task->startdatetime;
$item->enddatetime = $task->enddatetime;
$item->carturl = $task->carturl;
$item->memo = $task->memo;
$item->onoff = $task->onoff;
$item->save();
}
}
return redirect('/carteventlists');
}
スケジュールには2つの要素を追加
コマンド作らなきゃデスけど、それさえ作ってしまえばララベルさんが勝手に処理してくれます。
- 週に1回上記functionを読み込む。
- 週に1回、日程の過ぎたイベントをdeleteする。
Project/app/Console/Commands/schedules/carteventlist
<?php
namespace App\Console\Commands\schedules;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;
use App\Models\Carteventlist;
class CopyMallEvent extends Command
{
//最大試行回数
public $tries = 1;
//実行は処理スピードによりcontrolする
protected $signature = 'command:CopyMallEvent';
protected $description = 'Masterのイベントをコピー';
public function __construct()
{
parent::__construct();
}
public function handle()
{
return redirect('CopyMallEvent');
}
}
毎日でもいいのだけど、ランキング情報取ったり結構Server働かせるので『毎日しなくてもいいものは毎日しない』方向で。
テストでスケジュールによらず自力で情報取得に行ったのでページアクセスになってますが、自動処理だけにするならLibrary にコマンド用意して、そこへのパスをhandleに書けばOK。
まとめ
よく考えたら意外と簡単に出来てしまった。
後は、このデータを使ってTOPページとかレフトナビを作成するパーツ作ればもっと楽になるかな。


