MediaWiki  master
PoolCounterWork.php
Go to the documentation of this file.
1 <?php
22 
26 abstract class PoolCounterWork {
28  protected $type = 'generic';
30  protected $cacheable = false; // does this override getCachedWork() ?
32  private $poolCounter;
33 
39  public function __construct( string $type, string $key, PoolCounter $poolCounter = null ) {
40  $this->type = $type;
41  // MW >= 1.35
42  $this->poolCounter = $poolCounter ??
43  MediaWikiServices::getInstance()->getPoolCounterFactory()->create( $type, $key );
44  }
45 
51  abstract public function doWork();
52 
58  public function getCachedWork() {
59  return false;
60  }
61 
69  public function fallback( $fast ) {
70  return false;
71  }
72 
79  public function error( $status ) {
80  return false;
81  }
82 
88  protected function isFastStaleEnabled() {
89  return $this->poolCounter->isFastStaleEnabled();
90  }
91 
98  public function logError( $status ) {
99  $key = $this->poolCounter->getKey();
100 
101  wfDebugLog( 'poolcounter', "Pool key '$key' ({$this->type}): "
102  . $status->getMessage()->inLanguage( 'en' )->useDatabase( false )->text() );
103  }
104 
132  public function execute( $skipcache = false ) {
133  if ( !$this->cacheable || $skipcache ) {
134  $status = $this->poolCounter->acquireForMe();
135  } else {
136  if ( $this->isFastStaleEnabled() ) {
137  // In fast stale mode, check for existing locks by acquiring lock with 0 timeout
138  $status = $this->poolCounter->acquireForAnyone( 0 );
139  if ( $status->isOK() && $status->value === PoolCounter::TIMEOUT ) {
140  // Lock acquisition would block: try fallback
141  $staleResult = $this->fallback( true );
142  if ( $staleResult !== false ) {
143  return $staleResult;
144  }
145  // No fallback available, so wait for the lock
146  $status = $this->poolCounter->acquireForAnyone();
147  } // else behave as if $status were returned in slow mode
148  } else {
149  $status = $this->poolCounter->acquireForAnyone();
150  }
151  }
152 
153  if ( !$status->isOK() ) {
154  // Respond gracefully to complete server breakage: just log it and do the work
155  $this->logError( $status );
156  return $this->doWork();
157  }
158 
159  switch ( $status->value ) {
161  // Better to ignore nesting pool counter limits than to fail.
162  // Assume that the outer pool limiting is reasonable enough.
163  /* no break */
164  case PoolCounter::LOCKED:
165  try {
166  return $this->doWork();
167  } finally {
168  $this->poolCounter->release();
169  }
170  // no fall-through, because try returns or throws
171  case PoolCounter::DONE:
172  $result = $this->getCachedWork();
173  if ( $result === false ) {
174  /* That someone else work didn't serve us.
175  * Acquire the lock for me
176  */
177  return $this->execute( true );
178  }
179  return $result;
180 
183  $result = $this->fallback( false );
184 
185  if ( $result !== false ) {
186  return $result;
187  }
188  /* no break */
189 
190  /* These two cases should never be hit... */
191  case PoolCounter::ERROR:
192  default:
193  $errors = [
194  PoolCounter::QUEUE_FULL => 'pool-queuefull',
195  PoolCounter::TIMEOUT => 'pool-timeout' ];
196 
197  $status = Status::newFatal( $errors[$status->value] ?? 'pool-errorunknown' );
198  $this->logError( $status );
199  return $this->error( $status );
200  }
201  }
202 }
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.
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.
Definition: PoolCounter.php:49
const QUEUE_FULL
Definition: PoolCounter.php:57
const LOCKED
Definition: PoolCounter.php:51
const TIMEOUT
Definition: PoolCounter.php:58
const LOCK_HELD
Definition: PoolCounter.php:59
static newFatal( $message,... $parameters)
Factory function for fatal errors.
Definition: StatusValue.php:73