Problem/Motivation

The menu link migration creates all menu link as "internal:/..." menu links. This leads to bad performance during cache rebuild.

I did some profiling on this.

Before (internal:/node/1): https://blackfire.io/profiles/ef057540-857b-45cf-a40d-7a46e53dc141/graph
After (entity:node/1); https://blackfire.io/profiles/0360f0cf-c6cf-4d7d-be47-ff84912c7159/graph

Compared: https://blackfire.io/profiles/compare/837c9e5b-4374-42e1-88a8-1979e38381...

Proposed resolution

Menu link migration should prefer entity-based urls (entity:node/1 instead of internal:/node/1).

Remaining tasks

User interface changes

API changes

Data model changes

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

webflo created an issue. See original summary.

webflo’s picture

Issue summary: View changes
webflo’s picture

webflo’s picture

Issue tags: +SprintWeekendBerlin
webflo’s picture

Issue tags: +SprintWeekend2016
tstoeckler’s picture

Assigned: Unassigned » tstoeckler

Working on it.

tstoeckler’s picture

Those graphs are very interesting!

The problem is that Uri::fromInternalUrl() calls \Drupal::pathValidator()->getUrlIfValidWithoutAccessCheck() which does route matching which does route enhancing which ends up loading the entity of the URL, i.e. node 1 for the internal:/node/1 URI. Thus, with ~2800 menu links this ends up loading ~2800 entities. Additionally painful is that this does not use loadMultiple() but loads the entities one by one.

In contrast Uri::fromEntityUrl() is not very expensive.

In theory we should probably try to optimize Uri::fromInternalUri() in some way, but in any case it is semantically more correct to store the proper entity URIs, so let's do that.

Will look into the issue now.

tstoeckler’s picture

Status: Active » Needs review
Issue tags: +Needs tests
FileSize
3.53 KB

Needs tests, of course. But here's a first stab. What do you think?

Status: Needs review » Needs work

The last submitted patch, 8: 2648996-8.patch, failed testing.

webflo’s picture

Looks great. Just a small nitpick, we could move $url->getRouteParameters() into the first if condition.

tstoeckler’s picture

Status: Needs work » Needs review
FileSize
5.98 KB
9.17 KB

Good point, fixed that.

Now also comes with a unit test. Hopefully some other tests fail, so that we do not need additional integration test coverage. Crossing my fingers...

Status: Needs review » Needs work

The last submitted patch, 11: 2648996-11.patch, failed testing.

tstoeckler’s picture

Status: Needs work » Needs review
FileSize
517 bytes
9.68 KB

Ahem.

benjy’s picture

