MediaWiki  master
PoolCounter Class Reference

When you have many workers (threads/servers) giving service, and a cached item expensive to produce expires, you may get several workers doing the job at the same time. More...

Inheritance diagram for PoolCounter:

Public Member Functions

 acquireForAnyone ( $timeout=null)
 I want to do this task, but if anyone else does it instead, it's also fine for me. More...
 
 acquireForMe ( $timeout=null)
 I want to do this task and I need to do it myself. More...
 
 getKey ()
 
 isFastStaleEnabled ()
 
 release ()
 I have successfully finished my task. More...
 

Static Public Member Functions

static factory (string $type, string $key)
 Create a Pool counter. More...
 

Public Attributes

const DONE = 3
 
const ERROR = -1
 
const LOCK_HELD = -5
 
const LOCKED = 1
 
const NOT_LOCKED = -2
 
const QUEUE_FULL = -3
 
const RELEASED = 2
 
const TIMEOUT = -4
 

Protected Member Functions

 __construct (array $conf, string $type, string $key)
 
 hashKeyIntoSlots ( $type, $key, $slots)
 Given a key (any string) and the number of lots, returns a slot key (a prefix with a suffix integer from the [0..($slots-1)] range). More...
 
 onAcquire ()
 Update any lock tracking information when the lock is acquired. More...
 
 onRelease ()
 Update any lock tracking information when the lock is released. More...
 
 precheckAcquire ()
 Checks that the lock request is sane. More...
 

Protected Attributes

string $key
 All workers with the same key share the lock. More...
 
int $maxqueue
 If this number of workers are already working/waiting, fail instead of wait. More...
 
int $slots = 0
 Maximum number of workers working on this task type, regardless of key. More...
 
int $timeout
 Maximum time in seconds to wait for the lock. More...
 
int $workers
 Maximum number of workers working on tasks with the same key simultaneously. More...
 

Private Attributes

bool $fastStale
 Enable fast stale mode (T250248). More...
 
bool $isMightWaitKey
 Whether the key is a "might wait" key. More...
 

Static Private Attributes

static bool $acquiredMightWaitKey = 0
 Whether this process holds a "might wait" lock key. More...
 

Detailed Description

When you have many workers (threads/servers) giving service, and a cached item expensive to produce expires, you may get several workers doing the job at the same time.

Given enough requests and the item expiring fast (non-cacheable, lots of edits...) that single work can end up unfairly using most (all) of the cpu of the pool. This is also known as 'Michael Jackson effect' since this effect triggered on the english wikipedia on the day Michael Jackson died, the biographical article got hit with several edits per minutes and hundreds of read hits.

The PoolCounter provides semaphore semantics for restricting the number of workers that may be concurrently performing such single task. Only one key can be locked by any PoolCounter instance of a process, except for keys that start with "nowait:". However, only 0 timeouts (non-blocking requests) can be used with "nowait:" keys.

By default PoolCounterNull is used, which provides no locking. You can get a useful one in the PoolCounter extension.

Definition at line 45 of file PoolCounter.php.

Constructor & Destructor Documentation

◆ __construct()

PoolCounter::__construct ( array  $conf,
string  $type,
string  $key 
)
protected
Parameters
array$conf
string$typeThe class of actions to limit concurrency for (task type)
string$key

Definition at line 92 of file PoolCounter.php.

References $key, and hashKeyIntoSlots().

Member Function Documentation

◆ acquireForAnyone()

PoolCounter::acquireForAnyone (   $timeout = null)
abstract

I want to do this task, but if anyone else does it instead, it's also fine for me.

I will read its cached data.

Parameters
int | null$timeoutWait timeout, or null to use value passed to the constructor
Returns
Status Value is one of Locked/Done/Error

Reimplemented in PoolCounterRedis, and PoolCounterNull.

◆ acquireForMe()

PoolCounter::acquireForMe (   $timeout = null)
abstract

I want to do this task and I need to do it myself.

Parameters
int | null$timeoutWait timeout, or null to use value passed to the constructor
Returns
Status Value is one of Locked/Error

Reimplemented in PoolCounterRedis, and PoolCounterNull.

◆ factory()

static PoolCounter::factory ( string  $type,
string  $key 
)
static

Create a Pool counter.

This should only be called from the PoolWorks.

Parameters
string$typeThe class of actions to limit concurrency for (task type)
string$key
Returns
PoolCounter

Definition at line 117 of file PoolCounter.php.

References $key, $type, and $wgPoolCounterConf.

Referenced by PoolCounterWork\__construct().

◆ getKey()

PoolCounter::getKey ( )
Returns
string

Definition at line 131 of file PoolCounter.php.

References $key.

◆ hashKeyIntoSlots()

PoolCounter::hashKeyIntoSlots (   $type,
  $key,
  $slots 
)
protected

Given a key (any string) and the number of lots, returns a slot key (a prefix with a suffix integer from the [0..($slots-1)] range).

This is used for a global limit on the number of instances of a given type that can acquire a lock. The hashing is deterministic so that PoolCounter::$workers is always an upper limit of how many instances with the same key can acquire a lock.

