lundi 3 mai 2021

I am having trouble setting up a singleton in Rust

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

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

    pub static INSTANCE: Lazy<Mutex<client::Client>> = Lazy::new(|| {
        // 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)
    });
}

and this was my code before the change

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

use crate::data::{
    custom_response::{CustomResponse, ResponseType, Status},
    slug::Slug,
};
use crate::database::redis::container::create_or_get_redis_client;
use nanoid::nanoid;
use rocket::response::content::Json;
use url::Url;

// For creating a shortened link
#[post("/<link>")]
pub fn route(link: String) -> Json<String> {
    if let Err(error) = Url::parse(&link) {
        let error_response = CustomResponse {
            status: Status::ERR,
            response: ResponseType::String(error.to_string()),
        };
        let error_response_string = serde_json::to_string(&error_response).unwrap();

        return Json(error_response_string);
    }

    let uuid = &nanoid!(10);
    let mut redis_client = create_or_get_redis_client().lock().unwrap();
    let created_slug_base = Slug {
        uuid: uuid.to_string(),
        original_url: link,
    };
    let created_slug_string = serde_json::to_string(&created_slug_base).unwrap();

    if let Err(error) = redis_client.set(&uuid, &*created_slug_string) {
        let error_response = CustomResponse {
            status: Status::ERR,
            response: ResponseType::String(error.to_string()),
        };
        let error_response_string = serde_json::to_string(&error_response).unwrap();

        return Json(error_response_string);
    }

    let created_slug_json = serde_json::from_str(&created_slug_string).unwrap();
    let response_base = CustomResponse {
        status: Status::OK,
        response: ResponseType::JSON(created_slug_json),
    };
    let response_string = serde_json::to_string(&response_base).unwrap();

    Json(response_string)
}

Here's the link to the GitHub repo

Also here's a screenshot from Postman:

Screenshot

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.

Aucun commentaire:

Enregistrer un commentaire