You are here

public function CapacityTracker::getRemainingInvalidationsLimit in Purge 8.3

Get the remaining number of allowed cache invalidations for this request.

External cache invalidation is expensive and can become exponentially more expensive when multiple platforms are being invalidated. To assure that we don't purge more than request lifetime allows for, ::getTimeHintTotal() gives the highest number of seconds a cache invalidation could take.

A call to ::getRemainingInvalidationsLimit() calculates how many cache invalidations are left to be processed during this request. It bases its decision on ::getMaxExecutionTime() and ::getIdealConditionsLimit() and information tracked during request lifetime. When it returns zero, no more items can be claimed from the queue or fed to the purgers service.

In order to track this global limit, ::decrementLimit() gets called every time the purgers service attempted one or more invalidations until the value becomes zero.

Return value

int The remaining number of allowed cache invalidations during the remainder of Drupal's request lifetime. When 0 is returned, no more can take place.

Overrides CapacityTrackerInterface::getRemainingInvalidationsLimit

See also

\Drupal\purge\Plugin\Purge\Purger\CapacityTrackerInterface::decrementLimit()

\Drupal\purge\Plugin\Purge\Purger\CapacityTrackerInterface::getTimeHintTotal()

\Drupal\purge\Plugin\Purge\Purger\CapacityTrackerInterface::getIdealConditionsLimit()

File

src/Plugin/Purge/Purger/CapacityTracker.php, line 264

Class

CapacityTracker
Provides the capacity tracker.

Namespace

Drupal\purge\Plugin\Purge\Purger

Code

public function getRemainingInvalidationsLimit() {
  if (is_null($this->purgers)) {
    throw new \LogicException("::setPurgers() hasn't been called!");
  }

  // Create a closure that calculates the current limit.
  $calculate = function ($spent_inv) {
    if (empty($this->purgers)) {
      return 0;
    }

    // Fetch PHP's maximum execution time. However, Purge can run longer when
    // the returned value is zero (=infinite). If so, we return outer limits.
    $time_max = $this
      ->getMaxExecutionTime();
    if ($time_max === 0) {
      return (int) ($this
        ->getIdealConditionsLimit() - $spent_inv);
    }

    // Calculate how much execution time is left, by subtracting the spent
    // execution time and waiting time, from the time max.
    $time_left = $time_max - $this
      ->spentExecutionTime()
      ->get() - $this
      ->getCooldownTimeTotal();

    // Calculate how many invaldiations can still be processed with the time
    // that is left and subtract the number of already invalidated items.
    $limit = intval(floor($time_left / $this
      ->getTimeHintTotal()) - $spent_inv);

    // In the rare case the limit exceeds ideal conditions, the limit is
    // lowered. Then return the limit or zero when it turned negative.
    if ($limit > $this
      ->getIdealConditionsLimit()) {
      return (int) $this
        ->getIdealConditionsLimit();
    }
    return (int) ($limit < 0 ? 0 : $limit);
  };

  // Fetch calculations from cache or generate new. We use the number of spent
  // invalidations as cache key, since this makes it change every time.
  $spent_inv = $this
    ->spentInvalidations()
    ->get();
  if (!isset($this->remainingInvalidationsLimits[$spent_inv])) {
    $this->remainingInvalidationsLimits[$spent_inv] = $calculate($spent_inv);
  }
  return $this->remainingInvalidationsLimits[$spent_inv];
}