Active
Project:
Drupal core
Version:
main
Component:
entity system
Priority:
Normal
Category:
Plan
Assigned:
Unassigned
Reporter:
Created:
23 Sep 2019 at 10:21 UTC
Updated:
2 Oct 2019 at 08:15 UTC
Jump to comment: Most recent
An entity's update and insert hooks are used to trigger effects once an entity is saved. However at this point the entity has not actually being committed to the database. See \Drupal\Core\Entity\Sql\SqlContentEntityStorage::save().
This causes interesting problems for modules that
Consider using queues to allow actions after an entity save to occur not in the same database transaction or even the same request. By default we could process x number of items on this queue so that the effects of the entity save don't have to wait until cron runs.
tbd
tbd
None
Comments
Comment #2
bojanz commentedThe main blocker here is introducing some kind of a post save hook, that would run outside of the transaction.
This has been discussed in several issues over the years. For example:
#2892654: Entity save post transactional hook
#2992426: Add entity methods and hooks for executing pre/post code outside of the save transaction
Comment #3
catchSome modules (usually dealing with notifications) already have their own queue handling, but there is quite a lot of boilerplate that goes into implementing hook_*_insert()/ hook_*_update() to create the queue item then defining the queue itself.
I think we could look at the queue itself invoking a post-save hook so that modules can simply implement that hook to do what they need to do.
Comment #4
hchonovThis still requires a post transactional hook as pointed out in #2, but will not be able to cover the second requirement from the issue summary:
Comment #5
catch@hchonov why doesn't it cover the second point? The queue runner will be outside the transaction, and (usually) outside the request.
Comment #6
hchonovBecause you've mentioned post-save I thought that you want to do that as part of the save process. But I guess I got that wrong.
Comment #7
catchAhh OK so what I am thinking of is something like this:
1. Every entity type gets an post-save (maybe after-save queue is better in case we ever add post-save hooks?), we always create a queue entry and run it (maybe only if there are hook implementations).
2. The queue runner invokes a post save / after save hook, which is documented as being run via a queue. Modules can then implement that hook, without having to implement their own queue.
Tricky issues:
1. What happens if an entity is saved twice and two queue items are created before either of them runs?
2. What happens if an entity is saved, creating a queue item, then deleted before the queue item is processed?
I doubt we want to save the entity object in the queue item, would think just ID and load it in the runner.
Comment #8
hchonovShouldn't there be only one item for an entity? Also it is possible to re-save an entity during the invocation of the entity hooks - I think that this definitely should not create two items.
I would block the entity deletion until the queue is fully processed.
This makes sense only if there is one item for an entity, otherwise one might be interested in the made changes.
Comment #9
catchWe don't have an API for unique queue items, although there's an issue at #1548286: API for handling unique queue items. That might help for the double save issue although I'm not sure it's a blocker.
Similarly there's no way to introspect queues to see what's in them - because we allow queue implementations that don't allow such introspection, preventing deletion doesn't seem like a good option to me just because a queue hasn't run yet.
Comment #10
hchonovI can see why one would not like such thing, but one is for sure - we cannot delete the queue item(s) for the entity, as it might be necessary to perform a certain action after the entity is saved. And performing actions for an entity which is already deleted is kind of strange and might lead to all kind of errors if the process might need to load previous revisions of the entity.
What about introducing a deleted flag/field and let the entity queries ignore deleted entities? After all the queue items are processed we can purge the entity.