summaryrefslogtreecommitdiff
blob: bf9aa6e8ef9b6fba4268d5afe8ba3bb536bc9422 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
<?php
/**
 * Web service utility class.
 *
 * @file
 * @author Niklas Laxström
 * @license GPL-2.0-or-later
 */

use MediaWiki\MediaWikiServices;

/**
 * Runs multiple web service queries asynchronously to save time.
 *
 * @ingroup TranslationWebService
 * @since 2015.02
 */
class QueryAggregator {
	protected $queries = [];
	protected $responses = [];
	protected $timeout = 0;
	protected $hasRun = false;

	/**
	 * Register a query to be run.
	 * @param TranslationQuery $query
	 * @return mixed Query id that can be used to fetch results.
	 */
	public function addQuery( TranslationQuery $query ) {
		$this->queries[] = $query;

		$this->timeout = max( $query->getTimeout(), $this->timeout );
		return count( $this->queries ) - 1;
	}

	/**
	 * Returns a response for a query.
	 * @param mixed $id Query id.
	 * @return TranslationQueryResponse
	 * @throws RuntimeException if called before run() has been called.
	 */
	public function getResponse( $id ) {
		if ( !$this->hasRun ) {
			throw new RuntimeException( 'Tried to get response before queries ran' );
		}

		return TranslationQueryResponse::newFromMultiHttp(
			$this->responses[$id],
			$this->queries[$id]
		);
	}

	/**
	 * Runs all the queries.
	 */
	public function run() {
		global $wgSitename;

		$version = TranslateUtils::getVersion();

		$clientOptions = [
			'reqTimeout' => $this->timeout,
			'connTimeout' => 3,
			'userAgent' => "MediaWiki Translate extension $version for $wgSitename"
		];

		$httpRequestFactory = MediaWikiServices::getInstance()->getHttpRequestFactory();
		// BC for MW < 1.35
		if ( is_callable( [ $httpRequestFactory, 'createMultiClient' ] ) ) {
			$http = $httpRequestFactory->createMultiClient( $clientOptions );
		} else {
			$http = new MultiHttpClient( $clientOptions );
		}

		$responses = $http->runMulti( $this->getMultiHttpQueries( $this->queries ) );
		foreach ( $responses as $index => $response ) {
			$this->responses[$index] = $response;
		}
		$this->hasRun = true;
	}

	/**
	 * Formats queries for format used by MultiHttpClient class.
	 * @param TranslationQuery[] $queries
	 * @return array[]
	 */
	protected function getMultiHttpQueries( $queries ) {
		$converter = function ( TranslationQuery $q ) {
			return [
				'url' => $q->getUrl(),
				'method' => $q->getMethod(),
				'query' => $q->getQueryParameters(),
				'body' => $q->getBody(),
				'headers' => $q->getHeaders(),
			];
		};

		return array_map( $converter, $queries );
	}
}