How to use gRPC with Rust Tonic and Postgres database with examples
Tags: rust, postgres, tutorial, beginners
Published: 2021-05-13 11:45:32

<!--
    Post{
        subtitle: "Learn how to use Tonic to use gRPC in Rust with CRUD examples"
        image: "posts/web/tonic.png",
        image_decription: "Image from the official website",
        tags: "gRPC Tonic Rust How",
    }
-->

<!-- Link -->

[Steadylearner]: https://www.steadylearner.com
[Rust Website]: https://www.rust-lang.org/

[Rust Rocket]: https://rocket.rs/
[Rocket Getting Started]: https://rocket.rs/v0.4/guide/getting-started
[Rocket JSON Example]: https://github.com/SergioBenitez/Rocket/tree/master/examples/json
[Redirect]: https://api.rocket.rs/v0.4/rocket/response/struct.Redirect.html
[Tera]: https://tera.netlify.com/
[Rocket Tera example]: https://github.com/SergioBenitez/Rocket/tree/master/examples/tera_templates

[CORS]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
[OPTIONS]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS
[Rocket CORS]: https://github.com/lawliet89/rocket_cors
[Rocket CORS examples]: https://github.com/lawliet89/rocket_cors/tree/master/examples
[Rocket CORS fairing example]: https://github.com/lawliet89/rocket_cors/blob/master/examples/fairing.rs
[Rocket CORS fairng test example]: https://github.com/lawliet89/rocket_cors/blob/master/tests/fairing.rs

[Rust Yew Examples]: https://github.com/yewstack/yew/tree/master/examples

[hyper]: https://github.com/hyperium/hyper

[Rust Dotenv]: https://crates.io/crates/dotenv
[Reqwest]: https://docs.rs/reqwest/0.9.18/reqwest/

[stdweb]: https://github.com/koute/stdweb

[YouTube API]: https://developers.google.com/youtube/v3/getting-started#before-you-start
[How to use YouTube API for developers]: https://www.google.com/search?q=how+to+use+youtube+api+for+developers

[Rust Full Stack]: https://github.com/steadylearner/Rust-Full-Stack
[JSON Webservice]: https://github.com/steadylearner/Rust-Full-Stack/tree/master/before/JSON_Webservice

[Rust Blog Example]: https://github.com/steadylearner/Rust-Full-Stack/tree/master/web/before/rust_blog

[CRA]: https://github.com/facebook/create-react-app

[protocol buffers]: https://developers.google.com/protocol-buffers/docs/overview
[Tonic]: https://github.com/hyperium/tonic
[Rust Postgresql]: https://github.com/sfackler/rust-postgres
[Rust Postgresql query]: https://docs.rs/postgres/0.15.2/postgres/struct.Connection.html#method.query
[Rust Postgresql execute]: https://docs.rs/postgres/0.15.2/postgres/struct.Connection.html#method.execute
[Tonic CRUD Example by Steadylearner]: https://github.com/steadylearner/Rust-Full-Stack/tree/master/gRPC/rust/user
[Official Tonic Guide]: https://github.com/hyperium/tonic/blob/master/examples/helloworld-tutorial.md
[gRPC Client]: https://github.com/uw-labs/bloomrpc

[How to install Postgresql]: https://www.digitalocean.com/community/tutorials/how-to-install-and-use-postgresql-on-ubuntu-18-04

[tonic-build]: https://github.com/hyperium/tonic/blob/master/tonic-build/README.md

[Rust uuid]: https://crates.io/crates/uuid
[chrono]: https://docs.rs/chrono/0.4.9/chrono/

[graphiql]: https://github.com/graphql/graphiql

<!-- / -->

<!-- Steadylearner Post -->

