From b1e8b3308511857dad488af6d169523c0de90c87 Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Mon, 25 Mar 2024 13:32:12 -0300 Subject: [PATCH] Theorhetical, better caching. --- embargo.services.yml | 7 ++ src/Cache/Context/IpRangeCacheContext.php | 81 +++++++++++++++++++ src/Entity/Embargo.php | 34 +++++--- src/Entity/IpRange.php | 10 +++ .../search_api/processor/EmbargoProcessor.php | 2 +- 5 files changed, 124 insertions(+), 10 deletions(-) create mode 100644 src/Cache/Context/IpRangeCacheContext.php diff --git a/embargo.services.yml b/embargo.services.yml index b316143..a7470c3 100644 --- a/embargo.services.yml +++ b/embargo.services.yml @@ -38,3 +38,10 @@ services: - '@service_container' tags: - { name: 'event_subscriber' } + cache_context.ip.embargo_range: + class: Drupal\embargo\Cache\Context\IpRangeCacheContext + arguments: + - '@request_stack' + - '@entity_type.manager' + tags: + - { name: cache.context } diff --git a/src/Cache/Context/IpRangeCacheContext.php b/src/Cache/Context/IpRangeCacheContext.php new file mode 100644 index 0000000..8f77b17 --- /dev/null +++ b/src/Cache/Context/IpRangeCacheContext.php @@ -0,0 +1,81 @@ +getRanges()); + sort($range_keys, SORT_NUMERIC); + return implode(',', $range_keys); + } + + /** + * {@inheritDoc} + */ + public function getCacheableMetadata() { + $cache_meta = new CacheableMetadata(); + + foreach ($this->getRanges() as $range) { + $cache_meta->addCacheableDependency($range); + } + + return $cache_meta; + } + + /** + * Get any IP range entities associated with the current IP address. + * + * @return \Drupal\embargo\IpRangeInterface[] + * Any relevant IP range entities. + * + * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException + * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException + */ + protected function getRanges() : array { + if (!isset($this->ranges)) { + /** @var \Drupal\embargo\IpRangeStorageInterface $embargo_ip_range_storage */ + $embargo_ip_range_storage = $this->entityTypeManager->getStorage('embargo_ip_range'); + $this->ranges = $embargo_ip_range_storage->getApplicableIpRanges($this->requestStack->getCurrentRequest() + ->getClientIp()); + } + + return $this->ranges; + } + +} diff --git a/src/Entity/Embargo.php b/src/Entity/Embargo.php index 03f8b57..1201540 100644 --- a/src/Entity/Embargo.php +++ b/src/Entity/Embargo.php @@ -378,33 +378,49 @@ public function setEmbargoedNode(NodeInterface $node): EmbargoInterface { } /** - * The maximum age for which this object may be cached. - * - * @return int - * The maximum time in seconds that this object may be cached. + * {@inheritDoc} */ public function getCacheMaxAge() { + $max_age = parent::getCacheMaxAge(); + $now = time(); // Invalidate cache after a scheduled embargo expires. if ($this->getExpirationType() === static::EXPIRATION_TYPE_SCHEDULED && !$this->expiresBefore($now)) { - return $this->getExpirationDate()->getTimestamp() - $now; + $max_age = Cache::mergeMaxAges($max_age, $this->getExpirationDate()->getTimestamp() - $now); } - // Other properties of the embargo are not time dependent. - return parent::getCacheMaxAge(); + + return $max_age; } /** * {@inheritdoc} */ public function getCacheTags() { - $tags = parent::getCacheTags(); - $tags[] = "node:{$this->getEmbargoedNode()->id()}"; + $tags = Cache::mergeTags(parent::getCacheTags(), $this->getEmbargoedNode()->getCacheTags()); + if ($this->getExemptIps()) { $tags = Cache::mergeTags($tags, $this->getExemptIps()->getCacheTags()); } return $tags; } + /** + * {@inheritDoc} + */ + public function getCacheContexts() { + $contexts = Cache::mergeContexts( + parent::getCacheContexts(), + $this->getEmbargoedNode()->getCacheContexts(), + [$this->getExemptUsers() ? 'user' : 'user.permissions'], + ); + + if ($this->getExemptIps()) { + $contexts = Cache::mergeContexts($contexts, $this->getExemptIps()->getCacheContexts()); + } + + return $contexts; + } + /** * {@inheritdoc} */ diff --git a/src/Entity/IpRange.php b/src/Entity/IpRange.php index 60bea11..1590688 100644 --- a/src/Entity/IpRange.php +++ b/src/Entity/IpRange.php @@ -3,6 +3,7 @@ namespace Drupal\embargo\Entity; use Drupal\Component\Utility\UrlHelper; +use Drupal\Core\Cache\Cache; use Drupal\Core\Entity\ContentEntityBase; use Drupal\Core\Entity\EntityStorageException; use Drupal\Core\Entity\EntityStorageInterface; @@ -239,4 +240,13 @@ public static function isValidCidr(string $cidr): bool { return FALSE; } + /** + * {@inheritDoc} + */ + public function getCacheContexts() { + return Cache::mergeContexts(parent::getCacheContexts(), [ + 'ip.embargo_range', + ]); + } + } diff --git a/src/Plugin/search_api/processor/EmbargoProcessor.php b/src/Plugin/search_api/processor/EmbargoProcessor.php index 82f9613..d1b6a64 100644 --- a/src/Plugin/search_api/processor/EmbargoProcessor.php +++ b/src/Plugin/search_api/processor/EmbargoProcessor.php @@ -251,7 +251,7 @@ protected function addEmbargoFilters(string $datasource_id, QueryInterface $quer $or_group->addCondition($field->getFieldIdentifier(), $ipRange->id()); $query->addCacheableDependency($ipRange); } - $query->addCacheContexts(['ip']); + $query->addCacheContexts(['ip.embargo_range']); } return (count($or_group->getConditions()) > 0) ? $or_group : NULL;