Giter Club home page Giter Club logo

Comments (4)

jmikrut avatar jmikrut commented on June 16, 2024 1

Hey @Jonashr — I might know what's going on here.

If you have transactions enabled, the transaction for updating a document will not yet have been completed by the time that you run your afterChange hook.

And if you are awaiting your revalidate method within your afterChange hook, Next.js would be attempting to fetch the document before the updates within the update operation's transaction are committed. That would mean that Next.js would then retrieve the data as it was before the change was made.

If you did not await your revalidation call within your afterChange hook, Payload could continue on to commit the transaction and it could then be completed before Next.js made its fetch for the new data.. but that doesn't seem ideal to me because there could still be a potential race condition if the transaction doesn't complete before Next fetches.

Here are 2 other options to consider:

1 - You can call commitTransaction yourself, before calling your revalidate endpoint, by doing the following:

  const { payload, transactionID } = req

  await payload.db.commitTransaction(transactionID)

2 - We could make some type of adjustment to our logic so that transactions are committed either before afterChange runs.

I am not sure if the second option would be ideal though - because some hooks might want to have logic included within their afterChange hook which should indeed be part of the same transaction (creating other documents, updating other documents, etc.)

Try number 1 for now. Does that work?

from payload.

Jonashr avatar Jonashr commented on June 16, 2024 1

@jmikrut @DanRibbens Thanks for the great suggestion! You were right about the transaction not being completed being the issue here. As suggested I added the code to commit the transaction:

  const { payload, transactionID } = req

  await payload.db.commitTransaction(transactionID)

Once I committed the transaction it worked like a charm. So I am just going to mark this issue as completed as has solved my issues. Thanks again!

from payload.

DanRibbens avatar DanRibbens commented on June 16, 2024

Hey @Jonashr,

Thanks for that info, this is helpful and very clear to me of what the issue is. I'll add some ideas on top of what James has already stated.

In your hook you can pass the req which includes a transactionID to any payload local API functions or payload.db operationsto use the same transactions. In that way your payload.findByID example could work to get "ABCDEF".

You could pass your data to the validation endpoint from this fetch if you wanted one workaround option.

Another option is to add a setTimeout() this isn't great because of course you won't really know how long to wait before knowing a transaction has completed and it is ugly. If an error occurs and revalidation occurs it shoudln't be a big deal since the content of the last validation will come up again on the next query after a rollback, so probably fine.

You could disable transactions as another option. If you are using mongoDB you'd do that with transactionOptions: false. Turning this off reduces your overall data integrity so errors that come up in normal operation might leave a bad state of data changes from one request. Not ideal, but still an option.

Ideally we should have a pattern for this that would let you push callbacks after a commit. I want it to have a good DX of course, so I'm open to ideas.

from payload.

felixmokross avatar felixmokross commented on June 16, 2024

I just ran into this too. For me it was quite confusing tbh, I did not expect the afterChangeHook to run before the changes are actually committed to the DB. After I read the source code, it made sense what was happening and your explanation confirms this.

Similarly to the op, in my use case I want to purge and prime a cache of an external app when the user has saved something in the CMS. The cache priming within the hook didn't work, as the external app would always pull the previous data from the CMS.

I understand that there may be other use cases where it is beneficial to have the transaction commit only after the hook has run. Your described solution with committing the transaction in the hook works for me well. I would appreciate a better API for this though (maybe an afterCommitHook)?

from payload.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.