middleware
Hello, I’ve read the articles on middleware and setting them up with customQuery helper functions. I still have a hard time understanding what the proper way to include 3rd party libs before/after a mutation would be.
1. Before: I know we can just make an action that in turn calls the mutation, but the docs highlight that as an anti pattern so I’m wondering if there’s any gotchas that make this the case.
2. After: scheduling an action with a runAfter(0,…) towards the end of your transaction in the mutation.
Are these the right approaches?
4 Replies
Gotchas for actions:
1. If the websocket connection drops, it's unclear to the client whether it succeeded. For mutations, it can automatically retry them & ensure it eventually goes through.
2. If a server dies or is restarted when an action is running and it doesn't have time to finish, then the action could fail mid-way. A mutation is transactional - all or nothing, and will get retried on another server safely.
You can mitigate these by calling a mutation that uses the action retrier https://stack.convex.dev/retry-actions
You can mitigate these by calling a mutation that uses the action retrier https://stack.convex.dev/retry-actions
Stack
Automatically Retry Actions
Learn how to automatically retry actions in Convex while also learning a little about scheduling, system tables, and function references.
Both of your approaches are acceptable at the end of the day, depending what your usecase is. If you want to commit that something is in progress before kicking off the action (to prevent races, e.g.), you call a mutation which can schedule an action. That action can then "finish up" and commit any result by calling a mutation directly at the end, if it needs to.
Out of curiosity, what is the 3rd party library you're calling?
Thinking of cases where I need to call 3rd party services like authentication/authorization/logging
Gotcha. Yeah most people will have authorization logic depend on data in the database vs external service, and do auth so the convex web socket has auth set (eg with the Clerk auth provider) which is directly accessible via ctx.auth. For logging you can get pretty far with just console.log and setting up a log stream to DataDog or Axiom.
We’ve tried to make it as easy as possible to just stay within a deterministic transaction to avoid the nondeterministic behavior you can get when making third-party requests. You will likely still need to call third-party for a variety of things, but hopefully those are the exceptions rather than on every mutation call.