Support from Acquia helps fund testing for Drupal Acquia logo

Comments

blazey created an issue. See original summary.

blazey’s picture

Issue summary: View changes
Status: Active » Needs work
FileSize
1.29 KB

Here's the test case.

blazey’s picture

Status: Needs work » Needs review
blazey’s picture

Title: EntityStorageBase::loadMultiple returns other entities when the static cache is warm » EntityStorageBase::loadMultiple returns unwanted entities when the static cache is warm

Status: Needs review » Needs work

The last submitted patch, 2: 3068733-2.patch, failed testing. View results

blazey’s picture

Here's an attempt to fix the problem. It works under the assumption that the active workspace doesn't change between the calls to loadMultiple. If the workspace change is something we want to support then it should probably be added to the static cache cid.

blazey’s picture

Assigned: blazey » Unassigned
Status: Needs work » Needs review
amateescu’s picture

Version: 8.8.x-dev » 8.7.x-dev
Status: Needs review » Needs work

Nice find, @blazey!

  1. +++ b/core/lib/Drupal/Core/Entity/EntityStorageBase.php
    @@ -276,8 +277,11 @@ public function loadMultiple(array $ids = NULL) {
    +    if (!$flipped_ids || !empty($ids)) {
    

    Let's use the same conditional logic that we have below in this method: if ($ids === NULL || $ids) {. It will make the code easier to parse visually :)

    And while we're at it, we should change the first sentence of the comment above this check to something like:

    "Try to gather any remaining entities from a 'preload' method."

    We should also remove the IDs that were preloaded from the list of entities that need to be loaded, with something like this inside the if (!empty($preloaded_entities)) { check:

          // If any entities were preloaded, remove them from the IDs still to load.
          $ids = array_keys(array_diff_key($flipped_ids, $entities));
    
  2. +++ b/core/modules/workspaces/tests/src/Kernel/WorkspaceIntegrationTest.php
    @@ -322,6 +323,10 @@ public function testWorkspaces() {
    +    foreach (Node::loadMultiple([1]) as $entity) {
    +      $this->assertEquals(1, $entity->id(), '::loadMultiple returns entities with the provided id.');
    +    }
    

    In order to be consistent with the rest of the assertions from this test class, let's assert this inside of assertEntityLoad(), between checking loadMultiple() and loadUnchanged():

        // Check loading entities one by one.
        foreach ($expected_default_revisions as $expected_default_revision) {
          $entity_id = $expected_default_revision[$id_key];
          $entities = $this->entityTypeManager->getStorage($entity_type_id)->loadMultiple([$entity_id]);
          $this->assertCount(1, $entities);
          $this->assertEquals($expected_default_revision[$revision_key], $entities[$entity_id]->getRevisionId());
          $this->assertEquals($expected_default_revision[$label_key], $entities[$entity_id]->label());
          $this->assertEquals($expected_default_revision[$published_key], $entities[$entity_id]->isPublished());
        }
    
cilefen’s picture

pmelab’s picture

amateescu’s picture

The last submitted patch, 11: 3068733-11-test-only.patch, failed testing. View results

pmelab’s picture

Status: Needs review » Reviewed & tested by the community

Reviewed and tested in an actual use case. Looks good!

hchonov’s picture

Very very nice find, @blazey and thank you folks for solving it!

----

Would it be possible to add a core test for the core functionality additionally to the one provided for the workspaces module? Nevertheless this is change in the entity API and therefore I think it should have its own test independent from the workspaces module as well. I think that \Drupal\KernelTests\Core\Entity\ContentEntityStaticCacheTest would be the perfect place for such a test.

I am not changing the issue status, because the patch looks good. I even think that it might be solving the problem leading to the only fail in #2620980-135: ContentEntityStorageBase::loadRevision() should use the static and the persistent entity cache like ContentEntityStorageBase::load().

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 11: 3068733-11.patch, failed testing. View results

amateescu’s picture

Status: Needs work » Reviewed & tested by the community
Ghost of Drupal Past’s picture

Just looking at loadMultiple do we want to clean it up in this issue or let's add more warts to it and clean it up in a second issue? The method should start with if ($ids === []) return [];. And then:

  1. Move $flipped_ids inside the if ($ids) {, the exact same check is run twice on subsequent lines (add else for FALSE)
  2. if (!empty($preloaded_entities)) which is double superflous: the empty() is unnecessary because the variable is always set and the check whether there are any entities unnecessary because both calls inside the if are fine with empty arrays and $preloaded_entities is always an array according to the preload typehint.
  3. if ($ids === NULL || $ids) { is now unnecessary since the only case when this if doesn't happen is for empty array $ids which we aborted early.
  4. if (!empty($queried_entities)) { because of our previous move, $queried_entities is now always set, you can drop another !empty()

The patch with the above abort-early optimization can lose $preloaded_entities = []; , if ($ids === NULL || $ids) {. And overall, the whole thing becomes much easier to read.

amateescu’s picture

@Charlie ChX Negyesi, since this is a bugfix, having a small patch here is preferable so I would rather do the cleanup in a followup issue.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 11: 3068733-11.patch, failed testing. View results

amateescu’s picture

Status: Needs work » Reviewed & tested by the community
Gábor Hojtsy’s picture

Status: Reviewed & tested by the community » Needs review

Hm, why is this built against 8.7.x and not 8.8.x? @amateescu did not explain that when he moved it to 8.7.x in July.

amateescu’s picture

Version: 8.7.x-dev » 8.8.x-dev
Status: Needs review » Reviewed & tested by the community

Because I thought the common practice is to target the lowest branch in which a bug fix should be committed, but I guess I was wrong :)

  • catch committed c86caa0 on 8.8.x
    Issue #3068733 by blazey, amateescu, pmelab, hchonov: EntityStorageBase...
catch’s picture

Status: Reviewed & tested by the community » Fixed

Committed c86caa0 and pushed to 8.8.x. Thanks!

Agreed it's worth opening a follow-up for #17.

amateescu’s picture

Version: 8.8.x-dev » 8.7.x-dev
Status: Fixed » Reviewed & tested by the community

Thanks, @catch! As mentioned above, this should be backported to 8.7.x :)

catch’s picture

Status: Reviewed & tested by the community » Fixed

Cherry-picked to 8.7.x too.

  • catch committed 9458d7a on 8.7.x
    Issue #3068733 by blazey, amateescu, pmelab, hchonov: EntityStorageBase...

Status: Fixed » Closed (fixed)

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