From f7973c735c05967041291899a740045c14679500 Mon Sep 17 00:00:00 2001 From: yukidaruma Date: Thu, 13 Aug 2020 23:08:41 +0900 Subject: [PATCH] refactor: Add caching mechanism for `players.metadata` and `players.weapons` Part of #18 --- app/Http/Controllers/SalmonPlayerMetadata.php | 105 ++++++++++-------- .../SalmonPlayerWeaponController.php | 10 +- 2 files changed, 66 insertions(+), 49 deletions(-) diff --git a/app/Http/Controllers/SalmonPlayerMetadata.php b/app/Http/Controllers/SalmonPlayerMetadata.php index cd3ca69..3eaaff7 100644 --- a/app/Http/Controllers/SalmonPlayerMetadata.php +++ b/app/Http/Controllers/SalmonPlayerMetadata.php @@ -3,6 +3,7 @@ namespace App\Http\Controllers; use Illuminate\Http\Request; +use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\DB; class SalmonPlayerMetadata extends Controller @@ -17,66 +18,74 @@ function __invoke(Request $request) abort(400); } - $selectQuery = [ + if (count($ids) === 1) { + $playerId = $ids[0]; + + return Cache::remember("players.metadata.$playerId", 86400, fn () => $this->getSinglePlayerMetadata($ids[0])); + } else { + return $this->getMultiplePlayersMetadata($ids); + } + } + + private function getSelectClause() { + return [ DB::raw('COALESCE(users.display_name, users.name, salmon_player_names.name) AS name'), DB::raw('CASE WHEN users.name IS NULL THEN FALSE ELSE TRUE END AS is_registered'), DB::raw('users.display_name IS NOT NULL AS is_custom_name'), DB::raw('CASE WHEN show_twitter_avatar = 1 THEN users.twitter_avatar ELSE NULL END AS twitter_avatar'), 'salmon_player_names.player_id AS player_id', ]; + } - if (count($ids) === 1) { - // TODO: cache - $id = $ids[0]; + private function getSinglePlayerMetadata(string $id) { + $metadata = DB::table('salmon_player_names') + ->leftJoin('user_accounts', 'user_accounts.player_id', '=', 'salmon_player_names.player_id') + ->leftJoin('users', 'users.id', '=', 'user_accounts.user_id') + ->select(...$this->getSelectClause()) + ->where('salmon_player_names.player_id', $id) + ->get() + ->toArray(); - $metadata = DB::table('salmon_player_names') - ->leftJoin('user_accounts', 'user_accounts.player_id', '=', 'salmon_player_names.player_id') - ->leftJoin('users', 'users.id', '=', 'user_accounts.user_id') - ->select(...$selectQuery) - ->where('salmon_player_names.player_id', $id) - ->get() - ->toArray(); + $metadata[0]->total = DB::table('salmon_player_results') + ->select( + DB::raw('CONVERT(SUM(golden_eggs), UNSIGNED) as golden_eggs'), + DB::raw('CONVERT(SUM(power_eggs), UNSIGNED) as power_eggs'), + DB::raw('CONVERT(SUM(rescue), UNSIGNED) as rescue'), + DB::raw('CONVERT(SUM(death), UNSIGNED) as death'), + DB::raw('CONVERT(SUM(boss_elimination_count), UNSIGNED) as boss_elimination_count'), + ) + ->where('salmon_player_results.player_id', $id) + ->first(); - $metadata[0]->total = DB::table('salmon_player_results') - ->select( - DB::raw('CONVERT(SUM(golden_eggs), UNSIGNED) as golden_eggs'), - DB::raw('CONVERT(SUM(power_eggs), UNSIGNED) as power_eggs'), - DB::raw('CONVERT(SUM(rescue), UNSIGNED) as rescue'), - DB::raw('CONVERT(SUM(death), UNSIGNED) as death'), - DB::raw('CONVERT(SUM(boss_elimination_count), UNSIGNED) as boss_elimination_count'), - ) - ->where('salmon_player_results.player_id', $id) - ->first(); + $results = collect(DB::table('salmon_player_results') + ->join('salmon_results', 'salmon_results.id', '=', 'salmon_player_results.salmon_id') + ->select( + DB::raw('CASE WHEN fail_reason_id IS NULL THEN "clear" ELSE "fail" END as result'), + DB::raw('count(*) as count'), + ) + ->where('salmon_player_results.player_id', $id) + ->groupBy('result') + ->get() + ); - $results = collect(DB::table('salmon_player_results') - ->join('salmon_results', 'salmon_results.id', '=', 'salmon_player_results.salmon_id') - ->select( - DB::raw('CASE WHEN fail_reason_id IS NULL THEN "clear" ELSE "fail" END as result'), - DB::raw('count(*) as count'), - ) - ->where('salmon_player_results.player_id', $id) - ->groupBy('result') - ->get() - ); + $clear = $results->firstWhere('result', 'clear'); + $fail = $results->firstWhere('result', 'fail'); - $clear = $results->firstWhere('result', 'clear'); - $fail = $results->firstWhere('result', 'fail'); + $metadata[0]->results = [ + 'clear' => $clear ? $clear->count : 0, + 'fail' => $fail ? $fail->count : 0, + ]; - $metadata[0]->results = [ - 'clear' => $clear ? $clear->count : 0, - 'fail' => $fail ? $fail->count : 0, - ]; + return $metadata; + } - return $metadata; - } - else { - return DB::table('salmon_player_names') - ->select(...$selectQuery) - ->whereIn('salmon_player_names.player_id', $ids) - ->leftJoin('user_accounts', 'user_accounts.player_id', '=', 'salmon_player_names.player_id') - ->leftJoin('users', 'users.id', '=', 'user_accounts.user_id') - ->limit(self::MAX_IDS_PER_REQUEST) - ->get(); - } + private function getMultiplePlayersMetadata(array $ids) { + return DB::table('salmon_player_names') + ->select(...$this->getSelectClause()) + ->whereIn('salmon_player_names.player_id', $ids) + ->leftJoin('user_accounts', 'user_accounts.player_id', '=', 'salmon_player_names.player_id') + ->leftJoin('users', 'users.id', '=', 'user_accounts.user_id') + ->limit(self::MAX_IDS_PER_REQUEST) + ->get(); } } diff --git a/app/Http/Controllers/SalmonPlayerWeaponController.php b/app/Http/Controllers/SalmonPlayerWeaponController.php index b232ed5..1527a8a 100644 --- a/app/Http/Controllers/SalmonPlayerWeaponController.php +++ b/app/Http/Controllers/SalmonPlayerWeaponController.php @@ -3,6 +3,7 @@ namespace App\Http\Controllers; use Illuminate\Http\Request; +use Illuminate\Support\Facades\Cache; class SalmonPlayerWeaponController extends Controller { @@ -13,12 +14,19 @@ class SalmonPlayerWeaponController extends Controller * @return \Illuminate\Http\Response */ public function __invoke(Request $request) + { + $playerId = $request->player_id; + + return Cache::remember("players.weapons.$playerId", 86400, fn () => $this->queryPlayerWeapons($playerId)); + } + + private function queryPlayerWeapons($playerId) { return \App\SalmonPlayerWeapon::select( 'weapon_id', \DB::raw('COUNT(*) as count'), ) - ->where('player_id', $request->player_id) + ->where('player_id', $playerId) ->groupBy('weapon_id') ->orderBy('count', 'desc') ->orderBy('weapon_id')