All calls to drupal_flush_all_caches() in the installer should no longer be required in the new kernel architecture.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Status: Needs review » Needs work

The last submitted patch, drupal8.dfac-installer.0.patch, failed testing.

Berdir’s picture

Looks like all the fails that I looked are because field types are missing?

That's #2155635: Allow plugin managers to opt in to cache clear during module install then, although we could add a workaround and call clearCachedDefinitions() on the field type manager for now, just like we do it for the entity manager.

sun’s picture

Yes, there appear to be two discrete problems:

  1. Routes are not rebuilt (at all).

    This causes the interactive installer tests to fail. When redirected to the actual site after installation, you get a 404.

    dfac() enforces a rebuild of all routes on every invocation + also calls hook_rebuild() in all modules.

    Technically, #2164367: Rebuild router as few times as possible per request should have resolved this.

    But the installer does not actually use a proper DrupalKernel, so terminate()/shutdown() is never invoked, and AFAIK that's where the solution kicks-in. (?)

    → We probably need to add an enforced termination/shutdown to the end of install_drupal() (which is the legacy, kernel-alike dispatcher that sends the response)

  2. Plugin manager caches are never cleared.

    Indeed, #2155635: Allow plugin managers to opt in to cache clear during module install could resolve this in a generic way.

    In light of a non-interactive/programmed/batched installation (single request), I wonder whether that issue should actually shoot for a solution that is essentially the same as #2164367: Rebuild router as few times as possible per request — i.e., only add a marker/pointer that a rebuild is needed, but don't rebuild immediately?

    Or is that irrelevant, because they are using a cache?

    But why are they using a cache to begin with? Why are plugin definitions not state?

    In any case, in light of this total test suite time on one of our slowest/oldest testbots:

    Test run duration: 1 hour 11 min
    

    …I'd totally shoot for a temporary stop-gap to clear a few necessary plugin manager caches manually in ModuleHandler::install(), unless we're able to resolve #2155635: Allow plugin managers to opt in to cache clear during module install in a timely fashion.

sun’s picture

The spin-off #2202477: Make FieldInfo implement a new CachedStateInterface might allow us to resolve these problems on a universal scale.

Berdir’s picture

#2155635: Allow plugin managers to opt in to cache clear during module install is blocked on two things:

1) Making it green. Thew new patch might be or at least brings us one step closer.
2) Decide on the exact approach to call the services/methods.

A quick fix here for the field type would require the same fixes as we have in the other issue, at least those that are related to field types (most are). So if that issue gets blocked further on 2), we could move forward here with a direct call.

As commented in the other issues, FieldInfo isn't the problem.

I disagree with persistent cache = state. Plugin caches can and need to be rebuilt when the thing they're caching is changing . State isn't rebuilt, it's just changed explicitly. State must be persistent, caches not because they can be rebuilt.

And yes, plugin cache clearing is already the same as rebuildIfNeeded(). We don't rebuild anything, we just clear the cache, so that whoever is going to get the definitions will trigger a rebuild. If nobody does, then it will never be rebuilt. The only problem, as the other issue showed is that cache clearing isn't a no-op, we could end up doing repeated cache clears even if nobody requested the information in the meantime. But we might be able to optimize that too.

Berdir’s picture

Status: Needs work » Needs review
FileSize
19.66 KB

Here's a combination of the patch here and the now green patch from #2155635: Allow plugin managers to opt in to cache clear during module install.

Only tried the first failing patch from the previous patch and that works now.

Based on that, we should be left with only the router related fails?

Status: Needs review » Needs work

The last submitted patch, 6: no-dfac-with-plugin-manager-clears-2201785-6.patch, failed testing.

sun’s picture

#2155635: Allow plugin managers to opt in to cache clear during module install is RTBC now.

#2213357: Use a proper kernel in early installer laid the ground for having a proper kernel in the installer at all times.

I'm not sure where exactly the router rebuilding kicks in, but it ought to be possible to manually trigger a rebuild in install_finished(); i.e., the very last install task/step — so that we only build the router once after installation completed.

sun’s picture

drupal8.dfac-installer.0.patch queued for re-testing.

The last submitted patch, drupal8.dfac-installer.0.patch, failed testing.

Berdir’s picture

Status: Needs work » Needs review
FileSize
1.75 KB

Re-roll.

Status: Needs review » Needs work

The last submitted patch, 11: drupal8.dfac-installer.11.patch, failed testing.

