Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chat App Discussions #13

Open
matzuk opened this issue Nov 30, 2021 · 8 comments
Open

Chat App Discussions #13

matzuk opened this issue Nov 30, 2021 · 8 comments

Comments

@matzuk
Copy link

matzuk commented Nov 30, 2021

@weeeBox Hi!
Here, there are some points about Chat Design based on my experience.

The main distinguishing feature of any Chat application is a very big number of states inside the App. Use A sent you a message, your message that was sent to a User B is delivered, the status of User C changed, Used D changed the name of Group AA and etc. How it affects the Application.

The first one is Architecture (close to the Presentation layer).
MVC, MVP, MVVM may work at the beginning but these solutions are absolutely non-scalable due to a big number of events and states that may affect each other and the absence of a State handling approach. That's why MVI approach does matter because MVI tries to set rules on how to handle a state. There are different implementations that you can consider as an example. My favorite one now is MVIKotlin.

The second consequence is CQRS and a Single source of True.
Let me show a diagram:
image

  1. All requests are divided into two groups: Commands (change state but doesn't return) and Queries (doesn't change a state but return a state). This separation is visible in MessageFeature. It's CQRS.
  2. All updates are coming from a special object called UpdateChannel. It's a source of queries in terms of CQRS and the single source of True (source of updates). Under the hood, UpdateChannel may subscribe to updates from DB, transform data and deliver it further.
  3. UpdateDispatcher. The responsibility: listening to UpdateChannel in a separate Thread (because the number of events is so big), distributing events to relative handlers (handlers are working in separate ThreadPool to avoid pauses in UpdateChannel thread).
@rakeshh91
Copy link

rakeshh91 commented Nov 30, 2021

@weeeBox Hi. Thanks for all your contribution to this repo.

I would be interested to deep dive into data flow (end to end) and how we can keep data as single source of truth for presentation layer with different use cases:

  1. Send message use case: (if two users are in a chat session and User A sends a message)

    • Do we store the sent message with its status (about delivery) to the DB first and then pass it on to dispatcher to actually send to backend? Or we can do both in parallel? What issues we might see if we do in parallel ?
    • When can we update the UI (Chat pagination list) with this new message (sent message)? Or can we simultaneously update UI as well as DB? Or the list should always come from DB and we should not be adding new message directly to UI?
  2. Receive message use case: either via notification or during active chat session (data flow end to end in this use case as well)

  3. Sent message status when user is on offline mode (sending/failed to deliver/delivered/read).
    Offline mode -> User sends multiple messages -> initially messages will be in sending state -> Once network is available -> Messages gets delivered (if successful)
    How would storing the messages and tracking its status and updating the appropriate status on the UI can be achieved? (Some of the concepts might be covered in the Offline support links that you attached. But, still adding this design in case, if you think anything else we can think of, apart from information provided in those links)

  4. Do we need to update our DB frequently from backend to keep data in sync with Backend? (Asking because users might send messages from different devices - Mobile/Tablet/etc). If yes, When is the best time to refetch data from backend or do we need update in regular intervals?

@weeeBox
Copy link
Owner

weeeBox commented Dec 1, 2021

Send message use case: (if two users are in a chat session and User A sends a message)

The actual implementation depends on the target platform but the idea is simple:

  • Everything goes to the database first: you write a message to the database with a "pending" status.
  • The network client subscribes to an observable stream from the database and waits for new "pending" messages, batches them into a WebSocket frame (or any other protocol), and sends them to the backend.
  • Once the "acknowledge" frame is received - the "pending" messages are marked as "sent".
  • The UI flow observes another stream and updates the message list accordingly.
  • There might be many optimizations on top of this - like calculating the updated diff for UI and only updating a part of UI (there's no need to re-draw the message text if you only need to update a status indicator).

My point - you only update the database and other components "react" to that.

Receive message use case: either via notification or during active chat session (data flow end to end in this use case as well)

Same idea - you receive the message - you write it to the database, UI-component react to the changes.

Sent message status when user is on offline mode (sending/failed to deliver/delivered/read).

You keep adding messages to the database but the network client ignores them while there's no connection. Once the connection is back - the network client send everything in a batch.

Do we need to update our DB frequently from backend to keep data in sync with Backend?

You update messages in 2 different ways:

  • When a data frame is received from the websocket
  • When you load the whole chat with paginated response (can also be replaced with sockets)

You generally don't pull any data on an interval basis - that does scale as the number of the clients go up

@weeeBox
Copy link
Owner

weeeBox commented Dec 1, 2021

@matzuk, I think it could be too much detail for the interview - it's really hard to explain in such a short time. I would start simple and only add details if needed. Nobody expects you to build a robust solution - it's more about the process and communications. If you bring MVx patterns - don't forget non-technical trade-offs: how easy it is to teach junior engineers to use a specific architecture. When you bring a 3rd-party library - you need to have a good understanding of the updates, support, and deprecation. There's always a trade-off - you need to clearly communicate this to the interviewer.

@rakeshh91
Copy link

rakeshh91 commented Dec 9, 2021

@weeeBox , If we come across a feature like Chat Backup to cloud. What are your thoughts on this? Do you see anything else to consider apart from below items?

  • User consent
  • Encryption of data that is backed up (i assume this encryption will be on the entire file)
  • Storing backup file in internal storage (not sure if this is required.. May be to download or copy the backup file manually?)
  • Back up at specified time interval (once a day)
  • Only when WIFI is available, etc (Conditions for backup to happen)

Also, Any use case you can think of, where we use these backed up data in our app apart from just restoring it when user reinstalls the app?

@weeeBox
Copy link
Owner

weeeBox commented Dec 11, 2021

@rakeshh91, this WhatsApp screenshot should answer all your questions 🙂
Screenshot_20211210-191822

@chipbk10
Copy link

Hi @weeeBox

  • the link to WhatsApp Encryption Overview. is dead
  • the sentence: only keep track if the attachment needs to be uploaded or uploaded should be only keep track if the attachment needs to be uploaded or downloaded

@chipbk10
Copy link

probably we can explain what is end-to-end encryption to the readers: Wiki: End-To-End Encryption

@mathiastck
Copy link

Great discussion. I found the complexity goes up greatly if you have to support multiple devices and/or message deletion. Both are possible with xmpp, for example, but hard to add to an app that wasn't designed from the start with both in mind.

https://en.m.wikipedia.org/wiki/XMPP

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants