Unverified Commit e3ccb201 authored by Alex Pott's avatar Alex Pott
Browse files

Issue #3549380 by catch, godotislate: Fiber entity multiple loading tweaks

parent dec1ded7
Loading
Loading
Loading
Loading
Loading
+10 −13
Original line number Diff line number Diff line
@@ -296,21 +296,18 @@ public function loadMultiple(?array $ids = NULL) {
        $this->entityIdsToLoad = array_unique(array_merge($this->entityIdsToLoad, $ids));
        $fiber->suspend();

        // At this point the entityIdsToLoad property will either have been
        // reset within another Fiber, or will contain the IDs passed in as
        // well as any others waiting to be loaded.
        if ($this->entityIdsToLoad) {
          $ids = $this->entityIdsToLoad;

          // Reset the entityIdsToLoad property so that any further calls start
          // with a blank slate (apart from the entity static cache).
          $this->entityIdsToLoad = [];
        }
        // If all the IDs we need to return have already been loaded into the
        // static cache, ignore any additionally requested entities here since
        // deferring these may allow them to be loaded with more other entities
        // later.
        $entities += $this->getFromStaticCache($ids);

        // If any entities were in the static cache remove them from the
        // remaining IDs.
        $ids = array_diff($ids, array_keys($entities));

        // Otherwise load additional entities now.
        if ($ids && $this->entityIdsToLoad) {
          $ids = array_unique(array_merge($ids, $this->entityIdsToLoad));
          $this->entityIdsToLoad = [];
        }
      }
    }

+1 −1
Original line number Diff line number Diff line
@@ -46,7 +46,7 @@ protected function testNodePageColdCache(): void {
    // response tasks run in different orders each time.
    $this->drupalGet('node/1');
    // Allow time for image style and aggregate requests to finish.
    sleep(1);
    sleep(2);
    $this->drupalGet('node/1');
    $this->clearCaches();
    $performance_data = $this->collectPerformanceData(function () {
+71 −0
Original line number Diff line number Diff line
@@ -240,6 +240,77 @@ public function testLazyPreLoadingMultiple(): void {
    $this->assertSame(\count($return1), 1);
  }

  /**
   * Test lazy preloading with additional entity load calls.
   */
  public function testLazyPreLoadingAdditional(): void {
    $storage = $this->container->get('entity_type.manager')->getStorage('entity_test');
    $ids = [];
    $entity = $storage->create(['name' => 'test']);
    $entity->save();
    $ids[] = $entity->id();

    $entity = $storage->create(['name' => 'test2']);
    $entity->save();
    $ids[] = $entity->id();

    $entity = $storage->create(['name' => 'test3']);
    $entity->save();
    $ids[] = $entity->id();

    $fiber1 = new \Fiber(function () use ($ids, $storage) {
      $storage->loadMultiple([$ids[0]]);
      return $storage->loadMultiple([$ids[2]]);
    });
    $fiber2 = new \Fiber(fn () => $storage->loadMultiple([$ids[1]]));

    // Make sure the entity cache is empty.
    $this->container->get('entity.memory_cache')->reset();

    // Start Fiber 1, this should set the first entity to be loaded, without
    // actually loading it, and then suspend.
    $fiber1->start();
    $this->assertTrue($fiber1->isSuspended());
    $this->assertFalse($this->container->get('entity.memory_cache')->get('values:entity_test:' . $ids[0]));

    // Start Fiber 2, this should set the second entity to be loaded, without
    // actually loading it, and then suspend.
    $fiber2->start();
    $this->assertTrue($fiber2->isSuspended());
    $this->assertFalse($this->container->get('entity.memory_cache')->get('values:entity_test:' . $ids[1]));

    // Resume Fiber 1, this should load both entities, and set the third entity
    // to be loaded, without actually loading it, then suspend again.
    $fiber1->resume();

    $this->assertTrue($fiber1->isSuspended());
    // Now the first and second entities should be loaded.
    $this->assertNotFalse($this->container->get('entity.memory_cache')->get('values:entity_test:' . $ids[0]));
    $this->assertNotFalse($this->container->get('entity.memory_cache')->get('values:entity_test:' . $ids[1]));

    // But the third entity should not.
    $this->assertFalse($this->container->get('entity.memory_cache')->get('values:entity_test:' . $ids[2]));

    $fiber2->resume();

    $this->assertTrue($fiber2->isTerminated());

    $return2 = $fiber2->getReturn();

    $this->assertSame($return2[2]->id(), $ids[1]);
    $this->assertSame(\count($return2), 1);

    // All three entities should be loaded if Fiber1 is resumed again.
    $fiber1->resume();
    $this->assertNotFalse($this->container->get('entity.memory_cache')->get('values:entity_test:' . $ids[0]));
    $this->assertNotFalse($this->container->get('entity.memory_cache')->get('values:entity_test:' . $ids[1]));
    $this->assertNotFalse($this->container->get('entity.memory_cache')->get('values:entity_test:' . $ids[2]));
    $this->assertTrue($fiber1->isTerminated());
    $return1 = $fiber1->getReturn();
    $this->assertSame($return1[3]->id(), $ids[2]);
    $this->assertSame(\count($return1), 1);
  }

  /**
   * Tests that the Entity storage loads the entities in the correct order.
   *