Problem

  • Pre-compiled + dumped data is read in again instead of being rebuilt in drupal_flush_all_caches() ["dfac()"] — the previous container is still in memory.
  • Drupal is not able to boot anything at all, if available vs. registered vs. requested services differ.

Details

  • dfac() is required when the system configuration is changed in significant ways and all caches need to be flushed and base data of subsystems and services needs to be rebuilt.
  • dfac() may also be able to successfully rebuild the system when definitions of "non-essential" services are changed (in code). "Non-essential" services means all services that are not in the critical path.
  • However, dfac() fails in case the definition of a service has changed and the service is requested before the kernel could be rebuilt.
  • dfac() always fails for base system services in the critical path; it requires the config system, lock system, variable system, and module system to operate.
  • Also, dfac() should not be invoked prior to DRUPAL_BOOTSTRAP_CODE, since it needs to call into all enabled modules to properly flush all caches and rebuild data.
  • A low-level rebuild is required when essential base system services are defined/registered differently, extended, or possibly changed altogether.

Proposed solution

  1. Fix dfac() to properly rebuild the kernel in cases it is possible.
  2. Introduce drupal_rebuild() for deadlock cases in which the current kernel and caches are corrupt and need to be rebuilt.

Notes

  • Invoking /unfreeze.php on an outdated D8 site allows to get back to a working, pre-existing D8 dev site without having to re-install.
  • This patch only educates how to use drupal_rebuild() in a suggested /unfreeze.php file, but does not introduce the file itself. Introducing a rebuild script is left for a separate issue.
  • Manually deleting the compiled container files only via sudo rm -rf sites/default/files/php is a workaround that might resolve the deadlock situation in certain situations.

Todo

  • Tests? Write a broken container to disk and try to recover from it?
CommentFileSizeAuthor
#89 1872522_84.patch5.5 KBchx
#89 interdiff.txt1.82 KBchx
#84 1872522_84.patch7.53 KBYesCT
#84 interdiff-83-84.txt1.4 KBYesCT
#83 1872522_83.patch7.52 KBdesmondmorris
#81 1872522_81.patch7.59 KBdesmondmorris
#80 1872522_80.patch5.57 KBdesmondmorris
#75 1872522_75.patch7.58 KBchx
#75 interdiff.txt892 byteschx
#72 1872522_71.patch7.57 KBchx
#72 interdiff.txt916 byteschx
#69 3u4kun.jpg24.36 KBchx
#69 1872522_69.patch7.27 KBchx
#69 interdiff.txt392 byteschx
#68 1872522_68.patch6.85 KBchx
#68 interdiff.txt896 byteschx
#64 1872522_64.patch6.78 KBchx
#64 interdiff.txt2.18 KBchx
#58 1872522_58.patch6.09 KBjibran
#54 1872522_52.patch7.83 KBchx
#54 interdiff.txt1.15 KBchx
#50 interdiff.txt487 byteschx
#50 1872522_50.patch6.5 KBchx
#48 1872522_48.patch5.89 KBchx
#48 interdiff.txt3.32 KBchx
#46 1872522_46.patch4.86 KBchx
#46 interdiff.txt2.45 KBchx
#43 unfreeze-1872522-43.patch9.57 KBBerdir
#41 unfreeze.41.patch24.68 KBBerdir
#38 unfreeze.36.patch18.75 KBaspilicious
#36 node_preview-86.patch24.7 KBaspilicious
#31 unfreeze.31.patch18.48 KBaspilicious
#26 unfreeze.26.patch18.41 KBeffulgentsia
#26 interdiff.txt839 byteseffulgentsia
#25 unfreeze.25.patch18.38 KBeffulgentsia
#21 unfreeze.21.patch9.54 KBeffulgentsia
#21 interdiff.txt914 byteseffulgentsia
#18 unfreeze.18.patch9.39 KBsun
#12 unfreeze.12.patch9.93 KBeffulgentsia
#12 interdiff.txt2.3 KBeffulgentsia
#11 unfreeze.11.patch9.17 KBeffulgentsia
#11 interdiff.txt593 byteseffulgentsia
#9 unfreeze.9.patch9.13 KBsun
#9 interdiff.txt3.03 KBsun
#5 _unfreeze.4.patch6.72 KBsun
comment_4.patch1.73 KBxjm
comment_3.txt778 bytesxjm
comment_1.patch1.05 KBxjm
comment_0.patch1.04 KBxjm
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

