Method response caching

← Method response caching

Ashterix

docs: rewrite JsonRpcBundle docs, add SDK docs, move them under docs/api

en/docs/api/json-rpc-bundle/add_rpc_service/cache.md new file +193 āˆ’0

1 + ## Summary
2 +
3 + ::::::block class="floatinginfobox"
4 + :::::columns border="1" zebra="1"
5 + ::::row
6 + :::col width="40%"
7 + **Classname**
8 + :::
9 +
10 + :::col
11 + `Cache`
12 + :::
13 + ::::
14 +
15 + ::::row
16 + :::col width="40%"
17 + **Namespace**
18 + :::
19 +
20 + :::col
21 + `Ufo\RpcObject\RPC`
22 + :::
23 + ::::
24 +
25 + ::::row
26 + :::col width="40%"
27 + **Target**
28 + :::
29 +
30 + :::col
31 + `method`
32 + :::
33 + ::::
34 + :::::
35 +
36 + :::::columns border="1" zebra="1"
37 + ::::row
38 + :::col align="center"
39 + Constructor
40 + :::
41 + ::::
42 +
43 + ::::row
44 + :::col
45 + ```php
46 + /**
47 + * Cache constructor.
48 + *
49 + * @param int $lifetimeSecond
50 + * @param array $environments
51 + */
52 + public function __construct(
53 + public int $lifetimeSecond = self::T_MINUTE,
54 + public array $environments = [self::ENV_PROD],
55 + ) {}
56 + ```
57 + :::
58 + ::::
59 + :::::
60 + ::::::
61 +
62 + # Method response caching
63 +
64 + By default, response caching for your RPC methods is disabled, and every time you call the API the method is executed.
65 +
66 + However, for certain methods whose result rarely changes, it sometimes makes sense to enable response caching to speed up request processing, preserve rate limits, reduce load on parts of the system, etc.
67 +
68 + Responses are stored in a separate cache pool of the bundle (`rpc.cache.pool`, filesystem-based in `%kernel.cache_dir%`). It can be replaced with any application pool, for example a shared Redis one, via `cache.pool` in the [configuration](/docs/api/json-rpc-bundle/config).
69 +
70 + Enabling caching is as simple as possible: all you need to do is add the `#[RPC\Cache]` attribute to the method.
71 +
72 + ```php
73 + namespace App\Api\Procedures;
74 +
75 + use Ufo\RpcObject\RPC;
76 +
77 + class SomeApiMethod implements IRpcService
78 + {
79 + #[RPC\Cache]
80 + public function methodThatWorksForALongTime(): void {}
81 + }
82 + ```
83 +
84 + This configuration caches the response for one minute; every subsequent request to this method with the same parameters gets the response instantly from the cache.
85 +
86 + The cache key consists of the method implementation (`Class::method`), the API version and the sorted request parameters, so the order of keys in nested objects does not affect the key. Methods without `#[RPC\Cache]` do not access the cache at all.
87 +
88 + As usual, you can clear the cache by running the Symfony command
89 +
90 + ```bash
91 + bin/console cache:clear
92 + ```
93 +
94 + If needed, you can increase the cache lifetime by passing the number of seconds in the lifetimeSecond parameter. For convenience, there are constants that cover most needs, but you can also pass the value as a plain number.
95 +
96 + ```php
97 + use Ufo\RpcObject\RPC\Cache;
98 +
99 + Cache::T_MINUTE; // 60
100 + Cache::T_5_MINUTES; // 300
101 + Cache::T_10_MINUTES; // 600
102 + Cache::T_30_MINUTES; // 1800
103 + Cache::T_HOUR; // 3600
104 + Cache::T_2_HOURS; // 7200
105 + Cache::T_5_HOURS; // 18000
106 + Cache::T_10_HOURS; // 36000
107 + Cache::T_DAY; // 86400
108 + Cache::T_2_DAYS; // 172800
109 + Cache::T_3_DAYS; // 259200
110 + Cache::T_5_DAYS; // 432000
111 + Cache::T_10_DAYS; // 864000
112 + Cache::T_WEEK; // 604800
113 + Cache::T_2_WEEKS; // 1209600
114 + Cache::T_3_WEEKS; // 1814400
115 + Cache::T_MONTH; // 2592000
116 + Cache::T_2_MONTHS; // 5184000
117 + Cache::T_3_MONTHS; // 7776000
118 + Cache::T_HALF_YEAR; // 15724800
119 + Cache::T_YEAR; // 31536000
120 + ```
121 +
122 + You can also change the environments in which caching can be enabled. By default, caching works only in the prod environment. But you can change this by passing an array of environment names in which you want to cache results. In the example below, the result is cached for one day in the prod and dev environments.
123 +
124 + ```php
125 + namespace App\Api\Procedures;
126 +
127 + use Ufo\RpcObject\RPC;
128 +
129 + class SomeApiMethod implements IRpcService
130 + {
131 + #[RPC\Cache(lifetimeSecond: RPC\Cache::T_DAY, environments: ['dev', 'prod'])]
132 + public function methodThatWorksForALongTime(): void {}
133 + }
134 + ```
135 +
136 + ## Bypassing the cache for a single request
137 +
138 + The special parameter `$rpc.ignoreCache` forces the response to be computed again and overwritten in the cache:
139 +
140 + ```json
141 + {"jsonrpc": "2.0", "id": 1, "method": "SomeApiMethod.methodThatWorksForALongTime", "params": {"$rpc": {"ignoreCache": true}}}
142 + ```
143 +
144 + ## `#[RPC\CacheRelation]`
145 +
146 + A method that changes data can clear the cached responses of related methods and, if needed, warm them up again right away.
147 +
148 + ```php
149 + public function __construct(
150 + public ?string $serviceFQCN = null, // class of the related methods; defaults to the current one
151 + public array $methods = [], // names of the related methods
152 + public bool $warmUp = false, // run them again right away to fill the cache
153 + )
154 + ```
155 +
156 + ```php
157 + use Ufo\RpcObject\RPC;
158 +
159 + #[RPC\Info('User')]
160 + final class UserProcedure implements IRpcService
161 + {
162 + #[RPC\Cache(lifetimeSecond: RPC\Cache::T_HOUR)]
163 + public function get(int $id): UserDto { /* ... */ }
164 +
165 + #[RPC\CacheRelation(methods: ['get'], warmUp: true)]
166 + public function rename(int $id, string $name): bool { /* ... */ }
167 + }
168 + ```
169 +
170 + After a successful `User.rename {"id": 5, ...}`, the cached `User.get {"id": 5}` is deleted and rebuilt. The key of the related request is made of those parameters of the current request whose names match the parameters of the related method. The attribute can be specified multiple times.
171 +
172 + Invalidation runs on the `rpc.post_response` event, i.e. after the response has been sent to the client. It does not run for an error response.
173 +
174 + :::tip
175 + On multiple servers, configure a shared `cache.pool` — otherwise invalidation only takes effect on the server that handled the request.
176 + :::
177 +
178 + ## Managing the cache from code
179 +
180 + `Ufo\JsonRpcBundle\Server\RpcCache\RpcCacheService` provides the same capabilities programmatically:
181 +
182 + | Method | What it does |
183 + | --- | --- |
184 + | `deleteRelationCache(string $class, array $methods, array $params)` | Deletes cached responses of the specified methods |
185 + | `warmCache(string $class, array $methods, array $params, bool $deleteCache = true)` | Deletes and immediately rebuilds the cache |
186 + | `deleteRequestCache(RpcRequest $request)` | Deletes the response of a single request |
187 +
188 + ```php
189 + public function __construct(private RpcCacheService $rpcCache) {}
190 +
191 + // after updating an entity outside RPC
192 + $this->rpcCache->deleteRelationCache(UserProcedure::class, ['get'], ['id' => $id]);
193 + ```