9

Drupal 8 introduced hook_post_update_NAME() which has some benefits over hook_update_n, for updating modules.

Each hook_post_update_NAME() should only run once, but sometimes I want to rerun it, like when I'm debugging the update hook during development. With hook_update_n, you can reset the schema version in the database.

How do you rerun hook_post_update_NAME()?

10

"post_update" hooks that have been run are stored in the database, in the key_value table, post_update collection, but the data is serialized and awkward to update directly.

I used some of the details from @kiamlaluno's answer to create a drush script which you can use to reset a single hook. Here's a basic version (longer version is here):

#!/usr/bin/env drush

$key_value = \Drupal::keyValue('post_update');
$update_list = $key_value->get('existing_updates');

$choice = drush_choice($update_list, dt('Which post_update hook do you want to reset?'));

if ($choice) {
  $removed_el = $update_list[$choice];
  unset($update_list[$choice]);
  $key_value->set('existing_updates', $update_list);
  drush_print("$removed_el was reset");
} else {
  drush_print("Reset was cancelled");
}

And here's an example of what it looks like when you run it from the command line:

./scripts/reset_hook_post_update_NAME.drush

Which post_update hook do you want to reset?
 [0]   :  Cancel
 [1]   :  system_post_update_add_region_to_entity_displays
 [2]   :  system_post_update_hashes_clear_cache
 [3]   :  system_post_update_recalculate_configuration_entity_dependencies
 [4]   :  system_post_update_timestamp_plugins
 [5]   :  my_module_post_update_example_hook

# The script pauses for user input. 
5 

my_module_post_update_example_hook was reset
  • 3
    have you thought about contributing this back to drush, github.com/drush-ops/drush? – powpow12 Jan 29 '18 at 17:30
  • This is a pretty sweet feature, but its a bit too niche for core Drush. Perhaps someone make a commandfile for it. – moshe weitzman Oct 9 '18 at 19:37
1

UpdateRegistry::getPendingUpdateFunctions() contains the following code. See what the comment says.

  // First figure out which hook_{$this->updateType}_NAME got executed
  // already.
  $existing_update_functions = $this->keyValue->get('existing_updates', []);

UpdateRegistry::$updateType is set to 'post_update'.
$this->keyValue is set from UpdateRegistryFactory::create() with the value of $this->container->get('keyvalue')->get('post_update').

The equivalent procedural code to get that keyvalue collection is the following one.

$key_value = \Drupal::keyValue('post_update');

Set existing_updates to an empty array, and Drupal will think none of the post update callbacks have been called.

$key_value = \Drupal::keyValue('post_update');
$key_value->set('existing_updates', []);

Remove the callback name from the existing_updates key of that keyvalue, and Drupal will think that post update callback has not yet been invoked.

1

Here is an example you can use from the command line with drush php-eval:

drush php-eval -e '$update_hook_name = "<my_hook_post_update_name>";
$key_value = \Drupal::keyValue('post_update');
$existing_updates = $key_value->get('existing_updates');
$index = array_search($update_hook_name,$existing_updates); 
unset($existing_updates[$index]);
$key_value->set('existing_updates', $existing_updates);'

When you re-run drush updatedb you will see your post_update_hook waiting to be run.

  • This worked well for me, just to mention that in drush 9, it is drush php:eval 'command' – powpow12 Jan 29 '18 at 17:31
0

Call it from within hook_update_n() and then do what you were doing before.

  • That doesn't seem like a good idea, since the entire purpose for the hook_post_update mechanism is to have a fully functional Drupal available after all updates have run. It was introduced because there are no guarantees about the state of Drupal during updates. – Eelke Blok Aug 8 '18 at 9:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.