Skip to content

Commit b431dbb

Browse files
authored
Merge pull request #53 from nlx-lars/feature/shorten-tags
FEATURE: Add option to use short md5 for cache tags
2 parents 6e6ca76 + b88d843 commit b431dbb

6 files changed

Lines changed: 99 additions & 14 deletions

File tree

Classes/Http/CacheControlHeaderComponent.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
use MOC\Varnish\Aspects\ContentCacheAspect;
77
use MOC\Varnish\Cache\MetadataAwareStringFrontend;
8+
use MOC\Varnish\Service\CacheTagService;
89
use MOC\Varnish\Service\TokenStorage;
910
use Neos\ContentRepository\Domain\Model\NodeInterface;
1011
use Neos\Flow\Annotations as Flow;
@@ -49,6 +50,12 @@ class CacheControlHeaderComponent implements ComponentInterface
4950
*/
5051
protected $propertyMapper;
5152

53+
/**
54+
* @var CacheTagService
55+
* @Flow\Inject
56+
*/
57+
protected $cacheTagService;
58+
5259
/**
5360
* @var MetadataAwareStringFrontend
5461
*/
@@ -109,7 +116,8 @@ public function handle(ComponentContext $componentContext)
109116
list($tags, $cacheLifetime) = $this->getCacheTagsAndLifetime();
110117

111118
if (count($tags) > 0) {
112-
$modifiedResponse = $modifiedResponse->withHeader('X-Cache-Tags', implode(',', $tags));
119+
$shortenedTags = $this->cacheTagService->shortenTags($tags);
120+
$modifiedResponse = $modifiedResponse->withHeader('X-Cache-Tags', implode(',', $shortenedTags));
113121
}
114122

115123
$modifiedResponse = $modifiedResponse->withHeader('X-Site', $this->tokenStorage->getToken());
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace MOC\Varnish\Service;
5+
6+
use Neos\Flow\Annotations as Flow;
7+
8+
/**
9+
* @Flow\Scope("singleton")
10+
*/
11+
class CacheTagService
12+
{
13+
14+
/**
15+
* @var int
16+
* @Flow\InjectConfiguration(path="cacheHeaders")
17+
*/
18+
protected $cacheHeaderConfiguration;
19+
20+
/**
21+
* @see \Neos\Fusion\Core\Cache\ContentCache::sanitizeTags()
22+
*
23+
* @param array $tags
24+
* @return array
25+
*/
26+
public function sanitizeTags(array $tags): array
27+
{
28+
return array_map(function (string $tag) {
29+
return strtr($tag, '.:', '_-');
30+
}, $tags);
31+
}
32+
33+
/**
34+
* Generate short md5 for cache tags if enabled
35+
*
36+
* See these two configuration options:
37+
* * MOC.Varnish.cacheHeaders.shortenCacheTags
38+
* * MOC.Varnish.cacheHeaders.cacheTagLength
39+
*
40+
* @param array $tags
41+
* @return array
42+
*/
43+
public function shortenTags(array $tags = []): array
44+
{
45+
if (!$this->shouldShortenTags()) {
46+
return $tags;
47+
}
48+
49+
return array_map(function (string $tag) {
50+
return substr(md5($tag), 0, (int)$this->cacheHeaderConfiguration['cacheTagLength'] ?? 8);
51+
}, $tags);
52+
}
53+
54+
protected function shouldShortenTags(): bool
55+
{
56+
return (bool)$this->cacheHeaderConfiguration['shortenCacheTags'] ?? false;
57+
}
58+
59+
}

Classes/Service/ContentCacheFlusherService.php

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,7 @@ protected function generateCacheTags(NodeInterface $node): void
111111
if ($nodeInWorkspace === null) {
112112
break;
113113
}
114-
$tagName = 'DescendantOf_' . $workspaceHash . '_' . $nodeInWorkspace->getIdentifier();
115-
$this->tagsToFlush[$tagName] = sprintf('which were tagged with "%s" because node "%s" has changed.', $tagName, $node->getPath());
114+
$this->generateCacheTagsForDescendantOf($workspaceHash . '_' . $nodeInWorkspace->getIdentifier());
116115
}
117116
}
118117

