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
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:
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