MediaWiki  master
PoolCounterWork.php
Go to the documentation of this file.
1 <?php
24 abstract class PoolCounterWork {
26  protected $type = 'generic';
28  protected $cacheable = false; // does this override getCachedWork() ?
30  private $poolCounter;
31 
37  public function __construct( string $type, string $key, PoolCounter $poolCounter = null ) {
38  $this->type = $type;
39  // MW >= 1.35
40  $this->poolCounter = $poolCounter ?? PoolCounter::factory( $type, $key );
41  }
42 
48  abstract public function doWork();
49 
55  public function getCachedWork() {
56  return false;
57  }
58 
66  public function fallback( $fast ) {
67  return false;
68  }
69 
76  public function error( $status ) {
77  return false;
78  }
79 
85  protected function isFastStaleEnabled() {
86  return $this->poolCounter->isFastStaleEnabled();
87  }
88 
95  public function logError( $status ) {
96  $key = $this->poolCounter->getKey();
97 
98  wfDebugLog( 'poolcounter', "Pool key '$key' ({$this->type}): "
99  . $status->getMessage()->inLanguage( 'en' )->useDatabase( false )->text() );
100  }
101 
129  public function execute( $skipcache = false ) {
130  if ( !$this->cacheable || $skipcache ) {
131  $status = $this->poolCounter->acquireForMe();
132  } else {
133  if ( $this->isFastStaleEnabled() ) {
134  // In fast stale mode, check for existing locks by acquiring lock with 0 timeout
135  $status = $this->poolCounter->acquireForAnyone( 0 );
136  if ( $status->isOK() && $status->value === PoolCounter::TIMEOUT ) {
137  // Lock acquisition would block: try fallback
138  $staleResult = $this->fallback( true );
139  if ( $staleResult !== false ) {
140  return $staleResult;
141  }
142  // No fallback available, so wait for the lock
143  $status = $this->poolCounter->acquireForAnyone();
144  } // else behave as if $status were returned in slow mode
145  } else {
146  $status = $this->poolCounter->acquireForAnyone();
147  }
148  }
149 
150  if ( !$status->isOK() ) {
151  // Respond gracefully to complete server breakage: just log it and do the work
152  $this->logError( $status );
153  return $this->doWork();
154  }
155 
156  switch ( $status->value ) {
158  // Better to ignore nesting pool counter limits than to fail.
159  // Assume that the outer pool limiting is reasonable enough.
160  /* no break */
161  case PoolCounter::LOCKED:
162  try {
163  return $this->doWork();
164  } finally {
165  $this->poolCounter->release();
166  }
167  // no fall-through, because try returns or throws
168  case PoolCounter::DONE:
169  $result = $this->getCachedWork();
170  if ( $result === false ) {
171  /* That someone else work didn't serve us.
172  * Acquire the lock for me
173  */
174  return $this->execute( true );
175  }
176  return $result;
177 
180  $result = $this->fallback( false );
181 
182  if ( $result !== false ) {
183  return $result;
184  }
185  /* no break */
186 
187  /* These two cases should never be hit... */
188  case PoolCounter::ERROR:
189  default:
190  $errors = [
191  PoolCounter::QUEUE_FULL => 'pool-queuefull',
192  PoolCounter::TIMEOUT => 'pool-timeout' ];
193 
194  $status = Status::newFatal( $errors[$status->value] ?? 'pool-errorunknown' );
195  $this->logError( $status );
196  return $this->error( $status );
197  }
198  }
199 }
wfDebugLog( $logGroup, $text, $dest='all', array $context=[])
Send a line to a supplementary debug log file, if configured, or main debug log if not.
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:50
const QUEUE_FULL
Definition: PoolCounter.php:58
const LOCKED
Definition: PoolCounter.php:52
const TIMEOUT
Definition: PoolCounter.php:59
static factory(string $type, string $key)
Create a Pool counter.
const LOCK_HELD
Definition: PoolCounter.php:60
static newFatal( $message,... $parameters)
Factory function for fatal errors.
Definition: StatusValue.php:73