MediaWiki  master
PoolCounterWork.php
Go to the documentation of this file.
1 <?php
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 ?? PoolCounter::factory( $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 
127  public function execute( $skipcache = false ) {
128  if ( $this->cacheable && !$skipcache ) {
129  if ( $this->isFastStaleEnabled() ) {
130  // In fast stale mode, do not wait if fallback() would succeed.
131  // Try to acquire the lock with timeout=0
132  $status = $this->poolCounter->acquireForAnyone( 0 );
133  if ( $status->isOK() && $status->value === PoolCounter::TIMEOUT ) {
134  // Lock acquisition would block: try fallback
135  $staleResult = $this->fallback( true );
136  if ( $staleResult !== false ) {
137  return $staleResult;
138  }
139  // No fallback available, so wait for the lock
140  $status = $this->poolCounter->acquireForAnyone();
141  } // else behave as if $status were returned in slow mode
142  } else {
143  $status = $this->poolCounter->acquireForAnyone();
144  }
145  } else {
146  $status = $this->poolCounter->acquireForMe();
147  }
148 
149  if ( !$status->isOK() ) {
150  // Respond gracefully to complete server breakage: just log it and do the work
151  $this->logError( $status );
152  return $this->doWork();
153  }
154 
155  switch ( $status->value ) {
157  // Better to ignore nesting pool counter limits than to fail.
158  // Assume that the outer pool limiting is reasonable enough.
159  /* no break */
160  case PoolCounter::LOCKED:
161  try {
162  return $this->doWork();
163  } finally {
164  $this->poolCounter->release();
165  }
166 
167  case PoolCounter::DONE:
168  $result = $this->getCachedWork();
169  if ( $result === false ) {
170  /* That someone else work didn't serve us.
171  * Acquire the lock for me
172  */
173  return $this->execute( true );
174  }
175  return $result;
176 
179  $result = $this->fallback( false );
180 
181  if ( $result !== false ) {
182  return $result;
183  }
184  /* no break */
185 
186  /* These two cases should never be hit... */
187  case PoolCounter::ERROR:
188  default:
189  $errors = [
190  PoolCounter::QUEUE_FULL => 'pool-queuefull',
191  PoolCounter::TIMEOUT => 'pool-timeout' ];
192 
193  $status = Status::newFatal( $errors[$status->value] ?? 'pool-errorunknown' );
194  $this->logError( $status );
195  return $this->error( $status );
196  }
197  }
198 }
PoolCounterWork\$cacheable
bool $cacheable
Definition: PoolCounterWork.php:31
StatusValue\newFatal
static newFatal( $message,... $parameters)
Factory function for fatal errors.
Definition: StatusValue.php:70
PoolCounterWork\isFastStaleEnabled
isFastStaleEnabled()
Should fast stale mode be used?
Definition: PoolCounterWork.php:88
PoolCounterWork\__construct
__construct(string $type, string $key, PoolCounter $poolCounter=null)
Definition: PoolCounterWork.php:40
PoolCounter\LOCK_HELD
const LOCK_HELD
Definition: PoolCounter.php:55
PoolCounter\LOCKED
const LOCKED
Definition: PoolCounter.php:47
PoolCounterWork\doWork
doWork()
Actually perform the work, caching it if needed.
wfDebugLog
wfDebugLog( $logGroup, $text, $dest='all', array $context=[])
Send a line to a supplementary debug log file, if configured, or main debug log if not.
Definition: GlobalFunctions.php:989
PoolCounter
When you have many workers (threads/servers) giving service, and a cached item expensive to produce e...
Definition: PoolCounter.php:45
PoolCounterWork\execute
execute( $skipcache=false)
Get the result of the work (whatever it is), or the result of the error() function.
Definition: PoolCounterWork.php:127
PoolCounterWork\getCachedWork
getCachedWork()
Retrieve the work from cache.
Definition: PoolCounterWork.php:58
PoolCounter\factory
static factory(string $type, string $key)
Create a Pool counter.
Definition: PoolCounter.php:117
PoolCounterWork\fallback
fallback( $fast)
A work not so good (eg.
Definition: PoolCounterWork.php:69
PoolCounter\QUEUE_FULL
const QUEUE_FULL
Definition: PoolCounter.php:53
PoolCounter\ERROR
const ERROR
Definition: PoolCounter.php:51
PoolCounterWork\$poolCounter
PoolCounter $poolCounter
Definition: PoolCounterWork.php:33
PoolCounterWork\error
error( $status)
Do something with the error, like showing it to the user.
Definition: PoolCounterWork.php:79
PoolCounterWork
Class for dealing with PoolCounters using class members.
Definition: PoolCounterWork.php:27
PoolCounter\TIMEOUT
const TIMEOUT
Definition: PoolCounter.php:54
PoolCounterWork\$type
string $type
Definition: PoolCounterWork.php:29
PoolCounterWork\logError
logError( $status)
Log an error.
Definition: PoolCounterWork.php:98
PoolCounter\DONE
const DONE
Definition: PoolCounter.php:49