WTF is Grpc? Part 3: Real time Chat ft. Flutter and Golang
Tags: flutter, go, grpc, tutorial
Published: 2023-10-27 18:30:00

Welcome back, dear readers, to the world of "Wtf is gRPC?" – where we turn tech into a comedy show! 🚀

In Part 3, we're diving into real-time chat with the grace of caffeine-fueled squirrels and the humor of rubber chickens at a stand-up gig!

Get ready to leave slow chats in the dust and make your app as snappy as a squirrel on roller skates. Grab your code editor, sense of humor, and let's chat it up in style. Part 3 is gonna be chat-tastic! 🍰💬😄

![grpc-socket-meme](https://i.imgflip.com/841302.jpg)

## Table of Contents: Part 3 - Real-Time Chat Extravaganza 🎉
- [Introduction to gRPC Bi-directional: The Magic of Two-Way Chats](#introduction-to-grpc-bi-directional-the-magic-of-two-way-chats)
- [Setup Your Server: Where the Real-Time Chat Spells Begin](#setup-your-server-where-the-real-time-chat-spells-begin)
- [Start with Flutter Application: Embark on Your Chatting Adventure](#start-with-flutter-application-embark-on-your-chatting-adventure)
- [Outputs: The Hilarious Messages of Success](#outputs-the-hilarious-messages-of-success)


## Introduction to gRPC Bi-directional: The Magic of Two-Way Chats
As we've journeyed through gRPC, we first delved into unary communication, which is essentially one-way communication from the client to the server. Then, we ventured into the world of server-side streaming.

Now, let's dive into gRPC Bi-directional communication. This is where things get really interesting! In Bi-directional streaming RPC, both the client and server engage in a lively conversation by sending a continuous stream of messages back and forth.

Here's how it works:

- The client initiates the action by setting up an HTTP stream with some initial header frames.
- Once this connection is established, both the client and the server can send messages simultaneously, without waiting for the other party to finish. It's like a dynamic chat where no one has to take turns.

> Think of gRPC as the superhero chat line. It's like Tony's suit and Bruce's lab assistant, J.A.R.V.I.S., having a direct line to each other.

##Socket vs. gRPC Bi-directional: A Cinematic Showdown" 🍿🎥

| Aspect                 | Socket                             | gRPC Bi-directional    | Top-Rated Movie Comparison     |
|------------------------|-----------------------------------|------------------------|-------------------------------|
| Setup Complexity       | Generally low, traditional sockets require less setup | Requires setting up gRPC services and protocols, which can be more complex | Like the simplicity of "The Shawshank Redemption" |
| Communication Type    | Low-level and can be used for any data format | High-level, designed for structured data transmission | Similar to the plot intricacies of "The Godfather" |
| Performance            | Can be efficient for simple data exchange | Optimized for high-performance, especially in microservices | Like the action-packed "Mad Max: Fury Road" |
| Bi-directional        | Possible with added complexity and custom handling | Inherently supports efficient bi-directional communication | Much like "Pulp Fiction's" non-linear storytelling |
| Error Handling        | Requires custom error handling | Provides built-in status codes and error handling | Comparable to the suspense in "The Silence of the Lambs" |
| Cross-Language        | Supports multiple programming languages | Multi-language support with protocol buffers | Like the multilingual charm of "Inglourious Basterds" |
| Integration Ease      | Requires more manual integration | Easier integration into gRPC-compatible systems | Much like the seamless blend in "The Dark Knight" |



![grpc bi-directional](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qrzoy09jps5uy9uh1fo4.png)

## Setup Your Server: Where the Real-Time Chat Spells Begin

- Let's continue code from part 2,where we left.

```
git clone git@github.com:Djsmk123/Wtf-is-grpc.git
```

- Switch to part-2 branch(for starter code)
```
git switch part2
```
- As we are going to create Chat one to one service for that we required to get all the users and then communicate.

- Create profobuf for getting users(`rpc_users.proto`)

{% gist https://gist.github.com/Djsmk123/21dd3a32b04471faf30e18960015eb63 %}

- Add `GetUsers` rpc service in `GRPCServerService`

```
// add this line to import
import "rpc_users.proto";

service GrpcServerService {
// add this line too
    rpc GetUsers(UsersListRequest) returns (ListUserMessage) {};
}
```

- Generate equivalent code for server(`Golang`)

```
protoc --proto_path=proto --go_out=pb --go_opt=paths=source_relative \
    --go-grpc_out=pb --go-grpc_opt=paths=source_relative \
    proto/*.proto
```

- Add function in `auth` package `get_users.go`


{% gist https://gist.github.com/Djsmk123/93edc7e6e9497d93c8a8870a13dabc9d %}

- Let's call this function in grpc-server interface(package `gapi`) and add this function in `auth.go`.

{% gist https://gist.github.com/Djsmk123/e9ff34c9ee4ee21b04a5d1f87418d504 %}

- We are done with this. But we required users so that we can send message so don't, I am providing list of users (around 35), just load them into `mongodb`.

[users-data.json](https://gist.github.com/Djsmk123/30e0b95258206911055c03f0f481c624)

> Note: Password for each user is `12345678`.

## Setting Up Your Chat Service:
Establishing a chat service is a straightforward procedure.
- **RPC Service Creation** : Creating an RPC (Remote Procedure Call) service is at the core of this setup.
- **Bidirectional Message Stream**: Implement a bidirectional stream of messages.Messages are initiated by the client and sent to the server.
- **Bidirectional Response Stream**: Create a bidirectional stream for responses.Responses are generated by the server and sent back to the client.
- **Acknowledgment Mechanism**: Before actual communication begins, an acknowledgment mechanism is necessary to connect both the client and the server.This mechanism helps ensure a successful connection.
- **Database Handling**: Notably, the acknowledgment message is designed to be transient and is not stored in the database.
- **Confirmation of Connection**: The acknowledgment message serves as a confirmation of a successful connection.

- **Setting up `protos`**: Setup proto for Sending message and get messages

{% gist https://gist.github.com/Djsmk123/85e2265146b0670d697b833a2f3ac68c %}

- Add these `rpc` function into service

```
service GrpcServerService {
//add these lines
    rpc SendMessage(stream SendMessageRequest) returns (stream Message){};
    rpc GetAllMessage(GetAllMessagesRequest) returns (GetAllMessagesResponse){};
}
```
- Generate equivalent code

```
protoc --proto_path=proto --go_out=pb --go_opt=paths=source_relative \
    --go-grpc_out=pb --go-grpc_opt=paths=source_relative \
    proto/*.proto
```

- We need JWT-based authentication for both receiving and sending messages. While there are two types of interceptors available, namely `unary interceptors` and `stream interceptors`, we currently utilize the `unary interceptor` as our middleware and lets add middleware for stream service too.

![user-auth](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uze08vugtzoi7h5mkqw2.jpg)

- update `middleware.go` in `gapi` package.

{% gist https://gist.github.com/Djsmk123/9f56db49d212730cebd5789ca1e5a17f %}

- Register middleware in `main.go`

```
//update this line
grpcServer := grpc.NewServer(
		grpc.UnaryInterceptor(server.UnaryAuthInterceptor),
		grpc.StreamInterceptor(server.StreamAuthInterceptor),
	)
```

- Now create `Message` Object for `mongodb` collection

{% gist https://gist.github.com/Djsmk123/933b819d07f0cd6c3f18647aa970d2cf %}
- Update MongoCollection 

```
type MongoCollections struct {
	Users *mongo.Collection
	Chats *mongo.Collection
}
```

- Before going to into complex part to listen message and store them into db, lets deal with simple rpc function `GetAllMessage` from db and `SendMessage` to store the message.

{% gist https://gist.github.com/Djsmk123/63d50fbd609a27c305289736d086db85 %}

- Now we are going to use go-routine to listen and send message to the client

> We are using `goroutines` and channels to listen for changes in the database. If you want to learn more about `goroutines`, you can read this [blog](https://betterprogramming.pub/golang-how-to-implement-concurrency-with-goroutines-channels-2b78b8077984)


- Let's Define `SendMessage` and `GetAllMesasge` for grpc server interface.

{% gist https://gist.github.com/Djsmk123/2a67f0ccb6b75ab183b756ce7f3a2bf0 %}

> Note: To make connection b/w two users, its required to send first message `Join_room` so that other user can get acknowledgment.

## Testing gRPC in CLI

![grpc-testing](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g5sodv01i5kry8xruqru.png)


## Start with Flutter Application: Embark on Your Chatting Adventure

- Add following dependency into your project:

```
flutter pub add intl
```


- Generate equivalent code for dart from `protos`.

```
protoc --proto_path=proto --dart_out=grpc:lib/pb proto/*.proto
```

- As it is known issue dart does not generate code `google/protobuf/timestamp.pb.dart`,[read here](https://github.com/google/protobuf.dart/issues/483). So download this file [google_timestamp.pb.dart](https://gist.github.com/Djsmk123/83025e60cbf2c5a931ffefdf2b3a5b7e) and update the generated code as required(just change import path)

- Before starting chat service we need to display all the users into home screen so that we can send message to other users

> PS: I am not going to talk about basic UI building for showing the list of users.

- Add function to get all users in `AuthService` class

```
class AuthServices{
//keep same, add this function
  static Future<List<UserModel>> getUsers(
      {int pageNumber = 1, String? search}) async {
    final res = await GrpcService.client.getUsers(
        UsersListRequest(pageSize: 10, pageNumber: pageNumber, name: search),
        options: CallOptions(metadata: {'authorization': 'bearer $authToken'}));
    return res.users.map((e) => UserModel(e.id, e.username, e.name)).toList();
  }
}
```
- Call this function in `HomeScreen()`,for reference use [this ui](https://gist.github.com/Djsmk123/3c39818c3a00c0b01ad8eadb36486102) or create your own.

- Let's Create chat service to get messages(History)

```
class ChatService {
  static Future<List<Message>> getMessages(String username) async {
    final res = await GrpcService.client.getAllMessage(
        GetAllMessagesRequest(
          reciever: username,
        ),
        options: CallOptions(
            metadata: {'authorization': 'bearer ${AuthService.authToken}'}));
    return res.messages;
  }
}

```

- Let's listen for messages,send message and fetch history.

{% gist https://gist.github.com/Djsmk123/6268f6d6becb42735ab0714d9ec039a4 %}

> Note: UI component maybe missing or you create your own. for reference check [source code](https://github.com/Djsmk123/Wtf-is-grpc/tree/part3/)

- Let's talk about what we did in above class.
   - In `initState()` we are starting to listen message by sending first message `Join_room` to make connection and another function `fetchChatsHistory()` as name suggested, getting earlier messages by calling `grpc` unary service.
   - on sending message we are adding message data to stream-controller to send stream of message to the server.

## Outputs: The Hilarious Messages of Success


{% youtube 93dg_-RDV_k %}

## End of the series 

Thank you to everyone who has supported me throughout this series. I promise to be more consistent next time. The blog series titled **'Wtf is gRPC?'** comes to an end with this post. In Part 1, we delved into authentication and authorization using unary gRPC communication. In Part 2, we had some fun creating a custom notification service in Flutter, along with server-side streaming gRPC. And now, in the grand finale, Part 3, we explored bi-directional gRPC to create a simple real-time chat application. Thanks again, and remember, gRPC isn't as mysterious as it sounds – it's just a protocol! Stay tuned for more tech adventures!

## Thank for 2k+ Followers on [dev.to](https://dev.to/djsmk123)
![Thanks You](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xzu9oxyp01vxxe8zz9le.jpg)

![flutter meme](https://miro.medium.com/v2/resize:fit:500/1*5XI0lRiqhaB0dKqCy3TD7Q.jpeg)
## Source code : 
[Github Repo](https://github.com/Djsmk123/wtf-is-grpc/tree/part3)



## Follow me on 

- [Twitter](https://twitter.com/smk_winner)

- [Instagram](https://www.instagram.com/smkwinner/)

- [Github](https://www.github.com/djsmk123)

- [linkedin](https://www.linkedin.com/in/md-mobin-bb928820b/)

- [dev.to](https://dev.to/djsmk123)

- [Medium](https://medium.com/@djsmk123)