1use api::{GQLLeetcodeRequest, QuestionRequest};
2use color_eyre::Result;
3use kdam::BarExt;
4use leetcode_core as api;
5use leetcode_tui_core::emit;
6use leetcode_tui_db::DbQuestion;
7
8fn should_update_db(runs_inside_tui: bool) -> Result<bool> {
9 let first_time_start = DbQuestion::get_total_questions()? == 0 && !runs_inside_tui;
10 if first_time_start || runs_inside_tui {
11 return Ok(true);
12 } else {
13 return Ok(false);
14 }
15}
16
17pub async fn update_database_questions(runs_inside_tui: bool) -> Result<()> {
18 if !should_update_db(runs_inside_tui)? {
19 return Ok(());
20 }
21
22 let query = api::QuestionRequest::default();
23 let query_response = query.send().await?;
24 let total_questions = query_response.get_total_questions();
25
26 let chunk_size = 1000;
27 let total_pages = (total_questions + chunk_size - 1) / chunk_size;
28
29 let mut handles = vec![];
30
31 for page in 0..(total_pages) {
32 let skip = page * chunk_size;
33 let take = chunk_size.min(total_questions - skip);
34
35 let join_handle = tokio::spawn(async move {
37 let resp = QuestionRequest::new(take, skip).send().await.unwrap();
38 let questions = resp.get_questions();
39 let db_questions = questions
40 .into_iter()
41 .map(|q| q.try_into().unwrap())
42 .collect::<Vec<DbQuestion>>();
43
44 db_questions
45 });
46
47 handles.push(join_handle);
48 }
49
50 let mut cli_progress_bar = kdam::tqdm!(total = total_questions as usize);
51 let mut all_questions = vec![];
52 for handle in handles {
53 let questions_result = handle.await.unwrap();
54 all_questions.extend(questions_result);
55
56 if runs_inside_tui {
58 let inside_tui_progress_bar_title = "Syncing db...".into();
60 emit!(ProgressUpdate(
61 inside_tui_progress_bar_title,
62 all_questions.len() as u32,
63 total_questions as u32
64 ))
65 } else {
66 cli_progress_bar.update(chunk_size as usize).unwrap();
68 }
69 }
70
71 DbQuestion::save_multiple_to_db(all_questions);
72 Ok(())
73}