Issue description
node_save() calls db_transaction() in it's first line. Since a transaction is commited when it's object goes out of scope the node will actually be saved at very end of node_save().
We invoke hook_node_insert() and hook_node_update() before the end of node_save() which means, that node has not been saved to DB at that moment. On the other hand documentation for this two hooks states:
This hook is invoked from node_save() after the node is updated in the node table in the database, ....
and
This hook is invoked from node_save() after the node is inserted into the node table in the database, ...
This makes you think, that you already have all data safely saved, when Drupal calls your hook implementations. Assuming this lead me to very strange situations, that were really hard to debug.
Same thing applies to user_save() and could also apply to some other similar function.
EDIT: I've also written a blog post with a bit more background to this: http://janezurevc.name/strange-behaviour-race-condition-during-nodesave
Proposal/solution
I propose that we either change place where this hooks are invoked or update docs to make people aware of this fact. I'd think about exposing another hook at the time after a node has been physically saved into DB even if we decide to only update docs. People might need something like this.
Comment | File | Size | Author |
---|---|---|---|
#22 | improve_api_docs_1677830_22.patch | 4.09 KB | slashrsm |
#20 | improve_api_docs_1677830_20.patch | 4.08 KB | slashrsm |
#17 | improve_api_docs_1677830_17.patch | 4.07 KB | slashrsm |
#15 | improve_api_docs_1677830_15.patch | 3.36 KB | slashrsm |
#12 | improve_api_docs_1677830_12.patch | 3.19 KB | slashrsm |
Comments
Comment #1
slashrsm CreditAttribution: slashrsm commentedRelated issue: #1679344: Race condition in node_save() when not using DB for cache_field
Comment #2
slashrsm CreditAttribution: slashrsm commentedI propose to something like this to hook_node_insert() and hook_node_update() api docs:
I will mark this as Major. Not being aware of this can result in really strange bugs and can be really frustrating for a developer.
Comment #3
tim.plunkettMoving to D8 first.
Comment #4
catchI actually think this is major, if only to add the documentation.
Comment #5
slashrsm CreditAttribution: slashrsm commentedThere might be other places that would need similar notice. hook_user_insert() and hook_user_update() are definitely two candidates.
I can prepare patch, but I'd like to have consensus about the actual text before that.
Comment #6
fagohm, this also relates to #1729812: Separate storage operations from reactions.
Given #1729812: Separate storage operations from reactions I think the transaction should be completed *before* the hooks are invoked, thus making the hooks for reactions only. We can't do that for d7, but for d8 we could. I guess this would deserve its own issue though and require field-storage to be moved to the entity controller (and separately re-usable) first.
Comment #7
jhodgdonThere is no patch on this issue, so reverting status to "active".
Comment #8
slashrsm CreditAttribution: slashrsm commentedI agree with #6. So should we improve docs for D7 here and do D8 changes in #1729812: Separate storage operations from reactions?
Comment #9
jhodgdonAt the moment, the process would be to fix the D8 docs here, then backport the changes to D7. That other issue may or may not be resolved any time soon.
Comment #10
slashrsm CreditAttribution: slashrsm commentedHere comes the patch....
Comment #12
slashrsm CreditAttribution: slashrsm commentedStupid me....
Comment #13
slashrsm CreditAttribution: slashrsm commentedComment #14
jhodgdonThanks, looking pretty good!
There shouldn't be a comma here though (the first one):
Actually, I think it needs a little rewriting to make more sense grammatically. How about something more like:
Note that when this hook is invoked, the changes will not yet be written to the database, because a database transaction is in progress. The transaction is not finalized until...
Also, this section has some extra commas and needs rewriting:
Comment #15
slashrsm CreditAttribution: slashrsm commentedImproved patch. I am wondering if there is any other hook, that also needs this notice?
Comment #16
jhodgdonMuch better, thanks! There are still a couple of small comma/article problems to fix:
- 3rd line: "...until *the* save operation..."
- 5th line: I don't think the information is really "out of date", it's just not updated yet?
- 6th line: Remove both commas
Also... The previous paragraph to this text that is added reads:
So this second paragraph contradicts the first one and the first one is really incorrect, right? Something needs to be done about that... maybe integrate them together?
Comment #17
slashrsm CreditAttribution: slashrsm commentedFixed.
How about this? I do not really like my current proposal, but it was the best I was able to produce right now...
Comment #18
slashrsm CreditAttribution: slashrsm commentedComment #19
jhodgdonI think the new wording is OK. The only thing I think needs to be fixed now is that the verb tenses documentation are inconsistent, which makes it a bit confusing (it switches between past, present, and future). And there is one missing "the" in the new text: "... that will insert *the* node into...". Other that that, I think it's OK.
Comment #20
slashrsm CreditAttribution: slashrsm commentedBetter?
Comment #21
jhodgdonBetter, thanks! There are still a few small errors that need to be fixed:
a) The word wrapping on this line is too long:
I think there are a couple others that are longer than 80 characters too.
b) Grammar problem:
changes *have* not yet... ... This grammar needs to be corrected in several places in the patch.
Comment #22
slashrsm CreditAttribution: slashrsm commentedComments from #21 fixed.
Comment #23
jhodgdonThanks! Assuming the test bot shows green (which it should), I'll get this committed shortly (patch will most likely work for both 8.x and 7.x).
Comment #24
slashrsm CreditAttribution: slashrsm commentedThat's great. Thank you for your time and effort!
Comment #25
jhodgdonCommitted to 8.x and 7.x. Thanks again for *your* time and effort!
Comment #26
jhodgdonComment #27.0
(not verified) CreditAttribution: commentedAdded link to blog post.