Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Cache] New Component #112

Merged
merged 29 commits into from
Nov 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/labeler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ Bard:
- docs/bard/*
- src/SonsOfPHP/Bard/*

Cache:
- docs/components/cache/*
- src/SonsOfPHP/**/Cache/*

Clock:
- docs/components/clock/*
- src/SonsOfPHP/Component/Clock/*
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ jobs:
with:
php-version: ${{ matrix.php-version }}
coverage: xdebug
extensions: apcu
- name: Cache Composer Packages
id: composer-cache
uses: actions/cache@v3
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/unit-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ jobs:
with:
php-version: ${{ matrix.php-version }}
coverage: none
extensions: apcu
- name: Cache Composer Packages
id: composer-cache
uses: actions/cache@v3
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ Examples:
* [PR #59](https://github.com/SonsOfPHP/sonsofphp/pull/59) Added new HttpMessage component
* [PR #59](https://github.com/SonsOfPHP/sonsofphp/pull/59) Added new HttpFactory component
* [PR #70](https://github.com/SonsOfPHP/sonsofphp/pull/70) Added new Core contract
* [PR #112](https://github.com/SonsOfPHP/sonsofphp/pull/112) [Cache] Added new component

## [0.3.8]

Expand Down
20 changes: 18 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,16 @@ purge: # Purge vendor and lock files
rm -rf vendor/ src/SonsOfPHP/Bridge/*/vendor/ src/SonsOfPHP/Bridge/*/composer.lock
rm -rf vendor/ src/SonsOfPHP/Bundle/*/vendor/ src/SonsOfPHP/Bundle/*/composer.lock
rm -rf vendor/ src/SonsOfPHP/Component/*/vendor/ src/SonsOfPHP/Component/*/composer.lock
rm -rf vendor/ src/SonsOfPHP/Contract/*/vendor/ src/SonsOfPHP/Contract/*/composer.lock

test: ## Run PHPUnit Tests
XDEBUG_MODE=off $(PHP) -dxdebug.mode=off $(PHPUNIT) --order-by=defects
XDEBUG_MODE=off \
$(PHP) \
-dxdebug.mode=off \
-dapc.enable_cli=1 \
$(PHPUNIT) \
--cache-result \
--order-by=defects

phpunit: test

Expand All @@ -55,7 +62,16 @@ lint-php: # lint php files
find src -name "*.php" -not -path "src/**/vendor/*" | xargs -I{} $(PHP) -l '{}'

coverage: ## Build Code Coverage Report
XDEBUG_MODE=coverage $(PHP) -dxdebug.mode=coverage $(PHPUNIT) --coverage-html $(COVERAGE_DIR)
XDEBUG_MODE=coverage \
$(PHP) \
-dxdebug.mode=coverage \
-dapc.enable_cli=1 \
$(PHPUNIT) \
--cache-result \
--coverage-html $(COVERAGE_DIR)

coverage-cache:
XDEBUG_MODE=coverage $(PHP) -dxdebug.mode=coverage $(PHPUNIT) --testsuite cache --coverage-html $(COVERAGE_DIR)

coverage-clock:
XDEBUG_MODE=coverage $(PHP) -dxdebug.mode=coverage $(PHPUNIT) --testsuite clock --coverage-html $(COVERAGE_DIR)
Expand Down
4 changes: 4 additions & 0 deletions bard.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
"path": "src/SonsOfPHP/Bard",
"repository": "git@github.com:SonsOfPHP/bard.git"
},
{
"path": "src/SonsOfPHP/Component/Cache",
"repository": "git@github.com:SonsOfPHP/cache.git"
},
{
"path": "src/SonsOfPHP/Component/Clock",
"repository": "git@github.com:SonsOfPHP/clock.git"
Expand Down
26 changes: 18 additions & 8 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@
"support": {
"issues": "https://github.com/SonsOfPHP/sonsofphp/issues",
"forum": "https://github.com/orgs/SonsOfPHP/discussions",
"docs": "https://docs.sonsofphp.com",
"chat": "https://discord.gg/sdVxNhFqND"
"docs": "https://docs.sonsofphp.com"
},
"funding": [
{
Expand All @@ -36,7 +35,9 @@
"psr/event-dispatcher-implementation": "1.0",
"psr/clock-implementation": "1.0",
"psr/http-message-implementation": "^1.0",
"psr/http-factory-implementation": "^1.0"
"psr/http-factory-implementation": "^1.0",
"psr/cache-implementation": "^3.0",
"psr/simple-cache-implementation": "^3.0"
},
"require": {
"php": ">=8.1",
Expand All @@ -55,7 +56,9 @@
"symfony/messenger": "^5|^6",
"psr/clock": "^1.0",
"psr/http-message": "^1.0",
"psr/http-factory": "^1.0"
"psr/http-factory": "^1.0",
"psr/cache": "^3.0",
"psr/simple-cache": "^3.0"
},
"replace": {
"sonsofphp/bard": "self.version",
Expand All @@ -73,11 +76,14 @@
"sonsofphp/cqrs-bundle": "self.version",
"sonsofphp/filesystem": "self.version",
"sonsofphp/http-message": "self.version",
"sonsofphp/http-factory": "self.version"
"sonsofphp/http-factory": "self.version",
"sonsofphp/core-contract": "self.version",
"sonsofphp/cache": "self.version"
},
"autoload": {
"psr-4": {
"SonsOfPHP\\Bard\\": "src/SonsOfPHP/Bard/src",
"SonsOfPHP\\Component\\Cache\\": "src/SonsOfPHP/Component/Cache",
"SonsOfPHP\\Component\\Clock\\": "src/SonsOfPHP/Component/Clock",
"SonsOfPHP\\Component\\Cqrs\\": "src/SonsOfPHP/Component/Cqrs",
"SonsOfPHP\\Bundle\\Cqrs\\": "src/SonsOfPHP/Bundle/Cqrs",
Expand All @@ -92,10 +98,12 @@
"SonsOfPHP\\Component\\HttpMessage\\": "src/SonsOfPHP/Component/HttpMessage",
"SonsOfPHP\\Component\\Json\\": "src/SonsOfPHP/Component/Json",
"SonsOfPHP\\Component\\Money\\": "src/SonsOfPHP/Component/Money",
"SonsOfPHP\\Component\\Version\\": "src/SonsOfPHP/Component/Version"
"SonsOfPHP\\Component\\Version\\": "src/SonsOfPHP/Component/Version",
"SonsOfPHP\\Contract\\Core\\": "src/SonsOfPHP/Contract/Core"
},
"exclude-from-classmap": [
"src/SonsOfPHP/Bard/Tests",
"src/SonsOfPHP/Component/Cache/Tests",
"src/SonsOfPHP/Component/Clock/Tests",
"src/SonsOfPHP/Component/Cqrs/Tests",
"src/SonsOfPHP/Bundle/Cqrs/Tests",
Expand All @@ -110,7 +118,8 @@
"src/SonsOfPHP/Component/HttpMessage/Tests",
"src/SonsOfPHP/Component/Json/Tests",
"src/SonsOfPHP/Component/Money/Tests",
"src/SonsOfPHP/Component/Version/Tests"
"src/SonsOfPHP/Component/Version/Tests",
"src/SonsOfPHP/Contract/Core/Tests"
]
},
"extra": {
Expand All @@ -124,7 +133,8 @@
"symfony/serializer": "^5|^6",
"symfony/phpunit-bridge": "^6",
"symfony/error-handler": "^6",
"symfony/messenger": "^5|^6"
"symfony/messenger": "^5|^6",
"phpunit/phpunit": "^10.4"
},
"autoload-dev": {
"psr-4": {
Expand Down
66 changes: 66 additions & 0 deletions docs/components/cache/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
---
title: Cache - Overview
---

Used for cache stuff

## Installation

```shell
composer require sonsofphp/cache
```

### PSR-16 - Simple Cache

To add support for PSR-16 Simple Cache, require the PSR.

```shell
composer require psr/simple-cache
```

## Usage

```php
<?php

use SonsOfPHP\Component\Cache\Adapter\ApcuAdapter;

$pool = new ApcuAdapter();
```

All Adapters implement `Psr\Cache\CacheItemPoolInterface`

### PSR-16 Simple Cache Wrapper

```php
<?php

use SonsOfPHP\Component\Cache\Adapter\ApcuAdapter;
use SonsOfPHP\Component\Cache\SimpleCache;

$pool = new ApcuAdapter();
$cache = new SimpleCache($pool);
```

`SimpleCache` implements `Psr\SimpleCache\CacheInterface`.

### Setting up a multi layer cache

```php
<?php

use SonsOfPHP\Component\Cache\Adapter\ArrayAdapter;
use SonsOfPHP\Component\Cache\Adapter\ApcuAdapter;
use SonsOfPHP\Component\Cache\Adapter\ChainAdapter;

$pool = new ChainAdapter([
new ArrayAdapter(),
new ApcuAdapter(),
]);
```

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.

The `ChainAdapter` will also write to and delete from all pools.
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ nav:
- bard/index.md
- Components:
- components/index.md
- Cache: components/clock/index.md
- Clock: components/clock/index.md
- CQRS:
- components/cqrs/index.md
Expand Down
4 changes: 4 additions & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
<!--<directory>src/SonsOfPHP/Bard/src/Tests</directory>-->
</testsuite>

<testsuite name="cache">
<directory>src/SonsOfPHP/Component/Clock/Tests</directory>
</testsuite>

<testsuite name="clock">
<directory>src/SonsOfPHP/Component/Clock/Tests</directory>
</testsuite>
Expand Down
4 changes: 4 additions & 0 deletions src/SonsOfPHP/Component/Cache/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/Tests export-ignore
/phpunit.xml.dist export-ignore
/.gitattributes export-ignore
/.gitignore export-ignore
3 changes: 3 additions & 0 deletions src/SonsOfPHP/Component/Cache/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
composer.lock
phpunit.xml
vendor/
14 changes: 14 additions & 0 deletions src/SonsOfPHP/Component/Cache/Adapter/AdapterInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

declare(strict_types=1);

namespace SonsOfPHP\Component\Cache\Adapter;

use Psr\Cache\CacheItemPoolInterface;

/**
* All Adapters MUST implement this interface
*
* @author Joshua Estes <joshua@sonsofphp.com>
*/
interface AdapterInterface extends CacheItemPoolInterface {}
122 changes: 122 additions & 0 deletions src/SonsOfPHP/Component/Cache/Adapter/ApcuAdapter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
<?php

