Problem/Motivation

Currently, all of the following happen inside of the database transaction started by SqlContentEntityStorage::save():

  • EntityInterface::preSave()
  • hook_ENTITY_TYPE_presave()
  • hook_entity_presave()
  • EntityInterface::postSave()
  • hook_ENTITY_TYPE_(insert|update)()
  • hook_entity_(insert|update)()

Sometimes there's code that needs to run before or after the save that does not need to be inside the transaction, but uses one of the above methods/hooks anyway, since that's all that's available. If the code is slow (e.g., makes a web service call and awaits a response), then the database ends up locked for longer than necessary, severely limiting the scalability of the website.

A couple examples:

  • In core, a Media entity with an oEmbed-provided source needs to fetch metadata from the oEmbed provider prior to save(), but this should be done prior to starting the database transaction. #2990896: Move Media::save() logic into storage handler to prevent data integrity issues when media items with remote content are saved is implementing this in a custom way for Media, but could benefit from a more generic API if one were available.
  • In contrib, the Lingotek Translation module implements hook_entity_insert() and hook_entity_update(), within which it waits for the remote translation service to return a translation prior to returning, and therefore prior to the database transaction being committed. If there were additional hooks that ran after the end of the transaction, then potentially Lingotek could use those instead.

Proposed resolution

  • Add an additional method and hook that runs before the transaction starts (and therefore, before preSave()).
  • Add an additional method and hook that runs after the transaction is committed (and therefore, after postSave(), insert, and update).

Remaining tasks

User interface changes

None.

API changes

No changes to existing methods/hooks. Some method/hook additions per the Proposed resolution.

Data model changes

None.

Comments

effulgentsia created an issue. See original summary.

effulgentsia’s picture

Issue summary: View changes
gabesullice’s picture

Do these need to be hooks? Perhaps they can be events instead. Those two events could receive an immutable entity. That would help convey that the events are for doing things because an entity is about to be/has been saved vs. altering the entity during its save.

If so, I'd propose before.save and after.save as the event names.

finex’s picture

I propose hook_before_transaction and hook_after_transaction. (Otherwise pre/post are equivalent).

wengerk’s picture

I think we should keep the idea of decoupling insert & update and so we have to provide 4 hooks. I suggest this idea to prevent mixing the same hook to deal with before-insert & before-update - which are not the same .

I suggest using the same wording as existing: insert & update.

Insert

  • hook_entity_before_insert (event: before.insert)
  • hook_entity_after_insert (event: after.insert)
  • hook_ENTITY_TYPE_before_insert
  • hook_ENTITY_TYPE_after_insert

Update

  • hook_entity_before_update (event: before.update)
  • hook_entity_after_update (event: after.update)
  • hook_ENTITY_TYPE_before_update
  • hook_ENTITY_TYPE_after_update

I also encourage using events with hooks. The events are the most logical way to go on the future but to keep consistency we have to expose hooks too - on Drupal 8.

What do you think about it ?

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

skaught’s picture

This issue is still relevant.

To mention, contrib offers hook_post_action. these namespaces seem like a good starting place..

jonathanshaw’s picture

It's worth being aware that there are both existing issue for creating a single hook that covers both insert and update (but WITHIN the transaction: #2221347: Add hook_entity_postsave hook.

jonathanshaw’s picture

I had to adopt the hook_post_action module because I needed to do a node entity query from within a node insert/update hook and I was getting deadlocked.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

dpi’s picture

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.

dqd’s picture

From a glimpse, it seems issue #2965989: Does not work with core media in Automatic Entity Label's issue queue is on hold and needs direction based on the outcome of this issue here. Set this here as related from over there.