xjm’s picture

Status: Active » Needs review

Sending patches to the bot.

xjm’s picture

Component: block.module » base system

Not the block module.

Status: Needs review » Needs work

The last submitted patch, comment_4.patch, failed testing.

sun’s picture

Assigned: Unassigned » sun
Status: Needs work » Needs review
FileSize
6.72 KB

The fix and approach taken in my existing patches is correct, however:

dfac() is actually not able to handle a deadlock situation of a corrupted kernel. Attached patch introduces a new wrapper function, and elaborately explains why it is required and what is being done.

I'll rewrite the issue summary in a moment.

sun’s picture

Issue summary: View changes

Updated issue summary.

chx’s picture

+ // @todo Once file system settings are converted to configuration, this means
+ // a massive circular dependency, since the configuration system requires a
+ // working kernel.

BootstrapConfigStorageFactory::get

Status: Needs review » Needs work

The last submitted patch, _unfreeze.4.patch, failed testing.

sun’s picture

re: #6:
BootstrapConfigStorageFactory is not of any help, unless PhpStorageFactory gets the configuration service injected.

That's left for another issue to figure out though.

sun’s picture

Status: Needs work » Needs review
FileSize
3.03 KB
9.13 KB
  1. Fixed dfac() needs to update the kernel's module list and reboot it, instead of replacing it.
  2. Fixed DrupalKernel::initializeContainer() does not persist instances of synthetic services.

Status: Needs review » Needs work

The last submitted patch, unfreeze.9.patch, failed testing.

effulgentsia’s picture

Status: Needs work » Needs review
FileSize
593 bytes
9.17 KB
+++ b/core/lib/Drupal/Core/DrupalKernel.php
@@ -262,9 +269,16 @@ protected function getClassName() {
+      // Collect all instances of synthetic services.
+      foreach ($this->container->getServiceIds() as $id) {
+        if (!isset($persist[$id]) && $this->container->initialized($id)) {
+          $persist[$id] = $this->container->get($id);
+        }
+      }

1. The comment says "synthetic services", but what's actually returned also includes non-synthetic services for which get() has already been called.

2. 'service_container' is a synthetic service that we do not want to persist.

This fixes the second issue only (and not very nicely). CNR for bot.

effulgentsia’s picture

FileSize
2.3 KB
9.93 KB

Here's a more robust fix to both parts of #11.

Status: Needs review » Needs work

The last submitted patch, unfreeze.12.patch, failed testing.

effulgentsia’s picture

Status: Needs work » Postponed

The test failure in #12 appears to be a latent bug with how/when LocaleConfigSubscriber gets added to the event dispatcher. The bug appears to get surfaced by the changes to dfac(), but masked by HEAD's overly aggressive service persistence across container rebuilds. To untangle it, I suggest committing #1187726-135: Add caching for configuration / rework config object loading (Was: Memory usage and i/o from config objects) first.

effulgentsia’s picture

Issue summary: View changes

Updated issue summary.

sun’s picture

Status: Postponed » Needs work
+    foreach ($container->getDefinitions() as $id => $definition) {

When rebuilding an already compiled + possibly dumped container, then we're acting on a Container - not a ContainerBuilder.

Therefore, unless I'm missing something big, there is no getDefinitions() method — all of the build information is stripped from a compiled container.

effulgentsia’s picture

That line of code is only called within buildContainer() where we know we have a ContainerBuilder. Looks like #1187726-138: Add caching for configuration / rework config object loading (Was: Memory usage and i/o from config objects) is RTBC, so once that's committed, I'll reroll #12 and try to work through the Locale test failure.

effulgentsia’s picture

sun’s picture

Status: Needs work » Needs review
FileSize
9.39 KB

Re-rolled against HEAD.

Status: Needs review » Needs work

The last submitted patch, unfreeze.18.patch, failed testing.

sun’s picture

Is anyone able to explain the failures?

I need this rebuild almost every day...

effulgentsia’s picture

Status: Needs work » Needs review
FileSize
914 bytes
9.54 KB

Status: Needs review » Needs work
Issue tags: -Framework Initiative, -WSCCI

The last submitted patch, unfreeze.21.patch, failed testing.

sun’s picture

Status: Needs work » Needs review

#21: unfreeze.21.patch queued for re-testing.

Status: Needs review » Needs work
Issue tags: +Framework Initiative, +WSCCI

The last submitted patch, unfreeze.21.patch, failed testing.

effulgentsia’s picture

Status: Needs work » Needs review
FileSize
18.38 KB

This combines #21 with #1878512-12: Clean up Simpletest's kernel/container preparation/rebuild logic now that the kernel is responsive to module enabling. While the issues have differing scopes, they also have some overlap, and the individual patches are small enough, that even combining them into this one patch is still reviewable, I think.

effulgentsia’s picture

FileSize
839 bytes
18.41 KB

And a small comment tweak.

Status: Needs review » Needs work
Issue tags: -Framework Initiative, -WSCCI

The last submitted patch, unfreeze.26.patch, failed testing.

effulgentsia’s picture

Status: Needs work » Needs review

#26: unfreeze.26.patch queued for re-testing.

tim.plunkett’s picture

#26: unfreeze.26.patch queued for re-testing.

Status: Needs review » Needs work
Issue tags: +Framework Initiative, +WSCCI

The last submitted patch, unfreeze.26.patch, failed testing.

aspilicious’s picture

Status: Needs work » Needs review
FileSize
18.48 KB

Reroll.

1) Not sur if the reroll is 100% correct as some stuff changed
2) I don't need any credits for this one.