declare(strict_types=1);

namespace SonsOfPHP\Component\Cache\Adapter;

use SonsOfPHP\Component\Cache\CacheItem;
use Psr\Cache\CacheItemInterface;
use SonsOfPHP\Component\Cache\Exception\CacheException;

/**
* @author Joshua Estes <joshua@sonsofphp.com>
*/
class ApcuAdapter implements AdapterInterface
{
private array $deferred = [];

public function __construct()
{
if (!extension_loaded('apcu') || !filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOL) || false === apcu_enabled()) {
throw new CacheException('APCu extension is required.');
}
}

/**
* {@inheritdoc}
*/
public function getItem(string $key): CacheItemInterface
{
if ($this->hasItem($key)) {
return (new CacheItem($key, true))->set(apcu_fetch($key));
}

return new CacheItem($key, false);
}

/**
* {@inheritdoc}
*/
public function getItems(array $keys = []): iterable
{
foreach ($keys as $key) {
yield $key => $this->getItem($key);
}
}

/**
* {@inheritdoc}
*/
public function hasItem(string $key): bool
{
CacheItem::validateKey($key);

return apcu_exists($key);
}

/**
* {@inheritdoc}
*/
public function clear(): bool
{
return apcu_clear_cache();
}

/**
* {@inheritdoc}
*/
public function deleteItem(string $key): bool
{
CacheItem::validateKey($key);

return apcu_delete($key);
}

/**
* {@inheritdoc}
*/
public function deleteItems(array $keys): bool
{
$ret = true;
foreach ($keys as $key) {
if (!$this->deleteItem($key)) {
$ret = false;
}
}

return $ret;
}

/**
* {@inheritdoc}
*/
public function save(CacheItemInterface $item): bool
{
$this->saveDeferred($item);

return $this->commit();
}

/**
* {@inheritdoc}
*/
public function saveDeferred(CacheItemInterface $item): bool
{
$this->deferred[$item->getKey()] = $item;

return true;
}

/**
* {@inheritdoc}
*/
public function commit(): bool
{
foreach ($this->deferred as $key => $item) {
apcu_store($key, $item->get(), 0);
}
$this->deferred = [];

return true;
}
}
Loading