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  // no fall-through, because try returns or throws
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 }
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.
PoolCounter $poolCounter
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.
When you have many workers (threads/servers) giving service, and a cached item expensive to produce e...
Definition: PoolCounter.php:49
const QUEUE_FULL
Definition: PoolCounter.php:57
const LOCKED
Definition: PoolCounter.php:51
const TIMEOUT
Definition: PoolCounter.php:58
static factory(string $type, string $key)
Create a Pool counter.
const LOCK_HELD
Definition: PoolCounter.php:59
static newFatal( $message,... $parameters)
Factory function for fatal errors.
Definition: StatusValue.php:70