Skip to content

Commit

Permalink
make use of spatie/once to reduce the amount of work done by the Cach…
Browse files Browse the repository at this point in the history
…ed class.
  • Loading branch information
david-d-h committed Jan 4, 2024
1 parent 34b1fff commit ce461fb
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 32 deletions.
6 changes: 3 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@
],
"require": {
"php": "^8.1",
"illuminate/contracts": "^10.0",
"spatie/laravel-package-tools": "^1.14.0",
"illuminate/contracts": "^10.0"
"spatie/once": "^3.1"
},
"require-dev": {
"laravel/pint": "^1.0",
Expand All @@ -34,8 +35,7 @@
},
"autoload": {
"psr-4": {
"Vormkracht10\\PermanentCache\\": "src/",
"Vormkracht10\\PermanentCache\\Database\\Factories\\": "database/factories/"
"Vormkracht10\\PermanentCache\\": "src/"
}
},
"autoload-dev": {
Expand Down
97 changes: 69 additions & 28 deletions src/Cached.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\PendingDispatch;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Cache;
use ReflectionClass;

/**
* @method mixed run()
*
* @template E
* @template V
*/
abstract class Cached
{
Expand All @@ -30,7 +31,7 @@ abstract class Cached
* as it can also be inferred by type hinting an argument
* in the run method.
*
* @var class-string<E>|null
* @var class-string|array<int, class-string>|null
*/
protected $event = null;

Expand All @@ -46,13 +47,11 @@ abstract class Cached
* Update the cached value, this method expects an event if
* the cacher is not static.
*
* @param E $event
* @internal You shouldn't call this yourself.
*/
final public function handle($event = null): void
{
[$driver, $ident] = self::parseCacheString($this->store
?? throw new \Exception('The $store property in ['.static::class.'] must be overridden'),
);
[$driver, $ident] = self::store();

Cache::driver($driver)->forever($ident,
/** @phpstan-ignore-next-line */
Expand All @@ -63,36 +62,58 @@ final public function handle($event = null): void
/**
* Manually force a static cache to update.
*/
final public static function update(): void
final public static function update(): ?PendingDispatch
{
$instance = app()->make(static::class);

if (! is_a(static::class, ShouldQueue::class, true)) {
$instance->handle();

return;
return null;
}

dispatch($instance);
return dispatch($instance);
}

/**
* Get the cached value this cacher provides.
*
* @param bool $update Whether the cache should update
* when it doesn't hold the value yet.
* @return V|mixed|null
*/
final public static function get(): mixed
final public static function get($default = null, bool $update = false): mixed
{
$store = (new ReflectionClass(static::class))
->getProperty('store')
->getDefaultValue();
[$driver, $ident] = self::store();

[$driver, $ident] = self::parseCacheString($store
?? throw new \Exception('The $store property in ['.static::class.'] must be overridden'),
);
$cache = Cache::driver($driver);

if ($update && ! $cache->has($ident)) {
static::update()?->onConnection('sync');
}

return $cache->get($ident, $default);
}

/**
* Get the cached value this cacher provides.
*
* This method should be used inside your cachers
* instead of the static `static::get` method to prevent
* infinite recursion.
*
* @return V|mixed|null
*/
final protected function value($default = null): mixed
{
[$driver, $ident] = self::store();

return Cache::driver($driver)->get($ident);
return Cache::driver($driver)->get(
$ident, $default,
);
}

// Default implementation for the \Scheduled::schedule method.
/// Default implementation for the `\Scheduled::schedule` method.
public static function schedule($callback)
{
if (! is_a(static::class, Scheduled::class, true)) {
Expand All @@ -113,20 +134,22 @@ public static function schedule($callback)
/**
* Get the event (if any) this cacher listens for.
*
* @return array<int, class-string<E>>
* @return array<int, class-string>
*/
final public static function getListenerEvent(): array
final public static function getListenerEvents(): array
{
$reflection = new ReflectionClass(static::class);
return once(function () {
$reflection = new ReflectionClass(static::class);

$concrete = Arr::wrap($reflection->getProperty('event')->getDefaultValue());
$concrete = Arr::wrap($reflection->getProperty('event')->getDefaultValue());

/** @phpstan-ignore-next-line */
return $concrete ?: Arr::wrap(($reflection
->getMethod('run')
->getParameters()[0] ?? null)
?->getType()
?->getName());
/** @phpstan-ignore-next-line */
return $concrete ?: Arr::wrap(($reflection
->getMethod('run')
->getParameters()[0] ?? null)
?->getType()
?->getName());
});
}

/**
Expand All @@ -142,4 +165,22 @@ private static function parseCacheString(string $store): array

return [$driver, $ident];
}

/**
* Get the driver and identifier specified in the $store property.
*
* @return array{string, string}
*/
private static function store(): array
{
return once(function () {
$store = (new ReflectionClass(static::class))
->getProperty('store')
->getDefaultValue();

return self::parseCacheString($store
?? throw new \Exception('The $store property in ['.static::class.'] must be overridden'),
);
});
}
}
3 changes: 2 additions & 1 deletion src/PermanentCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ class PermanentCache
*/
public function caches(array $cachers): self
{
/** @var class-string<Cached> $cacher */
foreach ($cachers as $cacher) {
$events = $cacher::getListenerEvent();
$events = $cacher::getListenerEvents();

$resolved[$cacher] = $events;

Expand Down

0 comments on commit ce461fb

Please sign in to comment.