mirror of
https://github.com/pesde-pkg/pesde.git
synced 2025-05-04 10:33:47 +01:00
Adds quite a lot of Clippy lints which fit with my personal taste for how pesde's codebase should look like. Stylistic lints are mostly warns, and behavioural lints are mostly denied.
91 lines
2.1 KiB
Rust
91 lines
2.1 KiB
Rust
use crate::{
|
|
error::RegistryError,
|
|
package::{read_package, PackageResponse},
|
|
search::find_max_searchable,
|
|
AppState,
|
|
};
|
|
use actix_web::{web, HttpResponse};
|
|
use pesde::names::PackageName;
|
|
use serde::Deserialize;
|
|
use std::{collections::HashMap, sync::Arc};
|
|
use tantivy::{collector::Count, query::AllQuery, schema::Value as _, DateTime, Order};
|
|
use tokio::task::JoinSet;
|
|
|
|
#[derive(Deserialize)]
|
|
pub struct Request {
|
|
#[serde(default)]
|
|
query: String,
|
|
#[serde(default)]
|
|
offset: usize,
|
|
}
|
|
|
|
pub async fn search_packages(
|
|
app_state: web::Data<AppState>,
|
|
request_query: web::Query<Request>,
|
|
) -> Result<HttpResponse, RegistryError> {
|
|
let searcher = app_state.search_reader.searcher();
|
|
let schema = searcher.schema();
|
|
|
|
let id = schema.get_field("id").unwrap();
|
|
|
|
let query = request_query.query.trim();
|
|
|
|
let query = if query.is_empty() {
|
|
Box::new(AllQuery)
|
|
} else {
|
|
app_state.query_parser.parse_query(query)?
|
|
};
|
|
|
|
let (count, top_docs) = searcher
|
|
.search(
|
|
&query,
|
|
&(
|
|
Count,
|
|
tantivy::collector::TopDocs::with_limit(50)
|
|
.and_offset(request_query.offset)
|
|
.order_by_fast_field::<DateTime>("published_at", Order::Desc),
|
|
),
|
|
)
|
|
.unwrap();
|
|
|
|
let source = Arc::new(app_state.source.clone().read_owned().await);
|
|
|
|
let mut results = top_docs
|
|
.iter()
|
|
.map(|_| None::<PackageResponse>)
|
|
.collect::<Vec<_>>();
|
|
|
|
let mut tasks = top_docs
|
|
.into_iter()
|
|
.enumerate()
|
|
.map(|(i, (_, doc_address))| {
|
|
let app_state = app_state.clone();
|
|
let doc = searcher.doc::<HashMap<_, _>>(doc_address).unwrap();
|
|
let source = source.clone();
|
|
|
|
async move {
|
|
let id = (&doc[&id])
|
|
.as_str()
|
|
.unwrap()
|
|
.parse::<PackageName>()
|
|
.unwrap();
|
|
|
|
let file = read_package(&app_state, &id, &source).await?.unwrap();
|
|
|
|
let (version_id, _) = find_max_searchable(&file).unwrap();
|
|
|
|
Ok::<_, RegistryError>((i, PackageResponse::new(&id, version_id, &file)))
|
|
}
|
|
})
|
|
.collect::<JoinSet<_>>();
|
|
|
|
while let Some(res) = tasks.join_next().await {
|
|
let (i, res) = res.unwrap()?;
|
|
results[i] = Some(res);
|
|
}
|
|
|
|
Ok(HttpResponse::Ok().json(serde_json::json!({
|
|
"data": results,
|
|
"count": count,
|
|
})))
|
|
}
|