Support from Acquia helps fund testing for Drupal Acquia logo

Comments

eiriksm created an issue. See original summary.

eiriksm’s picture

Status: Active » Needs review
FileSize
2.84 KB

Just trying to prove it in a test for now

eiriksm’s picture

Forgot to add the actual assertions :(

Did not have time to run it locally again, so let's see if it fails as expected.

Status: Needs review » Needs work

The last submitted patch, 3: 3061280.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

eiriksm’s picture

Title: Adding or creating a price list with a variation should invalidate the cache of the product view » Adding or editing a price list item should invalidate the cache of the product view
Status: Needs work » Needs review
FileSize
3.53 KB
3.5 KB

Rushing patches before leaving the sprint makes for bad titles I guess. Updating accordingly. :)

Also, the patch did not really prove anything, it would have failed anyway. Here are two patches: One that is expected to fail (proves the bug). One that is expected to pass (also proves the bug, since it shows you have to clear the caches to get the expected output).

I will split it into its own test class once I can actually prove it with a test :p

Status: Needs review » Needs work

The last submitted patch, 5: 3061280-should-fail.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

eiriksm’s picture

Status: Needs work » Needs review
FileSize
4.45 KB
5.85 KB

So here is a patch that invalidates caches on entity save of price list items. In theory, we should probably invalidate all products in a price list on price list entity saves as well, since that could for example change their "active" state (or condition, or date, or whatever). But this fixes the issue in question at least.

The last submitted patch, 7: 3061280-7-test-only.patch, failed testing. View results

Status: Needs review » Needs work

The last submitted patch, 7: 3061280-7.patch, failed testing. View results

eiriksm’s picture

Status: Needs work » Needs review
FileSize
4.45 KB
6.04 KB

The last submitted patch, 10: 3061280-10-test-only.patch, failed testing. View results

bojanz’s picture

Status: Needs review » Needs work
+  /**
+   * {@inheritdoc}
+   */
+  public function save() {
+    // Make sure we invalidate the cache for the variation in question.
+    $variation = $this->getPurchasableEntity();
+    if (!$variation) {
+      // We could not find any entity to collect cache tags from, which means we
+      // can just proceed with the regular saving.
+      return parent::save();
+    }
+    $tags = $variation->getCacheTags();
+    // And if we can resolve the product of it, also invalidate that. Since the
+    // purchasable entity theoretically can be any purchasable entity, we have
+    // to make sure we are actually able to find a product from the variation.
+    if (method_exists($variation, 'getProduct')) {
+      $product = $variation->getProduct();
+      if ($product) {
+        $tags = array_merge($tags, $product->getCacheTags());
+      }
+    }
+    Cache::invalidateTags($tags);
+    return parent::save();
+  }

1. Drupal core tends to invalidate caches in postSave(). Any reason why we can't do the same? Would simplify this code.
2. Instead of the method_exists() call could we check $purchasable_entity->getEntityTypeId()? Seems cleaner.
3. As a Commerce followup it would probably make sense to have $variation->getCacheTags() start returning the product cache tags as well, removing the need for this workaround here.

mglaman’s picture

As a Commerce followup it would probably make sense to have $variation->getCacheTags() start returning the product cache tags as well, removing the need for this workaround here.

  /**
   * {@inheritdoc}
   */
  public function getCacheTagsToInvalidate() {
    $tags = parent::getCacheTagsToInvalidate();
    // Invalidate the variations view builder and product caches.
    return Cache::mergeTags($tags, [
      'commerce_product:' . $this->getProductId(),
      'commerce_product_variation_view',
    ]);
  }

https://git.drupalcode.org/project/commerce/blob/8.x-2.x/modules/product...

We should assert getPurchasableEntity is an instance of \Drupal\commerce\PurchasableEntityInterface and then we can get cache tags.

eiriksm’s picture

Awesome review, thanks!

Re 12:
1. Moved to ::postSave (good call).
2 and 3 are fixed by Matts suggestion,

eiriksm’s picture

FileSize
1.84 KB

Sorry, posted the same patch twice, meant to post the interdiff

bojanz’s picture

Status: Needs review » Needs work

That postSave can be a lot simpler, by calling the parent only once, on top of the method. And we should keep the variable as $purchasable_entity, there's no need to assume it's a variation.

We can do something like this:

  public function postSave(EntityStorageInterface $storage, $update = TRUE) {
    parent::postSave($storage, $update);

    if ($purchasable_entity = $this->getPurchasableEntity()) {
      Cache::invalidateTags($purchasable_entity->getCacheTagsToInvalidate());
    }
  }

PriceListProductCacheTest can be just ProductCacheTest.

+  /**
+   * A test variation.
+   *
+   * @var \Drupal\commerce_product\Entity\ProductVariationInterface
+   */
+  protected $firstVariation;

Should be just $variation, since we don't have two.

+  /**
+   * Tests creating a price list item.
+   */
+  public function testCreatePriceListItem() {

None of this is true :)

  • bojanz committed 4eeb393 on 8.x-2.x authored by eiriksm
    Issue #3061280 by eiriksm, bojanz, mglaman: Adding or editing a price...
bojanz’s picture

Status: Needs work » Fixed

Addressed #17 and committed. Thanks!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.