#AfterChangeHook Not Running After DB Insertion
38 messages · Page 1 of 1 (latest)
Original message from @toxic canyon - Moved from #general message
Help is on the way! To mark it as solved, use the /solve command. In the meantime, here are some existing threads that may help you:
Documentation:
Hey @toxic canyon
Yeah, this is a good use case for an afterChange or a beforeChange collection hook. afterChange should run after the data has been saved
For some reason it's complaining that the document does not yet exist.
Note that document and document-chunk are two different collections
import { Document } from '@/payload-types'
import type { CollectionAfterChangeHook, CollectionConfig } from 'payload'
const afterChangeHook: CollectionAfterChangeHook<Document> = async ({ doc, req }) => {
await req.payload.create({
collection: 'document-chunk',
data: {
chunk: 'chunk2',
embedding: '[1,2,3,4,5,6,7,8,8,8]',
document: doc.id, // This complains that there's no document with this ID yet
},
req,
})
console.log('About to fetch chunks')
await req.payload.find({
collection: 'document-chunk',
where: {
document: {
equals: doc.id,
},
},
req,
})
}
export const Documents: CollectionConfig = {
slug: 'documents',
upload: {
staticDir: 'documents',
adminThumbnail: 'thumbnail',
mimeTypes: ['application/pdf'],
},
fields: [
{
name: 'alt',
type: 'text',
},
],
hooks: {
afterChange: [afterChangeHook],
},
}
Can you try scoping it to the 'create' operation, there should definitely be an id there. Also your second req.payload.find operation there is redundant as the create operation will return the created document
document-chunk has a relationship field set to documents with a field name of document, correct?
I've had this happen before if I have any other hooks that are involved with the above collections (both collection-level and field-level) that don't have a req assigned to them.
Most recently it was a beforeValidate hook without a req that caused a very similar issue for me, make sure to check there.
Yes
Selectively including/excluding req can create all sorts of nonsense
This is a completely new project
What are the odds that your issues go away if you remove the req from the find
I learnt that the hard way 😂
Oh man, I've been trying to find the root of this issue since beta - something real weird happens. I have a PR for plugin-search from October that shows this
What are the odds that your issues go away if you remove the req from the find
Which is why I ponder the above
Yeah that straight up worked. Not sure what exactly I changed, cause initially I didn't pass req on either
Bingo
I've seen so many of these I actually have notes in my notebook on different scenarios. I have theories but nothing conclusive and have inspected the transaction code pretty intensely and am still not too sure. My leading theory is that if you follow the transaction, from the POV of that transaction that document has not been "comitted" or "created" yet so it fails to find it within the transaction itself.
If I remove the req from the create, it also breaks
The create necessarily needs that req
It must be there
But subsequent finds will fail if you include the req there. I can tell in advance that you're on Postgres by the way you describe how the calls fail
Interesting. So conceptually, by including req in the create, we simply add the creation to the transaction
Hold up, but I still don't get why that would necessarily be required
Like why would it be required on the create
Because everything up to that point is operating within a transaction https://payloadcms.com/docs/database/transactions#async-hooks-with-transactions
To be clear - you don't have to use a req but it is highly encouraged especially if you have other hooks or operations
In this particular case, a create with a req followed by a find with a req does something weird and fails, as you've observed
Well in this particular case, a create without a req followed by a find without a req also does something weird and fails
^ This is the scenario which confuses me
It's for sure just my own lack of knowledge of how Payload works. I'll do some more research to understand this better
Because that create is assuming that a doc.id exists but what I think is happening is that the transaction, while saving the data, is not necessarily comitted yet
You can assume that the afterChange runs after the data is saved, but that transaction may not have been comitted yet if that makes sense
I need a deeper understanding of postgres to understand the difference between comitted transactions and data being saved 😅
Don't sweat it too much, just try to pass req where possible and be mindful of this caveat here. I like to think of transactions as isolated "paths" where there's a path outside the transaction, and inside the transaction. Read through the link I sent above too, ti should make things a bit more clear.
Otherwise I'll go ahead and mark this as solved if things started working for ya here!