Skip to content

Commit

Permalink
Copy edit "cache key" section of readme.
Browse files Browse the repository at this point in the history
Minor style changes to tests.
  • Loading branch information
Bilge committed Mar 16, 2017
1 parent e484fae commit c13eb95
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 20 deletions.
22 changes: 14 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,9 +188,7 @@ Durability only applies when connectors throw a recoverable exception type. If a
Caching
-------

Caching is available at the connector level if the connector implements `CacheToggle`. Connectors typically extend `CachingConnector` which implements [PSR-6][PSR-6]-compatible caching. Porter ships with just one cache implementation, `MemoryCache`, which stores data in memory but this can be substituted for any PSR-6 cache if the connector permits it.

When available, the connector caches raw responses for each unique [cache key](#cache-key). Cache keys are generated by an implementation-defined strategy or the default `JsonCacheKeyGenerator` strategy.
Caching is available at the connector level if the connector implements `CacheToggle`. Connectors typically extend `CachingConnector` which implements [PSR-6][PSR-6]-compatible caching. Porter ships with just one cache implementation, `MemoryCache`, which stores data in memory but this can be substituted for any PSR-6 cache if the connector permits it. When available, the connector caches raw responses for each unique [cache key](#cache-keys).

### Cache advice

Expand All @@ -214,15 +212,23 @@ $records = $porter->import(
);
```

### Cache key
### Cache keys

The cache key can optionally be generated by an implementation of `CacheKeyGeneratorInterface` if the connector permits it. This implementation should provide one method `generateCacheKey` which returns a [PSR-6][PSR-6]-compatible cache key.
The cache key is generated by a `CacheKeyGenerator` that encodes parameters to produce a unique cache key for each distinct `Connector::fetch` request. The default `JsonCacheKeyGenerator` simply JSON-encodes the parameters to create a cache key. The cache key generation strategy may be changed by calling `CachingConnector::setCacheKeyGenerator`.

The default implementation `JsonCacheKeyGenerator` generates keys comprised of the source and options parameters passed to `Connector::fetch`. Options are sorted before the cache key is created so the order of options are insignificant.
#### Writing a cache key generator

#### Implementation example
The `CacheKeyGenerator` interface defines one method with the following interface.

```php
public function generateCacheKey(string $source, array $sortedOptions) : string;
```

Implementations receive arguments similar to [connectors](#connectors), with the notable exception that the options parameter is converted to an array and sorted so that the same options specified in a different order result in the same cache key. The method must return a [PSR-6][PSR-6] compatible cache key.

##### Implementation example

The following example demonstrates a simple cache key generation implementation using an md5 hash of the json encoded parameters.
The following example demonstrates cache key generation using a hash of JSON-encoded parameters.

```php
class MyCacheKeyGenerator implements CacheKeyGenerator
Expand Down
5 changes: 3 additions & 2 deletions src/Connector/CachingConnector.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,13 +108,14 @@ public function setCacheKeyGenerator(CacheKeyGenerator $cacheKeyGenerator)
*
* @return string
*
* @throws InvalidCacheKeyException
* @throws InvalidCacheKeyException Cache key contains invalid data.
*/
private function validateCacheKey($key)
{
if (!is_string($key)) {
throw new InvalidCacheKeyException('Cache key must be of type string.');
throw new InvalidCacheKeyException('Cache key must be a string.');
}

if (strpbrk($key, self::RESERVED_CHARACTERS) !== false) {
throw new InvalidCacheKeyException(
sprintf('Cache key "%s" contains one or more reserved characters: "%s"', $key, self::RESERVED_CHARACTERS)
Expand Down
12 changes: 2 additions & 10 deletions test/Integration/Porter/Connector/CachingConnectorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,6 @@ public function testCacheUsedForCacheKeyGenerator()

public function testFetchThrowsInvalidCacheKeyExceptionOnNonStringCackeKey()
{
$this->setExpectedException(InvalidCacheKeyException::class, 'Cache key must be of type string.');

$this->connector->setCacheKeyGenerator(
\Mockery::mock(CacheKeyGenerator::class)
->shouldReceive('generateCacheKey')
Expand All @@ -107,21 +105,14 @@ public function testFetchThrowsInvalidCacheKeyExceptionOnNonStringCackeKey()
->getMock()
);

$this->setExpectedException(InvalidCacheKeyException::class, 'Cache key must be a string.');
$this->connector->fetch('quux', $this->options);
}

public function testFetchThrowsInvalidCacheKeyExceptionOnNonPSR6CompliantCacheKey()
{
$cacheKey = CachingConnector::RESERVED_CHARACTERS;

$this->setExpectedException(
InvalidCacheKeyException::class,
sprintf('Cache key "%s" contains one or more reserved characters: "%s"',
$cacheKey,
CachingConnector::RESERVED_CHARACTERS
)
);

$this->connector->setCacheKeyGenerator(
\Mockery::mock(CacheKeyGenerator::class)
->shouldReceive('generateCacheKey')
Expand All @@ -130,6 +121,7 @@ public function testFetchThrowsInvalidCacheKeyExceptionOnNonPSR6CompliantCacheKe
->getMock()
);

$this->setExpectedException(InvalidCacheKeyException::class, 'contains one or more reserved characters');
$this->connector->fetch('quux', $this->options);
}

Expand Down

0 comments on commit c13eb95

Please sign in to comment.