Skip to main content

scitadel_core/ports/
repository.rs

1use std::collections::HashMap;
2
3use crate::error::CoreError;
4use crate::models::{
5    Assessment, Citation, Paper, PaperId, ResearchQuestion, Search, SearchResult, SearchTerm,
6    SnowballRun,
7};
8
9/// Port for paper persistence.
10pub trait PaperRepository: Send + Sync {
11    fn save(&self, paper: &Paper) -> Result<(), CoreError>;
12    /// Save multiple papers, resolving DOI conflicts with existing records.
13    /// Returns a map of original_id → resolved_id for papers whose ID was
14    /// remapped to an existing record (callers should use this to fix up
15    /// search_results and other references).
16    fn save_many(&self, papers: &[Paper]) -> Result<HashMap<PaperId, PaperId>, CoreError>;
17    fn get(&self, paper_id: &str) -> Result<Option<Paper>, CoreError>;
18    fn find_by_doi(&self, doi: &str) -> Result<Option<Paper>, CoreError>;
19    fn find_by_title(&self, title: &str) -> Result<Option<Paper>, CoreError>;
20    fn list_all(&self, limit: i64, offset: i64) -> Result<Vec<Paper>, CoreError>;
21}
22
23/// Port for search run persistence.
24pub trait SearchRepository: Send + Sync {
25    fn save(&self, search: &Search) -> Result<(), CoreError>;
26    fn get(&self, search_id: &str) -> Result<Option<Search>, CoreError>;
27    fn save_results(&self, results: &[SearchResult]) -> Result<(), CoreError>;
28    fn get_results(&self, search_id: &str) -> Result<Vec<SearchResult>, CoreError>;
29    fn list_searches(&self, limit: i64) -> Result<Vec<Search>, CoreError>;
30    fn diff_searches(
31        &self,
32        search_id_a: &str,
33        search_id_b: &str,
34    ) -> Result<(Vec<String>, Vec<String>), CoreError>;
35}
36
37/// Port for research question and search term persistence.
38pub trait QuestionRepository: Send + Sync {
39    fn save_question(&self, question: &ResearchQuestion) -> Result<(), CoreError>;
40    fn get_question(&self, question_id: &str) -> Result<Option<ResearchQuestion>, CoreError>;
41    fn list_questions(&self) -> Result<Vec<ResearchQuestion>, CoreError>;
42    fn save_term(&self, term: &SearchTerm) -> Result<(), CoreError>;
43    fn get_terms(&self, question_id: &str) -> Result<Vec<SearchTerm>, CoreError>;
44}
45
46/// Port for relevance assessment persistence.
47pub trait AssessmentRepository: Send + Sync {
48    fn save(&self, assessment: &Assessment) -> Result<(), CoreError>;
49    fn get_for_paper(
50        &self,
51        paper_id: &str,
52        question_id: Option<&str>,
53    ) -> Result<Vec<Assessment>, CoreError>;
54    fn get_for_question(&self, question_id: &str) -> Result<Vec<Assessment>, CoreError>;
55}
56
57/// Port for citation edge and snowball run persistence.
58pub trait CitationRepository: Send + Sync {
59    fn save(&self, citation: &Citation) -> Result<(), CoreError>;
60    fn save_many(&self, citations: &[Citation]) -> Result<(), CoreError>;
61    fn get_references(&self, paper_id: &str) -> Result<Vec<Citation>, CoreError>;
62    fn get_citations(&self, paper_id: &str) -> Result<Vec<Citation>, CoreError>;
63    fn exists(
64        &self,
65        source_paper_id: &str,
66        target_paper_id: &str,
67        direction: &str,
68    ) -> Result<bool, CoreError>;
69    fn save_snowball_run(&self, run: &SnowballRun) -> Result<(), CoreError>;
70    fn get_snowball_run(&self, run_id: &str) -> Result<Option<SnowballRun>, CoreError>;
71    fn list_snowball_runs(&self, limit: i64) -> Result<Vec<SnowballRun>, CoreError>;
72}