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
6declare(strict_types=1);
7
8namespace App\Jobs;
9
10use App\Libraries\Search\ScoreSearch;
11use App\Models\Beatmap;
12use App\Models\Beatmapset;
13use App\Models\Solo\Score;
14use Illuminate\Bus\Queueable;
15use Illuminate\Contracts\Queue\ShouldQueue;
16use Illuminate\Database\Eloquent\Collection;
17use Illuminate\Queue\InteractsWithQueue;
18use Illuminate\Queue\Middleware\WithoutOverlapping;
19
20class RemoveBeatmapsetSoloScores implements ShouldQueue
21{
22 use InteractsWithQueue, Queueable;
23
24 public $timeout = 36000;
25
26 private int $beatmapsetId;
27 private int $maxScoreId;
28 private array $schemas;
29 private ScoreSearch $scoreSearch;
30
31 /**
32 * Create a new job instance.
33 *
34 * @return void
35 */
36 public function __construct(Beatmapset $beatmapset)
37 {
38 $this->beatmapsetId = $beatmapset->getKey();
39 $this->maxScoreId = Score::max('id') ?? 0;
40 }
41
42 public function displayName()
43 {
44 return static::class." (Beatmapset {$this->beatmapsetId})";
45 }
46
47 /**
48 * Execute the job.
49 *
50 * @return void
51 */
52 public function handle()
53 {
54 $this->scoreSearch = new ScoreSearch();
55 $this->schemas = $this->scoreSearch->getActiveSchemas();
56
57 $beatmapIds = Beatmap::where('beatmapset_id', $this->beatmapsetId)->pluck('beatmap_id');
58 Score
59 ::whereIn('beatmap_id', $beatmapIds)
60 ->where('id', '<=', $this->maxScoreId)
61 ->chunkById(1000, fn ($scores) => $this->deleteScores($scores));
62 }
63
64 public function middleware(): array
65 {
66 return [new WithoutOverlapping((string) $this->beatmapsetId, $this->timeout, $this->timeout)];
67 }
68
69 private function deleteScores(Collection $scores): void
70 {
71 $ids = $scores->pluck('id')->all();
72
73 Score::whereKey($ids)->update(['ranked' => false]);
74 $this->scoreSearch->queueForIndex($this->schemas, $ids);
75 }
76}