This looks great, just a couple of comments.

  1. +++ /dev/null
    @@ -1,35 +0,0 @@
    -class InternalUri extends ProcessPluginBase {
    

    Removing this would be an api break, we could leave it as deprecated? It could even proxy through to the new plugin?

  2. +++ b/core/modules/menu_link_content/src/Plugin/migrate/process/d6/LinkUri.php
    @@ -0,0 +1,98 @@
    +        if (
    +          count($route_parts) === 3 &&
    +          $route_parts[0] === 'entity' &&
    +          $route_parts[2] === 'canonical'
    ...
    +          if (
    +            $this->entityTypeManager->hasDefinition($entity_type_id) &&
    +            isset($route_parameters[$entity_type_id])
    +          ) {
    

    I thought our coding standard had all these on one line?

tstoeckler’s picture

Assigned: tstoeckler » Unassigned

Thanks for the review!

1. I thought that Migrate was exempt from the whole API stability scheme. I just thought that calling it "InternalUri" if it can produce both "internal:" and also "entity:" URIs doesn't make much sense. So sure, we could leave in a BC layer, or we could just add a "@todo D9 Rename to LinkUri" or something like that which would be a little less maintenance overhead. Don't feel strongly either way.

2. I thought we were allowed to split ifs by now, but not sure and don't feel strongly either. Sure, can be fixed.

Not sure I will be able to work on this any more, so unassigning for now.

benjy’s picture

Not sure about point 1, guess we name a product manager review?

quietone’s picture

Issue tags: +migrate-d6-d8
benjy’s picture

Will ping alexpott for a product manager review. I'd rather leave the BC in place if this going into 8.0, don't mind removing it in 8.1 or 8.2 though.

alexpott’s picture

Migrate is exempt and this sort of change that does not affect already migrated seems fine to go into any 8.x version to me.

alexpott’s picture

Removing the tag - as this didn't need product manager review - I reviewed it as a framework manager - the actual question was a release management question. I answered because on previous discussions with the release managers (@xjm and @catch).

benjy’s picture

Status: Needs review » Reviewed & tested by the community

OK, RTBC for me.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs change record

This change does still need a change record. And given it is only an optimisation I think that committing to 8.1.x and 8.2.x is fine. 8.0.x will be history soon.

+++ b/core/modules/menu_link_content/src/Plugin/migrate/process/d6/LinkUri.php
@@ -0,0 +1,98 @@
+          list(, $entity_type_id, ) = $route_parts;

Coding standards says - There should be no white space before a closing ")" - I'm pretty sure the last comma is unnecessary.

neclimdul’s picture

Along the lines of alex's review,

+++ b/core/modules/menu_link_content/src/Plugin/migrate/process/d6/LinkUri.php
@@ -0,0 +1,98 @@
+          list(, $entity_type_id, ) = $route_parts;

Why not just $entity_type_id = $route_parts[1];? list() mostly helps with returns of methods/functions where you can't use [] or where you are assigning multiple variables. This is neither.

therealssj’s picture

Modified the patch in accordance with #22 and #23.

quietone’s picture

Status: Needs work » Needs review

thx, therealssj. Setting to Needs review for the testbot.

tstoeckler’s picture

Thanks, the interdiff looks great. In general I prefer the list() syntax but in this particular case I think I went a bit far. Code looks better now.

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

mikeryan’s picture

Queued an 8.1.x test to see if this needs a reroll.

Status: Needs review » Needs work

The last submitted patch, 24: 2648996-24.patch, failed testing.

mikeryan’s picture

Issue tags: +Needs reroll
Sonal.Sangale’s picture

Assigned: Unassigned » Sonal.Sangale
Status: Needs work » Needs review
FileSize
1.32 MB

Rerolling the patch.

Sonal.Sangale’s picture

Assigned: Sonal.Sangale » Unassigned

Status: Needs review » Needs work

The last submitted patch, 31: 2648996-31.patch, failed testing.

Sonal.Sangale’s picture

Can anyone explain why the rerolled patch failed?

There was conflict in file core/modules/menu_link_content/src/Plugin/migrate/process/d6/InternalUri.php since this file was deleted. I have just removed the deleted file from git.

quietone’s picture

Status: Needs work » Needs review
FileSize
9.37 KB

@Sonal.Sangale, your patch is 1.32MB, much larger than the patch in #24, which is 9KB. That's a good sign that something is amiss. Maybe you were not working from HEAD when you made the patch?

Reroll of patch #24. Interdiff fails.

tstoeckler’s picture

Patch looks good to me, thanks for the re-roll. This still needs a change record, though, before it can go in.

quietone’s picture

OK. I've not done a change record before but I started one, https://www.drupal.org/node/2761389.

tstoeckler’s picture

Status: Needs review » Reviewed & tested by the community

Yay, thanks. Slightly expanded it to mention that internal: URIs are still sometimes returned.

I can't actually RTBC the patch itself, but it was RTBC before and basically only held up on a change notice, and I feel comfortable approving the latter, so -> back to RTBC.

quietone’s picture

@tstoeckler, thanks.

phenaproxima’s picture

Status: Reviewed & tested by the community » Needs review
  1. +++ b/core/modules/menu_link_content/src/Plugin/migrate/process/d6/LinkUri.php
    @@ -0,0 +1,93 @@
    +      $path = 'internal:/' . $path;
    

    Should this be ltrim($path, '/'), to remove any leading slashes?

  2. +++ b/core/modules/menu_link_content/tests/src/Unit/Plugin/migrate/process/d6/LinkUriTest.php
    @@ -0,0 +1,134 @@
    +    $container = new Container();
    

    Maybe I'm out of date, but don't we use ContainerBuilder in unit tests?

quietone’s picture

1. I moved the ltrim so it is trimmed before it goes to parse_url.
2. Fixed

phenaproxima’s picture

Status: Needs review » Reviewed & tested by the community

Love it.

chx’s picture

Status: Reviewed & tested by the community » Needs review
FileSize
9.25 KB
2.57 KB

Simplified it a little.

Status: Needs review » Needs work

The last submitted patch, 43: 2648996_43.patch, failed testing.

tstoeckler’s picture

Great simplification, thanks!!

chx’s picture

Status: Needs work » Needs review
benjy’s picture

Status: Needs review » Reviewed & tested by the community
alexpott’s picture

Status: Reviewed & tested by the community » Fixed
Issue tags: -Needs change record, -Needs reroll

Committed and pushed 11904f8ea6000f3ccd93080d08886219137e3950 to 8.2.x and 310666e to 8.1.x. Thanks!

diff --git a/core/modules/menu_link_content/src/Plugin/migrate/process/d6/LinkUri.php b/core/modules/menu_link_content/src/Plugin/migrate/process/d6/LinkUri.php
index fcdd7b7..08c45d8 100644
--- a/core/modules/menu_link_content/src/Plugin/migrate/process/d6/LinkUri.php
+++ b/core/modules/menu_link_content/src/Plugin/migrate/process/d6/LinkUri.php
@@ -2,7 +2,6 @@
 
 namespace Drupal\menu_link_content\Plugin\migrate\process\d6;
 
-use Drupal\Core\Entity\EntityTypeInterface;
 use Drupal\Core\Entity\EntityTypeManagerInterface;
 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
 use Drupal\Core\Url;
diff --git a/core/modules/menu_link_content/tests/src/Unit/Plugin/migrate/process/d6/LinkUriTest.php b/core/modules/menu_link_content/tests/src/Unit/Plugin/migrate/process/d6/LinkUriTest.php
index 656e2a5..93a7280 100644
--- a/core/modules/menu_link_content/tests/src/Unit/Plugin/migrate/process/d6/LinkUriTest.php
+++ b/core/modules/menu_link_content/tests/src/Unit/Plugin/migrate/process/d6/LinkUriTest.php
@@ -10,7 +10,6 @@
 use Drupal\Tests\UnitTestCase;
 use Drupal\Core\Entity\EntityTypeManagerInterface;
 use Drupal\Core\Path\PathValidator;
-use Prophecy\Argument;
 
 /**
  * Tests \Drupal\menu_link_content\Plugin\migrate\process\d6\LinkUri.

Unused uses removed on commit.

  • alexpott committed 11904f8 on 8.2.x
    Issue #2648996 by tstoeckler, quietone, chx, therealssj, webflo, benjy:...

  • alexpott committed 310666e on 8.1.x
    Issue #2648996 by tstoeckler, quietone, chx, therealssj, webflo, benjy:...

Status: Fixed » Closed (fixed)

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