Chad Maycumber
Chad Maycumber14mo ago

Help with an edge case

I currently have an action which calls other mutations. In this scenario; we're trying to create an AI chat. I'm running into a scenario where the users message is created inside of the chat action before the AI's chat message. On the first chat the frontend doesn't update until the action fully completes leading the frontend to update with the user message, and AI chat at the same time. After the first message subsequent chats work as expected where the users message is created, updated on the frontend and then the AI chat message is updated and streamed in. Any help with understanding what I might be doing wrong would be great!
13 Replies
ballingt
ballingt14mo ago
How is the user's message created, is this an action with two mutations in it? Ideally the UI is driven by a query that reads from tables that are modified at least twice during the action: first for the user's message, second for the AI message. (or if it's a streaming AI chat response, maybe dozens of times for the AI message)
ian
ian14mo ago
One thing you might be seeing is that the logs from the Action don't print until the action fully succeeds. However, the data in the DB will be readable once the runMutation has completed. If you have a query looking for the message when the action runs (could be run from the dashboard or CLI), it should show up ~instantly
Chad Maycumber
Chad MaycumberOP14mo ago
Hey just saw this now! It does have two mutations!
ian
ian14mo ago
Could you share the chunk of action code where you see this?
Chad Maycumber
Chad MaycumberOP14mo ago
Here's the bulk of the start of the action w/ the 2 mutations! I read recently I shouldn't be calling actions from the frontend whenever possible so I may need to re-factor things a bit!
Chad Maycumber
Chad MaycumberOP14mo ago
No description
ian
ian14mo ago
Does it return the chat ID at the end of the action? My guess is the frontend doesn't know what to query for until the action returns the first time
Chad Maycumber
Chad MaycumberOP14mo ago
Ahh that would make sense It does currently
ian
ian14mo ago
if the first mutation makes the chat and returns it, and kicks off the action to make the new message and update the chat you should be all set "kicks off" with ctx.scheduler.runAfter(0, ...
Chad Maycumber
Chad MaycumberOP14mo ago
Okay cool I figured. I reread the "zen of convex" and noticed I wasn't technically following the paradigm correctly
ian
ian14mo ago
Though it's a bit annoying that it can't make the first message until the embedding is created, so the first mutation would just be creating the chatId I guess
Chad Maycumber
Chad MaycumberOP14mo ago
Hmm that's true. Not the biggest deal I can create the embedding slightly later and update
ian
ian14mo ago
I would personally store embeddings in their own table and have message have an embeddingId on them, so you can query for messages from a vector search (by adding an index on embeddingId), but never have to read the embedding value in DB fetches. Pattern covered here: https://docs.convex.dev/vector-search#advanced-patterns
Vector Search | Convex Developer Hub
Run vector search queries on embeddings

Did you find this page helpful?