Skip to content

Commit ec396c3

Browse files
committed
minor #20966 [Cache] Improve the docs about cache namespaces (javiereguiluz)
This PR was merged into the 7.3 branch. Discussion ---------- [Cache] Improve the docs about cache namespaces After talking with `@nicolas`-grekas about this, I think we should improve the recent docs about cache namespaces with more details like invalidation, a bit more context about when to use this, etc. Commits ------- 5ad20ab [Cache] Improve the docs about cache namespaces
2 parents bf9dd19 + 5ad20ab commit ec396c3

File tree

2 files changed

+47
-14
lines changed

2 files changed

+47
-14
lines changed

cache.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,8 @@ Symfony stores the item automatically in all the missing pools.
539539
;
540540
};
541541
542+
.. _cache-using-cache-tags:
543+
542544
Using Cache Tags
543545
----------------
544546

components/cache.rst

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -91,30 +91,61 @@ Creating Sub-Namespaces
9191

9292
Cache sub-namespaces were introduced in Symfony 7.3.
9393

94-
All cache adapters provided by the component implement the
95-
:class:`Symfony\\Contracts\\Cache\\NamespacedPoolInterface` to provide the
96-
:method:`Symfony\\Contracts\\Cache\\NamespacedPoolInterface::withSubNamespace` method.
97-
This method allows namespacing cached items by transparently prefixing their keys::
94+
Sometimes you need to create context-dependent variations of data that should be
95+
cached. For example, the data used to render a dashboard page may be expensive
96+
to generate and unique per user, so you can't cache the same data for everyone.
9897

99-
$subCache = $cache->withSubNamespace('foo');
98+
In such cases, Symfony allows you to create different cache contexts using
99+
namespaces. A cache namespace is an arbitrary string that identifies a set of
100+
related cache items. All cache adapters provided by the component implement the
101+
:class:`Symfony\\Contracts\\Cache\\NamespacedPoolInterface`, which provides the
102+
:method:`Symfony\\Contracts\\Cache\\NamespacedPoolInterface::withSubNamespace`
103+
method.
100104

101-
$subCache->get('my_cache_key', function (ItemInterface $item): string {
105+
This method allows you to namespace cached items by transparently prefixing their keys::
106+
107+
$userCache = $cache->withSubNamespace(sprintf('user-%d', $user->getId()));
108+
109+
$userCache->get('dashboard_data', function (ItemInterface $item): string {
102110
$item->expiresAfter(3600);
103111

104112
return '...';
105113
});
106114

107-
In this example, the cache item will use the ``my_cache_key`` key, but it will be
108-
stored internally under the ``foo`` namespace. This is handled transparently for
109-
you, so you **don't** need to manually prefix keys like ``foo.my_cache_key``.
115+
In this example, the cache item uses the ``dashboard_data`` key, but it will be
116+
stored internally under a namespace based on the current user ID. This is handled
117+
automatically, so you **dont** need to manually prefix keys like ``user-27.dashboard_data``.
110118

111-
This is useful when using namespace-based cache invalidation to isolate or
112-
invalidate a subset of cached data based on some context. Typical examples
113-
include namespacing by user ID, locale, or entity ID and hash::
119+
There are no guidelines or restrictions on how to define cache namespaces.
120+
You can make them as granular or as generic as your application requires:
114121

115-
$userCache = $cache->withSubNamespace((string) $userId);
116122
$localeCache = $cache->withSubNamespace($request->getLocale());
117-
$productCache = $cache->withSubNamespace($productId.'_'.$productChecksum);
123+
124+
$flagCache = $cache->withSubNamespace(
125+
$featureToggle->isEnabled('new_checkout') ? 'checkout-v2' : 'checkout-v1'
126+
);
127+
128+
$channel = $request->attributes->get('_route')?->startsWith('api_') ? 'api' : 'web';
129+
$channelCache = $cache->withSubNamespace($channel);
130+
131+
.. tip::
132+
133+
You can even combine cache namespaces with :ref:`cache tags <cache-using-cache-tags>`
134+
for more advanced needs.
135+
136+
There is no built-in way to invalidate caches by namespace. Instead, the recommended
137+
approach is to change the namespace itself. For this reason, it's common to include
138+
static or dynamic versioning data in the cache namespace::
139+
140+
// for simple applications, an incrementing static version number may be enough
141+
$userCache = $cache->withSubNamespace(sprintf('v1-user-%d', $user->getId()));
142+
143+
// other applications may use dynamic versioning based on the date (e.g. monthly)
144+
$userCache = $cache->withSubNamespace(sprintf('%s-user-%d', date('Ym'), $user->getId()));
145+
146+
// or even invalidate the cache when the user data changes
147+
$checksum = hash('xxh128', $user->getUpdatedAt()->format(DATE_ATOM));
148+
$userCache = $cache->withSubNamespace(sprintf('user-%d-%s', $user->getId(), $checksum));
118149

119150
.. _cache_stampede-prevention:
120151

0 commit comments

Comments
 (0)