Skip to content

Commit 6a32a9e

Browse files
committed
Add more explanations for the different cache types
1 parent 53f0b1e commit 6a32a9e

File tree

1 file changed

+55
-44
lines changed

1 file changed

+55
-44
lines changed

docs/migration/wsc61/caching.md

Lines changed: 55 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2,98 +2,109 @@
22

33
In the upcoming version of WoltLab Suite, the caching system has been reworked to provide a more flexible and efficient way to cache data.
44

5-
To solve the problems:
5+
The previous implementation had three distinct shortcomings:
66

77
- Resetting a cache causes the next request that needs this cache to trigger a synchronous rebuild.
88
- Non-critical caches can sometimes be expensive to generate, causing dips in response times.
99
- The same rebuild can take place simultaneously by concurrent requests.
1010

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 thread 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+
1119
## General Guidelines
1220

13-
- MUST NOT rely on any (runtime) cache
14-
- Return a `CacheData` object instead of an `array`
15-
- Optional, parameterized caches with state
16-
- Use `readonly` properties in the constructor
17-
```PHP
18-
final class FooCache extends AbstractTolerantCache {
19-
public function __construct(
20-
public readonly int $categoryID
21-
) {}
22-
// Additional methods …
23-
}
24-
```
21+
- MUST NOT rely on any (runtime) cache.
22+
- Return a `CacheData` object instead of an `array`.
23+
- (Optional) For parameterized caches with state:
24+
- Use `readonly` properties in the constructor.
25+
```php
26+
final class FooCache extends AbstractTolerantCache {
27+
public function __construct(
28+
public readonly int $categoryID
29+
) {}
30+
// Additional methods …
31+
}
32+
```
2533

2634
## Eager Caches
2735

28-
The eager cache has no lifetime and must be updated manually by the developer if the data changes.
29-
`(new FooEagerCache())->rebuild()`
36+
The eager cache has no lifetime and must be rebuild manually by the developer if the data changes.
37+
An eager cache is guaranteed to be always present, either by fetching the cached data or by rebuilding it synchronously.
38+
39+
```php
40+
(new FooCache())->rebuild()
41+
```
3042

3143
#### Example
3244

33-
```PHP
45+
```php
3446
/**
35-
* @extends AbstractEagerCache<\stdClass>
47+
* @extends AbstractEagerCache<FooCacheData>
3648
*/
37-
final class FooEagerCache extends AbstractEagerCache
49+
final class FooCache extends AbstractEagerCache
3850
{
3951
public function __construct(
40-
public readonly int $categoryID,
52+
public readonly bool $snafucated,
4153
) {}
42-
54+
4355
#[\Override]
44-
protected function getCacheData(): \stdClass
56+
protected function getCacheData(): FooCacheData
4557
{
46-
// Load cache data from database
47-
return new \stdClass();
58+
// Load and return the data here …
4859
}
4960
}
5061
```
5162

52-
The parameter `$categoryID` is certainly not required.
53-
It can also be omitted.
54-
55-
This cache can be used as follows
63+
Parameters for a stateful cache are passed through the constructor and are required to be marked as `readonly`.
5664

57-
```PHP
58-
$cache = (new FooEagerCache(1))->getCache();
59-
// without a state
60-
$cache = (new FooEagerCache())->getCache();
65+
```php
66+
$cache = (new FooCache(true))->getCache();
6167
```
6268

6369
## Tolerant Caches
6470

65-
The tolerant cache is a special cache that can return outdated content.
66-
This must not cause any problems at runtime.
71+
A tolerant cache is similar to an eager cache but has a maximum lifetime after which it is queued up for a rebuild.
72+
Similar to the eager cache, it is also guaranteed to exist when queried, serving either cached data or rebuilding it synchronously.
73+
74+
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.
75+
The cache content will be refreshed eventually, but callees must not expect the data to be of a precise age.
6776

6877
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).
78+
The early expiration will randomly queue a tolerant cache for a rebuild before it exceeds its maximum lifetime.
79+
The odds of an early rebuild increase significantly the less time is remaining, making it very likely that a tolerant does not become stale.
6980

7081
#### Example
7182

72-
```PHP
83+
```php
7384
/**
74-
* @extends AbstractTolerantCache<\stdClass>
85+
* @extends AbstractTolerantCache<BarCacheData>
7586
*/
76-
final class FooAsyncCache extends AbstractTolerantCache
87+
final class BarCache extends AbstractTolerantCache
7788
{
7889
#[\Override]
7990
public function getLifetime(): int
8091
{
81-
return 6000;
92+
// 3,600 seconds = 1 hour
93+
return 3_600;
8294
}
83-
95+
8496
#[\Override]
85-
protected function rebuildCacheData(): \stdClass
97+
protected function rebuildCacheData(): BarCacheData
8698
{
87-
// Load cache data from database
88-
return new \stdClass();
99+
// Load and return the data here …
89100
}
90101
}
91102
```
92103

93104
This cache can be used as follows
94105

95-
```PHP
96-
$cache = (new FooAsyncCache())->getCache();
106+
```php
107+
$cache = (new BarCache())->getCache();
97108
// with a state
98-
$cache = (new FooAsyncCache($parameterOne, $parameterTwo, …))->getCache();
109+
$cache = (new BarCache($parameterOne, $parameterTwo, …))->getCache();
99110
```

0 commit comments

Comments
 (0)