Skip to content

Commit 5b3be40

Browse files
authored
Merge pull request #507 from WoltLab/6.2-Eager-and-Tolerant-Caching
Document Eager and Tolerant Caching
2 parents f31298f + 831c8dd commit 5b3be40

File tree

2 files changed

+118
-0
lines changed

2 files changed

+118
-0
lines changed

docs/migration/wsc61/caching.md

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
# Migrating from WoltLab Suite 6.1 - Tolerant and Eager Caching
2+
3+
In the upcoming version of WoltLab Suite, the caching system has been reworked to provide a more flexible and efficient way to cache data.
4+
5+
The previous implementation had three distinct shortcomings:
6+
7+
- Resetting a cache causes the next request that needs this cache to trigger a synchronous rebuild.
8+
- Non-critical caches can sometimes be expensive to generate, causing dips in response times.
9+
- The same rebuild can take place simultaneously by concurrent requests.
10+
11+
The new caching systems solves this moving the any request for a cache rebuild into the request that triggered the cache invalidation.
12+
13+
This will add the burden to rebuild these caches onto the current request which is usually an (in comparison) expensive request anyway.
14+
The idea behind this is that adding a few miliseconds to a request that already takes half a second makes no difference to the user.
15+
On the other hand, accessing a page and suddenly have a significantly longer loading time is unexpected to the visitor.
16+
17+
Performing a full cache reset will still have the same latency impact as before.
18+
19+
## General Guidelines
20+
21+
- MUST NOT rely on any (runtime) cache.
22+
- Return a `CacheData` object instead of an `array`.
23+
- Parametrized caches are supported through `readonly` properties in the constructor.
24+
```php
25+
namespace wcf\system\cache\tolerant;
26+
27+
final class FooCache extends AbstractTolerantCache {
28+
public function __construct(
29+
public readonly int $categoryID
30+
) {}
31+
// Additional methods …
32+
}
33+
```
34+
35+
## Eager Caches
36+
37+
The eager cache has no lifetime and must be rebuild manually by the developer if the data changes.
38+
An eager cache is guaranteed to be always present, either by fetching the cached data or by rebuilding it synchronously.
39+
40+
```php
41+
(new FooCache())->rebuild()
42+
```
43+
44+
#### Example
45+
46+
```php
47+
namespace wcf\system\cache\eager;
48+
49+
use wcf\system\cache\eager\data\FooCacheData;
50+
51+
/**
52+
* @extends AbstractEagerCache<FooCacheData>
53+
*/
54+
final class FooCache extends AbstractEagerCache
55+
{
56+
public function __construct(
57+
public readonly bool $snafucated,
58+
) {}
59+
60+
#[\Override]
61+
protected function getCacheData(): FooCacheData
62+
{
63+
// Load and return the data here …
64+
}
65+
}
66+
```
67+
68+
Parameters for a stateful cache are passed through the constructor and are required to be marked as `readonly`.
69+
70+
```php
71+
$cache = (new FooCache(true))->getCache();
72+
```
73+
74+
## Tolerant Caches
75+
76+
A tolerant cache is similar to an eager cache but has a maximum lifetime after which it is queued up for a rebuild.
77+
Similar to the eager cache, it is also guaranteed to exist when queried, serving either cached data or rebuilding it synchronously.
78+
79+
The main difference is that the tolerant cache is permitted to serve stale content. For example, a cache is set a lifetime of 300 seconds but querying it 307 seconds after its creation may still return the old data.
80+
The cache content will be refreshed eventually, but callees must not expect the data to be of a precise age.
81+
82+
The cache is updated by a background job when the lifetime expires or by a [probabilistic early expiration](https://en.wikipedia.org/wiki/Cache_stampede#Probabilistic_early_expiration).
83+
The early expiration will randomly queue a tolerant cache for a rebuild before it exceeds its maximum lifetime.
84+
The odds of an early rebuild increases significantly the less time is remaining, making it very likely that a tolerant does not become stale.
85+
86+
#### Example
87+
88+
```php
89+
namespace wcf\system\cache\tolerant;
90+
91+
use wcf\system\cache\tolerant\data\BarCacheData;
92+
93+
/**
94+
* @extends AbstractTolerantCache<BarCacheData>
95+
*/
96+
final class BarCache extends AbstractTolerantCache
97+
{
98+
#[\Override]
99+
public function getLifetime(): int
100+
{
101+
// 3,600 seconds = 1 hour
102+
return 3_600;
103+
}
104+
105+
#[\Override]
106+
protected function rebuildCacheData(): BarCacheData
107+
{
108+
// Load and return the data here …
109+
}
110+
}
111+
```
112+
113+
This cache can be used as follows:
114+
115+
```php
116+
$cache = (new BarCache())->getCache();
117+
```

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ nav:
133133
- 'PHP API': 'migration/wsc61/php.md'
134134
- 'Templates': 'migration/wsc61/templates.md'
135135
- 'Quotes': 'migration/wsc61/quotes.md'
136+
- 'Caching': 'migration/wsc61/caching.md'
136137
- 'From WoltLab Suite 6.0':
137138
- 'PHP API': 'migration/wsc60/php.md'
138139
- 'Templates': 'migration/wsc60/templates.md'

0 commit comments

Comments
 (0)