Add duration to header response.

Add sort_id to processes_table.
Remove postgresql errors from error messages.
Filter "Codigo de Referencia" on the DB side.
Optimize get_random_process_id by using sort_id.
This commit is contained in:
Pedro de Oliveira 2023-06-03 21:53:00 +01:00
parent 49896cd208
commit f9ae423e39
4 changed files with 54 additions and 55 deletions

View File

@ -18,56 +18,55 @@ pub struct AppState {
} }
pub fn get_random_process_id(db: &DbPool) -> i32 { pub fn get_random_process_id(db: &DbPool) -> i32 {
sql_function!(fn random() -> Text); use diesel::dsl::*;
let mut conn = db.get().unwrap(); let mut conn = db.get().unwrap();
processes::table let random_sort_id: i32 = processes::table
.limit(1) .select(sql::<diesel::sql_types::Integer>(
"CAST(floor(random() * max(sort_id)) + 1 AS INTEGER)",
))
.first::<i32>(&mut conn)
.expect("fail");
let result: i32 = processes::table
.filter(processes::sort_id.ge(random_sort_id))
.select(processes::id) .select(processes::id)
.order(random())
.first(&mut conn) .first(&mut conn)
.expect("fail") .expect("fail");
result
} }
pub fn get_full_process(process_id: i32, db: &DbPool) -> Value { pub fn get_full_process(process_id: i32, db: &DbPool) -> Result<Value, String> {
let mut conn = db.get().unwrap(); let mut conn = db.get().unwrap();
let result = processes::table
let process = processes::table
.select(Process::as_select()) .select(Process::as_select())
.filter(processes::id.eq(process_id)) .filter(processes::id.eq(process_id))
.first(&mut conn) .first(&mut conn);
.expect("fail");
let mut results: Vec<(String, String)> = ProcessTag::belonging_to(&process) if let Ok(process) = result {
.inner_join(tags::table) let mut results: Vec<(String, String)> = ProcessTag::belonging_to(&process)
.select((tags::title_api, process_tags::contents)) .inner_join(tags::table)
.load(&mut conn) .select((tags::title_api, process_tags::contents))
.expect("fail"); .filter(process_tags::tag_id.ne(1)) // Codigo de Referencia
.load(&mut conn)
.expect("fail");
results.sort_by_key(|(key, _)| key.clone());
results.sort_by_key(|(key, _)| key.clone()); let mut data = json!({
"document": {
"titulo": process.title,
},
});
let mut data = json!({ if let Some(document) = data.get_mut("document").and_then(Value::as_object_mut) {
"document": { for (title, contents) in results {
"titulo": process.title,
},
});
if let Some(document) = data.get_mut("document").and_then(Value::as_object_mut) {
for (title, contents) in results {
if title != "codigo_de_referencia" {
document.insert(title, Value::String(contents)); document.insert(title, Value::String(contents));
} }
document.insert("digital".to_owned(), Value::Bool(process.scan));
} }
document.insert("digital".to_owned(), Value::Bool(process.scan));
}
if let Some(object) = data.as_object_mut() { Ok(data)
object.insert( } else {
"link".to_owned(), Err("Invalid process id".to_owned())
Value::String(format!("https://inquisicao.info/view/{process_id}")),
);
} }
data
} }
fn get_total(key: &str, db: &DbPool) -> Result<i64, String> { fn get_total(key: &str, db: &DbPool) -> Result<i64, String> {
@ -87,22 +86,16 @@ fn get_total(key: &str, db: &DbPool) -> Result<i64, String> {
match result { match result {
Ok(total) => Ok(total), Ok(total) => Ok(total),
Err(error) => { Err(_error) => Err("Not found".to_owned()),
// TODO: Dont show PostgreSQL errors
Err(error.to_string())
}
} }
} }
pub fn find_process(key: &str, offset: i64, db: &DbPool) -> Result<Value, String> { pub fn find_process(key: &str, offset: i64, db: &DbPool) -> Result<Value, String> {
let ts_config = TsConfigurationByName("SIMPLE"); let ts_config = TsConfigurationByName("SIMPLE");
let mut conn = db.get().unwrap(); let mut conn = db.get().unwrap();
let total_result = get_total(key, db); let total_result = get_total(key, db);
match total_result { match total_result {
Ok(total) => { Ok(_total) => {
dbg!(&total);
let result = OffsetDsl::offset( let result = OffsetDsl::offset(
process_tags::table process_tags::table
.inner_join(tags::table) .inner_join(tags::table)
@ -139,12 +132,9 @@ pub fn find_process(key: &str, offset: i64, db: &DbPool) -> Result<Value, String
match result { match result {
Ok(value) => { Ok(value) => {
let (process_id, _title_api, _headline, _rank) = value; let (process_id, _title_api, _headline, _rank) = value;
Ok(get_full_process(process_id, db)) Ok(get_full_process(process_id, db).unwrap())
}
Err(error) => {
// TODO: Dont show PostgreSQL errors
Err(error.to_string())
} }
Err(_error) => Err("Not found".to_owned()),
} }
} }
Err(error) => Err(error), Err(error) => Err(error),

View File

@ -1,7 +1,8 @@
use crate::database::{find_process, get_full_process, get_random_process_id, AppState};
use actix_web::{get, web, HttpResponse}; use actix_web::{get, web, HttpResponse};
use serde_json::json; use serde_json::json;
use std::collections::HashMap; use std::collections::HashMap;
use crate::database::{AppState, find_process, get_full_process, get_random_process_id}; use std::time::Instant;
pub fn config(conf: &mut web::ServiceConfig) { pub fn config(conf: &mut web::ServiceConfig) {
let scope = web::scope("/api") let scope = web::scope("/api")
@ -12,9 +13,13 @@ pub fn config(conf: &mut web::ServiceConfig) {
#[get("/degredo")] #[get("/degredo")]
pub async fn get_degredo(data: web::Data<AppState>) -> HttpResponse { pub async fn get_degredo(data: web::Data<AppState>) -> HttpResponse {
let start = Instant::now();
let id = get_random_process_id(&data.db); let id = get_random_process_id(&data.db);
let data = get_full_process(id, &data.db); let data = get_full_process(id, &data.db);
HttpResponse::Ok().json(data) let duration = start.elapsed();
HttpResponse::Ok()
.append_header(("duration", duration.as_millis().to_string()))
.json(data)
} }
#[get("/adcautelam")] #[get("/adcautelam")]
@ -22,6 +27,7 @@ pub async fn get_adcautelam(
params: web::Query<HashMap<String, String>>, params: web::Query<HashMap<String, String>>,
data: web::Data<AppState>, data: web::Data<AppState>,
) -> HttpResponse { ) -> HttpResponse {
let start = Instant::now();
let key = match params.get("key") { let key = match params.get("key") {
Some(value) if !value.is_empty() => value.as_str(), Some(value) if !value.is_empty() => value.as_str(),
_ => { _ => {
@ -38,9 +44,11 @@ pub async fn get_adcautelam(
let offset = page - 1; let offset = page - 1;
let result = find_process(key, offset, &data.db); let result = find_process(key, offset, &data.db);
let duration = start.elapsed();
match result { match result {
Ok(data) => HttpResponse::Ok().json(data), Ok(data) => HttpResponse::Ok()
.append_header(("duration", duration.as_millis().to_string()))
.json(data),
Err(error) => HttpResponse::NotFound().json(error), Err(error) => HttpResponse::NotFound().json(error),
} }
} }

View File

@ -1,4 +1,4 @@
use chrono::naive::NaiveDate; //use chrono::naive::NaiveDate;
use diesel::prelude::*; use diesel::prelude::*;
#[derive(Identifiable, Queryable, Selectable, PartialEq, Debug)] #[derive(Identifiable, Queryable, Selectable, PartialEq, Debug)]
@ -8,9 +8,9 @@ pub struct Process {
pub id: i32, pub id: i32,
pub title: String, pub title: String,
pub scan: bool, pub scan: bool,
dt_start: Option<NaiveDate>, //dt_start: Option<NaiveDate>,
dt_finish: Option<NaiveDate>, //dt_finish: Option<NaiveDate>,
origin: Option<String>, //origin: Option<String>,
} }
#[derive(Identifiable, Associations, Queryable, Selectable, Debug)] #[derive(Identifiable, Associations, Queryable, Selectable, Debug)]

View File

@ -20,6 +20,7 @@ diesel::table! {
dt_start -> Nullable<Date>, dt_start -> Nullable<Date>,
dt_finish -> Nullable<Date>, dt_finish -> Nullable<Date>,
origin -> Nullable<Varchar>, origin -> Nullable<Varchar>,
sort_id -> Int4,
} }
} }