Parameters
string$typeThe class of actions to limit concurrency for (task type)
string$keyPoolCounter instance key (any string)
int$slotsThe number of slots (max allowed value is 65536)
Returns
string Slot key with the type and slot number

Definition at line 217 of file PoolCounter.php.

References $key, $slots, and $type.

Referenced by __construct().

◆ isFastStaleEnabled()

PoolCounter::isFastStaleEnabled ( )

Definition at line 221 of file PoolCounter.php.

References $fastStale.

◆ onAcquire()

PoolCounter::onAcquire ( )
finalprotected

Update any lock tracking information when the lock is acquired.

Since
1.25

Definition at line 193 of file PoolCounter.php.

References $isMightWaitKey.

Referenced by PoolCounterRedis\waitForSlotOrNotif().

◆ onRelease()

PoolCounter::onRelease ( )
finalprotected

Update any lock tracking information when the lock is released.

Since
1.25

Definition at line 201 of file PoolCounter.php.

References $isMightWaitKey.

Referenced by PoolCounterRedis\release(), and PoolCounterRedis\waitForSlotOrNotif().

◆ precheckAcquire()

PoolCounter::precheckAcquire ( )
finalprotected

Checks that the lock request is sane.

Returns
Status - good for sane requests fatal for insane
Since
1.25

Definition at line 168 of file PoolCounter.php.

References StatusValue\newFatal(), and StatusValue\newGood().

Referenced by PoolCounterRedis\acquireForAnyone(), and PoolCounterRedis\acquireForMe().

◆ release()

PoolCounter::release ( )
abstract

I have successfully finished my task.

Lets another one grab the lock, and returns the workers waiting on acquireForAnyone()

Returns
Status Value is one of Released/NotLocked/Error

Reimplemented in PoolCounterRedis, and PoolCounterNull.

Member Data Documentation

◆ $acquiredMightWaitKey

bool PoolCounter::$acquiredMightWaitKey = 0
staticprivate

Whether this process holds a "might wait" lock key.

Definition at line 80 of file PoolCounter.php.

◆ $fastStale

bool PoolCounter::$fastStale
private

Enable fast stale mode (T250248).

This may be overridden by the work class.

Definition at line 85 of file PoolCounter.php.

Referenced by isFastStaleEnabled().

◆ $isMightWaitKey

bool PoolCounter::$isMightWaitKey
private

Whether the key is a "might wait" key.

Definition at line 76 of file PoolCounter.php.

Referenced by onAcquire(), and onRelease().

◆ $key

string PoolCounter::$key
protected

All workers with the same key share the lock.

Definition at line 58 of file PoolCounter.php.

Referenced by PoolCounterRedis\__construct(), __construct(), factory(), getKey(), and hashKeyIntoSlots().

◆ $maxqueue

int PoolCounter::$maxqueue
protected

If this number of workers are already working/waiting, fail instead of wait.

Definition at line 69 of file PoolCounter.php.

◆ $slots

int PoolCounter::$slots = 0
protected

Maximum number of workers working on this task type, regardless of key.

0 means unlimited. Max allowed value is 65536. The way the slot limit is enforced is overzealous - this option should be used with caution.

Definition at line 67 of file PoolCounter.php.

Referenced by hashKeyIntoSlots().

◆ $timeout

int PoolCounter::$timeout
protected

Maximum time in seconds to wait for the lock.

Definition at line 71 of file PoolCounter.php.

Referenced by PoolCounterRedis\acquireForAnyone(), PoolCounterRedis\acquireForMe(), and PoolCounterRedis\waitForSlotOrNotif().

◆ $workers

int PoolCounter::$workers
protected

Maximum number of workers working on tasks with the same key simultaneously.

Definition at line 60 of file PoolCounter.php.

◆ DONE

const PoolCounter::DONE = 3

Definition at line 49 of file PoolCounter.php.

Referenced by PoolCounterWork\execute(), and PoolCounterRedis\waitForSlotOrNotif().

◆ ERROR

const PoolCounter::ERROR = -1

Definition at line 51 of file PoolCounter.php.

Referenced by PoolCounterWork\execute().

◆ LOCK_HELD

const PoolCounter::LOCK_HELD = -5

Definition at line 55 of file PoolCounter.php.

Referenced by PoolCounterWork\execute(), and PoolCounterRedis\waitForSlotOrNotif().

◆ LOCKED

◆ NOT_LOCKED

const PoolCounter::NOT_LOCKED = -2

Definition at line 52 of file PoolCounter.php.

Referenced by PoolCounterRedis\release().

◆ QUEUE_FULL

const PoolCounter::QUEUE_FULL = -3

Definition at line 53 of file PoolCounter.php.

Referenced by PoolCounterWork\execute(), and PoolCounterRedis\waitForSlotOrNotif().

◆ RELEASED

const PoolCounter::RELEASED = 2

Definition at line 48 of file PoolCounter.php.

Referenced by PoolCounterNull\release(), and PoolCounterRedis\release().

◆ TIMEOUT

const PoolCounter::TIMEOUT = -4

Definition at line 54 of file PoolCounter.php.

Referenced by PoolCounterWork\execute(), and PoolCounterRedis\waitForSlotOrNotif().


The documentation for this class was generated from the following file: