Subversion Repositories qbpwcf-lib(archive)

Rev

Rev 915 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 liveuser 1
# Cache
2
 
3
[![Build Status](https://travis-ci.org/reactphp/cache.svg?branch=master)](https://travis-ci.org/reactphp/cache)
4
 
5
Async, [Promise](https://github.com/reactphp/promise)-based cache interface
6
for [ReactPHP](https://reactphp.org/).
7
 
8
The cache component provides a
9
[Promise](https://github.com/reactphp/promise)-based
10
[`CacheInterface`](#cacheinterface) and an in-memory [`ArrayCache`](#arraycache)
11
implementation of that.
12
This allows consumers to type hint against the interface and third parties to
13
provide alternate implementations.
14
This project is heavily inspired by
15
[PSR-16: Common Interface for Caching Libraries](https://www.php-fig.org/psr/psr-16/),
16
but uses an interface more suited for async, non-blocking applications.
17
 
18
**Table of Contents**
19
 
20
* [Usage](#usage)
21
  * [CacheInterface](#cacheinterface)
22
    * [get()](#get)
23
    * [set()](#set)
24
    * [delete()](#delete)
25
    * [getMultiple()](#getmultiple)
26
    * [setMultiple()](#setmultiple)
27
    * [deleteMultiple()](#deletemultiple)
28
    * [clear()](#clear)
29
    * [has()](#has)
30
  * [ArrayCache](#arraycache)
31
* [Common usage](#common-usage)
32
  * [Fallback get](#fallback-get)
33
  * [Fallback-get-and-set](#fallback-get-and-set)
34
* [Install](#install)
35
* [Tests](#tests)
36
* [License](#license)
37
 
38
## Usage
39
 
40
### CacheInterface
41
 
42
The `CacheInterface` describes the main interface of this component.
43
This allows consumers to type hint against the interface and third parties to
44
provide alternate implementations.
45
 
46
#### get()
47
 
48
The `get(string $key, mixed $default = null): PromiseInterface<mixed>` method can be used to
49
retrieve an item from the cache.
50
 
51
This method will resolve with the cached value on success or with the
52
given `$default` value when no item can be found or when an error occurs.
53
Similarly, an expired cache item (once the time-to-live is expired) is
54
considered a cache miss.
55
 
56
```php
57
$cache
58
    ->get('foo')
59
    ->then('var_dump');
60
```
61
 
62
This example fetches the value of the key `foo` and passes it to the
63
`var_dump` function. You can use any of the composition provided by
64
[promises](https://github.com/reactphp/promise).
65
 
66
#### set()
67
 
68
The `set(string $key, mixed $value, ?float $ttl = null): PromiseInterface<bool>` method can be used to
69
store an item in the cache.
70
 
71
This method will resolve with `true` on success or `false` when an error
72
occurs. If the cache implementation has to go over the network to store
73
it, it may take a while.
74
 
75
The optional `$ttl` parameter sets the maximum time-to-live in seconds
76
for this cache item. If this parameter is omitted (or `null`), the item
77
will stay in the cache for as long as the underlying implementation
78
supports. Trying to access an expired cache item results in a cache miss,
79
see also [`get()`](#get).
80
 
81
```php
82
$cache->set('foo', 'bar', 60);
83
```
84
 
85
This example eventually sets the value of the key `foo` to `bar`. If it
86
already exists, it is overridden.
87
 
88
This interface does not enforce any particular TTL resolution, so special
89
care may have to be taken if you rely on very high precision with
90
millisecond accuracy or below. Cache implementations SHOULD work on a
91
best effort basis and SHOULD provide at least second accuracy unless
92
otherwise noted. Many existing cache implementations are known to provide
93
microsecond or millisecond accuracy, but it's generally not recommended
94
to rely on this high precision.
95
 
96
This interface suggests that cache implementations SHOULD use a monotonic
97
time source if available. Given that a monotonic time source is only
98
available as of PHP 7.3 by default, cache implementations MAY fall back
99
to using wall-clock time.
100
While this does not affect many common use cases, this is an important
101
distinction for programs that rely on a high time precision or on systems
102
that are subject to discontinuous time adjustments (time jumps).
103
This means that if you store a cache item with a TTL of 30s and then
104
adjust your system time forward by 20s, the cache item SHOULD still
105
expire in 30s.
106
 
107
#### delete()
108
 
109
The `delete(string $key): PromiseInterface<bool>` method can be used to
110
delete an item from the cache.
111
 
112
This method will resolve with `true` on success or `false` when an error
113
occurs. When no item for `$key` is found in the cache, it also resolves
114
to `true`. If the cache implementation has to go over the network to
115
delete it, it may take a while.
116
 
117
```php
118
$cache->delete('foo');
119
```
120
 
121
This example eventually deletes the key `foo` from the cache. As with
122
`set()`, this may not happen instantly and a promise is returned to
123
provide guarantees whether or not the item has been removed from cache.
124
 
125
#### getMultiple()
126
 
127
The `getMultiple(string[] $keys, mixed $default = null): PromiseInterface<array>` method can be used to
128
retrieve multiple cache items by their unique keys.
129
 
130
This method will resolve with an array of cached values on success or with the
131
given `$default` value when an item can not be found or when an error occurs.
132
Similarly, an expired cache item (once the time-to-live is expired) is
133
considered a cache miss.
134
 
135
```php
136
$cache->getMultiple(array('name', 'age'))->then(function (array $values) {
137
    $name = $values['name'] ?? 'User';
138
    $age = $values['age'] ?? 'n/a';
139
 
140
    echo $name . ' is ' . $age . PHP_EOL;
141
});
142
```
143
 
144
This example fetches the cache items for the `name` and `age` keys and
145
prints some example output. You can use any of the composition provided
146
by [promises](https://github.com/reactphp/promise).
147
 
148
#### setMultiple()
149
 
150
The `setMultiple(array $values, ?float $ttl = null): PromiseInterface<bool>` method can be used to
151
persist a set of key => value pairs in the cache, with an optional TTL.
152
 
153
This method will resolve with `true` on success or `false` when an error
154
occurs. If the cache implementation has to go over the network to store
155
it, it may take a while.
156
 
157
The optional `$ttl` parameter sets the maximum time-to-live in seconds
158
for these cache items. If this parameter is omitted (or `null`), these items
159
will stay in the cache for as long as the underlying implementation
160
supports. Trying to access an expired cache items results in a cache miss,
161
see also [`getMultiple()`](#getmultiple).
162
 
163
```php
164
$cache->setMultiple(array('foo' => 1, 'bar' => 2), 60);
165
```
166
 
167
This example eventually sets the list of values - the key `foo` to `1` value 
168
and the key `bar` to `2`. If some of the keys already exist, they are overridden.
169
 
170
#### deleteMultiple()
171
 
172
The `setMultiple(string[] $keys): PromiseInterface<bool>` method can be used to
173
delete multiple cache items in a single operation.
174
 
175
This method will resolve with `true` on success or `false` when an error
176
occurs. When no items for `$keys` are found in the cache, it also resolves
177
to `true`. If the cache implementation has to go over the network to
178
delete it, it may take a while.
179
 
180
```php
181
$cache->deleteMultiple(array('foo', 'bar, 'baz'));
182
```
183
 
184
This example eventually deletes keys `foo`, `bar` and `baz` from the cache. 
185
As with `setMultiple()`, this may not happen instantly and a promise is returned to
186
provide guarantees whether or not the item has been removed from cache.
187
 
188
#### clear()
189
 
190
The `clear(): PromiseInterface<bool>` method can be used to
191
wipe clean the entire cache.
192
 
193
This method will resolve with `true` on success or `false` when an error
194
occurs. If the cache implementation has to go over the network to
195
delete it, it may take a while.
196
 
197
```php
198
$cache->clear();
199
```
200
 
201
This example eventually deletes all keys from the cache. As with `deleteMultiple()`, 
202
this may not happen instantly and a promise is returned to provide guarantees 
203
whether or not all the items have been removed from cache.
204
 
205
#### has()
206
 
207
The `has(string $key): PromiseInterface<bool>` method can be used to
208
determine whether an item is present in the cache.
209
 
210
This method will resolve with `true` on success or `false` when no item can be found 
211
or when an error occurs. Similarly, an expired cache item (once the time-to-live 
212
is expired) is considered a cache miss.
213
 
214
```php
215
$cache
216
    ->has('foo')
217
    ->then('var_dump');
218
```
219
 
220
This example checks if the value of the key `foo` is set in the cache and passes 
221
the result to the `var_dump` function. You can use any of the composition provided by
222
[promises](https://github.com/reactphp/promise).
223
 
224
NOTE: It is recommended that has() is only to be used for cache warming type purposes
225
and not to be used within your live applications operations for get/set, as this method
226
is subject to a race condition where your has() will return true and immediately after,
227
another script can remove it making the state of your app out of date.
228
 
229
### ArrayCache
230
 
231
The `ArrayCache` provides an in-memory implementation of the [`CacheInterface`](#cacheinterface).
232
 
233
```php
234
$cache = new ArrayCache();
235
 
236
$cache->set('foo', 'bar');
237
```
238
 
239
Its constructor accepts an optional `?int $limit` parameter to limit the
240
maximum number of entries to store in the LRU cache. If you add more
241
entries to this instance, it will automatically take care of removing
242
the one that was least recently used (LRU).
243
 
244
For example, this snippet will overwrite the first value and only store
245
the last two entries:
246
 
247
```php
248
$cache = new ArrayCache(2);
249
 
250
$cache->set('foo', '1');
251
$cache->set('bar', '2');
252
$cache->set('baz', '3');
253
```
254
 
255
This cache implementation is known to rely on wall-clock time to schedule
256
future cache expiration times when using any version before PHP 7.3,
257
because a monotonic time source is only available as of PHP 7.3 (`hrtime()`).
258
While this does not affect many common use cases, this is an important
259
distinction for programs that rely on a high time precision or on systems
260
that are subject to discontinuous time adjustments (time jumps).
261
This means that if you store a cache item with a TTL of 30s on PHP < 7.3
262
and then adjust your system time forward by 20s, the cache item may
263
expire in 10s. See also [`set()`](#set) for more details.
264
 
265
## Common usage
266
 
267
### Fallback get
268
 
269
A common use case of caches is to attempt fetching a cached value and as a
270
fallback retrieve it from the original data source if not found. Here is an
271
example of that:
272
 
273
```php
274
$cache
275
    ->get('foo')
276
    ->then(function ($result) {
277
        if ($result === null) {
278
            return getFooFromDb();
279
        }
280
 
281
        return $result;
282
    })
283
    ->then('var_dump');
284
```
285
 
286
First an attempt is made to retrieve the value of `foo`. A callback function is 
287
registered that will call `getFooFromDb` when the resulting value is null. 
288
`getFooFromDb` is a function (can be any PHP callable) that will be called if the 
289
key does not exist in the cache.
290
 
291
`getFooFromDb` can handle the missing key by returning a promise for the
292
actual value from the database (or any other data source). As a result, this
293
chain will correctly fall back, and provide the value in both cases.
294
 
295
### Fallback get and set
296
 
297
To expand on the fallback get example, often you want to set the value on the
298
cache after fetching it from the data source.
299
 
300
```php
301
$cache
302
    ->get('foo')
303
    ->then(function ($result) {
304
        if ($result === null) {
305
            return $this->getAndCacheFooFromDb();
306
        }
307
 
308
        return $result;
309
    })
310
    ->then('var_dump');
311
 
312
public function getAndCacheFooFromDb()
313
{
314
    return $this->db
315
        ->get('foo')
316
        ->then(array($this, 'cacheFooFromDb'));
317
}
318
 
319
public function cacheFooFromDb($foo)
320
{
321
    $this->cache->set('foo', $foo);
322
 
323
    return $foo;
324
}
325
```
326
 
327
By using chaining you can easily conditionally cache the value if it is
328
fetched from the database.
329
 
330
## Install
331
 
332
The recommended way to install this library is [through Composer](https://getcomposer.org).
333
[New to Composer?](https://getcomposer.org/doc/00-intro.md)
334
 
335
This project follows [SemVer](https://semver.org/).
336
This will install the latest supported version:
337
 
338
```bash
339
$ composer require react/cache:^1.1
340
```
341
 
342
See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades.
343
 
344
This project aims to run on any platform and thus does not require any PHP
345
extensions and supports running on legacy PHP 5.3 through current PHP 7+ and
346
HHVM.
347
It's *highly recommended to use PHP 7+* for this project.
348
 
349
## Tests
350
 
351
To run the test suite, you first need to clone this repo and then install all
352
dependencies [through Composer](https://getcomposer.org):
353
 
354
```bash
355
$ composer install
356
```
357
 
358
To run the test suite, go to the project root and run:
359
 
360
```bash
361
$ php vendor/bin/phpunit
362
```
363
 
364
## License
365
 
366
MIT, see [LICENSE file](LICENSE).