Skip to content

Commit b67565d

Browse files
authored
[Cache] Various Updates (#227)
1 parent e89d747 commit b67565d

25 files changed

Lines changed: 711 additions & 110 deletions

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ To get the diff between two versions, go to https://github.com/SonsOfPHP/sonsofp
1010

1111
## [Unreleased]
1212

13+
* [PR #227](https://github.com/SonsOfPHP/sonsofphp/pull/227) [Cache] FilesystemAdapter, Marshallers, and other updates
1314
* [PR #226](https://github.com/SonsOfPHP/sonsofphp/pull/226) [Registry] New Component and Contract
1415
* [PR #225](https://github.com/SonsOfPHP/sonsofphp/pull/225) Maintenance
1516
* [PR #222](https://github.com/SonsOfPHP/sonsofphp/pull/222) [Assert] New Component

composer.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,7 @@
8888
"psr/http-server-handler": "^1.0",
8989
"psr/http-server-middleware": "^1.0",
9090
"aws/aws-sdk-php": "^3.0",
91-
"liip/imagine-bundle": "^2.0",
92-
"sonsofphp/registry-contract": "0.3.x-dev"
91+
"liip/imagine-bundle": "^2.0"
9392
},
9493
"replace": {
9594
"sonsofphp/bard": "self.version",
@@ -247,4 +246,4 @@
247246
"SonsOfPHP\\Bridge\\Symfony\\Cqrs\\Tests\\": "src/SonsOfPHP/Bridge/Symfony/Cqrs/Tests"
248247
}
249248
}
250-
}
249+
}

docs/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
* [Assert](components/assert.md)
1717
* [Cache](components/cache/README.md)
1818
* [Adapters](components/cache/adapters.md)
19+
* [Marshallers](components/cache/marshallers.md)
1920
* [Clock](components/clock.md)
2021
* [Container](components/container.md)
2122
* [Cookie](components/cookie.md)

docs/components/cache/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
title: Cache - Overview
33
---
44

5-
# Cache
6-
75
## Installation
86

97
```shell
@@ -59,6 +57,8 @@ $pool = new ChainAdapter([
5957
]);
6058
```
6159

62-
The `ChainAdapter` will read from all pools and return the first result it finds. So in the above example, if the cache item is not found in `ArrayAdapter`, it will look for it in the `ApcuAdapter` pool.
60+
The `ChainAdapter` will read from all pools and return the first result it
61+
finds. So in the above example, if the cache item is not found in
62+
`ArrayAdapter`, it will look for it in the `ApcuAdapter` pool.
6363

6464
The `ChainAdapter` will also write to and delete from all pools.

docs/components/cache/adapters.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,82 @@
1+
---
2+
title: Cache Adapters
3+
---
4+
15
# Adapters
26

7+
All adapters implement the PSR-6 `\Psr\Cache\CacheItemPoolInterface` and can be used as
8+
standalone cache pools.
9+
310
## ApcuAdapter
411

12+
Requires the APCu extension is loaded and enabled.
13+
14+
```php
15+
<?php
16+
17+
use SonsOfPHP\Componenet\Cache\Adapter\ApcuAdapter;
518

19+
$cache = new ApcuAdapter();
20+
21+
// You can set a default TTL in seconds and Marshaller as well.
22+
$cache = new ApcuAdapter(60, new CustomMarshaller());
23+
```
624

725
## ArrayAdapter
826

27+
Stores cache items in an internal PHP array.
28+
29+
```php
30+
<?php
931

32+
use SonsOfPHP\Componenet\Cache\Adapter\ArrayAdapter;
33+
34+
$cache = new ArrayAdapter();
35+
```
1036

1137
## ChainAdapter
1238

39+
The Chain Adapter will take one or more adapters. It will WRITE to all adapters
40+
and will READ from each adapter until it finds a hit and return that cache item.
41+
42+
```php
43+
<?php
1344

45+
use SonsOfPHP\Componenet\Cache\Adapter\ApcuAdapter;
46+
use SonsOfPHP\Componenet\Cache\Adapter\ArrayAdapter;
47+
use SonsOfPHP\Componenet\Cache\Adapter\ChainAdapter;
48+
49+
$cache = new ChainAdapter([
50+
new ArrayAdapter(),
51+
new ApcuAdapter(),
52+
]);
53+
```
54+
55+
## FilesystemAdapter
56+
57+
Stores cache files on disk
58+
59+
```php
60+
<?php
61+
62+
use SonsOfPHP\Componenet\Cache\Adapter\FilesystemAdapter;
63+
64+
$cache = new FilesystemAdapter();
65+
66+
// You can configure the directory, default permissions, default ttl, and
67+
// marshaller
68+
$cache = new FilesystemAdapter('/path/to/cache', 0777, 60, new CustomMarshaller());
69+
```
1470

1571
## NullAdapter
1672

73+
Mainly used for testing, however you could have some checks in place and if
74+
those checks fail, you could fallback to this adapter.
75+
76+
```php
77+
<?php
1778

79+
use SonsOfPHP\Componenet\Cache\Adapter\NullAdapter;
1880

81+
$cache = new NullAdapter();
82+
```
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
---
2+
title: Cache Marshallers
3+
---
4+
5+
# Marshallers
6+
7+
Using marshallers will allow you to serialize the cache values differently.
8+
9+
## SerializableMarshaller
10+
11+
This marshaller will use php's native `serialize` and `unserialize` functions on
12+
the values.
13+
14+
```php
15+
<?php
16+
17+
use SonsOfPHP\Componenet\Cache\Marshaller\SerializableMarshaller;
18+
19+
$marshaller = new SerializableMarshaller();
20+
```
21+
22+
## JsonMarshaller
23+
24+
The json marshaller will use php's native `json_encode` and `json_decode`
25+
functions to serialize data.
26+
27+
```php
28+
<?php
29+
30+
use SonsOfPHP\Componenet\Cache\Marshaller\JsonMarshaller;
31+
32+
$marshaller = new JsonMarshaller();
33+
```
34+
35+
# Custom Marshaller
36+
37+
You can create a custom marshaller. For example, you could create one the
38+
encrypts/decrypts the values.
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SonsOfPHP\Component\Cache\Adapter;
6+
7+
use Psr\Cache\CacheItemInterface;
8+
use Psr\Log\LoggerAwareInterface;
9+
use Psr\Log\LoggerAwareTrait;
10+
use SonsOfPHP\Component\Cache\Marshaller\MarshallerInterface;
11+
use SonsOfPHP\Component\Cache\Marshaller\SerializableMarshaller;
12+
13+
/**
14+
* @author Joshua Estes <joshua@sonsofphp.com>
15+
*/
16+
abstract class AbstractAdapter implements AdapterInterface, LoggerAwareInterface
17+
{
18+
use LoggerAwareTrait;
19+
20+
protected array $deferred = [];
21+
22+
public function __construct(
23+
protected int $defaultTTL = 0,
24+
protected ?MarshallerInterface $marshaller = null,
25+
) {
26+
if (!$this->marshaller instanceof MarshallerInterface) {
27+
$this->marshaller = new SerializableMarshaller();
28+
}
29+
}
30+
31+
public function __destruct()
32+
{
33+
$this->commit();
34+
}
35+
36+
/**
37+
* {@inheritdoc}
38+
*/
39+
public function getItems(array $keys = []): iterable
40+
{
41+
foreach ($keys as $key) {
42+
yield $key => $this->getItem($key);
43+
}
44+
}
45+
46+
/**
47+
* {@inheritdoc}
48+
*/
49+
public function deleteItems(array $keys): bool
50+
{
51+
$isOk = true;
52+
foreach ($keys as $key) {
53+
if (!$this->deleteItem($key)) {
54+
$this->logger?->debug(sprintf('Unable to delete key "%s".', $key));
55+
$isOk = false;
56+
}
57+
}
58+
59+
return $isOk;
60+
}
61+
62+
/**
63+
* {@inheritdoc}
64+
*/
65+
public function saveDeferred(CacheItemInterface $item): bool
66+
{
67+
$this->deferred[$item->getKey()] = $item;
68+
69+
return true;
70+
}
71+
72+
/**
73+
* {@inheritdoc}
74+
*/
75+
public function commit(): bool
76+
{
77+
$isOk = true;
78+
79+
foreach ($this->deferred as $item) {
80+
if (!$this->save($item)) {
81+
$this->logger?->debug(sprintf('Unable to save key "%s".', $item->getKey()));
82+
$isOk = false;
83+
}
84+
}
85+
86+
$this->deferred = [];
87+
88+
return $isOk;
89+
}
90+
}

src/SonsOfPHP/Component/Cache/Adapter/ApcuAdapter.php

Lines changed: 15 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,25 @@
77
use Psr\Cache\CacheItemInterface;
88
use SonsOfPHP\Component\Cache\CacheItem;
99
use SonsOfPHP\Component\Cache\Exception\CacheException;
10+
use SonsOfPHP\Component\Cache\Marshaller\MarshallerInterface;
1011

1112
/**
1213
* @author Joshua Estes <joshua@sonsofphp.com>
1314
*/
14-
class ApcuAdapter implements AdapterInterface
15+
final class ApcuAdapter extends AbstractAdapter
1516
{
16-
private array $deferred = [];
17-
18-
public function __construct()
19-
{
17+
public function __construct(
18+
int $defaultTTL = 0,
19+
?MarshallerInterface $marshaller = null,
20+
) {
2021
if (!extension_loaded('apcu') || !filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOL) || false === apcu_enabled()) {
2122
throw new CacheException('APCu extension is required.');
2223
}
24+
25+
parent::__construct(
26+
defaultTTL: $defaultTTL,
27+
marshaller: $marshaller,
28+
);
2329
}
2430

2531
/**
@@ -28,22 +34,14 @@ public function __construct()
2834
public function getItem(string $key): CacheItemInterface
2935
{
3036
if ($this->hasItem($key)) {
31-
return (new CacheItem($key, true))->set(apcu_fetch($key));
37+
return (new CacheItem($key, true))
38+
->set($this->marshaller->unmarshall(apcu_fetch($key)))
39+
;
3240
}
3341

3442
return new CacheItem($key, false);
3543
}
3644

37-
/**
38-
* {@inheritdoc}
39-
*/
40-
public function getItems(array $keys = []): iterable
41-
{
42-
foreach ($keys as $key) {
43-
yield $key => $this->getItem($key);
44-
}
45-
}
46-
4745
/**
4846
* {@inheritdoc}
4947
*/
@@ -72,52 +70,11 @@ public function deleteItem(string $key): bool
7270
return apcu_delete($key);
7371
}
7472

75-
/**
76-
* {@inheritdoc}
77-
*/
78-
public function deleteItems(array $keys): bool
79-
{
80-
$ret = true;
81-
foreach ($keys as $key) {
82-
if (!$this->deleteItem($key)) {
83-
$ret = false;
84-
}
85-
}
86-
87-
return $ret;
88-
}
89-
9073
/**
9174
* {@inheritdoc}
9275
*/
9376
public function save(CacheItemInterface $item): bool
9477
{
95-
$this->saveDeferred($item);
96-
97-
return $this->commit();
98-
}
99-
100-
/**
101-
* {@inheritdoc}
102-
*/
103-
public function saveDeferred(CacheItemInterface $item): bool
104-
{
105-
$this->deferred[$item->getKey()] = $item;
106-
107-
return true;
108-
}
109-
110-
/**
111-
* {@inheritdoc}
112-
*/
113-
public function commit(): bool
114-
{
115-
foreach ($this->deferred as $key => $item) {
116-
apcu_store($key, $item->get(), 0);
117-
}
118-
119-
$this->deferred = [];
120-
121-
return true;
78+
return apcu_store($item->getKey(), $this->marshaller->marshall($item->get()), 0);
12279
}
12380
}

0 commit comments

Comments
 (0)