How to use the result of a scheduled action?
My mutation schedules an action using
await ctx.scheduler.runAfter(0, ...)
The action returns a value that then is used by the mutation to write to the DB, or that's what I planned
Pseudocode:
But this is not how it works, right? Because the return value of a scheduled action is a promise that resolves to a Id<"_scheduled_functions">
So it looks like I have to schedule the action, and from the action itself run an internal mutation that writes the output of the action to the DB, i.e.:
1. Run public mutation
2. Schedule action
3. Action gets some external data
4. Action runs internal mutation to write to DB
Is that second way the "correct way"?5 Replies
that is correct @saito200
actions -> mutation -> query, but never the other direction (where -> means "can call")
the docs say to avoid calling an action directly from the client, and instead calling a mutation that schedules an action
In my case then it would be:
client -> public mutation -> run query to get a doc -> run scheduled action -> call third party API -> call internal mutation that writes to DB
it honestly feels a bit overcomplicated, I am doing a refactoring where before I simply called an action from the client that did everything
feel free to call the action directly if it simplifies things for you. the only reason to involve a mutation first is for systems later on that want to guarantee at-least-once execution of the action even if the app disconnects
if you don't require anything like this, directly calling the action from the app is fine
we do it in a few of our demo apps: https://github.com/search?q=repo%3Aget-convex%2Fconvex-demos%20useAction&type=code
GitHub
Build software better, together
GitHub is where people build software. More than 100 million people use GitHub to discover, fork, and contribute to over 420 million projects.
expanding for posterity: mutation + schedule will succeed quickly, and then the app can "know" when the mutation returns that the asynchronous process will definitely (eventually) finish. if the app is responsible for directly invoking the action, if the action fails, the app needs to try it again, etc. if the needs of the action are only for the current user in the app, might not matter much. but if the action represents some shared state advancement you want to make sure actually happens with broader interest than whatever user was in the app when it was triggered, you should make the job "owned" by the backend, which is what a mutation + scheduling can accomplish (especially using a helper like https://github.com/JamesCowling/convex-action-retrier )
GitHub
GitHub - JamesCowling/convex-action-retrier: Helper function to ret...
Helper function to retry a Convex action until it succeeds. - GitHub - JamesCowling/convex-action-retrier: Helper function to retry a Convex action until it succeeds.