Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 50 |
|
0.00% |
0 / 6 |
CRAP | |
0.00% |
0 / 1 |
PurgeExpiredMentorStatus | |
0.00% |
0 / 44 |
|
0.00% |
0 / 6 |
210 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
2 | |||
initServices | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
getRows | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
2 | |||
filterAndBatch | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
42 | |||
execute | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
12 | |||
deleteTimestamps | |
0.00% |
0 / 12 |
|
0.00% |
0 / 1 |
6 |
1 | <?php |
2 | |
3 | namespace GrowthExperiments\Maintenance; |
4 | |
5 | use GrowthExperiments\MentorDashboard\MentorTools\MentorStatusManager; |
6 | use MediaWiki\Maintenance\Maintenance; |
7 | use Wikimedia\Rdbms\IDatabase; |
8 | use Wikimedia\Rdbms\IReadableDatabase; |
9 | use Wikimedia\Timestamp\ConvertibleTimestamp; |
10 | |
11 | $IP = getenv( 'MW_INSTALL_PATH' ); |
12 | if ( $IP === false ) { |
13 | $IP = __DIR__ . '/../../..'; |
14 | } |
15 | require_once "$IP/maintenance/Maintenance.php"; |
16 | |
17 | /** |
18 | * Purge expired rows related to mentor status from user_properties |
19 | */ |
20 | class PurgeExpiredMentorStatus extends Maintenance { |
21 | |
22 | /** @var IReadableDatabase */ |
23 | private $dbr; |
24 | |
25 | /** @var IDatabase */ |
26 | private $dbw; |
27 | |
28 | public function __construct() { |
29 | parent::__construct(); |
30 | $this->requireExtension( 'GrowthExperiments' ); |
31 | $this->addDescription( |
32 | 'Remove expired values of MentorStatusManager::MENTOR_AWAY_TIMESTAMP_PREF from user_properties' |
33 | ); |
34 | $this->addOption( 'dry-run', 'Do not actually change anything.' ); |
35 | $this->setBatchSize( 100 ); |
36 | } |
37 | |
38 | private function initServices(): void { |
39 | $this->dbr = $this->getReplicaDB(); |
40 | $this->dbw = $this->getPrimaryDB(); |
41 | } |
42 | |
43 | private function getRows() { |
44 | yield from $this->dbr->newSelectQueryBuilder() |
45 | ->select( [ 'up_user', 'up_value' ] ) |
46 | ->from( 'user_properties' ) |
47 | ->where( [ 'up_property' => MentorStatusManager::MENTOR_AWAY_TIMESTAMP_PREF ] ) |
48 | ->caller( __METHOD__ )->fetchResultSet(); |
49 | } |
50 | |
51 | private function filterAndBatch() { |
52 | $batch = []; |
53 | foreach ( $this->getRows() as $row ) { |
54 | if ( |
55 | $row->up_value === null || |
56 | ConvertibleTimestamp::convert( TS_UNIX, $row->up_value ) < wfTimestamp( TS_UNIX ) |
57 | ) { |
58 | $batch[] = $row->up_user; |
59 | |
60 | if ( count( $batch ) >= $this->getBatchSize() ) { |
61 | yield $batch; |
62 | $batch = []; |
63 | } |
64 | } |
65 | } |
66 | |
67 | if ( $batch !== [] ) { |
68 | yield $batch; |
69 | } |
70 | } |
71 | |
72 | /** |
73 | * @inheritDoc |
74 | */ |
75 | public function execute() { |
76 | $this->initServices(); |
77 | |
78 | $deletedCount = 0; |
79 | foreach ( $this->filterAndBatch() as $batch ) { |
80 | $this->deleteTimestamps( $batch ); |
81 | $deletedCount += count( $batch ); |
82 | } |
83 | |
84 | if ( $this->getOption( 'dry-run' ) ) { |
85 | $this->output( "Would delete $deletedCount rows from user_properties.\n" ); |
86 | } else { |
87 | $this->output( "Deleted $deletedCount rows from user_properties.\n" ); |
88 | } |
89 | } |
90 | |
91 | private function deleteTimestamps( array $toDelete ): void { |
92 | if ( $this->getOption( 'dry-run' ) ) { |
93 | return; |
94 | } |
95 | $this->beginTransaction( $this->dbw, __METHOD__ ); |
96 | $this->dbw->newDeleteQueryBuilder() |
97 | ->deleteFrom( 'user_properties' ) |
98 | ->where( [ |
99 | 'up_property' => MentorStatusManager::MENTOR_AWAY_TIMESTAMP_PREF, |
100 | 'up_user' => $toDelete |
101 | ] ) |
102 | ->caller( __METHOD__ ) |
103 | ->execute(); |
104 | $this->commitTransaction( $this->dbw, __METHOD__ ); |
105 | } |
106 | } |
107 | |
108 | $maintClass = PurgeExpiredMentorStatus::class; |
109 | require_once RUN_MAINTENANCE_IF_MAIN; |