tRPC, Prisma, Discord Bot and tracking mass messages

Currently rebuilding building an app which is using NextJS (on Vercel), tRPC, Prisma, PlanetScale with a Discord bot all housed in a nice little Turborepo. Now, you can create posts from the web app that get posted to fairly large number of Discord Servers (~700, and growing). When the post gets approved by an admin (in the web app), it updates the post to approved through tRPC, tRPC calls the Discord bots little Express API to tell it to get the approved post and start sending the messages. Then the messages are being sent out to the Discord servers via the bot, which will create an entry in the DB to track the status. This is where I'm unsure, should the bot be creating those entries directly with Prisma initialized on the bot itself, or be going through tRPC on Next/Vercel. I suppose if I'm batch creating all those entries from the Discord Bot, and then making a single call back to tRPC, but again it'll likely be ~700 entries to create and I'm unsure on the efficiencies here, as if there's 10 posts, that's 7K entries just to track which messages have been sent... Or maybe there is a better way to track which messages have been sent?
44 Replies
jdsl
jdsl2y ago
Do you need to store the transaction "receipts" long term? You could use a message queue system instead maybe.
Rhys
Rhys2y ago
Do they need to be sent as bot messages or can they be sent as webhooks? When someone makes a post does it get posted in all servers or just a subset? Instead of storing this data in planetscale also, Redis / Upstash might be a better fit
jdsl
jdsl2y ago
Agreed - redis/upstash is my go-to for this kind of thing. Then have other processes consume out of there on a schedule or event.
Rhys
Rhys2y ago
I feel like what you want is webhooks not a discord bot sending messages for this https://discord.com/developers/docs/resources/webhook
Discord Developer Portal
Discord Developer Portal — API Docs for Bots and Developers
Integrate your service with Discord — whether it's a bot or a game or whatever your wildest imagination can come up with.
Rhys
Rhys2y ago
That’d scale significantly better since I don’t think you’d get rate limited
Froge
Froge2y ago
I was thinking that. The bot can be used to manage the webhooks in that case. Say we do that, the logic is moved from the Discord bot to tRPC hosted on Next/Vercel. They don't need to be long-term receipts, we do need to perform some analytics. Don't really need to store every message receipt. The "trigger" event is that a posting is approved by an admin in the web app. Then we work out which channels (or webhooks) need to receive the messages. Ideally we get all the channels/webhooks, then send to a queue system, however I'm not really sure how to manage that, and how that'd play with upstash/redis. Hmm, doing a bit of research, and thinking something like BullMQ, and Upstash. So post gets approved, creates a job in the queue to register all of the messages that need to be sent about the approved post, registering each message in the queue. Then each message get's sent out from the queue. Can just be a fairly lightweight node server, I'm not sure if you'd be able to do a message queue serverless Doing a bit more research now Maybe QStash with Vercel serverless functions world work? Rather than an entire service for sending/receiving requests? Maaaybe? I don't know if sending 1000 requests to Vercel serverless functions to send a post to each Discord server is efficient?
Rhys
Rhys2y ago
Reading through this I feel like you may be overcomplicating it, just to break down the problem statement again: You need the same post to be sent in 700+ Discord servers once approved by an admin via a vercel dashboard The way these posts are made, whether it be via webhook, discord bot posting, does not matter
Rhys
Rhys2y ago
Any reason you can't just use an announcement channel and crosspost the message letting Discord do all of the work? https://old.discordjs.dev/#/docs/discord.js/main/class/Message?scrollTo=crosspost
Discord.js
Discord.js is a powerful node.js module that allows you to interact with the Discord API very easily. It takes a much more object-oriented approach than most other JS Discord libraries, making your bot's code significantly tidier and easier to comprehend.
Froge
Froge2y ago
Yes, that's correct, it's that simple. It's pretty old school is my understanding, we already have ~700 servers with the bot installed, so the bot needs to do the work as we can't tell the servers to do any additional work or we'll likely lose a bunch. (The bot can create and manage webhooks if we use them), as the people in the Discord server will be managing the subscription to the approved posts. So the post will have categories such as: - Marketing - Design The user will run /watch-category the bot will register that server and channel to receive approved posts of that category. But that's easy enough, no issues there. (That's also why we can't do announcement channels). It's about when the post comes out, how to manage the distribution of the messages into the specific channels.
Sturlen
Sturlen2y ago
I suggest asking around in the discord dev server, they probably have a lot more experience than most when it comes to running this kind of bot
Rhys
Rhys2y ago
From a non technical perspective, it may be worth making the switch now to using Discords' official system as once your bot reaches a certain size they would probably want you to use the official methods Along with that, you can programmatically subscribe to announcements channels same as you would webhooks, so it wouldn't require any extra work from your subscribers https://discord.js.org/#/docs/discord.js/main/class/NewsChannel?scrollTo=addFollower So all you'd need to do is make an announcement channel for each topic, the only constraint then would be you can only follow a max of 9 channels per channel
discord.js
discord.js
discord.js is a powerful Node.js module that allows you to interact with the Discord API very easily. It takes a much more object-oriented approach than most other JS Discord libraries, making your bot's code significantly tidier and easier to comprehend.
Froge
Froge2y ago
Hmm, interesting. I might do some research on that, and come back to you. Forgetting the Discord component just for the moment, is there a way we can translate a single job being approved, then get all of the webhook/or similar and creating the message queue (of 700-100) I'm not sure if that latter part of that is possible on Vercel, as that's a large DB query and then posting that off message queue system may exceed timeouts, etc.
Rhys
Rhys2y ago
At that point, Vercel is not the right fit for what you're trying to do It's similar to where if you have some sort of AI model, you need to run that outside of Vercel and have the functions call into it, or just have the functions hit it directly If I were you I would host this on my Discord bot since I already have the resources allocated for that, as for the message queue part, something like https://upstash.com/blog/qstash-announcement would probably work incase the bot goes offline in the middle of sending the announcements
QStash: Messaging for the Serverless
Designed for the serverless with per-request pricing and Redis®/Kafka® API.
Froge
Froge2y ago
Yeah, I think we'll do that, the bot can handle creating the queue, and then the queue can call Vercel serverless functions to send out the messages to the servers.
Rhys
Rhys2y ago
tbh going from the bot -> vercel may be overkill instead of writing this to a queue, maybe just store in redis something like post-id-channel-id-server-id: true / false, with a time to live of 7 days and dispatch the events from the discord bot, updating those as you go you've already done all the work on the bot to get that data there, no point spinning up extra vercel charges even though they are pretty cheap
Froge
Froge2y ago
Flow could be: 1. Job approved (tRPC from the web app) 2. tRPC would create a message in the QStash queue jobApproved 3. Discord Bot would listen for jobApproved 4. Discord Bot would then go an create the entire message queue sendJobToServer 5. Discord Bot would listen for sendJobToServer and send them out But, it does also seem like the queue might be pointless, like you say above..,. Agree, the Queue/Discord Bot, should send the messages out itself, not from Vercel, as to avoid excess charges, etc As I'm sure as things scale, that could be a lot of calls to the API in a short period of time
post-id-channel-id-server-id: true / false, with a time to live of 7 days and dispatch the events from the discord bot, updating those as you go
How would the bot listen for this? My Redis knowledge is not that extensive
Rhys
Rhys2y ago
This flow seems good, if you use webhooks you'd be able to run all of this in parallel as well
Froge
Froge2y ago
I think webhooks are the way to go tbh I'm asumming node can listen for QStash messages, if not can probably just use MQBull I don't want to expose an endpoint to the Discord bot if I can get away with it
Rhys
Rhys2y ago
Job Dispatch Flow 1. Bot receives dispatch post request 2. Bot creates a list of channels that need to receive the message 3. Bot writes to Redis the following data: postId-channelId: false for all channels that need to receive the message 4. Bot in parallel does the following: a. dispatch webhook notification b. removes the postId-channelId entry from Redis To handle unsent messages: Bot Start Up 1. Fetch all entries from Redis 2. Repeat step 4 If you're adding Upstash I'd just keep it simple and do this all through Upstash, or, just add a basic rest api endpoint onto your bot to hit and skip all of the queue stuff all together as it's overly complex It's fine to have an endpoint exposed on your bot, just add a basic bearer token verification
Froge
Froge2y ago
Ahh, I didn't consider that Upstash would send the webhook itself
Rhys
Rhys2y ago
oh huh yeah you could just do that
Froge
Froge2y ago
That could be tidy
Rhys
Rhys2y ago
yeah do that instead lol thats so much easier only thing to maybe think about with that is error handling, unsure how upstash will handle that
Froge
Froge2y ago
But we still think Vercel isn't the right option for creating the queue
Rhys
Rhys2y ago
eh you could use vercel for it 700 entries isn't that many, all you need to select is IDs as well
Froge
Froge2y ago
It may take longer than serverless executive time out though? Posting all that to Upstash Even if it is done in parallel
Rhys
Rhys2y ago
If it did, you could chunk the request up into N smaller requests and do those in parallel should be fine
Froge
Froge2y ago
Yeah, interesting. Not sure, to be honest
Rhys
Rhys2y ago
You can specify an Upstash-Callback endpoint which returns the status of the request
Rhys
Rhys2y ago
Publish Messages | Upstash: Documentation
Publishing a message is as easy as sending a HTTP request to the /publish
Rhys
Rhys2y ago
im skimming the docs and it doesn't seem like you can add to the queue in bulk which kind of sucks since that'd be 700 requests you need to make
Froge
Froge2y ago
I mean, if the bot sends the webhook (when it receives the request from Upstash), it would just create an entry in the DB for error.
Rhys
Rhys2y ago
Topics | Upstash: Documentation
Sending messages to a single endpoint and not having to worry about retries is
Froge
Froge2y ago
That's also a worry But surely it'd be able to handle receiving those requests as it queue system ahaha Seems straight forward enough
Rhys
Rhys2y ago
New Flow Registering a channel 1. /register [topicName] 2. create a webhook 3. add that webhook to the topics upstash endpoint Queueing an event: 1. tRPC call to publish endpoint from website 2. call upstash topics dispatch easypeasy
Froge
Froge2y ago
Ohhhhh That's big brain Damn, don't have to do anything...
Rhys
Rhys2y ago
The only problem with webhooks is I don’t think you can add components to them, I.e buttons so you can’t have any interactivity with the posts
Froge
Froge2y ago
The bot can listen for the webhooks
Rhys
Rhys2y ago
That’s something you’ll want to look into and make sure you’re comfortable sacrificing if it’s the case
Froge
Froge2y ago
And add the buttons But I can check
Rhys
Rhys2y ago
It’d edit the webhook message to add the buttons?
Froge
Froge2y ago
Something along those lines, I saw something where someone was doing that Just looking at webhook docco Looks like you can
Scot
Scot2y ago
Diagrams help a lot here If you draw up your internet architecture, it can be easier to spot flaws or areas of improvement
Froge
Froge2y ago
I'll draw something up soon
Want results from more Discord servers?
Add your server