Skip to content

Commit

Permalink
Added MetadataStorage
Browse files Browse the repository at this point in the history
  • Loading branch information
vudaltsov committed Feb 20, 2024
1 parent 7ffa117 commit bb8366b
Show file tree
Hide file tree
Showing 18 changed files with 248 additions and 224 deletions.
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ var_dump($dataReflection->getTyphoonType()); // object representation of T templ

## Caching

You can use any [PSR-16](https://www.php-fig.org/psr/psr-16/) implementation for caching, but we highly recommend [Typhoon OPcache](https://github.com/typhoon-php/opcache).
By default, Typhoon Reflection uses in-memory LRU cache which should be enough for the majority of use cases.

However, if you need persistent cache, you can use any [PSR-16](https://www.php-fig.org/psr/psr-16/) implementation. We highly recommend [Typhoon OPcache](https://github.com/typhoon-php/opcache).
It stores values as php files that could be opcached. It is much faster than an average file cache implementation that uses `serialize`.

```php
Expand All @@ -67,15 +69,15 @@ $reflector = TyphoonReflector::build(
);
```

To detect file changes during development, decorate your cache with [ChangeDetectingCache](src/Cache/ChangeDetectingCache.php).
To detect file changes during development, decorate your cache with [FreshCache](src/Cache/FreshCache.php).

```php
use Typhoon\Reflection\TyphoonReflector;
use Typhoon\Reflection\Cache\ChangeDetectingCache;
use Typhoon\Reflection\Cache\FreshCache;
use Typhoon\OPcache\TyphoonOPcache;

$reflector = TyphoonReflector::build(
cache: new ChangeDetectingCache(new TyphoonOPcache('path/to/cache/dir')),
cache: new FreshCache(new TyphoonOPcache('path/to/cache/dir')),
);
```

Expand Down
10 changes: 0 additions & 10 deletions src/Cache/Changeable.php

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@
namespace Typhoon\Reflection\Cache;

use Psr\SimpleCache\CacheInterface;
use Typhoon\Reflection\Metadata\MetadataCacheItem;

/**
* @api
* @psalm-suppress MixedAssignment
*/
final class ChangeDetectingCache implements CacheInterface
final class FreshCache implements CacheInterface
{
public function __construct(
private readonly CacheInterface $cache,
Expand All @@ -20,7 +21,7 @@ public function get(string $key, mixed $default = null): mixed
{
$value = $this->cache->get($key, $default);

if ($value instanceof Changeable && $value->changed()) {
if ($value instanceof MetadataCacheItem && $value->changed()) {
return $default;
}

Expand Down Expand Up @@ -51,7 +52,7 @@ public function getMultiple(iterable $keys, mixed $default = null): iterable
$values = [];

foreach ($this->cache->getMultiple($keys) as $key => $value) {
if ($value instanceof Changeable && $value->changed()) {
if ($value instanceof MetadataCacheItem && $value->changed()) {
$value = $default;
}

Expand All @@ -75,7 +76,7 @@ public function has(string $key): bool
{
$value = $this->cache->get($key);

if ($value instanceof Changeable && $value->changed()) {
if ($value instanceof MetadataCacheItem && $value->changed()) {
return false;
}

Expand Down
51 changes: 32 additions & 19 deletions src/Cache/InMemoryCache.php → src/Cache/LruCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,16 @@
* @api
* @psalm-suppress MixedAssignment
*/
final class InMemoryCache implements CacheInterface
final class LruCache implements CacheInterface
{
/**
* @var array<string, mixed>
*/
private array $items = [];
private array $values = [];

public function __construct(
private readonly int $capacity = 1000,
) {}

private static function validateKey(string $key): void
{
Expand All @@ -28,18 +32,23 @@ public function get(string $key, mixed $default = null): mixed
{
self::validateKey($key);

if (\array_key_exists($key, $this->items)) {
return $this->items[$key];
if (!\array_key_exists($key, $this->values)) {
return $default;
}

return $default;
$value = $this->values[$key];
unset($this->values[$key]);

return $this->values[$key] = $value;
}

public function set(string $key, mixed $value, null|\DateInterval|int $ttl = null): bool
{
self::validateKey($key);

$this->items[$key] = $value;
unset($this->values[$key]);
$this->values[$key] = $value;
$this->evict();

return true;
}
Expand All @@ -48,29 +57,27 @@ public function delete(string $key): bool
{
self::validateKey($key);

unset($this->items[$key]);
unset($this->values[$key]);

return true;
}

public function clear(): bool
{
$this->items = [];
$this->values = [];

return true;
}

public function getMultiple(iterable $keys, mixed $default = null): iterable
{
$items = [];
$values = [];

foreach ($keys as $key) {
self::validateKey($key);

$items[$key] = $this->get($key, $default);
$values[$key] = $this->get($key, $default);
}

return $items;
return $values;
}

public function setMultiple(iterable $values, null|\DateInterval|int $ttl = null): bool
Expand All @@ -79,27 +86,33 @@ public function setMultiple(iterable $values, null|\DateInterval|int $ttl = null
\assert(\is_string($key));
self::validateKey($key);

$this->items[$key] = $value;
unset($this->values[$key]);
$this->values[$key] = $value;
}

$this->evict();

return true;
}

public function deleteMultiple(iterable $keys): bool
{
foreach ($keys as $key) {
self::validateKey($key);

unset($this->items[$key]);
$this->delete($key);
}

return true;
}

public function has(string $key): bool
{
self::validateKey($key);
return $this->get($key, $this) !== $this;
}

return \array_key_exists($key, $this->items);
private function evict(): void
{
if (\count($this->values) > $this->capacity) {
$this->values = \array_slice($this->values, -$this->capacity);
}
}
}
2 changes: 1 addition & 1 deletion src/Metadata/ClassMetadata.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ final class ClassMetadata extends RootMetadata
* @param list<MethodMetadata> $ownMethods
*/
public function __construct(
ChangeDetector $changeDetector,
string $name,
public readonly int $modifiers,
ChangeDetector $changeDetector,
public readonly bool $internal = false,
public readonly string|false $extension = false,
public readonly string|false $file = false,
Expand Down
42 changes: 42 additions & 0 deletions src/Metadata/MetadataCacheItem.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

declare(strict_types=1);

namespace Typhoon\Reflection\Metadata;

/**
* @internal
* @psalm-internal Typhoon\Reflection
* @template TMetadata of RootMetadata
*/
final class MetadataCacheItem
{
/**
* @param TMetadata|\Closure(): TMetadata $metadata
*/
public function __construct(
private RootMetadata|\Closure $metadata,
) {}

/**
* @return TMetadata
*/
public function get(): RootMetadata
{
if ($this->metadata instanceof \Closure) {
$this->metadata = ($this->metadata)();
}

return $this->metadata;
}

public function changed(): bool
{
return $this->get()->changeDetector->changed();
}

public function __serialize(): array
{
return ['metadata' => $this->get()];
}
}
72 changes: 0 additions & 72 deletions src/Metadata/MetadataCollection.php

This file was deleted.

Loading

0 comments on commit bb8366b

Please sign in to comment.