@@ -133,8 +132,17 @@ protected function generateCacheTags(NodeInterface $node): void
133132
*/
134133
protected function generateCacheTagsForNodeIdentifier(string $cacheIdentifier): void
135134
{
136-
$this->tagsToFlush['Node_' . $cacheIdentifier] = sprintf('which were tagged with "Node_%s" because that identifier has changed.', $cacheIdentifier);
135+
$tagName = 'Node_' . $cacheIdentifier;
136+
$this->tagsToFlush[$tagName] = sprintf('which were tagged with "%s" because node identifier "%s" has changed.', $tagName, $cacheIdentifier);
137137
// Note, as we don't have a node here we cannot go up the structure.
138+
$this->generateCacheTagsForDescendantOf($cacheIdentifier);
139+
}
140+
141+
/**
142+
* @param string $cacheIdentifier
143+
*/
144+
protected function generateCacheTagsForDescendantOf(string $cacheIdentifier): void
145+
{
138146
$tagName = 'DescendantOf_' . $cacheIdentifier;
139147
$this->tagsToFlush[$tagName] = sprintf('which were tagged with "%s" because node "%s" has changed.', $tagName, $cacheIdentifier);
140148
}
@@ -154,7 +162,8 @@ protected function generateCacheTagsForNodeType(string $nodeTypeName, string $re
154162
$nodeTypePrefix = rtrim($nodeTypePrefix, '_') . '_';
155163
}
156164
foreach ($nodeTypesToFlush as $nodeTypeNameToFlush) {
157-
$this->tagsToFlush['NodeType_' . $nodeTypePrefix . $nodeTypeNameToFlush] = sprintf('which were tagged with "NodeType_%s" because node "%s" has changed and was of type "%s".', $nodeTypeNameToFlush, ($referenceNodeIdentifier ? $referenceNodeIdentifier : ''), $nodeTypeName);
165+
$tagName = 'NodeType_' . $nodeTypePrefix . $nodeTypeNameToFlush;
166+
$this->tagsToFlush[$tagName] = sprintf('which were tagged with "%s" because node "%s" has changed and was of type "%s".', $tagName, $referenceNodeIdentifier ?: '', $nodeTypeName);
158167
}
159168
}
160169

Classes/Service/VarnishBanService.php

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ class VarnishBanService
2929
*/
3030
protected $tokenStorage;
3131

32+
/**
33+
* @Flow\Inject
34+
* @var CacheTagService
35+
*/
36+
protected $cacheTagService;
37+
3238
/**
3339
* @var array
3440
*/
@@ -109,13 +115,8 @@ public function banByTags(array $tags, $domains = null): void
109115
$tags = array_diff($tags, $this->settings['ignoredCacheTags']);
110116
}
111117

112-
/**
113-
* Sanitize tags
114-
* @see \Neos\Fusion\Core\Cache\ContentCache
115-
*/
116-
foreach ($tags as $key => $tag) {
117-
$tags[$key] = strtr($tag, '.:', '_-');
118-
}
118+
$tags = $this->cacheTagService->sanitizeTags($tags);
119+
$tags = $this->cacheTagService->shortenTags($tags);
119120

120121
$this->varnishProxyClient->forHosts(...$this->domainsToArray($domains));
121122
$this->cacheInvalidator->invalidateTags($tags);

Configuration/Settings.yaml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,14 @@ MOC:
66
varnishUrl: 'http://127.0.0.1'
77
# Cache header sending configuration
88
cacheHeaders:
9-
# Default and maximum TTL in seconds
10-
defaultSharedMaximumAge: null
119
# Disable sending headers (useful for staging environments)
1210
disabled: false
11+
# Default and maximum TTL in seconds
12+
defaultSharedMaximumAge: null
13+
# Enable shortening of Cache Tags (useful when response headers get too large)
14+
shortenCacheTags: false
15+
# Length of the short md5 if shortenCacheTags is enabled
16+
cacheTagLength: 8
1317

1418
# Maximum length of header in bytes for requests to varnish. Used when banning. Large requests will be split across multiple smaller ones
1519
maximumHeaderLength: 7500

Documentation/Index.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ There are several configuration options can/needs to be set:
1919
If not set, the Varnish configuration needs to cache by default since no ``Cache-Control`` header will be sent
2020
- Disable sending of cache headers - can be used to disable Varnish on staging environment e.g.
2121
``MOC.Varnish.cacheHeaders.disabled`` accepts boolean value (defaults to ``FALSE``)
22+
- Since 4.1.0: The generated Cache Tags can be shortened using this option
23+
``MOC.Varnish.cacheHeaders.shortenCacheTags`` accepts boolean value (defaults to ``FALSE``)
24+
- Since 4.1.0: If shortenCacheTags is enabled, this option controls the length of the used md5 for tags
25+
``MOC.Varnish.cacheHeaders.cacheTagLength`` accepts integer value (defaults to ``8``)
2226
- Reverse lookup port can be set to allow debugging in the backend module if the web server port is not ``80``
2327
``MOC.Varnish.reverseLookupPort`` accepts integer (defaults to ``NULL``)
2428
- Ignored cache tags can be used to ignore certain cache tags from being cleared at all (useful for optimizing)

0 commit comments

Comments
 (0)