Skip to content

Instantly share code, notes, and snippets.

@nrctkno
Last active July 8, 2025 01:10
Show Gist options
  • Select an option

  • Save nrctkno/8d30d2bbe06e58164b550d8da5202c87 to your computer and use it in GitHub Desktop.

Select an option

Save nrctkno/8d30d2bbe06e58164b550d8da5202c87 to your computer and use it in GitHub Desktop.
Just a generalized cache workflow
<?php
final class Cacheable {
/**
* fn($keys)
*/
private $search;
/**
* fn($hits, $keys)
*/
private $diff;
/**
* fn($diff)
*/
private $hydrate;
/**
* fn($new)
*/
private $store;
public function __construct(
callable $search,
callable $diff,
callable $hydrate,
callable $store
) {
$this->search = $search;
$this->diff = $diff;
$this->hydrate = $hydrate;
$this->store = $store;
}
public function run(array $keys): array {
$hits = ($this->search)($keys);
$diff = ($this->diff)($hits, $keys);
if (empty($diff)) {
return $hits;
}
$new = ($this->hydrate)($diff);
if (empty($new)) {
return $hits;
} else {
($this->store)($new);
}
return array_merge($hits, $new);
}
}
class CacheableTestSuite {
private $search;
private $diff;
private $hydrate;
private $store;
private $save;
function setUp(): self {
$cached = [
'a' =>['foo', 'bar'],
'c' =>['John', 'Doe'],
];
$stored = [
'a' =>['foo', 'bar'],
'b' =>['Jane', 'Johnson'],
'c' =>['John', 'Doe'],
];
$this->search = fn($keys) => array_filter(
$cached,
fn($key) => in_array($key, $keys),
ARRAY_FILTER_USE_KEY
);
$this->diff = fn($hits, $keys) => array_filter(
$keys,
fn($key) => !array_key_exists($key, $hits)
);
$this->hydrate = fn($diff) => array_filter(
$stored,
fn($key) => in_array($key, $diff),
ARRAY_FILTER_USE_KEY
);
$this->store = function($new) {
foreach ($new as $key => $value) {
$this->save[$key] = $value;
}
};
$this->save = [];
return $this;
}
function testTwoHitsOneMiss() {
$save = [];
$results = (new Cacheable(
search: $this->search,
diff: $this->diff,
hydrate: $this->hydrate,
store: $this->store
))->run(['a', 'b']);
assert(array_keys($results) == ['a', 'b']);
assert(array_keys($this->save) == ['b']);
}
function testNotExists() {
$results = (new Cacheable(
search: $this->search,
diff: $this->diff,
hydrate: $this->hydrate,
store: $this->store
))->run(['d']);
assert(array_keys($results) == []);
assert(array_keys($this->save) == []);
}
}
$suite = new CacheableTestSuite();
$suite->setUp()->testTwoHitsOneMiss();
$suite->setUp()->testNotExists();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment