#calling an action from an action
1 messages · Page 1 of 1 (latest)
Hi @rich beacon. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
In Convex, you can call an action from another action using the ctx.scheduler.runAfter method. This method schedules an action to execute after a certain delay. Here's an example:
import { v } from "convex/values";
import { internal } from "./_generated/api";
import { internalAction, mutation } from "./_generated/server";
export const actionThatSchedulesAnotherAction = internalAction({
args: { text: v.string() },
handler: async (ctx, { text }) => {
await ctx.scheduler.runAfter(0, internal.myFunctions.anotherAction, {
text,
});
},
});
export const anotherAction = internalAction({
args: { text: v.string() },
handler: (_, args): void => {
// do something with `text`, like call an API
// then run another mutation to store the result
},
});
In this example, actionThatSchedulesAnotherAction schedules anotherAction to run immediately after it completes. The 0 in ctx.scheduler.runAfter(0, ...) specifies the delay before the next action is run, in this case, it's set to 0 to run immediately.
Please note that this is a simplified example and you might need to adjust it according to your specific use case.
Source: Stack > Using Pinecone and Embeddings > Adding data to Convex and Pinecone > Kick off a background action (https://stack.convex.dev/pinecone-and-embeddings#kick-off-a-background-action)
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@rich beacon kapa.ai is still learning and improving, please let us know how it did by reacting below
if I put an await on the xtx.scheduler thing I get "{ jobId: 'kc211bnmzpgax89d4brdmm76c56v7b9t' }" and not what I really want (the result of the action, awaited). How to do? @candid egret
Let me check the knowledge base for you. One moment! :books:
The ctx.scheduler.runAfter function returns a promise that resolves to the ID of the scheduled function, not the result of the function itself. This is because the function is scheduled to run asynchronously, and its result may not be immediately available.
If you want to use the result of the scheduled function, you would typically have the scheduled function itself trigger another mutation to store its result in the database. Then, you can retrieve the result from the database in your original function or elsewhere in your application.
Here's a simplified example:
export const myMutation = mutation({
handler: async (ctx) => {
const jobId = await ctx.scheduler.runAfter(0, internal.myFunctions.myAction);
// The job ID can be used to check the status of the scheduled function
// But it does not contain the result of the function
}
});
export const myAction = internalAction({
handler: async (ctx) => {
const result = ... // Get some result
await ctx.db.insert('myTable', { result }); // Store the result in the database
}
});
In this example, myAction gets some result and stores it in the database. myMutation schedules myAction to run, but it does not directly receive the result of myAction. Instead, it gets a job ID that can be used to check the status of the scheduled function.
Sources:
- Discord support thread: How to use the result of a scheduled action? (https://discord.com/channels/1019350475847499849/1202467257561776180)
- Stack > Automatically Retry Actions > How it works > Execute action (https://stack.convex.dev/retry-actions#execute-action)
- Stack > Automatically Retry Actions > How it works > Check job status (https://stack.convex.dev/retry-actions#check-job-status)
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@rich beacon kapa.ai is still learning and improving, please let us know how it did by reacting below
@candid egret give an example using ctx.runAction, not using the scheduler
Let me check the knowledge base for you. One moment! :books:
Sure, you can use ctx.runAction to call an action from another action. Here's an example:
import { v } from "convex/values";
import { internal } from "./_generated/api";
import { internalAction } from "./_generated/server";
export const actionThatCallsAnotherAction = internalAction({
args: { text: v.string() },
handler: async (ctx, { text }) => {
const result = await ctx.runAction(internal.myFunctions.anotherAction, { text });
// do something with the result
},
});
export const anotherAction = internalAction({
args: { text: v.string() },
handler: async (_, { text }) => {
// do something with `text`, like call an API
// return the result
return "result";
},
});
In this example, actionThatCallsAnotherAction calls anotherAction using ctx.runAction. The result of anotherAction is awaited and stored in the result variable.
Please note that this is a simplified example and you might need to adjust it according to your specific use case.
Source: Api > Interfaces > Interface: GenericActionCtx<DataModel> > Methods > runAction (https://docs.convex.dev/api/interfaces/server.GenericActionCtx#runaction)
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@velvet whale kapa.ai is still learning and improving, please let us know how it did by reacting below
Note there's only one main reason to use ctx.runAction: to switch between the node runtime and the default convex runtime (there are other small reasons like it runs argument validation). In most cases like in the example kapa gave you should just call the function with plain javascript/typescript.
what happens if a user triggers a scheduled action from the client which then calls other actions via ctx.runAction AND the user closes the client (say that he closes the browser)? Will everything stop?
Actions run from the client (or with runAction from such an action) can be canceled when the client disconnects (but they might not). But once it's a scheduled action, it doesn't matter whether the client stays connected