[Rust blog posts]: https://www.steadylearner.com/blog/search/Rust
[How to install Rust]: https://www.steadylearner.com/blog/read/How-to-install-Rust
[Rust Chat App]: https://www.steadylearner.com/blog/read/How-to-start-Rust-Chat-App
[Rust Yew Frontend]: https://github.com/yewstack/yew
[Yew Counter]: https://www.steadylearner.com/yew_counter
[How to use Rust Yew]: https://www.steadylearner.com/blog/read/How-to-use-Rust-Yew
[How to deploy Rust Web App]: https://www.steadylearner.com/blog/read/How-to-deploy-Rust-Web-App
[How to start Rust Chat App]: https://www.steadylearner.com/blog/read/How-to-start-Rust-Chat-App
[Fullstack Rust with Yew]: https://www.steadylearner.com/blog/read/Fullstack-Rust-with-Yew
[How to use NPM packages with Rust Frontend]: https://www.steadylearner.com/blog/read/How-to-use-NPM-packages-with-Rust-Frontend
[How to use markdown with code snippets in Rust Yew Frontend]: https://www.steadylearner.com/blog/read/How-to-use-markdown-with-code-snippets-in-Rust-Yew-Frontend
[How to modulize your Rust Frontend]: https://www.steadylearner.com/blog/read/How-to-modulize-your-Rust-Frontend
[How to write Full Stack Rust Code]: https://www.steadylearner.com/blog/read/How-to-write-Full-Stack-Rust-code
[How to use a modal in Rust]: https://www.steadylearner.com/blog/read/How-to-use-a-modal-in-Rust
[How to use routers in Rust Frontend]: https://www.steadylearner.com/blog/read/How-to-use-routers-in-Rust-Frontend
[How to serve static files with Rust]: https://www.steadylearner.com/blog/read/How-to-serve-static-files-with-Rust
[How to use a single page app wtih Rust]: https://www.steadylearner.com/blog/read/How-to-use-a-single-page-app-with-Rust
[How to use Rust Tera for undefined paths]: https://www.steadylearner.com/blog/read/How-to-use-Rust-Tera-for-undefined-paths
[How to make JSON Webservice with Rust and YouTube API]: https://www.steadylearner.com/blog/read/How-to-make-JSON-Webservice-with-Rust-and-YouTube-API
[How to use CORS and OPTIONS HTTP request with Rust Rocket]: https://www.steadylearner.com/blog/read/How-to-use-CORS-and-OPTIONS-HTTP-request-with-Rust-Rocket
[How to render a YouTube vlog with Rust Yew fetch API]: https://www.steadylearner.com/blog/read/How-to-render-a-YouTube-vlog-with-Rust-Yew-fetch-API

[How to use Python in JavaScript]: https://www.steadylearner.com/blog/read/How-to-use-Python-in-JavaScript
[How to use React Spring to animate your message]: https://medium.com/@steadylearner/how-to-use-react-spring-to-animate-your-message-2bd2a7e62a5a

<!-- / -->

<!-- Steadylearner Twitter and LinkedIn  -->

[Twitter]: https://twitter.com/steadylearner_p
[LinkedIn]: https://www.linkedin.com/in/steady-learner-3151b7164/

<!--  -->

In this post, we will learn how to use Rust [Tonic] gRPC crate and implement CRUD with [Postgresql database][Rust Postgresql].

