Trigger an action from a query?
@punn
Is there a way to listen to changes in a specific table and trigger an action based on those changes?
7 Replies
Hey there! Currently we don't have an explicit trigger mechanism. Some things you can do:
1. Have a client subscribe to a query and call an action when the query updates.
2. Explicitly schedule an action from inside a mutation using the scheduler, if certain conditions are met.
We have talked about building a trigger mechanism to run a mutation / action based on a query, but haven't prioritized it yet. Would be interested in your usecase
Ah got it thanks for the reply!
We're building a multi-user chat app and automating replies. So we 'd like to subscribe to new chat events and trigger our automated reply pipeline!
Do you think 1 would be better for this then? since 2 would require the scheduling to be quite granular
It depends what sort of automating replies you have in mind. I made a chatGPT clone, where for every message, I scheduled an action to talk to OpenAI and reply with a message. So that would be (2). However, if each user would be prompted with auto-replies, then each user could be subscribing to the list of messages and kicking off an action to create their auto-reply options. does that make sense?
You can pass parameters to the scheduled function to be specific to the user. Say more about what you mean by "granular"?
right yea that makes sense. I think in your clone the OpenAI is triggered by your message correct?
In our case we're acting as the "hub" and users are "nodes" and we generate automated replies to each user as messages arrive. If I'm understanding correctly, we'd want to listen to the table storing messages (using something like useQuery(userId) for each user), and call the action whenever that happens. How would (or could) we do this server side?
For the scheduling function, since we want to kick off the automated reply process right away, we'd have to schedule the function to execute every few seconds to check for any new messages, so the time delay is more granular than what I'm expecting other use cases for the scheduled functions to be.
If for every message you want to do some action, I'd suggest not doing (1) and instead doing one of these:
A: Every message comes in as a mutation and does a
scheduler.runAfter(0, "generateReply", {body, messageId: messageToUpdate})
where the generateReply
action does something to make an automated reply to the body
(e.,g. calling ChatGPT API), then sending a reply by updating the messageId
. The runAfter(0
means it'll execute right after the mutation commits to the DB. This is discussed in the "Starting a job without waiting for it" section of this post: https://stack.convex.dev/background-job-management
B: Every message comes in as an action (via useAction
on the client) and does three things: 1. calls an internalMutation
to send the user's message. 2. generates the reply. 3. updates the message to be sent. This is the approach in my chatgpt code here: https://github.com/ianmacartney/convex-chat-gpt/blob/main/convex/actions/openai.js#L35Background Job Management
Implement asynchronous job patterns using a table to track progress. Fire-and-forget, cancelation, timeouts, and more.
GitHub
convex-chat-gpt/openai.js at main · ianmacartney/convex-chat-gpt
Chat GPT interface using Convex as the backend. Contribute to ianmacartney/convex-chat-gpt development by creating an account on GitHub.
I think the term "scheduler" is confusing things here, since we aren't running these actions "on a schedule" (you can do that with our "cron jobs") - but rather kicking off an action to run immediately or in some defined amount of time in the future. It can support scheduling a job for every message that comes in, and so your use case isn't too granular for that flow.
Ahh got it that makes sense. I think A seems like a good approach for us right now and will definitely look into using the conditionally triggered cron jobs too.
thanks for the help