#Collection hooks, operation create error

10 messages · Page 1 of 1 (latest)

grand crag
#
  hooks: {
    afterChange: [
      async ({ doc, operation, req }) => {
        // Trigger MediaConvert transcoding when video is created or updated
        if (operation === 'create' || operation === 'update') {
          if (doc.filename) {
            try {
              // Update status to 'processing'
              await req.payload.update({
                collection: 'videos',
                id: doc.id,
                data: {
                  convertStatus: 'processing',
                },
              })
...

part of my upload collection have this code, and i want to update the data after i have submit it. But while the media is uploading this afterchange hook triggers, Thus it throws a not found error (image attached).

but if i remove this afterchange hook, it works.

How do i trigger the hook after it finished uploading?

terse cobalt
#

Hey @grand crag

the issue is that afterChange fires within the same database transaction as the original create/update.

When the hook immediately calls req.payload.update() on the same document while passing req, it inherits that transaction context — and the document may not be committed yet, causing the not found error

#

so the simplest fix would be to drop Drop req from the nested update

await req.payload.update({
  collection: 'videos',
  id: doc.id,
  data: { convertStatus: 'processing' },
  // no req — runs outside the current transaction
})
#

Or, you could utilize the jobs queue

afterChange: [
  async ({ doc, operation, req }) => {
    if ((operation === 'create' || operation === 'update') && doc.filename) {
      await req.payload.jobs.queue({
        task: 'transcodeVideo',
        input: { videoId: doc.id },
      })
    }
  },
]
grand crag
#

how about using afterOperation? does this trigger after the transaction?

grand crag
#

i think i understand what you mean.

    afterChange: [
      async ({ operation, req, doc }) => {
        // Trigger MediaConvert transcoding when video is created or updated
        if (operation === 'create' || operation === 'update') {
          if (doc) {
            try {
              // Get fresh payload instance outside transaction context
              const freshPayload = await getPayload({ config })

              // Update status to 'processing'
              await freshPayload.update({
                collection: 'videos',
                id: doc.id,
                data: {
                  convertStatus: 'processing',
                },
              })

I updated into this, but still throw the same error

terse cobalt
#

Hmm.. this feels like a recursive loop

#

Video is created/updated → afterChange fires
Hook calls update({ data: { convertStatus: 'processing' } })
That update triggers afterChange again (it's an update operation with doc.filename still set)
Loop repeats → breaks