[You can contact me with Telegram if you need to hire a full stack blockchain dev.](https://t.me/steadylearner)

[You can also join the Telegram group where I maintain and you can find other blockchain developers, recruiters, project owners, ask questions and network.](https://t.me/solanadevelopers)

The purpose of it is to help you to have the working Rust Tonic code and start your own project immediately with it.

<br />

<h2 class="red-white">Prerequisite</h2>

1. [What is gRPC](https://grpc.io/docs/guides/) and [protocol buffers]
2. Rust, Postgresql or other databases
3. [Official Tonic Guide]
4. [gRPC Client]

---

If you haven't installed Rust in your machine, read [How to install Rust]. We will use [Rust Postgresql] crate for this post. [You should install Postgresql database][How to install Postgresql] first if you haven't yet.

I will assume that you are already familiar with gRPC, Rust and Postgresql or other databases. Otherwise, please read the documentations for them thoroughly before you read on.

You may not need [gRPC Client] at this point. But, I let it here before other contents because it is very useful and it takes long time to install it. [Follow the instruction](https://github.com/uw-labs/bloomrpc#installation) first to save your time later.

<br />

<h2 class="blue">Table of Contents</h2>

1. Project Setup
2. Define the CRUD gRPC service
3. Prepare Cargo.toml to install dependencies
4. Make gRPC server with Tonic
5. Implement gRPC Crud Service with Rust Postgresql
6. Use gRPC client to test it
7. Conclusion

---

I reused some parts of [Official Tonic Guide] to make the working flow of this post be similar to it. This will help you find the blog post better.

[You can find gRPC relevant source code here.](https://github.com/steadylearner/Rust-Full-Stack/tree/master/gRPC)

<br />

## 1. Project Setup

We will first set up data before all others. I hope you already have any sql database installed in your machine. [Refer to this sql commands](https://www.linode.com/docs/databases/postgresql/how-to-back-up-your-postgresql-database/).

Create database for whatever name you want.

```sql
CREATE DATABASE grpc OWNER you;
\c grpc;
```

Then, **$psql users < users.sql** or manually paste them to your psql console after you login to it.

```sql
-- users.sql
CREATE TABLE users(
  id VARCHAR(255) PRIMARY KEY,
  first_name VARCHAR(255) NOT NULL,
  last_name VARCHAR(255) NOT NULL,
  date_of_birth Date NOT NULL
);

INSERT INTO users VALUES
   ('steadylearner', 'steady', 'learner', 'yours');
INSERT INTO users VALUES
    ('mybirthdayisblackfriday', 'mybirthdayis', 'blackfriday', '2019-11-25');
INSERT INTO users VALUES
    ('mybirthdayisnotblackfriday', 'mybirthdayis', 'notblackfriday', '2019-11-26');
```

You can save those data from Postgresql with **$pg_dump users > users.sql** later.

The database setup is ready. Create a new Rust project to use the data and learn how to use [Tonic].

```console
$cargo new user
$cd user
```

Make .env file first in the folder to proetct your database login information. Refer to this command.

```console
$echo DATABASE_URL=postgres://postgres:postgres@localhost/grpc > .env
```

<br />

## 2. Define the CRUD gRPC service

We prepared minimal set up for this blog post in the previous part. We will define the gRPC **service** with the method **request** and **response** types. We will use [protocol buffers] for the user data we made before with Postgresql.

We will make `.proto` files in **proto** folder. Use this commands.

```console
$mkdir proto
$touch proto/user.proto
```

Then, first we will define our package name, which is what Tonic uses when including your protos in the client and server applications. It will be **user**.

```proto
syntax = "proto3";
package user;
```

Then, we wil define our Crud service. This service will contain the actual RPC calls. We will use them for the Rust Tonic CRUD example.

```proto
service Crud { // Use whatever name you want, this is for blog posts and not prouction files.
  rpc GetUser (UserRequest) returns (UserReply) {} // becomes get_user in impl functions in Rust files
  rpc ListUsers(Empty) returns (Users) {}
  rpc CreateUser (CreateUserRequest) returns (CreateUserReply) {}
  rpc UpdateUser (UpdateUserRequest) returns (UpdateUserReply) {}
  rpc DeleteUser (UserRequest) returns (DeleteUserReply) {}
  rpc DeleteUsers (Empty) returns (DeleteUserReply) {}
}
```

Nothing complicated here. It is a little bit verbose. But, it is to make them more explicit and easily write separate logics for them later. 

If you have better options for them or expertise of gRPC, please contact me with [Twitter] or make a Github issue for this post etc.

Finally, we will make those types we used above in our **Crud** RPC method. RPC types are defined as messages which contain typed fields. They will be similar to this.

```proto
message Empty {}

message UserRequest {
    string id = 1;
}

message UserReply {
    string id = 1;
    string first_name = 2;
    string last_name = 3;
    string date_of_birth = 4;
}

message CreateUserRequest {
    string first_name = 1;
    string last_name = 2;
    string date_of_birth = 3;
}

message CreateUserReply {
    string message = 1;
}

message UpdateUserRequest {
    string id = 1;
    string first_name = 2;
    string last_name = 3;
    string date_of_birth = 4;
}

message UpdateUserReply {
    string message = 1;
}

message DeleteUserReply {
    string message = 1;
}

message Users {
    repeated UserReply users = 1;
}
```

You can see that I used **string** type for **date_of_birth** instead of **date**. I did that because I couldn't find the example to correctly type **DATE** in protobuf and make it also work with [Tonic], [protocol buffers] and Rust type system.

If you are an expert with this and have a better way, you can help me to correct this.

The complete **.proto** file for our CRUD project will be similar to this.

```proto
// user.proto
syntax = "proto3";

package user;

service Crud {
  rpc GetUser (UserRequest) returns (UserReply) {}
  rpc ListUsers(Empty) returns (Users) {}
  rpc CreateUser (CreateUserRequest) returns (CreateUserReply) {}
  rpc UpdateUser (UpdateUserRequest) returns (UpdateUserReply) {}
  rpc DeleteUser (UserRequest) returns (DeleteUserReply) {}
  rpc DeleteUsers (Empty) returns (DeleteUserReply) {}
}

message Empty {}

message UserRequest {
    string id = 1;
}

message UserReply {
    string id = 1;
    string first_name = 2;
    string last_name = 3;
    string date_of_birth = 4;
}

message CreateUserRequest {
    string first_name = 1;
    string last_name = 2;
    string date_of_birth = 3;
}

message CreateUserReply {
    string message = 1;
}

message UpdateUserRequest {
    string id = 1;
    string first_name = 2;
    string last_name = 3;
    string date_of_birth = 4;
}

message UpdateUserReply {
    string message = 1;
}

message DeleteUserReply {
    string message = 1;
}

message Users {
    repeated UserReply users = 1;
}
```

Finding working Rust code is not easy and becomes even harder when you want to satisfy Rust compiler, [protocol buffers] type specification, [Rust Postgresql] at the same time.

If you want to make your own Rust Tonic project with other proto files later, compile
[Tonic CRUD Example by Steadylearner] first to collect binary files and then start by editing small parts of the Rust code and protobuf definitions in there.

<br />

## 3. Prepare Cargo.toml to install dependencies

We set up the proejct and made the protobuf file to use gRPC with Rust. Therefore, we can write Rust code for it with Tonic.

We will first prepare the dependencies for them with `Cargo.toml`.

```toml
[package]
name = "rust-tonic-crud-example"
version = "0.1.0"
authors = ["www.steadylearner.com"]
edition = "2018"

[dependencies]
tonic = { version = "0.1.0-alpha.4", features = ["rustls"] }
bytes = "0.4"
prost = "0.5"
prost-derive = "0.5"
prost-types = "0.5.0"
tokio = "=0.2.0-alpha.6"
futures-preview = { version = "=0.3.0-alpha.19", default-features = false, features = ["alloc"]}
async-stream = "0.1.2"
http = "0.1"
tower = "=0.3.0-alpha.2"
serde = "1.0.101"
serde_json = "1.0.41"
serde_derive = "1.0.101"
console = "0.9.0"
# Database(Postgresql)
postgres = { version = "0.15.2", features = ["with-chrono"] }
dotenv = "0.15.0"
chrono = "0.4.9"
uuid = { version = "0.8.1", features = ["serde", "v4"] }

# Help you use gRPC protobuf files in Rust.
[build-dependencies]
tonic-build = "0.1.0-alpha.4"
```

There are many dependencies for this simple project. But, it will be easy if you think this part

```toml
# Database(Postgresql)
postgres = { version = "0.15.2", features = ["with-chrono"] }
dotenv = "0.15.0"
chrono = "0.4.9"
uuid = { version = "0.8.1", features = ["serde", "v4"] }
```

is for the [Rust Postgresql] and others are for [Tonic].

We include `tonic-build` to make our client and server side gRPC code.

If you haven't used gRPC or tonic it may confuse you. But, every languages that use gRPC integration have the similar process to use proto buffer definitions with them.

With Rust Tonic, we need to include it in build process of our application. We will setup this with **build.rs** at the root of your crate.

```rust
fn main() -> Result<(), Box<dyn std::error::Error>> {
    tonic_build::compile_protos("proto/user.proto")?;
    Ok(())
}
```

Nothing complicated here. You just need to modify the file name from other examples. This makes **tonic-build** to compile your **protobufs** files to work with your Rust gRPC projects.

It automatically builds some Rust modules you can use later with your Rust code depending on the protobuf definitions you used in your protobuf files. You can verify this with the Rust code you will read later.

If you want more details, please refer to [tonic-build].

<br />

## 4. Make gRPC server with Tonic

The preparation process ended with the previous part. Finally, we will write our own Rust code. Start with building Rust Tonic gRPC server similar to this.

```rust
// main.rs
extern crate postgres;
extern crate dotenv;

extern crate chrono;

// 1.
pub mod user {
    tonic::include_proto!("user");
}

use tonic::{transport::Server};

// 1.
use user::{
    server::{CrudServer},
};

extern crate uuid;

extern crate console;
use console::Style;

mod db_connection; // 2.

mod service;
use crate::service::User;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let addr = "[::1]:50051".parse().unwrap(); // 3.
    let user = User::default();

    let blue = Style::new()
        .blue();

    println!("\nRust gRPC Server ready at {}", blue.apply_to(addr)); // 4.

    Server::builder().serve(addr, CrudServer::new(user)).await?;
    Ok(())
}
```

It will be the entry point when we start our Rust Tonic gRPC server. [Most of them are to define dependencies, modules you will use][How to modulize your Rust Frontend].

The file is simple but there are some points you need to know.

**1.** This is where you can use auto generated codes from **tonic_build::compile_protos("proto/user.proto")?;** and **tonic-build = "0.1.0-alpha.4"**.

You can use modules made from it similar to this and handlers we will build with **models.rs**.

```rust
use user::{
    server::{CrudServer},
};
```

**2.** The contents of db_connection file will be similar to this.

```rust
use postgres::{Connection, TlsMode};
use dotenv::dotenv;
use std::env;

pub fn establish_connection() -> Connection {
    dotenv().ok();
    let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
    Connection::connect(database_url, TlsMode::None).unwrap()
}
```

For it can be reused many times without modifications, we will separate this to function and can include it wherever we want.

**3.** This is code from the [Tonic] authors. You should use it without http prefix when you use CURL and [gRPC client].

**4.** We use **console::Style;** with println! to easily visit the server with browsers and send CURL commands with it.

<br />

## 5. Implement gRPC Crud Service with Rust Postgresl

In this part, we will make some handlers in **service.rs** while we follow the definitions we made in **user.proto** file. The entire code will be similar to this.

The code snippet is long. This is to implement every gRPC CRUD operation with Postgresql database relevant logics. You may read only parts you want.

```rust
use chrono::*;
use uuid::Uuid;

use crate::db_connection::establish_connection;

use tonic::{Request, Response, Status};

// Compare it with user.proto file, imported from the main.rs file
use crate::user::{
    server::Crud, CreateUserReply, CreateUserRequest, DeleteUserReply, Empty, UpdateUserReply,
    UpdateUserRequest, UserReply, UserRequest, Users,
};

#[derive(Default)]
pub struct User {}

#[tonic::async_trait]
impl Crud for User {
    // Compare it with the Crud service definition in user.proto file
    // The method GetUser becomes get_user etc
    async fn get_user(&self, request: Request<UserRequest>) -> Result<Response<UserReply>, Status> {
        println!("Got a request: {:#?}", &request);
        // request is private, so use this instead to get the data in it.
        let UserRequest { id } = &request.into_inner();

        let conn = establish_connection();

        // 1.
        let rows = &conn
            .query("SELECT * FROM users WHERE id = $1", &[&id])
            .unwrap();

        // println!("{:#?}", rows);
        // println!("{:#?}", rows.get(0));
        // https://docs.rs/postgres/0.17.0-alpha.1/postgres/row/struct.Row.html

        let row = rows.get(0);
        println!("{:#?}", &row);

        // 2.
        let date_of_birth: NaiveDate = row.get(3);

        let reply = UserReply {
            id: row.get(0),
            first_name: row.get(1),
            last_name: row.get(2),
            // 2.
            date_of_birth: date_of_birth.to_string(),
        };

        Ok(Response::new(reply))
    }

    async fn list_users(&self, request: Request<Empty>) -> Result<Response<Users>, Status> {
        println!("Got a request: {:#?}", &request);
        let conn = establish_connection();

        // 3.
        let mut v: Vec<UserReply> = Vec::new();
        for row in &conn.query("SELECT * FROM users", &[]).unwrap() {
            let date_of_birth: NaiveDate = row.get(3);
            let user = UserReply {
                id: row.get(0),
                first_name: row.get(1),
                last_name: row.get(2),
                date_of_birth: date_of_birth.to_string(),
            };
            v.push(user);
        }

        let reply = Users { users: v };

        Ok(Response::new(reply))
    }

    // Test with create_users, Rust compiler shows errors to help you.
    async fn create_user(
        &self,
        request: Request<CreateUserRequest>,
    ) -> Result<Response<CreateUserReply>, Status> {
        println!("Got a request: {:#?}", &request);
        // 4.
        let user_id = Uuid::new_v4().to_hyphenated().to_string();
        let CreateUserRequest {
            first_name,
            last_name,
            date_of_birth,
        } = &request.into_inner();
        // 5.
        let serialize_date_of_birth = NaiveDate::parse_from_str(date_of_birth, "%Y-%m-%d").unwrap(); // String to Date

        let conn = establish_connection();
        // 6.
        let number_of_rows_affected = &conn.execute(
                "INSERT INTO users (id, first_name, last_name, date_of_birth) VALUES ($1, $2, $3, $4)",
                &[
                    &user_id,
                    &first_name,
                    &last_name,
                    &serialize_date_of_birth,
                ]
            )
            .unwrap();

        let reply = if number_of_rows_affected == &(0 as u64) {
            CreateUserReply {
                message: format!(
                    "Fail to create user with id {}.",
                    &user_id
                ),
            }
        } else {
            CreateUserReply {
                message: format!(
                    "Create {} user with id {}.",
                    &number_of_rows_affected, &user_id
                ),
            }
        };

        Ok(Response::new(reply))
    }

    async fn update_user(
        &self,
        request: Request<UpdateUserRequest>,
    ) -> Result<Response<UpdateUserReply>, Status> {
        println!("Got a request: {:#?}", &request);
        let UpdateUserRequest {
            id,
            first_name,
            last_name,
            date_of_birth,
        } = &request.into_inner();
        // 3.
        let serialize_date_of_birth = NaiveDate::parse_from_str(date_of_birth, "%Y-%m-%d").unwrap(); // String to Date

        let conn = establish_connection();

        let number_of_rows_affected = &conn
            .execute(
                "UPDATE users SET first_name = $2, last_name = $3, date_of_birth = $4 WHERE id = $1",
                &[
                    &id,
                    &first_name,
                    &last_name,
                    &serialize_date_of_birth,
                ]
            )
            .unwrap();

        let reply = if number_of_rows_affected == &(0 as u64) {
            UpdateUserReply {
                message: format!("Fail to update the user with id {}.", id),
            }
        } else {
            UpdateUserReply {
                message: format!("Update {} user with id {}", &number_of_rows_affected, &id),
            }
        };

        Ok(Response::new(reply))
    }

    async fn delete_user(
        &self,
        request: Request<UserRequest>,
    ) -> Result<Response<DeleteUserReply>, Status> {
        println!("Got a request: {:#?}", &request);
        let UserRequest { id } = &request.into_inner();
        let conn = establish_connection();

        let number_of_rows_affected = &conn
            .execute("DELETE FROM users WHERE id = $1", &[&id])
            .unwrap();

        let reply = if number_of_rows_affected == &(0 as u64) {
            DeleteUserReply {
                message: format!("Fail to delete the user with id {}.", id),
            }
        } else {
            DeleteUserReply {
                message: format!("Remove the user with id {}.", id),
            }
        };

        Ok(Response::new(reply))
    }

    async fn delete_users(
        &self,
        request: Request<Empty>,
    ) -> Result<Response<DeleteUserReply>, Status> {
        println!("Got a request: {:#?}", &request);
        let conn = establish_connection();

        let rows = &conn.query("DELETE FROM users", &[]).unwrap();

        let reply = DeleteUserReply {
            message: format!("Remove {} user data from the database.", rows.len()),
        };

        Ok(Response::new(reply))
    }
}
```

There were many lines of Rust code here. So it may be complicated to start with. I want you to test your project with **get_user** and **list_users** parts first. Then, you can improve it while you refer to these separate comments.

**1.** When you read [Rust Postgresql] documentation and examples, you can see that there are [execute][Rust Postgresql execute] and [query][Rust Postgresql query] API to use Postgresql SQL commands. The difference is that execute retunrs **the number of rows modified** query returns data(returning the resulting rows"). You should find when to use them depending on your needs.

**2.** When you use [Rust Postgresql], you may see the error message similar to this.

```console
cannot infer type
the trait `postgres::types::FromSql` is not implemented for
```

Then, you should type [the data with the definition that help your Rust code compatible with postgresql](https://docs.rs/postgres/0.17.0-alpha.1/postgres/types/trait.FromSql.html#tymethod.from_sql) with [chrono].

```rust
let date_of_birth: NaiveDate = row.get(3);
```

We used the string type for **date_of_birth** in **user.proto** file. [We should turn date_of_birth to string](https://docs.rs/postgres/0.17.0-alpha.1/postgres/types/trait.FromSql.html?search=to_string) similar to this.

```rust
date_of_birth: date_of_birth.to_string(),
```

This is the cost we have to pay to make it work with your Rust code, Postgresql database and Protobuf at the same time. You may find the better way.

**3.** We use imperative way to make the list of users following the documentation from the author. You should easily infer that **repeated** part of proto becomes vec in Rust.

```proto
message Users {
    repeated UserReply users = 1;
}
```

Then, you also need to know that Rust postgresql crate requires you to include empty **&[]** when you have no values to pass in your sql commands.

```rust
&conn.query("SELECT * FROM users", &[])
```

**4.** We make random id for users with [Rust uuid] API. You should include **v4** relevant parts in your cargo.toml to make it work.

```toml
uuid = { version = "0.8.1", features = ["serde", "v4"] }
```

**5.** We use API from [chrono] to make the string to DATE type to make it compatible with Postgresql.

**6.** We use **let number_of_rows_affected = &conn.execute** and its relevant logic to handle the database result from the gRPC client request. You can see that the similar logic is used in **update_user**, **delete_user**, **delete_users**.

I hope you read the entire code of the project and its relevant documentations. If you haven't tested the project, do it with **cargo run --release** and see the result similar to this.

```console
Rust gRPC Server ready at [::1]:50051
```

Then, you can test it with CURL with **$curl [::1]:50051**.

If it worked well, it should show this.

```console
Warning: Binary output can mess up your terminal. Use "--output -" to tell
Warning: curl to output it to your terminal anyway, or consider "--output
Warning: <FILE>" to save to a file.
```

Then, you can write [Tonic] gRPC client code similar to this.

```rust
pub mod user {
    tonic::include_proto!("user");
}

use user::{client::CrudClient, UserRequest};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut client = CrudClient::connect("http://[::1]:50051")?;

    let request = tonic::Request::new(UserRequest {
        id: "steadylearner".into(),
    });

    let response = client.get_user(request).await?;

    println!("RESPONSE={:?}", response);
    let user_date_of_birth = &response.into_inner().date_of_birth;
    println!("{}", user_date_of_birth);

    Ok(())
}
```

It will be easy to find how this works if you read [Official Tonic Guide] already. Make it compile if you want and back to improve it later after you test all the gRPC end points with [gRPC Client].

<br />

## 6. Use gRPC client to test it

<!-- [![BloomRPC Usage Example from the official repository](https://raw.githubusercontent.com/uw-labs/bloomrpc/master/resources/editor-preview.gif)][gRPC Client] -->

<section class="flex center" >
    <a href="https://raw.githubusercontent.com/uw-labs/bloomrpc/master/resources/blue/256x256.png" title="BloomRPC" >
        <img src="https://raw.githubusercontent.com/uw-labs/bloomrpc/master/resources/blue/256x256.png" />
    </a>
</section>

I want you already installed [gRPC Client] in your machine. You should have **BloomRPC version.AppImage** executable file in your **release** folder.

You may manually execute it or refer to the process similar to this with your editor.

Use **pwd** to find the location of the gRPC client and **$vim ~/.bashrc** to include alias similar to this.

```bash
# gRPC

alias grpc-client="grpc/bloomrpc/release/'BloomRPC version.AppImage'"
```

and use this command.

```console
$source ~/.bashrc
```

Then, you can use it with **$grpc-client** whenever you want.

It will show the desktop application similar to this from the official repository.

[![BloomRPC Usage Example from the official repository](https://raw.githubusercontent.com/uw-labs/bloomrpc/master/resources/editor-preview.gif)][gRPC Client]

If you used graphql before, you will find it is very similar to use [graphiql] to test its end points.

You will need to include your proto files first. For example, **user.proto** we made.

Then, it will automatically show the methods you can use.

When you click each methods, it will give the default value at the editor part. You can send requests with them or use your custom values.

For this example, you should have cautions when you define value for **"date_of_birth"** part. You should use correct **DATE** type string for Rust and Postgresql.

When the process pauses, you can stop it easily by clicking the same button you used to send gRPC request.

Refer to the request examples I let it here before you use it.

### GetUser

```json
{
  "id": "steadylearner"
}
```

### ListUsers

```json
{}
```

### CreateUser

```json
{
  "first_name": "steady",
  "last_name": "learner",
  "date_of_birth": "%Y-%m-%d"
}
```

### UpdateUser

```json
{
  "id": "random-id",
  "first_name": "steadylearner",
  "last_name": "rust developer",
  "date_of_birth": "use-numbers-instead"
}
```

### DeleteUser

```json
{
  "id": "steadylearner"
}
```

### DeleteUsers

```json
{}
```

Test the gRPC server end points with your own code. Then, write more complicated Rust [Tonic] client in separate Rust files. 

[You can also use it with other Rust servers to make microservices](https://github.com/steadylearner/Rust-Full-Stack/tree/master/microservices_with_docker).

<br />

## 7. Conclusion

I hope you made it work. You can edit the protobuf definition for your own project and write more Rust code to handle database relevant logics.

Rust and [Tonic] helped me to learn and write better gRPC codes. But, it was difficult to find the working examples with database integration and want this post be helpful for others.

If you want the latest contents, follow me here, [Twitter] or star [Rust Full Stack].

[If you need to hire a developer, you can contact me.](https://t.me/steadylearner)

Thanks.