You are here

public function AcquiaCloudPurger::invalidateTags in Acquia Purge 8

Invalidate a set of tag invalidations.

See also

\Drupal\purge\Plugin\Purge\Purger\PurgerInterface::invalidate()

\Drupal\purge\Plugin\Purge\Purger\PurgerInterface::routeTypeToMethod()

File

src/Plugin/Purge/Purger/AcquiaCloudPurger.php, line 212

Class

AcquiaCloudPurger
Acquia Cloud.

Namespace

Drupal\acquia_purge\Plugin\Purge\Purger

Code

public function invalidateTags(array $invalidations) {
  $this
    ->debugger()
    ->callerAdd(__METHOD__);

  // Set invalidation states to PROCESSING. Detect tags with spaces in them,
  // as space is the only character Drupal core explicitely forbids in tags.
  foreach ($invalidations as $invalidation) {
    $tag = $invalidation
      ->getExpression();
    if (strpos($tag, ' ') !== FALSE) {
      $invalidation
        ->setState(InvalidationInterface::FAILED);
      $this->logger
        ->error("Tag '%tag' contains a space, this is forbidden.", [
        '%tag' => $tag,
      ]);
    }
    else {
      $invalidation
        ->setState(InvalidationInterface::PROCESSING);
    }
  }

  // Create grouped sets of 12 so that we can spread out the BAN load.
  $group = 0;
  $groups = [];
  foreach ($invalidations as $invalidation) {
    if ($invalidation
      ->getState() !== InvalidationInterface::PROCESSING) {
      continue;
    }
    if (!isset($groups[$group])) {
      $groups[$group] = [
        'tags' => [],
        [
          'objects' => [],
        ],
      ];
    }
    if (count($groups[$group]['tags']) >= self::TAGS_GROUPED_BY) {
      $group++;
    }
    $groups[$group]['objects'][] = $invalidation;
    $groups[$group]['tags'][] = $invalidation
      ->getExpression();
  }

  // Test if we have at least one group of tag(s) to purge, if not, bail.
  if (!count($groups)) {
    foreach ($invalidations as $invalidation) {
      $invalidation
        ->setState(InvalidationInterface::FAILED);
    }
    return;
  }

  // Now create requests for all groups of tags.
  $site = $this->platformInfo
    ->getSiteIdentifier();
  $ipv4_addresses = $this->platformInfo
    ->getBalancerAddresses();
  $requests = function () use ($groups, $ipv4_addresses, $site) {
    foreach ($groups as $group_id => $group) {
      $tags = new TagsHeaderValue($group['tags'], Hash::cacheTags($group['tags']));
      foreach ($ipv4_addresses as $ipv4) {
        (yield $group_id => function ($poolopt) use ($site, $tags, $ipv4) {
          $opt = [
            'headers' => [
              'X-Acquia-Purge' => $site,
              'X-Acquia-Purge-Tags' => $tags
                ->__toString(),
              'Accept-Encoding' => 'gzip',
              'User-Agent' => 'Acquia Purge',
            ],
          ];

          // Pass the TagsHeaderValue to DebuggerMiddleware (when loaded).
          if ($this
            ->debugger()
            ->enabled()) {
            $opt['acquia_purge_tags'] = $tags;
          }
          if (is_array($poolopt) && count($poolopt)) {
            $opt = array_merge($poolopt, $opt);
          }
          return $this->httpClient
            ->requestAsync('BAN', "http://{$ipv4}/tags", $opt);
        });
      }
    }
  };

  // Execute the requests generator and retrieve the results.
  $results = $this
    ->getResultsConcurrently($requests);

  // Triage the results and set all invalidation states correspondingly.
  foreach ($groups as $group_id => $group) {
    if (!isset($results[$group_id]) || !count($results[$group_id])) {
      foreach ($group['objects'] as $invalidation) {
        $invalidation
          ->setState(InvalidationInterface::FAILED);
      }
    }
    else {
      if (in_array(FALSE, $results[$group_id])) {
        foreach ($group['objects'] as $invalidation) {
          $invalidation
            ->setState(InvalidationInterface::FAILED);
        }
      }
      else {
        foreach ($group['objects'] as $invalidation) {
          $invalidation
            ->setState(InvalidationInterface::SUCCEEDED);
        }
      }
    }
  }
  $this
    ->debugger()
    ->callerRemove(__METHOD__);
}