I'm making an app that plans to monitor slack messages. Using RTM, i'm already monitoring the public channels, but is there a way of monitoring private communication ?
I saw there is Compliance Exports but it's far away of what I want to do as I want to process all messages easily and in real time.
There is a way to monitor all messages both from public and private channel and you don't need to bother with the RTM API.
Use the Events Api and subscribe your app to following event types:
message.channels for all messages from public channels
message.groups for all messages from private channels
When you subscribe you have two options. Team Event and Bot Events. You want to subscribe to Team Events to get everything and without having to join any channels. You can also subscribe to bot events, but then your bot will only get events for channels he is invited to.
If you don't need to monitor all channels I strongly recommend the second option to increase transparency for users and to avoid unnecessary traffic on your server. There also is a upper limit on how many events Slack will send you (max 5.000 per hour). So depending on the traffic on your Slack you might miss events if you subscribe to everything.
Note that this is the ultimate spy app that enables you to monitor all communication on your Slack team. Please use this feature responsibly and make sure you don't break any local laws. e.g. in some European countries it is illegal to monitor the communication of an employee without his/her knowledge.
Your app needs to be invited to the private channel in order to monitor it.
Related
Background
I have a monolith Node.js + PostgreSQL app that, besides other things, needs to provide real-time in-app notifications to end users.
It is currently implemented in the following way:
there's a db table notifications which has state (pending/sent), userid (id of the notification receiver), isRead (did a user read the notification), type and body - notification data.
once specific resources get created or specific events occur, a various number of users should receive in-app notifications. When a notification is created, it gets persisted to the db and gets sent to the user using WebSockets. Notifications can also get created by a cron job.
when a user receives N number of notifications of the same type, they get collapsed into one single notification. This is done via db trigger by deleting repeated notifications and inserting a new one.
usually it works fine. But when the number of receivers exceeds several thousands, the app lags or other requests get blocked or not all notifications get sent via WebSockets.
Examples of notifications
Article published
A user is awarded with points
A user logged in multiple times but didn't perform some action
One user sends a friend request to another
One user sent a message to another
if a user receives 3+ Article published notifications, they get collapsed into the N articles published notification (N gets updated if new same notifications get received).
What I currently have doesn't seem to work very well. For example, for the Article created event the api endpoint that handles the creation, also handles notifications send-outs (which is maybe not a good approach - it creates ~5-6k notifications and sends them to users via websockets).
Question
How to correctly design such functionality?
Should I stay with a node.js + db approach or add a queuing service? Redis Pub/Sub? RabbitMQ?
We deploy to the k8s cluster, so adding another service is not a problem. More important question - is it really needed in my case?
I would love some general advice or resources to read on this topic.
I've read several articles on messaging/queuing/notifications system design but still don't quite get if this fits my case.
Should the queue store the notifications or should they be in the db? What's the correct way to notify thousands of users in real-time (websockets? SSE?)?
Also, the more I read about queues and message brokers, the more it feels like I'm overcomplicating things and getting more confused.
Consider using the Temporal open source project. It would allow modeling each user lifecycle as a separate program. The Temporal makes the code fully fault tolerant and preserves its full state (including local variables and blocking await calls) across process restarts.
I'm building an application in which we have worked on Payment gateway named flutterwave.
And now the scenario is on every success or failure of a payment, I receive a webhook and then we take further actions such as sending emails, SMS and updating the statuses of the payment in the DB.
For now, we have implemented polling in the client side and for a particular time span if the client receives a status (success or fail) we show it otherwise they can check later it in the payment history page.
Now we want to remove this polling and update users in real time about the success or failure of a payment.
What are the ways by which we can achieve this?
The questions are how we will notify a specific user about the same as we have a multiplatform app and the same user can be logged in different platforms.
What you are looking for is a real-time communication pattern with WebSockets a layer 7 protocol in the OSI model which offers bi-directional communication.
This means that you can establish communication between your servers and your user's browser (client). As a result, you can send notification data to the client and consume and react to the notification, by showing visual cues in your UI for the user to see.
Some examples of implementing WebSockets with Socket.io and Nodejs: https://dev.to/novu/sending-real-time-notifications-with-socketio-in-nodejs-1l5j
There are also paid services that can offer this functionality like Pusher, and I would actually recommend that route at the beginning so you can avoid spending too much time implementing this and focus more on the stuff that matters and is part of your roadmap.
Additionally, you can use Push Notifications as another way to notify your users even when they are not using the app.
I have a load balanced situation, in which I have multiple instances running. I'm subscribing to a channel in each instance, but I only want one of them to trigger when a message comes through.
Is there any way to accomplish this?
If you want to have different subscribers and some are only interested in a subset of the messages distributed by a your publisher. Then your messaging service must allow subscribers to specify the topics relevant for them and/or inspect the messages and specify the content they are interested in.
that kind of goes against pub/sub pattern. Even if you added a streaming application in between you channel and your clients, this will still need to read all messages to decide which one to filter out to different clients
If you mean, for example, Android or IOS notifications, then you are able to store push tokens in your database, filter them and send a message only selected users.
P.S. It could help if you provide more details about the environment of push notifications you ask, and an architecture of the application you develop.
So i currently have a chat system running NodeJS that passes messages via rabbit and each connected user has their own unique queue that subscribed and only listening to messages (for only them). The backend can also use this chat pipeline to communicate other system messages like notifications/friend requests and other user event driven information.
Currently the backend would have to loop and publish each message 1 by 1 per user even if the payload of the message is the same for let's say 1000 users. I would like to get away from that and be able to send the same message to multiple different users but not EVERY user who's connected.
(example : notifying certain users their friend has come online).
I considered implementing a rabbit queue system where all messages are pooled into the same queue and instead of rabbit sending all user queues node takes these messages and emit's the message to the appropriate user via socket connections (to whoever is online).
Proposed - infrastructure
This way the backend does not need to loop for 100s and 1000s of users and can send a single payload containing all users this message should go to. I do plan to cluster the nodejs servers together.
I was also wondering since ive never done this in a production environment, will i need to track each socketID.
Potential pitfalls i've identified so far:
slower since 1000s of messages can pile up in a single queue.
manually storing socket IDs to manually trasmit to users.
offloading routing to NodeJS instead of RabbitMQ
Has anyone done anything like this before? If so, what are your recommendations. Is it better to scale with user unique queues, or pool all grouped messages for all users into smaller (but larger pools) of queues.
as a general rule, queue-per-user is an anti-pattern. there are some valid uses of this, but i've never seen it be a good idea for a chat app (in spite of all the demos that use this example)
RabbitMQ can be a great tool for facilitating the delivery of messages between systems, but it shouldn't be used to push messages to users.
I considered implementing a rabbit queue system where all messages are pooled into the same queue and instead of rabbit sending all user queues node takes these messages and emit's the message to the appropriate user via socket connections (to whoever is online).
this is heading down the right direction, but you have to remember that RabbitMQ is not a database (see previous link, again).
you can't randomly seek specific messages that are sitting in the queue and then leave them there. they are first in, first out.
in a chat app, i would have rabbitmq handling the message delivery between your systems, but not involved in delivery to the user.
your thoughts on using web sockets are going to be the direction you want to head for this. either that, or Server Sent Events.
if you need persistence of messages (history, search, last-viewed location, etc) then use a database for that. keep a timestamp or other marker of where the user left off, and push messages to them starting at that spot.
you're concerns about tracking sockets for the users are definitely something to think about.
if you have multiple instances of your node server running sockets with different users connected, you'll need a way to know which users are connected to which node server.
this may be a good use case for rabbitmq - but not in a queue-per-user manner. rather, in a binding-per-user. you could have each node server create a queue to receive messages from the exchange where messages are published. the node server would then create a binding between the exchange and queue based on the user id that is logged in to that particular node server
this could lead to an overwhelming number of bindings in rmq, though.
you may need a more intelligent method of tracking which server has which users connected, or just ignore that entirely and broadcast every message to every node server. in that case, each server would publish an event through the websocket based on the who the message should be delivered to.
if you're using a smart enough websocket library, it will only send the message to the people that need it. socket.io did this, i know, and i'm sure other websocket libraries are smart like this, as well.
...
I probably haven't given you a concrete answer to your situation, and I'm sure you have a lot more context to consider. hopefully this will get you down the right path, though.
I have 40 categories and each category has 10-100 subcategories. By default, the user listens to all categories and subcategories. I want to give each user the ablity to select to unbind from the whole category or from a specific subcategory. So, right now what I have is each category is a channel, and each subcategory is a event.
Now, I have something like each user is bound to 2000-3000 events, and I know this is wrong, so what is the right way to let the user to filter between 3000 events? Is it okay to bind to that many events?
It's important to remember that when you subscribe to a channel all events for the channel will be sent to the client (Pusher - clients), even if you have not bound to the event.
With the information above in mind, I'd recommend using channels to filter data. The overhead when subscribing to a channels isn't great. For example, subscribing to 40 channels wouldn't represent any significant resource usage. You will need to consider if the channels are public (anybody can subscribe) or private where each call to pusher.subscribe( 'private-channel-x' ); will result in an authentication request to your server. There is a multi-auth plugin that allows batching of authentication requests to take place.
One solution is to have each user subscribe to their own notification channel and send them events for the things that they are interested in on that single channel. You can use the multi publish functionality for this, which lets you send the same event on many channels. This may be useful if you wish to send the same event to multiple users. However, this solution may not be as elegant from an information architecture point of view.
The best solution here really depends on your application. But with the above you now have all the facts which will let you make the most efficient choice.