Actix_web & actix_protobuf

I am trying to customise the example given below:

which uses actix_web with sqlx.

The above example uses serde for serialization & deserialization. I'm am trying to replace serde with protobuf using the following example:

In my model file, I have the following code:

// this struct will be used to represent database record
#[derive(Clone, PartialEq, Message)]
pub struct LastUpdated {
    #[prost(uint64, tag = "1")]
    pub last_updated: u64,
}

// implementation of Actix Responder for LastUpdated struct so we can return LastUpdated from action handler
impl Responder for LastUpdated {
    type Error = Error;
    type Future = Ready<Result<HttpResponse, Error>>;

    fn respond_to(self, _req: &HttpRequest) -> Self::Future {
        // create response
        ready(Ok(HttpResponse::Ok().protobuf(self).unwrap()))
    }
}

impl LastUpdated {
    pub async fn get(location: i32, pool: &MySqlPool) -> Result<LastUpdated> {
        let rec = sqlx::query("SELECT last_updated FROM main_categories WHERE location = ?")
        .bind(location)
        .fetch_one(&*pool)
        .await?;

        Ok(LastUpdated {
            last_updated: rec.get("last_updated")
        })
    }
}

In my route file, I have the following code:

use actix_web::*;
use sqlx::MySqlPool;
use crate::models::main_categories::LastUpdated;


#[get("/last_updated/{id}")]
pub async fn last_updated(id: web::Path<i32>, db_pool: web::Data<MySqlPool>) -> impl Responder {
    let result = LastUpdated::get(id.into_inner(), db_pool.get_ref()).await.unwrap();
    match result {
        Ok(lastUpdated) => HttpResponse::Ok().body(lastUpdated),
        _ => HttpResponse::BadRequest().body("Last updated not found")
    }
}

Unfortunately, in my route file, I get an error from section Ok(lastUpdated) saying expected struct models::main_categories::LastUpdated, found enum std::result::Result

I'm just learning RUST, and am stuck. Any help would be appreciated.

Thank you.

I did't try it, but I guess you have to change this line:

let result = LastUpdated::get(id.into_inner(), db_pool.get_ref())
   .await
   .unwrap();  // <- Remove this 

Removing the unwrap() at the end to avoid open the Result, as you want to do it later in the match.

let result = LastUpdated::get(id.into_inner(), db_pool.get_ref()).await;

Thank you very much for your help @alexmario74.

I went through actix-web tutorials, and realised that we simply had to pass the custom response we created, as it already implements a responder. Slowly but steadily, I'm getting a hang of things.

I changed my route file to the following:

use actix_web::*;
use sqlx::MySqlPool;
use crate::models::main_categories::LastUpdated;


#[get("/last_updated/{id}")]
pub async fn last_updated(id: web::Path<i32>, db_pool: web::Data<MySqlPool>) -> impl Responder {
    LastUpdated::get(id.into_inner(), db_pool.get_ref()).await.unwrap()
}

That is of course a better solution. :slight_smile: