agtrace_runtime/client/
projects.rs1use crate::Result;
2use crate::ops::{IndexProgress, IndexService, ProjectInfo, ProjectService};
3use agtrace_index::Database;
4use agtrace_providers::ProviderAdapter;
5use std::path::PathBuf;
6use std::sync::{Arc, Mutex};
7
8#[derive(Debug, Clone)]
9pub struct ScanSummary {
10 pub total_sessions: usize,
11 pub scanned_files: usize,
12 pub skipped_files: usize,
13}
14
15pub struct ProjectOps {
16 db: Arc<Mutex<Database>>,
17 provider_configs: Arc<Vec<(String, PathBuf)>>,
18}
19
20impl ProjectOps {
21 pub fn new(db: Arc<Mutex<Database>>, provider_configs: Arc<Vec<(String, PathBuf)>>) -> Self {
22 Self {
23 db,
24 provider_configs,
25 }
26 }
27
28 pub fn list(&self) -> Result<Vec<ProjectInfo>> {
29 self.ensure_index_is_fresh()?;
30
31 let db = self.db.lock().unwrap();
32 let service = ProjectService::new(&db);
33 service.list_projects()
34 }
35
36 fn ensure_index_is_fresh(&self) -> Result<()> {
37 let db = self.db.lock().unwrap();
38
39 let providers: Vec<(ProviderAdapter, PathBuf)> = self
40 .provider_configs
41 .iter()
42 .filter_map(|(name, path)| {
43 agtrace_providers::create_adapter(name)
44 .ok()
45 .map(|p| (p, path.clone()))
46 })
47 .collect();
48
49 let service = IndexService::new(&db, providers);
50
51 let scope = agtrace_types::ProjectScope::All;
53
54 service.run(scope, false, |_progress: IndexProgress| {})?;
55
56 Ok(())
57 }
58
59 pub fn scan<F>(
60 &self,
61 scope: agtrace_types::ProjectScope,
62 force: bool,
63 provider_filter: Option<&str>,
64 mut on_progress: F,
65 ) -> Result<ScanSummary>
66 where
67 F: FnMut(IndexProgress),
68 {
69 let db = self.db.lock().unwrap();
70 let providers: Vec<(ProviderAdapter, PathBuf)> = self
71 .provider_configs
72 .iter()
73 .filter_map(|(name, path)| {
74 if let Some(filter) = provider_filter
76 && filter != "all"
77 && name != filter
78 {
79 return None;
80 }
81 agtrace_providers::create_adapter(name)
82 .ok()
83 .map(|p| (p, path.clone()))
84 })
85 .collect();
86 let service = IndexService::new(&db, providers);
87
88 let mut total_sessions = 0;
89 let mut scanned_files = 0;
90 let mut skipped_files = 0;
91
92 service.run(scope, force, |progress| {
93 if let IndexProgress::Completed {
94 total_sessions: ts,
95 scanned_files: sf,
96 skipped_files: skf,
97 } = progress
98 {
99 total_sessions = ts;
100 scanned_files = sf;
101 skipped_files = skf;
102 }
103 on_progress(progress);
104 })?;
105
106 Ok(ScanSummary {
107 total_sessions,
108 scanned_files,
109 skipped_files,
110 })
111 }
112}