Berdir’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 11: drupal8.dfac-installer.11.patch, failed testing.

sun’s picture

We still need to implement a manual router rebuild in install_finished(). Should be easy?

sun’s picture

Status: Needs work » Needs review
FileSize
1.92 KB

This will come back green.

Berdir’s picture

Nice. Yeah, I just did the re-test because I wanted to see the test result on a fast bot.

Looks like it's not as much faster as before, probably because the tests are much faster already anyway and doing less extension scans and router rebuilds isn't that much of a time saver.

It's not really the problem of this issue, but I was wondering if we should do a rebuildIfNeeded() after the module was installed instead of the manual rebuild at the end.

We had the problem that we did something in hook_modules_installed() that resulted in a router lookup for one of the new modules, which didn't work as we no rebuild happened. We can do this ourself, but it would be nice if core could handle that correctly. On the other side, this will probably result in quite a few additional rebuilds as the batch stuff will request routes on every page load?

sun’s picture

Spent some to tinker about that question...

I actually don't think that any module install hook should rely on possibly existing router information... that sounds like asking for trouble.

The installer itself doesn't actually use any of the module routes. Even when we will have converted it into a micro-app, it's going to use a small set of hard-coded routes.

Lastly, I didn't actually check/confirm yet whether this patch improves the installer performance for me locally...

Berdir’s picture

Hm, Note that I'm talking about hook_modules_installed(), which happens *after* the module installer completed it's job. Shouldn't a module be completely installed at that point, *including* routes?

This is my use case:

I'm using the default_content module from https://github.com/larowlan/default_content, which allows to install default content that from hal+json encoded files. The path alias is a field now, so it is possible to put the alias directly into that file and it works perfectly - except that by the time it now runs, the routes aren't rebuild and the route the alias is supposed to point to does not exist, resulting in an exception. I'm not interested in *accessing* any routes, but they do need to exist in the system to be able to save things that reference them.

There's nobody else that's there to do this, content_translation could but should not care about routes and path.module certainly shouldn't have to worry about this.

You can use entity types and plugins of any type now in this hook (before the plugin cache clearer, we've run into the problem that the rest plugin manager wasn't cleared, so denormalizing them didn't work for entity types that were installed after rest.module), why not routes?

Again, not saying that we have to solve it here, but I feel pretty strongly that we have to solve it somehow and instead of adding a forced rebuild in the installer, we could let the module system deal with it?

sun’s picture

Yeah, just to clarify, I'm not opposed to (re)building the router after installing each module. Retaining that but skipping a full dfac() should still present a major performance increase, since plenty of unrelated caches are no longer flushed.

But I'm confused:

  1. Wasn't the new router supposed to be optimized in the sense of being able to build/install the routes of a particular module only? (instead of rebuilding the whole system)

  2. Why does ModuleHandler::install() not build the routes of the module being installed? — This appears to be the actual root cause and bug revealed by this patch...?

Berdir’s picture

1. Yes, but I'm not sure if that's just an implementation detail and this point or an actual API. Looking at RouteBuilder, it seems to be the former, it collects all routes and then only the processing/dumping is by provider.

2. Yes, that's kind of what I'm saying :)

tstoeckler’s picture

#21.1 is correct but even that part is being ripped out as that causes all kinds of problems. See #2158571: Routes added in RouteSubscribers cannot be altered
It would be cool though if we can optimize this, instead of a full rebuild each time.

sun’s picture

I finally get it now!

ModulesListConfirmForm::submitForm() manually calls drupal_flush_all_caches()! :-(

Berdir’s picture

Status: Needs review » Needs work

The last submitted patch, 16: drupal8.dfac-installer.16.patch, failed testing.

sun’s picture

Status: Needs work » Needs review
FileSize
1.89 KB
Berdir’s picture

Status: Needs review » Reviewed & tested by the community

Yeah, let's do this, opened #2248297: Ensure routes are rebuilt when install modules for the route rebuild problem, wasn't caused by this issue in any way, so that shouldn't block it.

As mentioned above, the difference isn't as huge anymore as it used to be, but it's still 27 instead of 31 minutes, based on the few test results that I checked.

catch’s picture

Status: Reviewed & tested by the community » Fixed

Nice! Committed/pushed to 8.x, thanks!

  • Commit e866c4c on 8.x by catch:
    Issue #2201785 by sun, Berdir: Remove drupal_flush_all_caches() from...

Status: Fixed » Closed (fixed)

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