Create Rust based Microservice using Rocket and Diesel

Reading Time: 3 minutes

Planning to write a new application using Rust? Confused with the approach? So this blog is for you. In this blog, we are going to write a simple Rust based Application using Microservices

Why Microservice?

Using a Microservice approach developers can build an application in a modularised way rather than writing a monolithic way. Which allows enterprises to create software which is more agile and independent. It helps to build an application which is more abstract and more manageable.

Rocket web framework is one of many great tools in rust to make perfect microservices with most abilities which microservice should possess. And to interact with the database in our case ‘Postgres’ we will use Diesel. It is a ORM and query builder designed to reduce boilerplate for database interaction.

Now, What to do?

n the blog, I elaborated a few functions required to use Rocket and Diesel. For a complete code download template from here.

Let’s start by setting the environment

The first objective is to set up Postgres. To do that you can follow this great blog beautifully explaining how to set up Postgres. 

Now the next objective is to install Diesel:-

First add few dependencies in cargo.toml

[dependencies]
diesel = { version = "1.4.4", features = ["postgres"] }
dotenv = "0.15.0"

Now run both of these commands to install Diesel_cli and then Diesel_cli will set up everything for you.

cargo install diesel_cli
diesel setup

Migrations allow us to evolve the database schema over time. To generate it

diesel migration generate YOUR_DERSIRED_NAME

The above command will generate two SQL files. Each migration can be applied (up.sql) or reverted (down.sql). 

Now we will write the SQL for migrations:

In up.sql

CREATE TABLE demodata(
  id SERIAL PRIMARY KEY,
  name VARCHAR NOT NULL,
  email VARCHAR NOT NULL,
  phoneno FLOAT NOT NULL
)

In down.sql

DROP TABLE demodata

Now to apply new migrations run:-

diesel migration run

For more you can follow their getting-started page.

Now it’s time to integrate Rocket with the project

Let’s start by adding related dependencies

[dependencies]
rocket = "0.4.5"
rocket_codegen = "0.4.5"
diesel = { version = "1.4.4", features = ["postgres"] }
dotenv = "0.15.0"
r2d2-diesel = "1.0.0"
r2d2 = "0.8.9"
serde = "1.0.116"
serde_derive = "1.0.116"
serde_json = "1.0.58"
env_logger = "0.5.12"
log = "0.4.6"

[dependencies.rocket_contrib]
version = "*"
default-features = false
features = ["json"]

If all dependencies are resolved then we are good to go.

Until this point we created a table on our database. Now let’s create something on Rust though which we can map our table.

use super::schema::people;

#[derive(Queryable, AsChangeset, Serialize, Deserialize)]
#[table_name = "demo"]
pub struct DemoData {
    pub id: i32,
    pub name: String,
    pub email: String,
    pub phoneno: i32,
}

Using the Person struct we created above, we can execute SELECT and UPDATE queries. But for INSERT queries Diesel suggest us to create other data structure. We can do it as below

#[derive(Insertable)]
#[table_name = “demo”]
struct InsertableData {
    name: String,
    email: String,
    age: i32,
    phoneno: i32,
}

impl InsertablePerson {

    fn from(data: DemoData) -> InsertableData {
        InsertablePerson {
            name: data.name,
            email: data.email,
            age: data.age,
            phoneno: data.phoneno,
        }
    }
}

Queries Execution

Until now we created table on Database and associated data structures in Rust to perform different database operations. Now lets implement methods for REST API.

pub fn get(id: i32, connection: &PgConnection) -> QueryResult<DemoData> {
    people::table.find(id).get_result::<DemoData>(connection)
}

Using the above method we can access the table and perform desired operations. For more such operations download a template which I created.

Now lets create a Handler of GET type to access the above function.

[get("/")]
fn get(id: i32, connection: DbConn) -> Result, Failure> {
people::repository::get(id, &connection)
.map(|data| Json(data))
.map_err(|error| error_status(error))
}

fn error_status(error: Error) -> Failure {
Failure(match error {
Error::NotFound => Status::NotFound,
_ => Status::InternalServerError
})
}

The above handler will return the record of the person with the given id. Now for the complete code download template from here.

If everything goes fine. After run it will look like below

Note: I hope our blogs help you to enhance your learning. I’ll post more blogs on Rust. Stay Tuned.

If you want to read more content like this?  Subscribe Rust Times Newsletter and receive insights and latest updates, bi-weekly, straight into your inbox. Subscribe Rust Times Newsletter: https://bit.ly/2Vdlld7.

Happy learning!!!

This image has an empty alt attribute; its file name is screenshot-from-2020-06-08-11-00-35.png

This image has an empty alt attribute; its file name is footer-2.jpg