MediaWiki  master
PoolCounterWork.php
Go to the documentation of this file.
1 <?php
23 
27 abstract 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 */
165  case PoolCounter::LOCKED:
166  try {
167  return $this->doWork();
168  } finally {
169  $this->poolCounter->release();
170  }
171  // no fall-through, because try returns or throws
172  case PoolCounter::DONE:
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... */
192  case PoolCounter::ERROR:
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.
Definition: PoolCounter.php:51
const QUEUE_FULL
Definition: PoolCounter.php:59
const LOCKED
Definition: PoolCounter.php:53
const TIMEOUT
Definition: PoolCounter.php:60
const LOCK_HELD
Definition: PoolCounter.php:61