January 5, 2023

Facebook Live: System Design

author: Michael Filipenko
email: [email protected]

Introduction

Here, I put more emphasis on the design of the client (frontend).

Content

  • Component
  • Structure
  • Details
  • Data flow
  • API
  • Code

Component

I skip the rest of app to talk only about the "stream" part. At a glance, I can split the application into several subsystems when we are already at someone's stream. Of course the entire app is more complex with more details, but I will speak further about only one component, so I think I can not mention them.

The root has 5 systems:

  • Video stream — obviously, it is about all video and sound streams that user watches
  • Social actions — any user action with streamer for expression his emotions
  • Account interactions — it can be subscribe or report or some other account/personal stuff
  • Stream information — literally the data of amount of subscribers or viewers, or how much time passed from start, or anything else
  • Widgets — it can be some unusual stuff supporting by app natively, for example streamer's advertising or special donates alerts, or links, etc.

I personally was interested how to realize comments section in "social actions". So I choose to explain how we can make the component/system of Chat/Comments/Toasts.

Structure

Lets imagine that we haven't realized comments section yet and we have some freedom to think how it can be looks.

I love to make minimalistic things, build something from scratch with minimum details to create simple easy understandable mechanic/concept/design which we can scale and develop further.

Also, the user needs the greatest immersion in what he is watching without losing interactivity. I mean we need to figure out how to show actual live comments, while taking care of the free space on the screen.

We have there some options:

  1. Show the comment button at the corner somewhere. When the user clicks on this button he sees the last comments and can chats too. But he doesn't see any people opinions when chat is closed.
  2. Show all messages over the video at some side. But its not comfortable to see this video because of mess on screen.
  3. And the last point is creating separate subsystems where we show some slice of limited comments by length or by time over the video at the corner somewhere and also when user clicks or scrolls on it he sees the fullscreen chat with all messages.

I pick the last one, because it more flexible to setting up and it improves user's experience.

How it works:

  • Comments - system that manage the messages/comments by users at stream. Exists separately from view (data flow will be further).
  • Chat - sidebar or fullscreen view with all messages and also provides interface to type new own message. It can also have flexible settings for different roles at stream (such as moderators, admins, viewers, etc.)
  • Toasts - simple short list of few the last comments that disappear after some time

Details

Okay, we made a choice. So, the task sounds simple — just draw the list of comments and provide interactivity to create new messages. But there are some pitfalls.

For all developers are obviously that RAM is not endlessly. Furthermore, often user has low-end smartphone with small ram. Then we need to figure out how to store not so many comments at a time.

We use socket connection with comments room, where we are getting new comments and storing somewhere at project outside the view. By long time, this list will be large and app will crash. Also, we need to toggle view of full list and short toasts list, so what we have there and what we can do:

  • get 10 comments (for example) in stream
  • post to server the oldest comment's id to get further new comments slice
  • show every new comment as a toast with expiring time
  • when user wants to open chat, he will see the last 10 comments quickly right now and app starts loading new older comments
  • when he scrolls the chat, we load new and new, but it can be also large by time, so we can make this list virtualized.

With this conditions we don't loose the RAM and can make efficient interface.

Also we have some options how to realize presentation layer:

№1 - Toasts and Chat

Separate subsystems, where we use common comments list from store, but they are works independent of each other.

I render it here side by side, but in real app clicking/scrolling the left list should toggle visibility of right list.

So, left list is the toasts, simple "stupid" presenter that renders the newest comment and hide it when its time expires.

Right list is the "chat" without the input in my example.

The main idea here is to separate comments by 2 independent subsystems, where we use any toast service to show shortly the last messages and high-load chat view.

But it has some issues with it, because we working with the same data but in different ways. So we need to keep different information in one domain for different views. For example, we need "expireAt" for toast and it is useless for chat. Also count of comment's likes is useless for toast. It can be ok if we use additional tools to map/decrease comments sizes, or we have complex functionality for chat.

№2 - Only Chat

For shorty list set small height of chat list without input and for chat just increase the height, add background color and show text input.

It is really simpler realization and if we no need complex chat functionality, just get and send messages so it would be the greatest choice to develop.

It will be looks almost the same if make blur transparent borders on shorty list.

Data flow

Legend:

  • blue arrow - http/socket messages
  • black arrow - local messages

At the first view looks like we no need a store and work only with service (local state). But it can be helpful in further development while working with chat different view and actions.

API

Here we are have 4 requests:

  1. Connect to socket room
    request { roomId }
  2. Get older messages by the oldest store comment's id
    request: { amount, lastId, roomId }

Messages from backend to client via socket

  1. Get new message from room
    response { id, author, timestamp, message }

Messages from client to backend via socket

  1. Send new message to room
    request { message }

Code

I introduce the first variant (toast and chat) in code to have better explanation what I talked above.

https://codesandbox.io/s/toast-chat-implmentaion-drxwz0?file=/src/toaster.jsx

There are Toaster class that provides interface to working with disappearing toasts, CommentsConnection to mock asynchronously getting comments data, Chat for taking last 10 comments and main wrapper for Comments, ToasterView, Toast which are just view presenters.

Summary of comments

Here I described some variants and opportunities how we can make a task with this entire section. It was superficial enough to highlight key points in the design process. Of course at real task needs more conversations with team (back-end at least) to configure more flexible and detailed interface with project components structure, bottleneck moments and other.