immutable_cache-pecl
immutable_cache-pecl copied to clipboard
Idea: Allow replacing immutables found for a given key
i.e. instead of making this a store with immutable entries, make this a store where entries point to immutable data and immutable data can be retrieved, but it can be changed to point to different immutable data
e.g.
function immutable_cache_store(string $key, mixed $value, int $ttl = 0, bool $allow_modify_entry = false) {}
function immutable_cache_add(string $key, mixed $value, int $ttl = 0, bool $allow_modify_entry = false) {}
function immutable_cache_delete(string $key) {}
By default, to prevent accidental memory leaks, $allow_modify_entry would default to false. If it's set to true, then subsequent immutable_cache_store calls can make the entry for $key point to a different immutable region of memory
- calls to store/delete would fail for an entry that has that flag and hasn't expired yet
This would allow for having immutable values in memory as long as there is a finite number of those.
// creates 2 immutable strings and an array and stores them in immutable_cache shared memory
immutable_cache_store('status', ['healthy'], 0, true);
// creates an immutable string unhealthy and an immutable array, and stores that in shared memory. Replaces the entry for status with that
immutable_cache_store('status', ['unhealthy'], 0, true);
// finds the entry for status already in cache and switches status back to it. No increase in usage of shared memory.
immutable_cache_store('status', ['healthy'], 0, true);
// remove entry. Same usage of shared memory.
immutable_cache_delete('status');
// look up a matching value and find one already in shared memory, Same memory
immutable_cache_store('status', ['healthy'], 0, true);
Other example
if (immutable_cache_add($configKey, 'my-placeholder', 5, true)) {
$data = my_get_config_from_service(); // avoid more than one caller to this service when starting up
if ($data) {
immutable_cache_store($configKey, $data); // permanently store this
} else {
// error handling
}
} else {
// e.g. wait or use default settings or throw.
}
(This would require internally adding a separate hash table supporting arbitrary types or serialized data as keys. See https://github.com/TysonAndre/pecl-teds/#tedsstricthashmap-and-tedsstricthashset)
(strings could be looked up there)
unique_value_set: Set<array|string> // new hash table to store these arrays or strings. other types are not reference counted
entries: Map<string, zval> // same as before
// use existing locks, etc
Use cases
Coordinating between processes sharing memory while avoiding cache clears Caching large data that is expected to change rarely or have few possible values (e.g. for a finite ttl cache of db results that rarely change)
It might be easier to encourage ordinary usage of apcu instead, to prevent replacement from being improperly used and slowly leaking memory (e.g. due to non-determinism such as time, request ids, etc in cached data).