Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 41 |
|
0.00% |
0 / 3 |
CRAP | |
0.00% |
0 / 1 |
DeleteExpiredUserImpactData | |
0.00% |
0 / 35 |
|
0.00% |
0 / 3 |
30 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
2 | |||
execute | |
0.00% |
0 / 25 |
|
0.00% |
0 / 1 |
6 | |||
getTimestampFromRelativeDate | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 |
1 | <?php |
2 | |
3 | namespace GrowthExperiments\Maintenance; |
4 | |
5 | use DateTime; |
6 | use Exception; |
7 | use GrowthExperiments\GrowthExperimentsServices; |
8 | use GrowthExperiments\UserImpact\DatabaseUserImpactStore; |
9 | use Maintenance; |
10 | use MediaWiki\MediaWikiServices; |
11 | use Wikimedia\Rdbms\SelectQueryBuilder; |
12 | use Wikimedia\Timestamp\ConvertibleTimestamp; |
13 | |
14 | $IP = getenv( 'MW_INSTALL_PATH' ); |
15 | if ( $IP === false ) { |
16 | $IP = __DIR__ . '/../../..'; |
17 | } |
18 | require_once "$IP/maintenance/Maintenance.php"; |
19 | |
20 | class DeleteExpiredUserImpactData extends Maintenance { |
21 | |
22 | public function __construct() { |
23 | parent::__construct(); |
24 | $this->requireExtension( 'GrowthExperiments' ); |
25 | $this->addDescription( 'Delete unused old data from the growthexperiments_user_impact table.' ); |
26 | $this->addOption( 'expiry', 'A relative timestring fragment passed to DateTime, such as "30days".', |
27 | false, true ); |
28 | $this->setBatchSize( 100 ); |
29 | } |
30 | |
31 | /** @inheritDoc */ |
32 | public function execute() { |
33 | $services = MediaWikiServices::getInstance(); |
34 | $growthServices = GrowthExperimentsServices::wrap( $services ); |
35 | $dbw = $growthServices->getLoadBalancer()->getConnection( DB_PRIMARY ); |
36 | |
37 | $expiry = $this->getOption( 'expiry', '30days' ); |
38 | $expiryTimestamp = $this->getTimestampFromRelativeDate( $expiry ); |
39 | |
40 | $queryBuilder = $dbw->newSelectQueryBuilder() |
41 | ->select( 'geui_user_id' ) |
42 | ->from( DatabaseUserImpactStore::TABLE_NAME ) |
43 | ->where( $dbw->expr( 'geui_timestamp', '<', $dbw->timestamp( $expiryTimestamp ) ) ) |
44 | ->orderBy( 'geui_timestamp', SelectQueryBuilder::SORT_ASC ) |
45 | ->limit( $this->getBatchSize() ) |
46 | ->caller( __METHOD__ ); |
47 | |
48 | $deletedCount = 0; |
49 | $idsToDelete = $queryBuilder->fetchFieldValues(); |
50 | while ( $idsToDelete !== [] ) { |
51 | $dbw->newDeleteQueryBuilder() |
52 | ->deleteFrom( DatabaseUserImpactStore::TABLE_NAME ) |
53 | ->where( [ 'geui_user_id' => $idsToDelete ] ) |
54 | ->caller( __METHOD__ ) |
55 | ->execute(); |
56 | $deletedCount += count( $idsToDelete ); |
57 | $this->output( '.' ); |
58 | $this->waitForReplication(); |
59 | $idsToDelete = $queryBuilder->fetchFieldValues(); |
60 | } |
61 | $this->output( "\nDeleted $deletedCount rows\n" ); |
62 | } |
63 | |
64 | /** |
65 | * @param string $relativeDate A relative date string fragment that will be prefixed with a |
66 | * minus sign and passed to the DateTime constructor |
67 | * @return string TS_MW formatted timestamp |
68 | */ |
69 | private function getTimestampFromRelativeDate( string $relativeDate ): string { |
70 | try { |
71 | $timestamp = new ConvertibleTimestamp( new DateTime( 'now - ' . $relativeDate ) ); |
72 | } catch ( Exception $e ) { |
73 | $this->fatalError( $e->getMessage() ); |
74 | } |
75 | return $timestamp->getTimestamp( TS_MW ); |
76 | } |
77 | |
78 | } |
79 | |
80 | $maintClass = DeleteExpiredUserImpactData::class; |
81 | require_once RUN_MAINTENANCE_IF_MAIN; |