Issue

This came up due to https://drupal.org/node/2200127. When I uninstalled node, I got the same error as in the issue: InvalidArgumentException: No check has been registered for access_check.node.add in Drupal\Core\Access\AccessManager->loadCheck() (line 335 of core/lib/Drupal/Core/Access/AccessManager.php). When I looked through what rebuild did, I found that in the route rebuilding phase, old (deprecated or routes that shouldn't be there) routes were not removed.

Proposal

Routes are properly cleared for each provider that is written. Modules that have been uninstalled however are now longer in the provider list and are therefore not cleared. Explicitly delete them when a module is uninstalled.

Comments

btmash’s picture

btmash’s picture

Priority: Normal » Major
Issue summary: View changes

Status: Needs review » Needs work

The last submitted patch, 1: 2200185.patch, failed testing.

btmash’s picture

StatusFileSize
new2.9 KB

The unit tests are a new thing to me and I totally didn't understand what the fails were on. Finally getting the gist of it and hopefully new patch resolves the test failures.

btmash’s picture

Status: Needs work » Needs review

Also...needs review.

damiankloip’s picture

Issue tags: +Stalking Crell

We should summon Crell here too I think.

I am wondering, if we go down this path or flushing before rebuilds we will have to decide what to do with code in MatcherDumper::dump() as alot of that may not be applicable anymore if we work under the assumption that all routes will be cleared out.

btmash’s picture

When I looked at the code in MatcherDumper::dump(), I thought it was really interesting since something else **could** clear out certain routes if it wanted (without necessarily clearing out all routes). I thought it was useful to have in there but I don't know too much about that set of code to really make a case for/against it.

dawehner’s picture

Just a general note: the old menu system ensured that the table was cleared before. This is a safe assumption, sure, thought I wonder whether we should have some bigger transaction, to be sure that we never loose our sort of working routing.

@BTMash
For this usecase I really think we need some integration kind of webtest, as we want to test the full system, not just each component.

catch’s picture

Priority: Major » Critical

Would be better to dump just before writing the routes as opposed to before collecting them - much shorter window where there's an empty table.

Do we already trigger a rebuild when there's no routes? Or is there already a lock/wait cycle? If not that should be added here.

damiankloip’s picture

StatusFileSize
new931 bytes
new1.6 KB

Was talking to catch about this, whilst doing so I had another idea. We could clear out any router items on module uninstall instead. That way we do not mess with any exiting functionality or have to worry about multiple rebuilds/locks/empty router tables.

Super small patch.

The last submitted patch, 10: 2200185-10-tests-only-FAIL.patch, failed testing.

dawehner’s picture

+++ b/core/lib/Drupal/Core/Extension/ModuleHandler.php
@@ -759,6 +759,9 @@ public function uninstall(array $module_list, $uninstall_dependents = TRUE) {
       $schema_store->delete($module);
+
+      // Make sure any route data is also removed for this module.
+      \Drupal::service('router.dumper')->dump(array('provider' => $module));
     }
     drupal_get_installed_schema_version(NULL, TRUE);

It is sad that we couple the module handle to even more bits. Can we at least inject the service?

btmash’s picture

I'm not wholly agreeing with the change as I do think that rebuilding the router should mean flushing it out fully and rebuilding it (module uninstall is one scenario; I'm guessing of a scenario where routes in a module change after an update and cache rebuild possibly doesn't remove the old ones or if something implements the idea of disabling routes. That is why I'll attach my patch from above with tests in another comment. But I also lack the level of knowledge everyone else has on this components in the issue which is where I can agree with the fix.

berdir’s picture

@BTMash: The dumper already flushes and re-inserts... per provider/module. The only problem should be when modules no longer exist, then they wouldn't be flushed.

damiankloip’s picture

@dawehner, that would then the the only service injected. Seems better to just follow suit in this case? Then maybe fix all of this when I have done this work on the module event?

@berdir, exactly, Our current code in the MatcherDumper already handles all other cases. This is the approach that is the least invasive also. Preserving the current functionality completely.

damiankloip’s picture

Also, just created #2206347: Use event system in ModuleHandler to hopefully untangle the rats nest that is the module handler.

dawehner’s picture

The fix seems to be the way to go on the midterm

btmash’s picture

Status: Needs review » Reviewed & tested by the community

Spoke with @damiankloip, @berdir on this in irc to clear up my concerns. All cases should be accounted for. Finally, patch works (and looks good). RTBC as far as I'm concerned.

berdir’s picture

Title: Router table is not cleared when caches are cleared and router is rebuilt » Router table is not cleared when modules are uninstalled
Issue summary: View changes

Agreed. Also updating the issue title to better reflect what we're doing. Slightly updated the proposal to reflect what we're doing in now.

catch’s picture

Status: Reviewed & tested by the community » Fixed

Yep, this looks great now. Committed/pushed to 8.x, thanks!

Status: Fixed » Closed (fixed)

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