Something went wrong. Try again.
@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
Something went wrong. Try again.
3.2 kB · 135 lines
PHP
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136<?php
/** * Stacks multiple caches on top of each other, with readthrough semantics: * * - For reads, we try each cache in order until we find all the keys. * - For writes, we set the keys in each cache. * * @task config Configuring the Stack */final class PhutilKeyValueCacheStack extends PhutilKeyValueCache {
/** * Forward list of caches in the stack (from the nearest cache to the farthest * cache). */ private $cachesForward;
/** * Backward list of caches in the stack (from the farthest cache to the * nearest cache). */ private $cachesBackward;
/** * TTL to use for any writes which are side effects of the next read * operation. */ private $nextTTL;
/* -( Configuring the Stack )---------------------------------------------- */
/** * Set the caches which comprise this stack. * * @param array<PhutilKeyValueCache> $caches Ordered list of key-value * caches. * @return $this * @task config */ public function setCaches(array $caches) { assert_instances_of($caches, parent::class); $this->cachesForward = $caches; $this->cachesBackward = array_reverse($caches);
return $this; }
/** * Set the readthrough TTL for the next cache operation. The TTL applies to * any keys set by the next call to @{method:getKey} or @{method:getKeys}, * and is reset after the call finishes. * * // If this causes any caches to fill, they'll fill with a 15-second TTL. * $stack->setNextTTL(15)->getKey('porcupine'); * * // TTL does not persist; this will use no TTL. * $stack->getKey('hedgehog'); * * @param int $ttl TTL in seconds. * @return $this * * @task config */ public function setNextTTL($ttl) { $this->nextTTL = $ttl; return $this; }
/* -( Key-Value Cache Implementation )------------------------------------- */
public function getKeys(array $keys) {
$remaining = array_fuse($keys); $results = array(); $missed = array();
try { foreach ($this->cachesForward as $cache) { $result = $cache->getKeys($remaining); $remaining = array_diff_key($remaining, $result); $results += $result; if (!$remaining) { while ($cache = array_pop($missed)) { // TODO: This sets too many results in the closer caches, although // it probably isn't a big deal in most cases; normally we're just // filling the request cache. $cache->setKeys($result, $this->nextTTL); } break; } $missed[] = $cache; } $this->nextTTL = null; } catch (Exception $ex) { $this->nextTTL = null; throw $ex; }
return $results; }
public function setKeys(array $keys, $ttl = null) { foreach ($this->cachesBackward as $cache) { $cache->setKeys($keys, $ttl); } return $this; }
public function deleteKeys(array $keys) { foreach ($this->cachesBackward as $cache) { $cache->deleteKeys($keys); } return $this; }
public function destroyCache() { foreach ($this->cachesBackward as $cache) { $cache->destroyCache(); } return $this; }
}