Skip to content

Commit 1f0f840

Browse files
authored
Cache Apigee entity ids in memory during one page load (#1148)
1 parent 6cdd9a5 commit 1f0f840

File tree

2 files changed

+44
-0
lines changed

2 files changed

+44
-0
lines changed

src/Entity/Storage/EdgeEntityStorageBase.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,11 @@ abstract class EdgeEntityStorageBase extends DrupalEntityStorageBase implements
8888
*/
8989
protected $systemTime;
9090

91+
/**
92+
* Indicates that all entities should be/have been loaded in this request.
93+
*/
94+
private bool $allEntitiesHaveBeenLoaded = FALSE;
95+
9196
/**
9297
* Constructs an EdgeEntityStorageBase instance.
9398
*
@@ -491,10 +496,48 @@ public function resetCache(?array $ids = NULL) {
491496
Cache::invalidateTags([$this->entityTypeId . ':values']);
492497
}
493498
}
499+
// When resetting cache for ANY of the entities, cache entry for ALL
500+
// entities MUST also be cleared to prevent cache poisoning eg. after a
501+
// loadMultiple(); save(); loadMultiple(); cycle.
502+
$this->memoryCache->delete($this->entityTypeId . '-all-entity-ids');
494503
// We do not clear the entity controller's cache here because our main goal
495504
// with the entity controller cache to reduce the API calls that we
496505
// send to Apigee Edge. Although we do delete the entity controller's cache
497506
// when it is necessary, like in loadUnchanged().
498507
}
499508

509+
/**
510+
* {@inheritdoc}
511+
*/
512+
public function loadMultiple(?array $ids = NULL) {
513+
// Without $ids the caller wants to load ALL entities. To speed things up,
514+
// let's assume the storage does not change during a page load; IOW, load
515+
// all the entities for the first time and store them in a memory cache.
516+
// For all subsequent calls for the same page load, return entities from
517+
// that memory cache instead (without making API calls to Apigee).
518+
if ($ids === NULL) {
519+
$all_known_entity_ids = $this->memoryCache->get($this->entityTypeId . '-all-entity-ids');
520+
if ($all_known_entity_ids !== FALSE) {
521+
return parent::loadMultiple($all_known_entity_ids->data);
522+
}
523+
$this->allEntitiesHaveBeenLoaded = TRUE;
524+
$return = parent::loadMultiple($ids);
525+
$this->allEntitiesHaveBeenLoaded = FALSE;
526+
return $return;
527+
}
528+
529+
return parent::loadMultiple($ids);
530+
}
531+
532+
/**
533+
* {@inheritdoc}
534+
*/
535+
protected function setStaticCache(array $entities) {
536+
if ($this->allEntitiesHaveBeenLoaded) {
537+
$ids = array_map(static fn(DrupalEdgeEntityInterface $entity) => $entity->id(), $entities);
538+
$this->memoryCache->set($this->entityTypeId . '-all-entity-ids', $ids);
539+
}
540+
parent::setStaticCache($entities);
541+
}
542+
500543
}

tests/src/Kernel/Entity/ListBuilder/AppListBuilderTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ public function testAppWarnings() {
327327
'apps' => [
328328
$this->approvedAppWithApprovedCredential,
329329
$this->approvedAppWithOneRevokedCredential,
330+
$this->approvedAppWithAllRevokedCredential,
330331
$this->revokedAppWithRevokedCredential,
331332
$this->approvedAppWithExpiredCredential,
332333
$this->revokedAppWithExpiredCredential,

0 commit comments

Comments
 (0)