saito200
saito20011mo ago

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:
myMutation = mutation({
handler: async (ctx) => {
const res = await ctx.scheduler.runAfter(0, ..run action..)
// write res to DB
}
})
myMutation = mutation({
handler: async (ctx) => {
const res = await ctx.scheduler.runAfter(0, ..run action..)
// write res to DB
}
})
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
jamwt
jamwt11mo ago
that is correct @saito200 actions -> mutation -> query, but never the other direction (where -> means "can call")
saito200
saito200OP11mo ago
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
jamwt
jamwt11mo ago
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
jamwt
jamwt11mo ago
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.
From An unknown user
From An unknown user
From An unknown user
jamwt
jamwt11mo ago
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.

Did you find this page helpful?