Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
89.29% covered (warning)
89.29%
75 / 84
50.00% covered (danger)
50.00%
1 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
UpdateQueryServiceLag
96.15% covered (success)
96.15%
75 / 78
50.00% covered (danger)
50.00%
1 / 2
5
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
51 / 51
100.00% covered (success)
100.00%
1 / 1
1
 execute
88.89% covered (warning)
88.89%
24 / 27
0.00% covered (danger)
0.00%
0 / 1
4.02
1<?php
2
3namespace WikidataOrg;
4
5use Maintenance;
6use MediaWiki\Logger\LoggerFactory;
7use MediaWiki\MediaWikiServices;
8use WikidataOrg\QueryServiceLag\CacheQueryServiceLagStore;
9use WikidataOrg\QueryServiceLag\WikimediaPrometheusQueryServiceLagProvider;
10
11$basePath = getenv( 'MW_INSTALL_PATH' ) !== false ?
12    getenv( 'MW_INSTALL_PATH' ) :
13    __DIR__ . '/../../..';
14
15require_once $basePath . '/maintenance/Maintenance.php';
16
17/**
18 * @license GPL-2.0-or-later
19 * @author Addshore
20 */
21class UpdateQueryServiceLag extends Maintenance {
22
23    /**
24     * 70 as the primary use case of this script is to be run by a cron job every 60 seconds
25     * 70 should mean that a cached value is always set
26     * If the script dies or something stops running we will not stop Wikidata from being edited
27     * while the script is broken.
28     */
29    private const TTL_DEFAULT = 70;
30
31    private const POOLED_SERVER_MIN_QUERY_RATE = 1.0;
32
33    public function __construct() {
34        parent::__construct();
35
36        $this->addDescription(
37            'Update the cache maxlag for the query service from Prometheus'
38        );
39
40        $this->addOption( 'dry-run', 'Do not cache lag, only output values.', false, false );
41        $this->addOption(
42            'cluster',
43            'Supported for backwards compatibility. To be removed.',
44            false,
45            true,
46            false,
47            true
48        );
49        $this->addOption(
50            'prometheus',
51            'One or more Prometheus services to query. e.g. "prometheus.svc.eqiad.wmnet"',
52            true,
53            true,
54            false,
55            true
56        );
57        $this->addOption(
58            'lb',
59            'Supported for backwards compatibility. To be removed.',
60            false,
61            true,
62            false,
63            true
64        );
65        $this->addOption(
66            'lb-pool',
67            'Supported for backwards compatibility. To be removed.',
68            false,
69            true,
70            false,
71            false
72        );
73
74        $this->addOption(
75            'ttl',
76            "The TTL for the cached lag value. Defaults to " . self::TTL_DEFAULT . " seconds",
77            false,
78            true
79        );
80
81        $this->addOption(
82            'pooled-server-min-query-rate',
83            "The minimal query rate that is expected to be served from a pooled server. " .
84            "Defaults to " . self::POOLED_SERVER_MIN_QUERY_RATE,
85            false,
86            true
87        );
88
89        $this->requireExtension( 'Wikidata.org' );
90    }
91
92    public function execute() {
93        $prometheusUrls = [];
94        foreach ( $this->getOption( 'prometheus' ) as $host ) {
95            $prometheusUrls[] = 'http://' . $host . '/ops/api/v1/query';
96        }
97        $ttl = (int)$this->getOption( 'ttl', self::TTL_DEFAULT );
98        $minQueryRate = floatval( $this->getOption( "pooled-server-min-query-rate",
99            self::POOLED_SERVER_MIN_QUERY_RATE ) );
100
101        $mw = MediaWikiServices::getInstance();
102        // For now just use the Wikibase log channel
103        $logger = LoggerFactory::getInstance( 'Wikibase' );
104
105        $lagProvider = new WikimediaPrometheusQueryServiceLagProvider(
106            $mw->getHttpRequestFactory(),
107            $logger,
108            $prometheusUrls,
109            $minQueryRate
110        );
111        [ 'lag' => $lag, 'host' => $server ] = $lagProvider->getLag();
112
113        if ( $lag === null ) {
114            $this->fatalError(
115                'Failed to get lagged pooled server from prometheus.'
116            );
117        }
118
119        $this->output( "Got lag of: " . $lag . " for host: " . $server . ".\n" );
120
121        if ( !$this->getOption( 'dry-run' ) ) {
122            $store = new CacheQueryServiceLagStore(
123                $mw->getMainWANObjectCache(),
124                $ttl
125            );
126            $store->updateLag( $server, $lag );
127            $this->output( "Stored in cache with TTL of: " . $ttl . ".\n" );
128        }
129    }
130}
131
132$maintClass = UpdateQueryServiceLag::class;
133require_once RUN_MAINTENANCE_IF_MAIN;