mardi 4 mai 2021

I am having trouble setting up a singleton in Rust [closed]

Description of my issue

I am making a URL shortener with Rust, Redis and Rocket.rs. I'm using the once_cell crate to create a Redis database connection singleton without reconnecting to it every time after my request:

I am using the latest version of simple_redis crate (0.6.0)

The Code - Repo on Github

pub mod container {
    use once_cell::sync::OnceCell;
    use simple_redis::client;
    use std::sync::Mutex;

    static INSTANCE: OnceCell<Mutex<client::Client>> = OnceCell::new();

    fn init() -> Mutex<client::Client> {
        // Getting the connection string from the environment
        let connection_string: String = dotenv::var("REDIS_URL").unwrap();
        // Connecting to redis
        let client: client::Client = simple_redis::create(&connection_string).unwrap();
        // Returning the connection in a Mutex
        Mutex::new(client)
    }

    pub fn create_or_get_redis_client() -> &'static Mutex<client::Client> {
        INSTANCE.get_or_init(init)
    }
}

Here's an example of how I am currently using it

// Get all links route
use crate::data::{
    custom_response::{CustomResponse, ResponseType, Status},
    shortened_link_response::ShortenedLinkResponse,
    slug::Slug,
};
use crate::database::redis::container::create_or_get_redis_client;

// For getting a link by it's slug
#[get("/<uuid>")]
pub fn route(uuid: String) -> ShortenedLinkResponse {
    let mut redis_client = create_or_get_redis_client().lock().unwrap();
    // Getting the key from redis
    match redis_client.get_string(&uuid) {
        Ok(value) => {
            let parsed_response: Slug = serde_json::from_str(&value).unwrap();

            ShortenedLinkResponse::Redirect(rocket::response::Redirect::to(
                parsed_response.original_url,
            ))
        }
        Err(_) => {
            let error_response = CustomResponse {
                status: Status::ERR,
                response: ResponseType::String("There was an error".to_string()),
            };

            ShortenedLinkResponse::Error(serde_json::to_string(&error_response).unwrap())
        }
    }
}

Here's the slug.rs file

use serde::{Deserialize, Serialize};

// Data that will go to redis
#[derive(Serialize, Deserialize, Debug)]
pub struct Slug {
    pub uuid: String,
    pub original_url: String,
}

Here's the custom_response file

use serde::{Deserialize, Serialize};

// Status
#[derive(Serialize, Deserialize, Debug)]
pub enum Status {
    OK,
    ERR,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(untagged)] // Without this line the responses will look like this `"JSON or String": { "foo": "bar" }`
pub enum ResponseType {
    JSON(serde_json::Value),
    String(String),
}

// Response sent by our backend
#[derive(Serialize, Deserialize, Debug)]
pub struct CustomResponse {
    pub status: Status,
    pub response: ResponseType,
}

Here's my main.rs file

// rocket.rs
#![feature(proc_macro_hygiene, decl_macro)]

// rocket.rs
#[macro_use]
extern crate rocket;
extern crate serde;
extern crate serde_json;

//...

// Modules
mod data;
mod database;
mod routes;

// Getting the `index` and `make` routes
use routes::{index, make, total};

// Starting the server
fn main() {
    // ...

    rocket::ignite()
        .mount(
            "/",
            rocket::routes![index::route],
        )
        .launch();
}

Here are my dependencies

[dependencies]
url = "2.2.1"
nanoid = "0.4.0"
rocket = "0.4.7"
dotenv = "0.15.0"
serde_json = "1.0"
once_cell = "1.7.2"
simple_redis = "0.6.0"
serde = { version = "1.0", features = ["derive"] }
rocket_cors = { version = "0.5.1", default-features = false }

My project structure looks like this

Project structure

I concluded that my singleton is not working because the response time from the server was really high(500ms+) even when I sent a simple keys * request that would have contained just 4 objects in it.

My conclusion may be wrong, because I have created a simple route that sends a string as a response and still takes 500ms+ to execute so there may be an issue with Rocket.rs too

Here's the link to the GitHub repo


And here's the response time screenshot from Postman:

Screenshot


Desired behavior

When I was writing a URL shortener in Kotlin, everything was fast. The same query took about 20ms or less which is great, whereas now, in Rust and Rocket.rs it takes 500ms+

Aucun commentaire:

Enregistrer un commentaire