mirror of
https://github.com/pesde-pkg/pesde.git
synced 2025-05-04 10:33:47 +01:00
feat(registry): ✨ add listing newest packages
This commit is contained in:
parent
970a8dce50
commit
9c806ba082
4 changed files with 75 additions and 37 deletions
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "pesde-registry"
|
name = "pesde-registry"
|
||||||
version = "0.3.0"
|
version = "0.4.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
@ -28,3 +28,4 @@ pretty_env_logger = "0.5.0"
|
||||||
sentry = "0.32.2"
|
sentry = "0.32.2"
|
||||||
sentry-log = "0.32.2"
|
sentry-log = "0.32.2"
|
||||||
sentry-actix = "0.32.2"
|
sentry-actix = "0.32.2"
|
||||||
|
chrono = "0.4.34"
|
|
@ -1,10 +1,11 @@
|
||||||
use actix_multipart::form::{bytes::Bytes, MultipartForm};
|
use actix_multipart::form::{bytes::Bytes, MultipartForm};
|
||||||
use actix_web::{web, HttpResponse, Responder};
|
use actix_web::{web, HttpResponse, Responder};
|
||||||
|
use chrono::Utc;
|
||||||
use flate2::read::GzDecoder;
|
use flate2::read::GzDecoder;
|
||||||
use log::error;
|
use log::error;
|
||||||
use reqwest::StatusCode;
|
use reqwest::StatusCode;
|
||||||
use rusty_s3::S3Action;
|
use rusty_s3::S3Action;
|
||||||
use tantivy::{doc, Term};
|
use tantivy::{doc, DateTime, Term};
|
||||||
use tar::Archive;
|
use tar::Archive;
|
||||||
|
|
||||||
use pesde::{
|
use pesde::{
|
||||||
|
@ -134,6 +135,7 @@ pub async fn create_package(
|
||||||
name_field => manifest.name.to_string(),
|
name_field => manifest.name.to_string(),
|
||||||
schema.get_field("version").unwrap() => manifest.version.to_string(),
|
schema.get_field("version").unwrap() => manifest.version.to_string(),
|
||||||
schema.get_field("description").unwrap() => manifest.description.unwrap_or_default(),
|
schema.get_field("description").unwrap() => manifest.description.unwrap_or_default(),
|
||||||
|
schema.get_field("published_at").unwrap() => DateTime::from_timestamp_secs(Utc::now().timestamp()),
|
||||||
)
|
)
|
||||||
).unwrap();
|
).unwrap();
|
||||||
|
|
||||||
|
@ -234,8 +236,8 @@ pub async fn get_package_versions(
|
||||||
Some(package) => {
|
Some(package) => {
|
||||||
let versions = package
|
let versions = package
|
||||||
.iter()
|
.iter()
|
||||||
.map(|v| v.version.to_string())
|
.map(|v| (v.version.to_string(), v.published_at.timestamp()))
|
||||||
.collect::<Vec<String>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
Ok(HttpResponse::Ok().json(versions))
|
Ok(HttpResponse::Ok().json(versions))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
use actix_web::{web, Responder};
|
use actix_web::{web, Responder};
|
||||||
|
use semver::Version;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde_json::{json, Value};
|
use serde_json::{json, Value};
|
||||||
|
use tantivy::{query::AllQuery, DateTime, DocAddress, Order};
|
||||||
|
|
||||||
|
use pesde::{index::Index, package_name::PackageName};
|
||||||
|
|
||||||
use crate::{errors, AppState};
|
use crate::{errors, AppState};
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct Query {
|
pub struct Query {
|
||||||
query: String,
|
query: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn search_packages(
|
pub async fn search_packages(
|
||||||
|
@ -20,32 +24,64 @@ pub async fn search_packages(
|
||||||
let version = schema.get_field("version").unwrap();
|
let version = schema.get_field("version").unwrap();
|
||||||
let description = schema.get_field("description").unwrap();
|
let description = schema.get_field("description").unwrap();
|
||||||
|
|
||||||
let query = query.query.trim();
|
let query = query.query.as_deref().unwrap_or_default().trim();
|
||||||
|
|
||||||
if query.is_empty() {
|
|
||||||
return Ok(web::Json(vec![]));
|
|
||||||
}
|
|
||||||
|
|
||||||
let query_parser =
|
let query_parser =
|
||||||
tantivy::query::QueryParser::for_index(&searcher.index(), vec![name, description]);
|
tantivy::query::QueryParser::for_index(&searcher.index(), vec![name, description]);
|
||||||
let query = query_parser.parse_query(&query)?;
|
let query = if query.is_empty() {
|
||||||
|
Box::new(AllQuery)
|
||||||
|
} else {
|
||||||
|
query_parser.parse_query(&query)?
|
||||||
|
};
|
||||||
|
|
||||||
let top_docs = searcher
|
let top_docs: Vec<(DateTime, DocAddress)> = searcher
|
||||||
.search(&query, &tantivy::collector::TopDocs::with_limit(10))
|
.search(
|
||||||
|
&query,
|
||||||
|
&tantivy::collector::TopDocs::with_limit(10)
|
||||||
|
.order_by_fast_field("published_at", Order::Desc),
|
||||||
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
{
|
||||||
|
let index = app_state.index.lock().unwrap();
|
||||||
|
|
||||||
Ok(web::Json(
|
Ok(web::Json(
|
||||||
top_docs
|
top_docs
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(_, doc_address)| {
|
.map(|(published_at, doc_address)| {
|
||||||
let retrieved_doc = searcher.doc(doc_address).unwrap();
|
let retrieved_doc = searcher.doc(doc_address).unwrap();
|
||||||
|
let name: PackageName = retrieved_doc
|
||||||
|
.get_first(name)
|
||||||
|
.unwrap()
|
||||||
|
.as_text()
|
||||||
|
.unwrap()
|
||||||
|
.parse()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let version: Version = retrieved_doc
|
||||||
|
.get_first(version)
|
||||||
|
.unwrap()
|
||||||
|
.as_text()
|
||||||
|
.unwrap()
|
||||||
|
.parse()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let entry = index
|
||||||
|
.package(&name)
|
||||||
|
.unwrap()
|
||||||
|
.unwrap()
|
||||||
|
.into_iter()
|
||||||
|
.find(|v| v.version == version)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
json!({
|
json!({
|
||||||
"name": retrieved_doc.get_first(name).unwrap().as_text().unwrap(),
|
"name": name,
|
||||||
"version": retrieved_doc.get_first(version).unwrap().as_text().unwrap(),
|
"version": version,
|
||||||
"description": retrieved_doc.get_first(description).unwrap().as_text().unwrap(),
|
"description": entry.description,
|
||||||
|
"published_at": published_at.into_timestamp_secs(),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.collect::<Vec<Value>>(),
|
.collect::<Vec<Value>>(),
|
||||||
))
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ use git2::{Cred, Signature};
|
||||||
use log::info;
|
use log::info;
|
||||||
use reqwest::{header::AUTHORIZATION, Client};
|
use reqwest::{header::AUTHORIZATION, Client};
|
||||||
use rusty_s3::{Bucket, Credentials, UrlStyle};
|
use rusty_s3::{Bucket, Credentials, UrlStyle};
|
||||||
use tantivy::{doc, IndexReader, IndexWriter};
|
use tantivy::{doc, DateTime, IndexReader, IndexWriter};
|
||||||
|
|
||||||
use pesde::{
|
use pesde::{
|
||||||
index::{GitIndex, IndexFile},
|
index::{GitIndex, IndexFile},
|
||||||
|
@ -126,10 +126,8 @@ fn search_index(index: &GitIndex) -> (IndexReader, IndexWriter) {
|
||||||
schema_builder.add_text_field("name", tantivy::schema::TEXT | tantivy::schema::STORED);
|
schema_builder.add_text_field("name", tantivy::schema::TEXT | tantivy::schema::STORED);
|
||||||
let version =
|
let version =
|
||||||
schema_builder.add_text_field("version", tantivy::schema::TEXT | tantivy::schema::STORED);
|
schema_builder.add_text_field("version", tantivy::schema::TEXT | tantivy::schema::STORED);
|
||||||
let description = schema_builder.add_text_field(
|
let description = schema_builder.add_text_field("description", tantivy::schema::TEXT);
|
||||||
"description",
|
let published_at = schema_builder.add_date_field("published_at", tantivy::schema::FAST);
|
||||||
tantivy::schema::TEXT | tantivy::schema::STORED,
|
|
||||||
);
|
|
||||||
|
|
||||||
let search_index = tantivy::Index::create_in_ram(schema_builder.build());
|
let search_index = tantivy::Index::create_in_ram(schema_builder.build());
|
||||||
let search_reader = search_index
|
let search_reader = search_index
|
||||||
|
@ -172,7 +170,8 @@ fn search_index(index: &GitIndex) -> (IndexReader, IndexWriter) {
|
||||||
.add_document(doc!(
|
.add_document(doc!(
|
||||||
name => package_name.to_string(),
|
name => package_name.to_string(),
|
||||||
version => entry.version.to_string(),
|
version => entry.version.to_string(),
|
||||||
description => entry.description.unwrap_or_default()
|
description => entry.description.unwrap_or_default(),
|
||||||
|
published_at => DateTime::from_timestamp_secs(entry.published_at.timestamp()),
|
||||||
))
|
))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
@ -267,7 +266,7 @@ fn main() -> std::io::Result<()> {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let generic_governor_config = GovernorConfigBuilder::default()
|
let generic_governor_config = GovernorConfigBuilder::default()
|
||||||
.burst_size(10)
|
.burst_size(50)
|
||||||
.per_second(10)
|
.per_second(10)
|
||||||
.use_headers()
|
.use_headers()
|
||||||
.finish()
|
.finish()
|
||||||
|
|
Loading…
Add table
Reference in a new issue