Use TTL for in-memory cache to support long-lived instances

This commit is contained in:
lukas committed 2026-10-14 16:03:21 +00:00
1 parent d52d7c3f2d
commit 62ad60f3df
3 files changed
+62 -10

No files matched your search

+36 -9
View File
@@ -35,9 +35,9 @@ class ObjectRetriever implements CustomCacheAndLogInterface {
private $client;
private $prefix;
private $options;
private $options = [];
private $cache;
private $objects;
private $objects = [];
private $defaultReader;
private $customCacheDefaultRequest;
@@ -245,12 +245,16 @@ class ObjectRetriever implements CustomCacheAndLogInterface {
$uriString = (string)$coid;
if (isset($this->objects[$uriString]))
// Return from in-memory cache if it exists
return $this->objects[$uriString];
$this->removeExpiredFromInMemoryCache();
$ts = microtime(true);
if (isset($this->objects[$uriString])) {
// Return from in-memory cache if it exists
$this->logInfoWithTime('Returning previous node for <'.$uriString.'>.', $ts);
return $this->objects[$uriString][1];
}
if (isset($this->options['static_config_path'])) {
$location = realpath($this->options['static_config_path'].DIRECTORY_SEPARATOR.
$coid->getHost().str_replace('/', DIRECTORY_SEPARATOR, $coid->getPath())
@@ -287,8 +291,8 @@ class ObjectRetriever implements CustomCacheAndLogInterface {
}
$document = JsonLD::getDocument($object);
$this->objects[$uriString] = $document->getGraph()->getNode($uriString);
return $this->objects[$uriString];
$this->objects[$uriString] = [ time(), $document->getGraph()->getNode($uriString) ];
return $this->objects[$uriString][1];
}
/**
@@ -325,7 +329,7 @@ class ObjectRetriever implements CustomCacheAndLogInterface {
if (!COIDParser::isValidCOID($iri)) continue;
if ($iri->getHost() != $namespaceCoid->getHost()) continue;
$this->objects[$object->getId()] = $object;
$this->objects[$object->getId()] = [ time(), $object ];
$this->putIntoCache($object->getId(), $object, $this->options['cache_ttl']);
$allIris[] = $iri;
}
@@ -366,7 +370,7 @@ class ObjectRetriever implements CustomCacheAndLogInterface {
if (!COIDParser::isValidCOID($iri)) continue;
if ($iri->getHost() != $namespaceCoid->getHost()) continue;
$this->objects[$object->getId()] = $object;
$this->objects[$object->getId()] = [ time(), $object ];
$this->putIntoCache($object->getId(), $object, $this->options['cache_ttl']);
$allIris[] = $iri;
}
@@ -560,4 +564,27 @@ class ObjectRetriever implements CustomCacheAndLogInterface {
return $this->getCloudObject($this->assertAuthenticatingNamespaceAndGetId());
}
/**
* Remove expired objects from the in-memory cache. Does not affect external cache.
*/
public function removeExpiredFromInMemoryCache() {
$expiryThreshold = time() - $this->options['cache_ttl'];
foreach ($this->objects as $uriString => $entry) {
if ($entry[0] < $expiryThreshold) {
unset($this->objects[$uriString]);
}
}
return $this;
}
/**
* Remove all entries from the in-memory cache. Does not affect external cache.
*/
public function clearInMemoryCache() {
$this->objects = [];
return $this;
}
}
+18
View File
@@ -0,0 +1,18 @@
## Caching
# Standard Caching
Object descriptions that are requested through the ObjectRetriever are fetched through the CloudObjects Core Object API. They are cached in-memory inside the class for a default of 60 seconds. This can be changed using the `cache_ttl` option, which takes a number of seconds.
This in-class memory obviously only works as long as the class is alive and prevents subsequent requests for the same object hitting the API, but the cache will not exist between multiple requests handled in different processes. For this purpose, an external cache should be added.
To add an external cache, provide a storage using the `cache_storage` interface. The storage must be a class that implements either of the following interfaces:
- `Kevinrob\GuzzleCache\Storage\CacheStorageInterface`
- `Psr\Cache\CacheItemPoolInterface`
- `Psr\SimpleCache\CacheInterface`
External storage is used twice:
- Storing the HTTP request according to the APIs caching headers.
- Storing the object data according to `cache_ttl`.
@@ -29,19 +29,26 @@ class ObjectRetrieverCacheTest extends \PHPUnit\Framework\TestCase {
$this->assertNotNull($cacheStorage->fetch($retriever->getCacheKey((string)$coid)));
$this->assertStringContainsString('from Core API', $logger->getLastLogMessage());
// Get from same retriever, assert in-memory-cache
$object2 = $retriever->getCloudObject($coid);
$this->assertNotNull($object1);
$this->assertStringContainsString('previous', $logger->getLastLogMessage());
// Reinitialize retriever with same cache storage to verify that cache is used
$retriever = new ObjectRetriever([
'cache_storage' => $cacheStorage,
'logger' => $logger
]);
$object2 = $retriever->getCloudObject($coid);
$object3 = $retriever->getCloudObject($coid);
$this->assertNotNull($object2);
$this->assertNotNull($cacheStorage->fetch($retriever->getCacheKey((string)$coid)));
$this->assertStringContainsString('from object cache', $logger->getLastLogMessage());
$this->assertEquals($object1->getRevision(), $object2->getRevision());
$this->assertEquals($object2->getRevision(), $object3->getRevision());
}
}