MediaWiki REL1_41
PoolCounterWork.php
Go to the documentation of this file.
1<?php
23
27abstract class PoolCounterWork {
29 protected $type = 'generic';
31 protected $cacheable = false; // does this override getCachedWork() ?
33 private $poolCounter;
34
40 public function __construct( string $type, string $key, PoolCounter $poolCounter = null ) {
41 $this->type = $type;
42 // MW >= 1.35
43 $this->poolCounter = $poolCounter ??
44 MediaWikiServices::getInstance()->getPoolCounterFactory()->create( $type, $key );
45 }
46
52 abstract public function doWork();
53
59 public function getCachedWork() {
60 return false;
61 }
62
70 public function fallback( $fast ) {
71 return false;
72 }
73
80 public function error( $status ) {
81 return false;
82 }
83
89 protected function isFastStaleEnabled() {
90 return $this->poolCounter->isFastStaleEnabled();
91 }
92
99 public function logError( $status ) {
100 $key = $this->poolCounter->getKey();
101
102 wfDebugLog( 'poolcounter', "Pool key '$key' ({$this->type}): "
103 . $status->getMessage()->inLanguage( 'en' )->useDatabase( false )->text() );
104 }
105
133 public function execute( $skipcache = false ) {
134 if ( !$this->cacheable || $skipcache ) {
135 $status = $this->poolCounter->acquireForMe();
136 } else {
137 if ( $this->isFastStaleEnabled() ) {
138 // In fast stale mode, check for existing locks by acquiring lock with 0 timeout
139 $status = $this->poolCounter->acquireForAnyone( 0 );
140 if ( $status->isOK() && $status->value === PoolCounter::TIMEOUT ) {
141 // Lock acquisition would block: try fallback
142 $staleResult = $this->fallback( true );
143 if ( $staleResult !== false ) {
144 return $staleResult;
145 }
146 // No fallback available, so wait for the lock
147 $status = $this->poolCounter->acquireForAnyone();
148 } // else behave as if $status were returned in slow mode
149 } else {
150 $status = $this->poolCounter->acquireForAnyone();
151 }
152 }
153
154 if ( !$status->isOK() ) {
155 // Respond gracefully to complete server breakage: just log it and do the work
156 $this->logError( $status );
157 return $this->doWork();
158 }
159
160 switch ( $status->value ) {
162 // Better to ignore nesting pool counter limits than to fail.
163 // Assume that the outer pool limiting is reasonable enough.
164 /* no break */
166 try {
167 return $this->doWork();
168 } finally {
169 $this->poolCounter->release();
170 }
171 // no fall-through, because try returns or throws
173 $result = $this->getCachedWork();
174 if ( $result === false ) {
175 /* That someone else work didn't serve us.
176 * Acquire the lock for me
177 */
178 return $this->execute( true );
179 }
180 return $result;
181
184 $result = $this->fallback( false );
185
186 if ( $result !== false ) {
187 return $result;
188 }
189 /* no break */
190
191 /* These two cases should never be hit... */
193 default:
194 $errors = [
195 PoolCounter::QUEUE_FULL => 'pool-queuefull',
196 PoolCounter::TIMEOUT => 'pool-timeout' ];
197
198 $status = Status::newFatal( $errors[$status->value] ?? 'pool-errorunknown' );
199 $this->logError( $status );
200 return $this->error( $status );
201 }
202 }
203}
wfDebugLog( $logGroup, $text, $dest='all', array $context=[])
Send a line to a supplementary debug log file, if configured, or main debug log if not.
Service locator for MediaWiki core services.
Generic operation result class Has warning/error list, boolean status and arbitrary value.
Definition Status.php:58
Class for dealing with PoolCounters using class members.
error( $status)
Do something with the error, like showing it to the user.
getCachedWork()
Retrieve the work from cache.
fallback( $fast)
A work not so good (eg.
execute( $skipcache=false)
Get the result of the work (whatever it is), or the result of the error() function.
isFastStaleEnabled()
Should fast stale mode be used?
doWork()
Actually perform the work, caching it if needed.
__construct(string $type, string $key, PoolCounter $poolCounter=null)
logError( $status)
Log an error.
Semaphore semantics to restrict how many workers may concurrently perform a task.
const QUEUE_FULL
const LOCK_HELD