親サーバーの特定テーブルを子サーバーにコピーする仕組みを作ってみた

親サーバーの特定テーブルを子サーバーにコピーする仕組みを作ってみた

サーバーを中央と子という関係に分割したら結構な頻度でコピーしたいと思う事が出てきました。

具体的に1例挙げると『モールイベント情報』のコピーです。

このモールのイベント企画って「自社が参加するか否かの判断」が反映されないといけないので、中央に置いた情報だけでは足りません。かといって、全てのクライアントで自書してもらうと言うのも効率が悪い。

だったらmysqldumpして、cronでコピー反映すればいいんじゃね?と思ったのですが問題がありました。

  • Docker化したMySQLコンテナにはcronが入っていない。
  • Laravelを入れたコンテナにはcronを入れてあるがMySQLコンテナへのコマンドが処理されない(よくわからない)。

と言う事で「調べるの時間かかかりそうだからLaravelからなんかできないかな」と思案し構築してみました。

条件や概要などなど

やりたいことは以下の通りです。

  1. 親サーバーのeventlists テーブルをCLIENT側のeventlistsにコピーする。
  2. 親サーバー側でeventlCop の中身を変える事がある。(更新/削除)
  3. 親サーバーで行った変更はCLIENT側で一部を除き受け取る。
  4. CLIENT側での変更は基本的にコピーを受けない一部のカラムのみとする。
  5. 親からの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. 週に1回上記functionを読み込む。
  2. 週に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ページとかレフトナビを作成するパーツ作ればもっと楽になるかな。

\ 最新情報をチェック /

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください