|
|
|
|
|
|
|
use crate::results::aggregation_models::RawSearchResult; |
|
use error_stack::{IntoReport, Result, ResultExt}; |
|
use std::{collections::HashMap, fmt, time::Duration}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)] |
|
pub enum EngineError { |
|
EmptyResultSet, |
|
RequestError, |
|
UnexpectedError, |
|
} |
|
|
|
impl fmt::Display for EngineError { |
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
|
match self { |
|
EngineError::EmptyResultSet => { |
|
write!(f, "The upstream search engine returned an empty result set") |
|
} |
|
EngineError::RequestError => { |
|
write!( |
|
f, |
|
"Error occurred while requesting data from upstream search engine" |
|
) |
|
} |
|
EngineError::UnexpectedError => { |
|
write!(f, "An unexpected error occurred while processing the data") |
|
} |
|
} |
|
} |
|
} |
|
|
|
impl error_stack::Context for EngineError {} |
|
|
|
|
|
#[async_trait::async_trait] |
|
pub trait SearchEngine { |
|
async fn fetch_html_from_upstream( |
|
&self, |
|
url: String, |
|
header_map: reqwest::header::HeaderMap, |
|
) -> Result<String, EngineError> { |
|
|
|
Ok(reqwest::Client::new() |
|
.get(url) |
|
.timeout(Duration::from_secs(30)) |
|
.headers(header_map) |
|
.send() |
|
.await |
|
.into_report() |
|
.change_context(EngineError::RequestError)? |
|
.text() |
|
.await |
|
.into_report() |
|
.change_context(EngineError::RequestError)?) |
|
} |
|
|
|
async fn results( |
|
&self, |
|
query: String, |
|
page: u32, |
|
user_agent: String, |
|
) -> Result<HashMap<String, RawSearchResult>, EngineError>; |
|
} |
|
|