#AfterChangeHook Not Running After DB Insertion

38 messages · Page 1 of 1 (latest)

sterile knotBOT
#

Hey, is the afterChangeHook not supposed to run after the data has been inserted to the DB?

My usecase is that I'd like to create several documents in another collection (collection b), whenever an item is changed in collection a

long terraceBOT
#

Original message from @toxic canyon - Moved from #general message

lofty crow
#

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

toxic canyon
# lofty crow Hey <@131537558453747712> Yeah, this is a good use case for an afterChange or ...

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],
  },
}

lofty crow
#

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?

fickle shadow
#

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.

lofty crow
#

Selectively including/excluding req can create all sorts of nonsense

toxic canyon
lofty crow
#

What are the odds that your issues go away if you remove the req from the find

fickle shadow
lofty crow
#

What are the odds that your issues go away if you remove the req from the find
Which is why I ponder the above

toxic canyon
lofty crow
#

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.

toxic canyon
#

If I remove the req from the create, it also breaks

lofty crow
#

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

toxic canyon
#

Interesting. So conceptually, by including req in the create, we simply add the creation to the transaction

lofty crow
#

Correct

#

But if you do a find right after (with a req), it will fail to find the doc

toxic canyon
#

Hold up, but I still don't get why that would necessarily be required

#

Like why would it be required on the create

lofty crow
#

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

toxic canyon
#

It's for sure just my own lack of knowledge of how Payload works. I'll do some more research to understand this better

lofty crow
#

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

toxic canyon
lofty crow
#

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!