Skip to content

Commit

Permalink
Cache: added events WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
dg committed Oct 15, 2020
1 parent eb57c44 commit 6be8ac9
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 7 deletions.
29 changes: 22 additions & 7 deletions src/Caching/Cache.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,18 @@ class Cache
NAMESPACES = 'namespaces',
ALL = 'all';

public const
EVENT_HIT = 'hit',
EVENT_MISS = 'miss',
EVENT_SAVE = 'save',
EVENT_REMOVE = 'remove';

/** @internal */
public const NAMESPACE_SEPARATOR = "\x00";

/** @var array */
public $onEvent;

/** @var Storage */
private $storage;

Expand Down Expand Up @@ -88,8 +97,9 @@ public function load($key, callable $generator = null)
{
$storageKey = $this->generateKey($key);
$data = $this->storage->read($storageKey);
$this->onEvent($this, $data === null ? self::EVENT_MISS : self::EVENT_HIT, $key);
if ($data === null && $generator) {
$this->storage->lock($storageKey);
$this->storage->lock($storageKey);
try {
$data = $generator(...[&$dependencies]);
} catch (\Throwable $e) {
Expand Down Expand Up @@ -134,12 +144,14 @@ public function bulkLoad(array $keys, callable $generator = null): array
foreach ($keys as $i => $key) {
$storageKey = $storageKeys[$i];
if (isset($cacheData[$storageKey])) {
$this->onEvent($this, self::EVENT_HIT, $key);
$result[$key] = $cacheData[$storageKey];
} elseif ($generator) {
$result[$key] = $this->load($key, function (&$dependencies) use ($key, $generator) {
return $generator(...[$key, &$dependencies]);
});
} else {
$this->onEvent($this, self::EVENT_MISS, $key);
$result[$key] = null;
}
}
Expand All @@ -165,27 +177,30 @@ public function bulkLoad(array $keys, callable $generator = null): array
*/
public function save($key, $data, array $dependencies = null)
{
$key = $this->generateKey($key);
$storageKey = $this->generateKey($key);

if ($data instanceof \Closure) {
trigger_error(__METHOD__ . '() closure argument is deprecated.', E_USER_WARNING);
$this->storage->lock($key);
$this->storage->lock($storageKey);
try {
$data = $data(...[&$dependencies]);
} catch (\Throwable $e) {
$this->storage->remove($key);
$this->storage->remove($storageKey);
throw $e;
}
}

if ($data === null) {
$this->storage->remove($key);
$this->storage->remove($storageKey);
$this->onEvent($this, self::EVENT_REMOVE, $key);
} else {
$dependencies = $this->completeDependencies($dependencies);
if (isset($dependencies[self::EXPIRATION]) && $dependencies[self::EXPIRATION] <= 0) {
$this->storage->remove($key);
$this->storage->remove($storageKey);
$this->onEvent($this, self::EVENT_REMOVE, $key);
} else {
$this->storage->write($key, $data, $dependencies);
$this->storage->write($storageKey, $data, $dependencies);
$this->onEvent($this, self::EVENT_SAVE, $key);
}
return $data;
}
Expand Down
24 changes: 24 additions & 0 deletions tests/Caching/Cache.bulkLoad.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -17,29 +17,53 @@ require __DIR__ . '/Cache.php';
test('storage without bulk load support', function () {
$storage = new TestStorage;
$cache = new Cache($storage, 'ns');
$cache->onEvent[] = function (...$args) use (&$event) {
$event[] = $args;
};

Assert::same([1 => null, 2 => null], $cache->bulkLoad([1, 2]), 'data');
Assert::same([[$cache, $cache::EVENT_MISS, 1], [$cache, $cache::EVENT_MISS, 2]], $event);

$event = [];
Assert::same([1 => 1, 2 => 2], $cache->bulkLoad([1, 2], function ($key) {
return $key;
}));
Assert::same([
[$cache, $cache::EVENT_MISS, 1], [$cache, $cache::EVENT_SAVE, 1],
[$cache, $cache::EVENT_MISS, 2], [$cache, $cache::EVENT_SAVE, 2],
], $event);

$event = [];
$data = $cache->bulkLoad([1, 2]);
Assert::same(1, $data[1]['data']);
Assert::same(2, $data[2]['data']);
Assert::same([[$cache, $cache::EVENT_HIT, 1], [$cache, $cache::EVENT_HIT, 2]], $event);
});

test('storage with bulk load support', function () {
$storage = new BulkReadTestStorage;
$cache = new Cache($storage, 'ns');
$cache->onEvent[] = function (...$args) use (&$event) {
$event[] = $args;
};

Assert::same([1 => null, 2 => null], $cache->bulkLoad([1, 2]));
Assert::same([[$cache, $cache::EVENT_MISS, 1], [$cache, $cache::EVENT_MISS, 2]], $event);

$event = [];
Assert::same([1 => 1, 2 => 2], $cache->bulkLoad([1, 2], function ($key) {
return $key;
}));
Assert::same([
[$cache, $cache::EVENT_MISS, 1], [$cache, $cache::EVENT_SAVE, 1],
[$cache, $cache::EVENT_MISS, 2], [$cache, $cache::EVENT_SAVE, 2],
], $event);

$event = [];
$data = $cache->bulkLoad([1, 2]);
Assert::same(1, $data[1]['data']);
Assert::same(2, $data[2]['data']);
Assert::same([[$cache, $cache::EVENT_HIT, 1], [$cache, $cache::EVENT_HIT, 2]], $event);
});

test('dependencies', function () {
Expand Down
9 changes: 9 additions & 0 deletions tests/Caching/Cache.load.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,25 @@ require __DIR__ . '/Cache.php';
// load twice with fallback
$storage = new TestStorage;
$cache = new Cache($storage, 'ns');
$cache->onEvent[] = function (...$args) use (&$event) {
$event[] = $args;
};

$value = $cache->load('key', function () {
return 'value';
});
Assert::same('value', $value);
Assert::same([
[$cache, $cache::EVENT_MISS, 'key'],
[$cache, $cache::EVENT_SAVE, 'key'],
], $event);

$event = [];
$data = $cache->load('key', function () {
return "won't load this value"; // will read from storage
});
Assert::same('value', $data['data']);
Assert::same([[$cache, $cache::EVENT_HIT, 'key']], $event);


// load twice with closure fallback, pass dependencies
Expand Down
4 changes: 4 additions & 0 deletions tests/Caching/Cache.save.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,13 @@ require __DIR__ . '/Cache.php';
// save value with dependencies
$storage = new testStorage;
$cache = new Cache($storage, 'ns');
$cache->onEvent[] = function (...$args) use (&$event) {
$event[] = $args;
};
$dependencies = [Cache::TAGS => ['tag']];

$cache->save('key', 'value', $dependencies);
Assert::same([[$cache, $cache::EVENT_SAVE, 'key']], $event);

$res = $cache->load('key');
Assert::same('value', $res['data']);
Expand Down

0 comments on commit 6be8ac9

Please sign in to comment.