Complete JSON:API's handling of field (including computed & empty fields) cache metadata

Created on 2 December 2021, about 3 years ago
Updated 27 April 2023, over 1 year ago

Problem/Motivation

#2997123: Cacheability of normalized computed fields' properties is not captured during serialization β†’ added the ability for computed field properties to contribute cacheable metadata to the normalization. However, entity reference fields are treated totally different by json:api module, since they must be converted to a "Relationship object" which references a UUID and resource type. As a result, there is no way for computed ER fields to express cache metadata.

Updated: We must also account for cacheability of empty fields.

Steps to reproduce

Create a computed ER field on an entity and observe it cannot vary by cache tags, context or TTL.

Proposed resolution

Use similar logic to the recently-added feature set, but for ER fields. We can use ResourceIdentifier::getDataReferencePropertyName() to be consistent.

Remaining tasks

Extend test coverage.

User interface changes

None.

API changes

None... well, we potentially change the visibility of the helper static method for getting the data reference property.

Data model changes

None.

Release notes snippet

TBD.

Original report

Hi,

I'm having an issue with a computed field (entity reference type) being displayed on JSON:API resources. The problem is that it's always cached, although it should change as I change for ex. categories or tags.

What I want is to have a computed/virtual field with similar articles for given article (depending on common categories and tags). For retrieving similar articles I use module called Similar By Terms => https://www.drupal.org/project/similarterms β†’ I want these similar articles to be outputted on JSON:API resources... and it works good, but it's cached all the time.

Here's my code:

function my_module_entity_bundle_field_info_alter(array &$fields, EntityTypeInterface $entityType, string $bundle): void {
  if ($entityType->id() === 'node' && $bundle === 'article') {
    $fields['field_similar_articles'] = BaseFieldDefinition::create('entity_reference')
      ->setName('field_similar_articles')
      ->setLabel('Similar articles')
      ->setTargetEntityTypeId('node')
      ->setTargetBundle('article')
      ->setComputed(TRUE)
      ->setRevisionable(FALSE)
      ->setTranslatable(FALSE)
      ->setCardinality(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED)
      ->setClass(SimilarArticlesComputedField::class);
  }
}
class SimilarArticlesComputedField extends EntityReferenceFieldItemList {

  use ComputedItemListTrait;

  protected function computeValue(): void {
    $similarArticles = <array of articles' entities get from the view>

    foreach ($similarArticles as $key => $similarArticle) {
      $this->list[$key] = $this->createItem($key, $similarArticle);
    }
  }

}

As I said, JSON:API resource displays field_similar_articles field correctly, but when I change some article's category or tag then output of this field in JSON:API resource should change as well, but it's not.

Let's say there is Article 1, 2, 3, 4 and 5.

Article 2, 3 and 4 are similar articles to the Article 1 (because they share common tags/categories).

When I go to this resources /jsonapi/node/article/{article-1-uuid} then I can see Article 2, 3 and 4 in section field_similar_articles and also in included section.

So far, so good.

But then, let's say that I delete tags and categories for Article 2 and once again go to the upper mentioned resource... I still can see Article 2, 3 and 4 in section field_similar_articles... but Article 2 should not be there. What's interesting, in the included section Article 2 disappears, which is good.

Could you please tell me what I can do about it ... and will it be possible after applying this patch β†’ (I'm using Drupal ver 9.2.10) from this issue β†’ ?

πŸ’¬ Support request
Status

Needs work

Version

9.5

Component
JSON APIΒ  β†’

Last updated 6 days ago

Created by

πŸ‡΅πŸ‡±Poland tivi22

Live updates comments and jobs are added and updated live.
  • Needs tests

    The change is currently missing an automated test that fails when run with the original code, and succeeds when the bug has been fixed.

  • Needs change record

    A change record needs to be drafted before an issue is committed. Note: Change records used to be called change notifications.

Sign in to follow issues

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

Production build 0.71.5 2024