Skip to content

Commit

Permalink
State instance cache (#143)
Browse files Browse the repository at this point in the history
* State instance cache

* Fix styling
  • Loading branch information
inxilpro authored May 30, 2024
1 parent be2f0bf commit 0598abc
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 31 deletions.
12 changes: 8 additions & 4 deletions src/Lifecycle/Broker.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,14 @@ public function replay(?callable $beforeEach = null, ?callable $afterEach = null
{
$this->is_replaying = true;

$state_manager = app(StateManager::class);

try {
app(StateManager::class)->reset(include_storage: true);
$state_manager->reset(include_storage: true);

app(StoresEvents::class)->read()
->each(function (Event $event) use ($beforeEach, $afterEach) {
app(StateManager::class)->setReplaying(true);
->each(function (Event $event) use ($state_manager, $beforeEach, $afterEach) {
$state_manager->setReplaying(true);

if ($beforeEach) {
$beforeEach($event);
Expand All @@ -99,10 +101,12 @@ public function replay(?callable $beforeEach = null, ?callable $afterEach = null
$afterEach($event);
}

$state_manager->prune();

return $event;
});
} finally {
app(StateManager::class)->setReplaying(false);
$state_manager->setReplaying(false);
$this->is_replaying = false;
}
}
Expand Down
11 changes: 9 additions & 2 deletions src/Lifecycle/StateManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
use Thunk\Verbs\Exceptions\StateCacheSizeTooLow;
use Thunk\Verbs\Facades\Id;
use Thunk\Verbs\State;
use Thunk\Verbs\Support\LeastRecentlyUsedCache;
use Thunk\Verbs\Support\StateInstanceCache;
use UnexpectedValueException;

class StateManager
Expand All @@ -22,7 +22,7 @@ public function __construct(
protected Dispatcher $dispatcher,
protected StoresSnapshots $snapshots,
protected StoresEvents $events,
protected LeastRecentlyUsedCache $states,
protected StateInstanceCache $states,
) {
$this->states->onDiscard(fn () => throw_unless($this->is_replaying, StateCacheSizeTooLow::class));
}
Expand Down Expand Up @@ -102,6 +102,13 @@ public function reset(bool $include_storage = false): static
return $this;
}

public function prune(): static
{
$this->states->prune();

return $this;
}

protected function reconstitute(State $state, bool $singleton = false): static
{
// When we're replaying, the Broker is in charge of applying the correct events
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use Closure;

class LeastRecentlyUsedCache
class StateInstanceCache
{
public function __construct(
protected int $capacity = 100,
Expand Down Expand Up @@ -43,11 +43,6 @@ public function put(string|int $key, mixed $value): static

$this->cache[$key] = $value;

if (count($this->cache) > $this->capacity) {
reset($this->cache);
$this->forget(key($this->cache));
}

return $this;
}

Expand All @@ -67,6 +62,13 @@ public function forget(string|int $key): static
return $this;
}

public function prune(): static
{
$this->cache = array_slice($this->cache, -1 * $this->capacity, null, true);

return $this;
}

public function values(): array
{
return $this->cache;
Expand Down
6 changes: 2 additions & 4 deletions src/VerbsServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@
use Thunk\Verbs\Livewire\SupportVerbs;
use Thunk\Verbs\Support\EventStateRegistry;
use Thunk\Verbs\Support\IdManager;
use Thunk\Verbs\Support\LeastRecentlyUsedCache;
use Thunk\Verbs\Support\Serializer;
use Thunk\Verbs\Support\StateInstanceCache;
use Thunk\Verbs\Support\Wormhole;

class VerbsServiceProvider extends PackageServiceProvider
Expand Down Expand Up @@ -77,7 +77,7 @@ public function packageRegistered()
dispatcher: $app->make(Dispatcher::class),
snapshots: $app->make(StoresSnapshots::class),
events: $app->make(StoresEvents::class),
states: new LeastRecentlyUsedCache(
states: new StateInstanceCache(
capacity: $app->make(Repository::class)->get('verbs.state_cache_size', 100)
),
);
Expand Down Expand Up @@ -156,7 +156,6 @@ public function boot()

$this->app->terminating(function () {
app(AutoCommitManager::class)->commitIfAutoCommitting();
app(StateManager::class)->reset(include_storage: false);
});

// Hook into Laravel event dispatcher
Expand All @@ -175,7 +174,6 @@ protected function handleEvent($event = null)
// Auto-commit after each job on the queue is processed
if ($event instanceof JobProcessed) {
app(AutoCommitManager::class)->commitIfAutoCommitting();
app(StateManager::class)->reset(include_storage: false);
}
}
}
22 changes: 7 additions & 15 deletions tests/Unit/LruCacheTest.php
Original file line number Diff line number Diff line change
@@ -1,31 +1,23 @@
<?php

use Thunk\Verbs\Support\LeastRecentlyUsedCache;
use Thunk\Verbs\Support\StateInstanceCache;

it('implements a least-recently-used strategy', function () {
$lru = new LeastRecentlyUsedCache(capacity: 5);
it('can be pruned', function () {
$lru = new StateInstanceCache(capacity: 5);

$lru->put('a', 1)->put('b', 2)->put('c', 3)->put('d', 4)->put('e', 5);

expect($lru->values())->toBe(['a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5]);

$lru->put('f', 6);

expect($lru->has('a'))->toBeFalse()
->and($lru->has('f'))->toBeTrue()
->and($lru->values())->toBe(['b' => 2, 'c' => 3, 'd' => 4, 'e' => 5, 'f' => 6]);
expect($lru->values())->toBe(['a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5, 'f' => 6]);

$lru->get('b');

expect($lru->values())->toBe(['c' => 3, 'd' => 4, 'e' => 5, 'f' => 6, 'b' => 2]);

$lru->put('a', 1);
expect($lru->values())->toBe(['a' => 1, 'c' => 3, 'd' => 4, 'e' => 5, 'f' => 6, 'b' => 2]);

expect($lru->has('c'))->toBeFalse()
->and($lru->values())->toBe(['d' => 4, 'e' => 5, 'f' => 6, 'b' => 2, 'a' => 1]);
$lru->prune();

$lru->forget('e');

expect($lru->has('e'))->toBeFalse()
->and($lru->values())->toBe(['d' => 4, 'f' => 6, 'b' => 2, 'a' => 1]);
expect($lru->values())->toBe(['c' => 3, 'd' => 4, 'e' => 5, 'f' => 6, 'b' => 2]);
});

0 comments on commit 0598abc

Please sign in to comment.