112 lines
3 KiB
PHP
112 lines
3 KiB
PHP
<?php
|
|
|
|
namespace Wikimedia\WRStats;
|
|
|
|
/**
|
|
* A class representing a batch of increment/peek operations on a WRStatsRateLimiter
|
|
*
|
|
* @since 1.39
|
|
*/
|
|
class LimitBatch {
|
|
/** @var WRStatsRateLimiter */
|
|
private $limiter;
|
|
|
|
/** @var int */
|
|
private $defaultAmount;
|
|
|
|
/** @var LimitOperation[] */
|
|
private $operations = [];
|
|
|
|
/**
|
|
* @internal Use WRStatsFactory::createRateLimiter()->createBatch() instead
|
|
* @param WRStatsRateLimiter $limiter
|
|
* @param int $defaultAmount
|
|
*/
|
|
public function __construct(
|
|
WRStatsRateLimiter $limiter,
|
|
$defaultAmount
|
|
) {
|
|
$this->limiter = $limiter;
|
|
$this->defaultAmount = $defaultAmount;
|
|
}
|
|
|
|
/**
|
|
* Construct a local entity key and queue an operation for it.
|
|
*
|
|
* @param string $condName The condition name to be incremented/tested,
|
|
* which must match one of the ones passed to createRateLimiter()
|
|
* @param mixed $components Entity key component or array of components
|
|
* @param int|null $amount The amount to increment by, or null to use the default
|
|
* @return $this
|
|
*/
|
|
public function localOp( $condName, $components = [], $amount = null ) {
|
|
if ( !is_array( $components ) ) {
|
|
$components = [ $components ];
|
|
}
|
|
$this->queueOp(
|
|
$condName,
|
|
new LocalEntityKey( array_merge( [ $condName ], $components ) ),
|
|
$amount
|
|
);
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Construct a global entity key and queue an operation for it.
|
|
*
|
|
* @param string $condName The condition name to be incremented/tested,
|
|
* which must match one of the ones passed to createRateLimiter()
|
|
* @param mixed $components Entity key components
|
|
* @param int|null $amount The amount, or null to use the default
|
|
* @return $this
|
|
*/
|
|
public function globalOp( $condName, $components = [], $amount = null ) {
|
|
if ( !is_array( $components ) ) {
|
|
$components = [ $components ];
|
|
}
|
|
$this->queueOp(
|
|
$condName,
|
|
new GlobalEntityKey( array_merge( [ $condName ], $components ) ),
|
|
$amount
|
|
);
|
|
return $this;
|
|
}
|
|
|
|
private function queueOp( $type, $entity, $amount ) {
|
|
$amount ??= $this->defaultAmount;
|
|
if ( isset( $this->operations[$type] ) ) {
|
|
throw new WRStatsError( 'Cannot queue multiple actions of the same type, ' .
|
|
'because the result array is indexed by type' );
|
|
}
|
|
$this->operations[$type] = new LimitOperation( $type, $entity, $amount );
|
|
}
|
|
|
|
/**
|
|
* Execute the batch, checking each operation against the defined limit,
|
|
* but don't actually increment the metrics.
|
|
*
|
|
* @return LimitBatchResult
|
|
*/
|
|
public function peek() {
|
|
return $this->limiter->peekBatch( $this->operations );
|
|
}
|
|
|
|
/**
|
|
* Execute the batch, unconditionally incrementing all the specified metrics.
|
|
*/
|
|
public function incr() {
|
|
$this->limiter->incrBatch( $this->operations );
|
|
}
|
|
|
|
/**
|
|
* Execute the batch, checking each operation against the defined limit.
|
|
* If all operations are allowed, all metrics will be incremented. If some
|
|
* of the operations exceed the limit, none of the metrics will be
|
|
* incremented.
|
|
*
|
|
* @return LimitBatchResult
|
|
*/
|
|
public function tryIncr() {
|
|
return $this->limiter->tryIncrBatch( $this->operations );
|
|
}
|
|
}
|