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\Console\Commands;
7
8use App\Libraries\Notification\BatchIdentities;
9use App\Models\UserNotification;
10use Illuminate\Console\Command;
11
12class UserNotificationsCleanup extends Command
13{
14 protected $signature = 'user-notifications:cleanup';
15
16 protected $description = 'Deletes old user notifications';
17
18 public function handle()
19 {
20 $total = $GLOBALS['cfg']['osu']['notification']['cleanup']['max_delete_per_run'];
21
22 if ($total === 0) {
23 return;
24 }
25
26 $perLoop = min($total, 10000);
27 $loops = $total / $perLoop;
28
29 $createdBefore = now()->subDays($GLOBALS['cfg']['osu']['notification']['cleanup']['keep_days']);
30 $this->line("Deleting user notifications before {$createdBefore}");
31
32 $progress = $this->output->createProgressBar($total);
33 $deletedTotal = 0;
34
35 for ($i = 0; $i < $loops; $i++) {
36 $userNotifications = UserNotification
37 ::with('notification')
38 ->orderBy('id', 'ASC')
39 ->limit($perLoop)
40 ->get();
41
42 $notificationIdByUserIds = [];
43 $pastKeepDays = false;
44
45 foreach ($userNotifications as $n) {
46 if ($n->created_at > $createdBefore) {
47 $pastKeepDays = true;
48 break;
49 }
50
51 $notificationIdByUserIds[$n->user_id][] = $n->notification->toIdentityJson();
52 }
53
54 foreach ($notificationIdByUserIds as $userId => $notificationIds) {
55 UserNotification::batchDestroy(
56 $userId,
57 BatchIdentities::fromParams(['notifications' => $notificationIds])
58 );
59 $deleted = count($notificationIds);
60 $deletedTotal += $deleted;
61 datadog_increment('notifications_cleanup.user_notifications', value: $deleted);
62 $progress->advance($deleted);
63 }
64
65 if ($pastKeepDays || count($userNotifications) < $perLoop) {
66 break;
67 }
68 }
69
70 $progress->finish();
71 $this->line('');
72 $this->line("Deleted {$deletedTotal} user notifications.");
73 }
74}