Problem/Motivation
While investigating some hard to debug cache misses on Cloudflare for a site we support I found the logic \Drupal\cloudflarepurger\EventSubscriber\CloudFlareCacheTagHeaderGenerator::cacheTagsToHashes()
implements to transform Drupal cache tags to what's sent back to Cloudflare. With a few cache tags found on our site, plenty of collisions were likely to occur when using substr(md5($cache_tag), 0, 3)
as the transformation method.
I then found issue
https://www.drupal.org/project/cloudflare/issues/3401335
🐛
Excessive Tag Hash Collisions
RTBC
that changes that logic into substr(base_convert(md5($entry), 16, 36), 0, 4)
. However, with the same set of example cache tags some other collisions still occur, although admittedly in a lesser amount.
Steps to reproduce
- Run the attached php script with the example list of cache tags
- Watch collisions occur as they're reported by the script
Proposed resolution
This is up for debate. By following the description in https://developers.cloudflare.com/cache/how-to/purge-cache/purge-by-tags... there are a few key items there:
For including cache tags in the response headers
Individual tags do not have a maximum length, but the aggregate Cache-Tag HTTP header cannot exceed 16 KB after the header field name, which is approximately 1,000 unique tags. Length includes whitespace and commas but does not include the header field name.
and
A single HTTP response can have more than one Cache-Tag HTTP header field.
For later purging (API call)
For cache purges, the maximum length of a cache-tag in an API call is 1,024 characters.
Two solutions are possible here:
- Changing the transforming logic to use a hash function - such as
md5()
alone - with which the chance of collision is virtually zero, while (a) splitting the Cache-Tags
response header into multiple headers per response if the maximum length is exceeded and (b) ensuring the cache purge API calls payload (request body) still work
- Keeping a single
Cache-Tags
response header per request while increasing the length to which we cut the transformed cache tags so collisions become a rare occurrence
Personally I think (1) is a better approach.
Remaining tasks
- Chime in and define an approach
- Writing patches, unit tests, etc
User interface changes
None
API changes
This would change the cache tags a site currently report for its pages and a full cache purge would be advisable / required upon deploying this to production.
Data model changes
None