Skip to content

Commit 5a3d88a

Browse files
committed
Merge pull request #237 from andrerom/tags
Add abstracted tag handling
2 parents ae8fd48 + bc36103 commit 5a3d88a

19 files changed

+444
-347
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ See also the [GitHub releases page](https://github.com/FriendsOfSymfony/FOSHttpC
1818
caching proxy.
1919
* Refactored the proxy client test system into traits. Removed ProxyTestCase,
2020
use the traits `CacheAssertions` and `HttpCaller` instead.
21+
* Abstracting tags by adding new `TagsInterface` for ProxyClients, as part of that also:
22+
BC break: Moved tag invalidation to `CacheInvalidator`, and rename TagHandler to ResponseTagger.
2123

2224
1.4.0
2325
-----

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ This library integrates your PHP applications with HTTP caching proxies such as
1212
Use this library to send invalidation requests from your application to the caching proxy
1313
and to test your caching and invalidation code against a Varnish setup.
1414

15+
It does this by abstracting some caching concepts and attempting to make sure these
16+
can be supported across Varnish, Nginx and Symfony HttpCache.
17+
1518
If you use Symfony2, have a look at the
1619
[FOSHttpCacheBundle](https://github.com/FriendsOfSymfony/FOSHttpCacheBundle).
1720
The bundle provides the invalidator as a service, along with a number of
@@ -22,6 +25,7 @@ Features
2225

2326
* Send [cache invalidation requests](http://foshttpcache.readthedocs.org/en/stable/cache-invalidator.html)
2427
with minimal impact on performance.
28+
* Cache tagging abstraction, uses BAN with Varnish and allows tagging support for other caching proxies in the future.
2529
* Use the built-in support for [Varnish](http://foshttpcache.readthedocs.org/en/stable/varnish-configuration.html)
2630
3 and 4, [NGINX](http://foshttpcache.readthedocs.org/en/stable/nginx-configuration.html), the
2731
[Symfony reverse proxy from the http-kernel component](http://foshttpcache.readthedocs.org/en/stable/symfony-cache-configuration.html)

doc/cache-invalidator.rst

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,32 @@ Refresh a URL with added header(s)::
8282

8383
.. _invalidate regex:
8484

85+
86+
Invalidating by Tags
87+
--------------------
88+
89+
.. note::
90+
91+
Make sure to :doc:`configure your proxy <proxy-configuration>` for tagging first,
92+
in the case of Varnish this is powered by banning.
93+
94+
When you are using :doc:`response tagging <response-tagging>`, you can invalidate
95+
all responses that where tagged with a specific label.
96+
97+
Invalidate a tag::
98+
99+
$cacheInvalidator->invalidateTags(['blog-post-44'])->flush();
100+
101+
See below for the :ref:`flush() <flush>` method.
102+
103+
Invalidate several tags::
104+
105+
$cacheInvalidator
106+
->invalidateTags(['type-65', 'location-3'])
107+
->flush()
108+
;
109+
110+
85111
Invalidating With a Regular Expression
86112
--------------------------------------
87113

doc/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ Contents:
2828
proxy-configuration
2929
proxy-clients
3030
cache-invalidator
31-
invalidation-handlers
31+
response-tagging
3232
user-context
3333

3434
testing-your-application

doc/invalidation-handlers.rst

Lines changed: 0 additions & 98 deletions
This file was deleted.

doc/proxy-clients.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,15 @@ include that port in the base URL::
9191

9292
$varnish = new Varnish($servers, 'my-cool-app.com:8080');
9393

94+
.. _varnish_custom_tags_header:
95+
96+
Another optional parameter available on Varnish client is ``tagsHeader``, which allows you to
97+
change the default HTTP header used for tagging, ``X-Cache-Tags``::
98+
99+
$varnish = new Varnish($servers, 'example.com', $adapter, 'X-Custom-Tags-Header');
100+
101+
Make sure to reflect this change in your :doc:`caching proxy configuration <proxy-configuration>`.
102+
94103
.. note::
95104

96105
To make invalidation work, you need to :doc:`configure Varnish <varnish-configuration>` accordingly.
@@ -267,5 +276,6 @@ Varnish client::
267276
Make sure to add any headers that you want to ban on to your
268277
:doc:`proxy configuration <proxy-configuration>`.
269278

279+
.. _header: http://php.net/header
270280
.. _HTTP Adapter: http://php-http.readthedocs.org/en/latest/
271281
.. _PSR-7 message implementation: https://packagist.org/providers/psr/http-message-implementation

doc/response-tagging.rst

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
Response Tagging
2+
================
3+
4+
The ``ResponseTagger`` helps you keep track tags for a response, which can be
5+
added to response headers that you can later use to invalidate all cache
6+
entries with that tag.
7+
8+
.. _tags:
9+
10+
Setup
11+
~~~~~
12+
13+
.. note::
14+
15+
Make sure to :doc:`configure your proxy <proxy-configuration>` for tagging first.
16+
17+
The response tagger is a decorator around a proxy client that implements
18+
the ``TagsInterface``, handling adding tags to responses::
19+
20+
use FOS\HttpCache\ResponseTagger;
21+
22+
// $proxyClient already created, implementing FOS\HttpCache\ProxyClient\Invalidation\TagsInterface
23+
$responseTagger = new ResponseTagger($proxyClient);
24+
25+
Usage
26+
~~~~~
27+
28+
With tags you can group related representations so it becomes easier to
29+
invalidate them. You will have to make sure your web application adds the
30+
correct tags on all responses. You can add tags to the response using::
31+
32+
$responseTagger->addTags(['tag-two', 'group-a']);
33+
34+
Before any content is sent out, you need to send the tag header_::
35+
36+
header(sprintf('%s: %s'),
37+
$responseTagger->getTagsHeaderName(),
38+
$responseTagger->getTagsHeaderValue()
39+
);
40+
41+
.. tip::
42+
43+
If you are using Symfony with the FOSHttpCacheBundle_, the tags
44+
added to ``ResponseTagger`` are added to the response automatically.
45+
You also have `additional methods of defining tags`_ with
46+
annotations and on URL patterns.
47+
48+
Assume you sent four responses:
49+
50+
+------------+-------------------------+
51+
| Response: | ``X-Cache-Tags`` header:|
52+
+============+=========================+
53+
| ``/one`` | ``tag-one`` |
54+
+------------+-------------------------+
55+
| ``/two`` | ``tag-two, group-a`` |
56+
+------------+-------------------------+
57+
| ``/three`` | ``tag-three, group-a`` |
58+
+------------+-------------------------+
59+
| ``/four`` | ``tag-four, group-b`` |
60+
+------------+-------------------------+
61+
62+
You can now invalidate some URLs using tags::
63+
64+
$tagHandler->invalidateTags(['group-a', 'tag-four'])->flush();
65+
66+
This will ban all requests having either the tag ``group-a`` /or/ ``tag-four``.
67+
In the above example, this will invalidate ``/two``, ``/three`` and ``/four``.
68+
Only ``/one`` will stay in the cache.
69+
70+
.. note::
71+
72+
For further reading on tag invalidation see :doc:`cache-invalidator page <cache-invalidator>`.
73+
For changing the cache header, :doc:`configure your proxy <proxy-clients>`.
74+
75+
.. _header: http://php.net/header
76+
.. _additional methods of defining tags: http://foshttpcachebundle.readthedocs.org/en/latest/features/tagging.html

doc/varnish-configuration.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ using an ``X-Cache-Tags`` header.
180180
If you need to use a different tag for the headers than the default
181181
``X-Cache-Tags`` used in ``fos_ban.vcl``, you will have to write your own VCL
182182
code for tag invalidation and change the tagging header
183-
:ref:`configured in the cache invalidator <custom_tags_header>`. Your custom
183+
:ref:`configured in the cache invalidator <varnish_custom_tags_header>`. Your custom
184184
VCL will look like this:
185185

186186
.. configuration-block::

src/CacheInvalidator.php

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,19 @@
1717
use FOS\HttpCache\Exception\ProxyUnreachableException;
1818
use FOS\HttpCache\Exception\UnsupportedProxyOperationException;
1919
use FOS\HttpCache\ProxyClient\ProxyClientInterface;
20+
use FOS\HttpCache\ProxyClient\Invalidation\TagsInterface;
2021
use FOS\HttpCache\ProxyClient\Invalidation\BanInterface;
2122
use FOS\HttpCache\ProxyClient\Invalidation\PurgeInterface;
2223
use FOS\HttpCache\ProxyClient\Invalidation\RefreshInterface;
2324
use Symfony\Component\EventDispatcher\EventDispatcher;
2425
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
25-
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
2626

2727
/**
2828
* Manages HTTP cache invalidation.
2929
*
3030
* @author David de Boer <[email protected]>
3131
* @author David Buchmann <[email protected]>
32+
* @author André Rømcke <[email protected]>
3233
*/
3334
class CacheInvalidator
3435
{
@@ -47,6 +48,11 @@ class CacheInvalidator
4748
*/
4849
const INVALIDATE = 'invalidate';
4950

51+
/**
52+
* Value to check support of invalidateTags operation.
53+
*/
54+
const TAGS = 'tags';
55+
5056
/**
5157
* @var ProxyClientInterface
5258
*/
@@ -90,6 +96,8 @@ public function supports($operation)
9096
return $this->cache instanceof RefreshInterface;
9197
case self::INVALIDATE:
9298
return $this->cache instanceof BanInterface;
99+
case self::TAGS:
100+
return $this->cache instanceof TagsInterface;
93101
default:
94102
throw new InvalidArgumentException('Unknown operation ' . $operation);
95103
}
@@ -197,6 +205,27 @@ public function invalidate(array $headers)
197205
return $this;
198206
}
199207

208+
/**
209+
* Remove/Expire cache objects based on cache tags
210+
*
211+
* @see TagsInterface::tags()
212+
*
213+
* @param array $tags Tags that should be removed/expired from the cache
214+
*
215+
* @throws UnsupportedProxyOperationException If HTTP cache does not support Tags invalidation
216+
*
217+
* @return $this
218+
*/
219+
public function invalidateTags(array $tags)
220+
{
221+
if (!$this->cache instanceof TagsInterface) {
222+
throw UnsupportedProxyOperationException::cacheDoesNotImplement('Tags');
223+
}
224+
$this->cache->invalidateTags($tags);
225+
226+
return $this;
227+
}
228+
200229
/**
201230
* Invalidate URLs based on a regular expression for the URI, an optional
202231
* content type and optional limit to certain hosts.

0 commit comments

Comments
 (0)