1<?php
2
3// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the GNU Affero General Public License v3.0.
4// See the LICENCE file in the repository root for full licence text.
5
6namespace App\Jobs;
7
8use App\Libraries\Elasticsearch\BoolQuery;
9use App\Models\Beatmap;
10use App\Models\Beatmapset;
11use App\Models\Score\Best\Model;
12use Illuminate\Bus\Queueable;
13use Illuminate\Contracts\Queue\ShouldQueue;
14use Illuminate\Queue\InteractsWithQueue;
15use Illuminate\Queue\Middleware\WithoutOverlapping;
16use Illuminate\Queue\SerializesModels;
17
18class RemoveBeatmapsetBestScores implements ShouldQueue
19{
20 use InteractsWithQueue, Queueable, SerializesModels;
21
22 public $timeout = 36000;
23 public $beatmapset;
24 public $maxScoreIds = null;
25
26 /**
27 * Create a new job instance.
28 *
29 * @return void
30 */
31 public function __construct(Beatmapset $beatmapset)
32 {
33 $this->beatmapset = $beatmapset;
34
35 foreach (Beatmap::MODES as $mode => $_modeInt) {
36 $this->maxScoreIds[$mode] = Model::getClass($mode)::max('score_id');
37 }
38 }
39
40 public function displayName()
41 {
42 return static::class." (Beatmapset {$this->beatmapset->getKey()})";
43 }
44
45 /**
46 * Execute the job.
47 *
48 * @return void
49 */
50 public function handle()
51 {
52 $beatmapIds = model_pluck($this->beatmapset->beatmaps(), 'beatmap_id');
53
54 foreach (Beatmap::MODES as $mode => $_modeInt) {
55 $query = new BoolQuery();
56 $query->filter(['terms' => ['beatmap_id' => $beatmapIds]]);
57 $query->filter(['range' => ['score_id' => ['lte' => $this->maxScoreIds[$mode]]]]);
58
59 $class = Model::getClass($mode);
60 // Just delete until no more matching rows.
61 $query = $class
62 ::with('user')
63 ->whereIn('beatmap_id', $beatmapIds)
64 ->where('score_id', '<=', $this->maxScoreIds[$mode] ?? 0)
65 ->orderBy('score', 'ASC')
66 ->limit(1000);
67 $scores = $query->get();
68
69 while ($scores->count() > 0) {
70 $scores->each->delete();
71 $scores = $query->get();
72 }
73 }
74 }
75
76 public function middleware(): array
77 {
78 return [new WithoutOverlapping((string) $this->beatmapset->getKey(), $this->timeout, $this->timeout)];
79 }
80}