Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 89 additions & 2 deletions modules/apigee_edge_teams/src/Entity/Storage/TeamStorage.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
use Drupal\apigee_edge_teams\Entity\Controller\TeamControllerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\State\StateInterface;

/**
* Entity storage implementation for teams.
Expand Down Expand Up @@ -65,6 +66,13 @@ class TeamStorage extends AttributesAwareFieldableEdgeEntityStorageBase implemen
*/
private $logger;

/**
* The state service.
*
* @var \Drupal\Core\State\StateInterface
*/
protected $state;

/**
* Constructs an TeamStorage instance.
*
Expand All @@ -84,15 +92,18 @@ class TeamStorage extends AttributesAwareFieldableEdgeEntityStorageBase implemen
* Configuration factory.
* @param \Psr\Log\LoggerInterface $logger
* The logger.
* @param \Drupal\Core\State\StateInterface $state
* The state service.
*/
public function __construct(EntityTypeInterface $entity_type, CacheBackendInterface $cache_backend, MemoryCacheInterface $memory_cache, TimeInterface $system_time, TeamControllerInterface $team_controller, EntityTypeManagerInterface $entity_type_manager, ConfigFactoryInterface $config, LoggerInterface $logger) {
public function __construct(EntityTypeInterface $entity_type, CacheBackendInterface $cache_backend, MemoryCacheInterface $memory_cache, TimeInterface $system_time, TeamControllerInterface $team_controller, EntityTypeManagerInterface $entity_type_manager, ConfigFactoryInterface $config, LoggerInterface $logger, StateInterface $state) {
parent::__construct($entity_type, $cache_backend, $memory_cache, $system_time);
$this->teamController = $team_controller;
$config = $config->get('apigee_edge_teams.team_settings');
$this->cacheExpiration = $config->get('cache_expiration');
$this->cacheInsertChunkSize = $config->get('cache_insert_chunk_size') ?? static::DEFAULT_PERSISTENT_CACHE_INSERT_CHUNK_SIZE;
$this->entityTypeManager = $entity_type_manager;
$this->logger = $logger;
$this->state = $state;
}

/**
Expand All @@ -107,7 +118,8 @@ public static function createInstance(ContainerInterface $container, EntityTypeI
$container->get('apigee_edge_teams.controller.team'),
$container->get('entity_type.manager'),
$container->get('config.factory'),
$container->get('logger.channel.apigee_edge_teams')
$container->get('logger.channel.apigee_edge_teams'),
$container->get('state')
);
}

Expand Down Expand Up @@ -211,4 +223,79 @@ protected function doDelete($entities) {
}
}

/**
* {@inheritdoc}
*/
protected function getFromPersistentCache(?array &$ids = NULL) {

if ($this->cacheExpiration === 0 || !$this->entityType->isPersistentlyCacheable()) {
return [];
}

if ($ids === NULL) {
// During tests, this state is set to TRUE (in parent::setUp()) to
// force a cache miss and take data from the Mock API.
// This prevents test isolation failures where
// stale data from a previous test could cause the current test to fail.
if ($this->state->get('apigee_teams_test_skip_cache', FALSE)) {
return [];
}
$all_ids_cid = 'all_ids:' . $this->entityTypeId;
// Try to load our "master ID list" from the cache.
if ($cache = $this->cacheBackend->get($all_ids_cid)) {
// We found the list! Set $ids to this list.
$ids = $cache->data;
}
// If we did NOT find the list, $ids remains NULL. The code
// will proceed as normal, hit the API, and our modified
// setPersistentCache() will create the list for next time.
}

if (empty($ids)) {
return [];
}

return parent::getFromPersistentCache($ids);
}

/**
* {@inheritdoc}
*/
protected function setPersistentCache(array $entities) {
parent::setPersistentCache($entities);

$entity_count = 0;
if (!empty($entities)) {
// Get all entity IDs.
$all_entity_ids = array_keys($entities);
$entity_count = count($all_entity_ids);
}

// After all chunks are saved, save the master ID list.
// We only do this if we actually processed entities from the API.
if ($entity_count > 0) {
$all_ids_cid = 'all_ids:' . $this->entityTypeId;
// Use the main entity type tag so this item is cleared when
// the rest of the entity cache is cleared.
$all_ids_tags = [$this->entityTypeId . ':values'];

$this->cacheBackend->set(
$all_ids_cid,
$all_entity_ids,
$this->getPersistentCacheExpiration(),
$all_ids_tags
);
}
}

/**
* {@inheritdoc}
*/
public function resetCache(?array $ids = NULL) {

$this->cacheBackend->delete('all_ids:' . $this->entityTypeId);

parent::resetCache($ids);
}

}
6 changes: 6 additions & 0 deletions modules/apigee_edge_teams/tests/src/Functional/AccessTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,12 @@ protected function setUp(): void {
$this->teamMembershipManager = $this->container->get('apigee_edge_teams.team_membership_manager');
$this->teamPermissionHandler = $this->container->get('apigee_edge_teams.team_permissions');
$this->state = $this->container->get('state');
// This state acts as a "kill switch." Our overridden
// `getFromPersistentCache()` method checks for this state.
// When it's TRUE, that method will *always* return [], forcing
// a cache miss and guaranteeing that every test gets fresh data
// from the source (the API) instead of the cache.
$this->state->set('apigee_teams_test_skip_cache', TRUE);

$team_entity_type = $this->container->get('entity_type.manager')->getDefinition('team');
$team_app_entity_type = $this->container->get('entity_type.manager')->getDefinition('team_app');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,13 +205,20 @@ protected function setUp(): void {
// Setting isApigeeX() to true for Apigee X org.
TeamApp::$apigeex = TRUE;
parent::setUp();

$this->teamStorage = $this->container->get('entity_type.manager')->getStorage('team');
$this->teamAppStorage = $this->container->get('entity_type.manager')->getStorage('team_app');
$this->teamRoleStorage = $this->container->get('entity_type.manager')->getStorage('team_role');
$this->teamMemberRoleStorage = $this->container->get('entity_type.manager')->getStorage('team_member_role');
$this->teamMembershipManager = $this->container->get('apigee_edge_teams.team_membership_manager');
$this->teamPermissionHandler = $this->container->get('apigee_edge_teams.team_permissions');
// This state acts as a "kill switch." Our overridden
// `getFromPersistentCache()` method checks for this state.
// When it's TRUE, that method will *always* return [], forcing
// a cache miss and guaranteeing that every test gets fresh data
// from the source (the API) instead of the cache.
$this->state = $this->container->get('state');
$this->state->set('apigee_teams_test_skip_cache', TRUE);

$team_entity_type = $this->container->get('entity_type.manager')->getDefinition('team');
$team_app_entity_type = $this->container->get('entity_type.manager')->getDefinition('team_app');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ class TeamListBuilderTest extends ApigeeEdgeTeamsFunctionalTestBase {
*/
protected $teamStorage;

/**
* The state service.
*
* @var \Drupal\Core\State\State
*/
protected $state;

/**
* The user 1 account.
*
Expand Down Expand Up @@ -113,6 +120,14 @@ class TeamListBuilderTest extends ApigeeEdgeTeamsFunctionalTestBase {
protected function setUp(): void {
parent::setUp();

// This state acts as a "kill switch." Our overridden
// `getFromPersistentCache()` method checks for this state.
// When it's TRUE, that method will *always* return [], forcing
// a cache miss and guaranteeing that every test gets fresh data
// from the source (the API) instead of the cache.
$this->state = $this->container->get('state');
$this->state->set('apigee_teams_test_skip_cache', TRUE);

$this->storeToken();
$this->addApigeexOrganizationMatchedResponse();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,27 @@ class TeamInvitationsTest extends ApigeeEdgeTeamsFunctionalTestBase {
*/
protected $teamB;

/**
* The state service.
*
* @var \Drupal\Core\State\State
*/
protected $state;

/**
* {@inheritdoc}
*/
protected function setUp(): void {
parent::setUp();

// This state acts as a "kill switch." Our overridden
// `getFromPersistentCache()` method checks for this state.
// When it's TRUE, that method will *always* return [], forcing
// a cache miss and guaranteeing that every test gets fresh data
// from the source (the API) instead of the cache.
$this->state = $this->container->get('state');
$this->state->set('apigee_teams_test_skip_cache', TRUE);

$this->addOrganizationMatchedResponse();

$this->teamA = $this->createTeam();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,27 @@ class TeamListBuilderTest extends ApigeeEdgeTeamsFunctionalTestBase {
*/
protected $customRole;

/**
* The state service.
*
* @var \Drupal\Core\State\State
*/
protected $state;

/**
* {@inheritdoc}
*/
protected function setUp(): void {
parent::setUp();

// This state acts as a "kill switch." Our overridden
// `getFromPersistentCache()` method checks for this state.
// When it's TRUE, that method will *always* return [], forcing
// a cache miss and guaranteeing that every test gets fresh data
// from the source (the API) instead of the cache.
$this->state = $this->container->get('state');
$this->state->set('apigee_teams_test_skip_cache', TRUE);

$this->addOrganizationMatchedResponse();

$this->teamStorage = $this->entityTypeManager->getStorage('team');
Expand Down