Status: Needs review » Needs work
Issue tags: -Framework Initiative, -WSCCI

The last submitted patch, unfreeze.31.patch, failed testing.

aspilicious’s picture

Status: Needs work » Needs review
Issue tags: +Framework Initiative, +WSCCI

#31: unfreeze.31.patch queued for re-testing.

aspilicious’s picture

testbot fail reference: FAILED: [[SimpleTest]]: [MySQL] Failed to run tests: failed attempting to get list of tests from run-tests.sh.

Status: Needs review » Needs work

The last submitted patch, unfreeze.31.patch, failed testing.

aspilicious’s picture

Status: Needs work » Needs review
FileSize
24.7 KB

New try

Status: Needs review » Needs work

The last submitted patch, node_preview-86.patch, failed testing.

aspilicious’s picture

Status: Needs work » Needs review
FileSize
18.75 KB

wrong patch...

Status: Needs review » Needs work

The last submitted patch, unfreeze.36.patch, failed testing.

Berdir’s picture

+++ b/core/includes/bootstrap.incundefined
@@ -3615,3 +3616,105 @@ function lock() {
+  // @todo Once file system settings are converted to configuration, this means
+  //   a massive circular dependency, since the configuration system requires a
+  //   working kernel.

As it looks now, this is not going to happen but the public path will move to $settings. So not sure i that needs to be documented.

Berdir’s picture

Status: Needs work » Needs review
FileSize
24.68 KB

Basic re-roll, renamed some rebuild/prepareContainer() method calls. Most of the test fails seem to be about theme() thinking that the module system is not yet fully bootstrapped?

Status: Needs review » Needs work

The last submitted patch, unfreeze.41.patch, failed testing.

Berdir’s picture

Status: Needs work » Needs review
FileSize
9.57 KB

Here's a reroll of #21. I think after the module handler went in, the test related changes became more complicated, what about getting this in separately?

Status: Needs review » Needs work

The last submitted patch, unfreeze-1872522-43.patch, failed testing.

chx’s picture

Assigned: sun » chx

This seems stalled, taking it for sprint work.

chx’s picture

Status: Needs work » Needs review
FileSize
2.45 KB
4.86 KB

This is about half-rewrite. I have added a new rebuild.php that can be requested via PHP and a rebuild.sh that calculates the token necessary. It's a small one but I think it'll do the job. It might be the answer to some drush woes as well. I am not terribly sure how helpful the interdiff is...

Status: Needs review » Needs work

The last submitted patch, 1872522_46.patch, failed testing.

chx’s picture

Status: Needs work » Needs review
FileSize
3.32 KB
5.89 KB

Status: Needs review » Needs work

The last submitted patch, 1872522_48.patch, failed testing.

chx’s picture

Status: Needs work » Needs review
FileSize
6.5 KB
487 bytes

This is solvable but the solution makes me cringe. It also makes me question wtf are we doing in tests re container.We have $this->container in tests. If this is not the same object as Drupal::getContainer() then whatever reset, set, etc etc we do via the container on one is not going to affect the services on the other. That's just bad. So in order to keep these together, WebTestBase already does two full container rebuild mostly because of this. After this patch, every time you do a drupal_flush_all_caches somewhere, your test needs to redo the $this->container = \Drupal::getContainer() part. I added that to resetAll hoping that will be enough but I can't be sure.

I see two exits:

  1. Don't do this updateModules call in drupal_flush_all_caches. It's almost superfluous, the only way the list of modules can change is if you delete one from disk. Move it perhaps to rebuild.php?
  2. Just throw out the 146 $this->container calls from the tests and use Drupal::getContainer. Who are we trying to fool by using $this->container, it's not like we inject anything into tests or we even could inject anything into tests...

Oh and both is an option too :D

Status: Needs review » Needs work

The last submitted patch, 1872522_50.patch, failed testing.

xmacinfo’s picture

It's almost superfluous, the only way the list of modules can change is if you delete one from disk.

The list can change when :

  • adding a new module,
  • deleting a module files,
  • adding a new version of a modules with sub-modules (although in D8 it would not be the case),
  • moving the database to a prod/staging/dev server that do not share the exact list of modules.
chx’s picture

The "list of modules" in question is the list of enabled modules and that can only change by deletion but, given mostly the patch passes, this is moot now. I will look into the failing test.

chx’s picture

Status: Needs work » Needs review
FileSize
1.15 KB
7.83 KB

I filed separate issues for the interdiff #1948650: Update is broken and #1948702: module_hook is broken for disabled modules and included hooks . Once those two are in, just press re-test on #50. This patch here just shows that once those two are in, we are in business.

jibran’s picture

This should be postponed as per #54

chx’s picture

Nope, nor those patches nor #54 merits a postpone yet -- we need reviews first and then we agree it's ready, we can postpone it then waiting for those.

jibran’s picture

#50: 1872522_50.patch queued for re-testing.

jibran’s picture

FileSize
6.09 KB

Here is a reroll of #50 run into conflict

--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@@ -6367,12 -6365,8 +6368,17 @@@ function drupal_flush_all_caches()
    // Flush all persistent caches.
    // This is executed based on old/previously known information, which is
    // sufficient, since new extensions cannot have any primed caches yet.
++<<<<<<< HEAD
 +  module_invoke_all('cache_flush');
 +  foreach (Cache::getBins() as $service_id => $cache_backend) {
 +    // @todo remove form after http://drupal.org/node/512026 is in.
 +    if ($service_id != 'cache.form' && $service_id != 'cache.menu') {
 +      $cache_backend->deleteAll();
 +    }
++=======
+   foreach (Drupal::service('module_handler')->invokeAll('cache_flush') as $bin) {
+     cache($bin)->deleteAll();
++>>>>>>> patch from http://drupal.org/node/1872522#comment-7196632
    }

    // Flush asset file caches.

and kept the head code as per @chx recommendation on IRC

moshe weitzman’s picture

The approach and the code look good and useful to me.

YesCT’s picture

#58: 1872522_58.patch queued for re-testing.

ParisLiakos’s picture

+++ b/core/includes/common.incundefined
@@ -6385,15 +6386,30 @@ function drupal_flush_all_caches() {
   // @todo Rebuild the kernel/container.

Lets update this comment if we are keeping updateModules()

+++ b/core/includes/common.incundefined
@@ -6385,15 +6386,30 @@ function drupal_flush_all_caches() {
+  Drupal::service('kernel')->updateModules(Drupal::service('module_handler')->getModuleList(), $files);
...
+  Drupal::service('module_handler')->loadAll();

@@ -6409,18 +6425,14 @@ function drupal_flush_all_caches() {
+  Drupal::service('module_handler')->invokeAll('rebuild');

Lets store somewhere module handler instead of calling Drupal::service('module_handler') all the time

+++ b/core/includes/common.incundefined
@@ -9,6 +9,7 @@
+use Drupal\Core\DrupalKernel;

where is this needed?

tstoeckler’s picture

Lets store somewhere module handler instead of calling Drupal::service('module_handler') all the time

Also we can now use the new and shiny \Drupal::moduleHandler() directly.

YesCT’s picture

Status: Needs review » Needs work

changing status to needs work to address #61 and #62

chx’s picture

Status: Needs work » Needs review
FileSize
2.18 KB
6.78 KB

Status: Needs review » Needs work
Issue tags: -Framework Initiative, -WSCCI

The last submitted patch, 1872522_64.patch, failed testing.

moshe weitzman’s picture

Status: Needs work » Needs review

#64: 1872522_64.patch queued for re-testing.

Status: Needs review » Needs work
Issue tags: +Framework Initiative, +WSCCI

The last submitted patch, 1872522_64.patch, failed testing.

chx’s picture

Status: Needs work » Needs review
FileSize
896 bytes
6.85 KB

*waves hand* this is not the module handler you are looking for.

chx’s picture

FileSize
392 bytes
7.27 KB
24.36 KB

catch all the exceptions

dawehner’s picture

+++ b/core/rebuild.phpundefined
@@ -0,0 +1,25 @@
+<?php

+++ b/core/scripts/rebuild_token_calculator.shundefined
@@ -0,0 +1,8 @@
+<?php

Can we have a @file to describe what this is all about?

+++ b/index.phpundefined
@@ -9,4 +9,10 @@
+  print 'If you have just changed code (for example deployed a new module or moved an existing one) read http://drupal.org/documentation/rebuild';

This is an intersting and helpful idea. Can we please make it translatable.

Status: Needs review » Needs work

The last submitted patch, 1872522_69.patch, failed testing.

chx’s picture

Status: Needs work » Needs review
FileSize
916 bytes
7.57 KB

Added some documentation. Translateable is hard because you are practically guaranteed that Drupal is not working and both reading the current language and the translation in that apgnauge is a significant challenge. I think we might be able to do something better in a followup.

dawehner’s picture

He, you broke index.php :)

+++ b/core/rebuild.phpundefined
@@ -1,5 +1,12 @@
+ * Rebuilds all Drupal caches even when Drupal itself does not work.

+++ b/core/scripts/rebuild_token_calculator.shundefined
@@ -1,5 +1,13 @@
+/**
+ * Command line token calculator for rebuild.php.

Thanks for the documentation. please add a @file

Status: Needs review » Needs work

The last submitted patch, 1872522_71.patch, failed testing.

chx’s picture

Status: Needs work » Needs review
FileSize
892 bytes
7.58 KB

meh.

aspilicious’s picture

Who is going to create the "rebuild" page?

chx’s picture

If you think of http://drupal.org/documentation/rebuild I will write it.

desmondmorris’s picture

Issue tags: -Framework Initiative, -WSCCI

#75: 1872522_75.patch queued for re-testing.

Status: Needs review » Needs work
Issue tags: +Framework Initiative, +WSCCI

The last submitted patch, 1872522_75.patch, failed testing.

desmondmorris’s picture

Status: Needs work » Needs review
FileSize
5.57 KB

@chx looks like that patch fails with the latest core build. here is my attempt at the updated patch.

desmondmorris’s picture

FileSize
7.59 KB

Last patch did not include file additions. Lets try this again

jibran’s picture

Status: Needs review » Needs work
+++ b/core/includes/common.incundefined
@@ -6089,16 +6088,32 @@ function drupal_flush_all_caches() {
-  Drupal::entityManager()->clearCachedDefinitions();
+  Drupal::service('plugin.manager.entity')->clearCachedDefinitions();

This change is not required see #1982984: Create Drupal::entityManager for improved DX.

desmondmorris’s picture

Status: Needs work » Needs review
FileSize
7.52 KB
YesCT’s picture

FileSize
1.4 KB
7.53 KB

I was reading and noticed a mis-spelling.
Fixed comment line wrap and moved a comment while I was at it.

jthorson’s picture

#83: 1872522_83.patch queued for re-testing.

tim.plunkett’s picture

Assigned: chx » catch
Status: Needs review » Reviewed & tested by the community
+++ b/core/lib/Drupal/Core/DrupalKernel.phpundefined
@@ -431,7 +431,19 @@ protected function buildContainer() {
+    // Identify all services whose instances should be persisted when rebuilding
+    // the container during the lifetime of the kernel (e.g., during a kernel
+    // reboot). Include synthetic services, because by definition, they cannot
+    // be automatically reinstantiated. Also include services tagged to persist.
+    $persist_ids = array();
+    foreach ($container->getDefinitions() as $id => $definition) {
+      if ($definition->isSynthetic() || $definition->getTag('persist')) {
+        $persist_ids[] = $id;
+      }
+    }
+    $container->setParameter('persistIds', $persist_ids);

I'm really glad this docblock is here. Very helpful.

+++ b/index.phpundefined
@@ -9,4 +9,10 @@
+try {
+  drupal_handle_request();
+}
+catch (Exception $e) {
+  print 'If you have just changed code (for example deployed a new module or moved an existing one) read http://drupal.org/documentation/rebuild';
+  throw $e;

The only possible change I'd say we would want to make here is moving the try/catch inside drupal_handle_request(), but there are pros and cons to both.

---

Overall, the changes to existing files make 100% sense to me.

I'm less certain about core/rebuild.php and core/scripts/rebuild_token_calculator.sh.

Not enough not to commit, just that I'd like catch's signoff here.

catch’s picture

I'm also not sure about core/rebuild.php and core/scripts/rebuild_token_calculator.sh. We've got existing issues to add something like that (although those were originally due to the D7 registry) and I'm sure there's discussion on those that isn't reflected here. For example why a cli token generator and not a flag in $settings similar to update_free_access? The latter would allow people with no cli access to rebuild for example, whereas this makes things command line only - but if it's command line only then why not directly rebuild in the shell script anyway?

I'd really like to get the bug fix in though (and that bit looks great), so could we maybe do a new issue?

catch’s picture

Assigned: catch » Unassigned
Status: Reviewed & tested by the community » Needs review
chx’s picture

Status: Needs review » Reviewed & tested by the community
FileSize
1.82 KB
5.5 KB

Same patch sans rebuild files.

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed 750b527 and pushed to 8.x. Thanks!

neclimdul’s picture

Status: Fixed » Needs work

Might I suggest 1) we write the node and 2) make the url a link?

xmacinfo’s picture

Status: Needs work » Fixed

@neclimdul: Looks like you need to open a new issue. I do not think your suggestion applies here.

genjohnson’s picture

I've moved neclimdul's suggestion to create the node to #2003204: Create http://drupal.org/documentation/rebuild.

genjohnson’s picture

neclimdul's suggestion to make the URL a link has been moved to #2003224: Make http://drupal.org/documentation/rebuild a link in index.php.

genjohnson’s picture

@chx: The page http://drupal.org/documentation/rebuild is ready for you to add content.

Status: Fixed » Closed (fixed)

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

webchick’s picture

The error message that was added to index.php here is a bit vague. I filed #2056915: Improve error message when drupal_handle_request() fails so we can try and improve it.

webchick’s picture

Change author to sun to match author of previous issue & summary. --xjm

sun’s picture

Thanks for moving forward here.

However, there are two major issues with the committed change:

  1. Catching any kind of Exception in index.php harms DX and cannot be desired.

    That was never the intention of this issue. In fact, as a developer, I was happy, and I do want to see where exactly the system blows up.

    In fact, the catch-all for any kind of exception is misleading in ~99% of all cases. Just because an exception was thrown doesn't inherently mean that the DI container has to be rebuilt.

    In short, this issue never had the intention to change the regular runtime behavior of Drupal.

    I am very confident that we want to revert that try/catch change to index.php.

  2. The actual problem in the OP was not resolved.

    It's good to see the fixes for drupal_flush_all_caches() & Co in core now, but none of these code paths can be reached in the first place; the system blows up much earlier already.

    Earlier patches added a new drupal_rebuild() function to core, without getting into the can of worms of a rebuild.php or any other interface.

    The most important goal was to get the fundamental facility into core. Whether you invoke that facility with a custom script, via Drush, or through any other mechanism doesn't matter.

    What matters is that there is a defined (API) way to resurrect your site when encountering the situation.

I'm not sure how to proceed here, as it appears that others are satisfied with the solution, but as the original reporter/author of this issue, I'm happy about the progress, but not satisfied with the solution, as it doesn't resolve the actual problem and introduced new problems.

olli’s picture

Issue summary: View changes
Related issues: +#2097189: Add a rebuild script

Here is the issue for rebuild.php.

#2097189: Add a rebuild script