After updating to 8.x-2.0-alpha2, entities that contain fields that have been marked as uncacheable are still being cached.

The reason for this is the changes to the last installed definition don't happen until a field config is modified and the cacheability settings for an entity type change. Therefore we need an update script to ensure the last installed definition settings for existing entity types are set correctly.

Also, in addition to acting on field config changes, I believe we also need to ensure the correct cache settings are applied on entity type updates. If the maintainer of an entity type utilizes \Drupal\Core\Entity\EntityDefinitionUpdateManager::getEntityType() to load the entity type definition before updating then all should be good as the field encrypt overrides should persist. But if they don't, or they modify the cache properties then entities we don't want cached could be cached again.

I have added a patch to:

  • Add an Entity Type listener to act on entity type definition updates.
  • Introduce a EntityTypeCacheableManager service (for lack of a better name) to consolidate the entity type cache property related logic.
  • Refactored field_encrypt_entity_type_alter() to use the EntityTypeCacheableManager service
  • Refactored \Drupal\field_encrypt\EventSubscriber\ConfigSubscriber::setUncacheableEntityTypes() to use the EntityTypeCacheableManager service and only affect the entity type containing the field who's configuration was updated

Here is the code for the update method which will need to be added to the patch before it is committed:

/**
 * Update all uncacheable entity types.
 *
 * This will ensure the last installed definition of these entity types are
 * set correctly.
 *
 * @see \Drupal\field_encrypt\EventSubscriber\EntityTypeSubscriber::onEntityTypeUpdate()
 */
function field_encrypt_update_8201() {
  $entity_definition_update_manager = \Drupal::entityDefinitionUpdateManager();
  $uncacheable_types = \Drupal::state()->get(EntityTypeCacheableManager::UNCACHEABLE_TYPES_STATE_KEY);
  foreach ($entity_definition_update_manager->getEntityTypes() as $entity_type_id => $entity_type) {
    if (array_key_exists($entity_type_id, $uncacheable_types)) {
      $entity_definition_update_manager->updateEntityType($entity_type);
    }
  }

  return t("Entity Types have been updated to account for Field Encrypt uncacheable settings.");
}
CommentFileSizeAuthor
#6 3153125-6.patch1.26 KBtame4tex
#3 3153125-3.patch24.72 KBtame4tex
#2 3153125-2.patch24.57 KBtame4tex

Comments

tame4tex created an issue. See original summary.

tame4tex’s picture

Status: Active » Needs review
StatusFileSize
new24.57 KB
tame4tex’s picture

StatusFileSize
new24.72 KB

Fixed PHP lint failure

alexpott’s picture

Status: Needs review » Needs work

@tame4tex nice catch on lacking an update path. We definitely need to fix that.

I'm not sure about whether additional complexity of the entity_type_subscriber is correct though.

If the maintainer of an entity type utilizes \Drupal\Core\Entity\EntityDefinitionUpdateManager::getEntityType() to load the entity type definition before updating then all should be good as the field encrypt overrides should persist. But if they don't, or they modify the cache properties then entities we don't want cached could be cached again.

If the maintainer of an entity type does not take use the current stored definitions & the results on hook_entity_type_alter into account then they are doing it wrong. They'd be breaking more than just this module. I do agree though that the changes to use the stored definition for the entirety of the entity type definition has added a decent amount of complexity and multiple states that make this a harder problem space.

I think I'd like to fix the update path first and then consider the larger issue. The update could be as simple as:

  1. Make \Drupal\field_encrypt\EventSubscriber\ConfigSubscriber::setUncacheableEntityTypes public
  2. Add a post update hook that does:
    \Drupal::state()->set('uncacheable_entity_types', []);
    \Drupal::service('field_encrypt.config_subscriber')->setUncacheableEntityTypes();
    
alexpott’s picture

Once we've added the update I think we should have a follow-up issue to consider one of the other parts of this. Making a version setUncacheableEntityTypes that only operates on a single entity type as that part of this makes a tonne of sense too.

tame4tex’s picture

Status: Needs work » Needs review
StatusFileSize
new1.26 KB

Good point @alexpott. It makes sense to fix the most urgent problem first. Attached is a patch with the post update hook as suggested. I will move all other parts to a follow up issue.

alexpott’s picture

Note the whole notion of storing uncacheable entity types has been removed in 3.0.x. It's been replaced by a single setting - see #3073924: Improve how the effects on cacheability are controlled

ptmkenny’s picture

Status: Needs review » Closed (outdated)

2.x is no longer being developed, and this is not an issue for 3.x (per #7), so I'm closing this as outdated.