Completed
Push — master ( 951284...b5c57e )
by
unknown
06:36 queued 11s
created

client/includes/ChangeNotificationJob.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Wikibase\Client;
4
5
use Job;
6
use Psr\Log\LoggerInterface;
7
use Title;
8
use Wikibase\Client\Changes\ChangeHandler;
9
use Wikibase\Lib\Changes\EntityChange;
10
use Wikimedia\Assert\Assert;
11
12
/**
13
 * Job for notifying a client wiki of a batch of changes on the repository.
14
 *
15
 * @see @ref md_docs_topics_change-propagation for an overview of the change propagation mechanism.
16
 *
17
 * @license GPL-2.0-or-later
18
 * @author Daniel Kinzler
19
 */
20
class ChangeNotificationJob extends Job {
21
22
	/**
23
	 * @var EntityChange[]|null Initialized lazily by getChanges.
24
	 */
25
	private $changes = null;
26
27
	/**
28
	 * @var ChangeHandler|null
29
	 */
30
	private $changeHandler = null;
31
32
	/**
33
	 * @var LoggerInterface
34
	 */
35
	private $logger;
36
37
	/**
38
	 * Constructs a ChangeNotificationJob representing the changes given by $changeIds.
39
	 *
40
	 * @note the constructor's signature is dictated by Job::factory, so we'll have to
41
	 *           live with it even though it's rather ugly for our use case.
42
	 *
43
	 * @see      Job::factory.
44
	 *
45
	 * @param Title $title
46
	 * @param array $params Needs to have two keys: "repo": the id of the repository,
47
	 *     "changeIds": array of change ids.
48
	 */
49
	public function __construct( Title $title, array $params = [] ) {
50
		parent::__construct( 'ChangeNotification', $title, $params );
51
52
		Assert::parameterType( 'array', $params, '$params' );
53
		Assert::parameter(
54
			isset( $params['repo'] ),
55
			'$params',
56
			'$params[\'repo\'] not set.'
57
		);
58
		Assert::parameter(
59
			isset( $params['changeIds'] ) && is_array( $params['changeIds'] ),
60
			'$params',
61
			'$params[\'changeIds\'] not set or not an array.'
62
		);
63
64
		// TODO inject me
65
		$this->logger = WikibaseClient::getDefaultInstance()->getLogger();
66
	}
67
68
	/**
69
	 * Returns the batch of changes that should be processed.
70
	 *
71
	 * EntityChange objects are loaded using a EntityChangeLookup.
72
	 *
73
	 * @return EntityChange[] the changes to process.
74
	 */
75
	private function getChanges() {
76
		if ( $this->changes === null ) {
77
			$params = $this->getParams();
78
			$ids = $params['changeIds'];
79
80
			$this->logger->debug(
81
				"{method}: loading {idCount} changes.",
82
				[
83
					'method' => __METHOD__,
84
					'idCount' => count( $ids ),
85
				]
86
			);
87
88
			// load actual change records from the changes table
89
			// TODO: allow mock store for testing!
90
			$changeLookup = WikibaseClient::getDefaultInstance()->getStore()->getEntityChangeLookup();
91
			$this->changes = $changeLookup->loadByChangeIds( $ids );
92
93
			$this->logger->debug(
94
				"{method}: loaded {changeCount} of {idCount} changes.",
95
				[
96
					'method' => __METHOD__,
97
					'changeCount' => count( $this->changes ),
98
					'idCount' => count( $ids ),
99
				]
100
			);
101
102
			if ( count( $this->changes ) != count( $ids ) ) {
103
				trigger_error( "Number of changes loaded mismatches the number of change IDs provided: "
104
					. count( $this->changes ) . " != " . count( $ids ) . ". "
105
					. " Some changes were lost, possibly due to premature pruning.",
106
					E_USER_WARNING );
107
			}
108
		}
109
110
		return $this->changes;
111
	}
112
113
	/**
114
	 * @return bool success
115
	 */
116
	public function run() {
117
		$changes = $this->getChanges();
118
119
		$changeHandler = $this->getChangeHandler();
120
		$changeHandler->handleChanges( $changes, $this->getRootJobParams() );
121
122
		if ( $changes ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $changes of type Wikibase\Lib\Changes\EntityChange[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
123
			/** @var EntityChange $last */
124
			$changeCount = count( $changes );
125
			$last = end( $changes );
126
127
			$this->logger->debug(
128
				"{method}: processed {changeCount} notifications, up to {lastChange}, timestamp {lastTime}; Lag is {lastAge} seconds.",
129
				[
130
					'method' => __METHOD__,
131
					'changeCount' => $changeCount,
132
					'lastChange' => $last->getId(),
133
					'lastTime' => $last->getTime(),
134
					'lastAge' => $last->getAge(),
135
				]
136
			);
137
		} else {
138
			$this->logger->debug( '{method}: processed no notifications.', [ 'method' => __METHOD__ ] );
139
		}
140
141
		return true;
142
	}
143
144
	/**
145
	 * @return ChangeHandler
146
	 */
147
	private function getChangeHandler() {
148
		if ( !$this->changeHandler ) {
149
			$this->changeHandler = WikibaseClient::getDefaultInstance()->getChangeHandler();
150
		}
151
152
		return $this->changeHandler;
153
	}
154
155
}
156