|
4 | 4 | use crate::git; |
5 | 5 | use crate::link::{LinkCheckResult, check_link}; |
6 | 6 | use chrono::Local; |
| 7 | +use once_cell::sync::Lazy; |
| 8 | +use std::collections::HashMap; |
| 9 | +use std::sync::Mutex; |
7 | 10 | use std::time::Duration; |
| 11 | +use tokio_util::sync::CancellationToken; |
| 12 | + |
| 13 | +static REPO_TASKS: Lazy<Mutex<HashMap<String, CancellationToken>>> = |
| 14 | + Lazy::new(|| Mutex::new(HashMap::new())); |
8 | 15 |
|
9 | 16 | pub async fn check_repository_links(repo_url: &str, interval_duration: Duration) { |
| 17 | + let token = CancellationToken::new(); |
| 18 | + { |
| 19 | + let mut map = REPO_TASKS.lock().unwrap(); |
| 20 | + map.insert(repo_url.to_string(), token.clone()); |
| 21 | + } |
10 | 22 | let mut interval = tokio::time::interval(interval_duration); |
11 | | - |
12 | 23 | loop { |
13 | | - interval.tick().await; |
14 | | - let current_time = Local::now().format("%Y-%m-%d %H:%M:%S").to_string(); |
15 | | - println!("[{}] 링크 확인 중", current_time); |
16 | | - |
17 | | - match git::extract_links_from_repo_url(repo_url) { |
18 | | - Ok(links) => { |
19 | | - let mut handles = Vec::new(); |
20 | | - for link in links { |
21 | | - let handle = tokio::spawn(async move { |
22 | | - let result = check_link(&link).await; |
23 | | - (link, result) |
24 | | - }); |
25 | | - handles.push(handle); |
26 | | - } |
27 | | - |
28 | | - for handle in handles { |
29 | | - if let Ok((link, LinkCheckResult::Invalid(message))) = handle.await { |
30 | | - println!("유효하지 않은 링크: '{}', 실패 원인: {}", link, message); |
| 24 | + tokio::select! { |
| 25 | + _ = interval.tick() => { |
| 26 | + let current_time = Local::now().format("%Y-%m-%d %H:%M:%S").to_string(); |
| 27 | + println!("[{}] 링크 확인 중", current_time); |
| 28 | + match git::extract_links_from_repo_url(repo_url) { |
| 29 | + Ok(links) => { |
| 30 | + let mut handles = Vec::new(); |
| 31 | + for link in links { |
| 32 | + let handle = tokio::spawn(async move { |
| 33 | + let result = check_link(&link).await; |
| 34 | + (link, result) |
| 35 | + }); |
| 36 | + handles.push(handle); |
| 37 | + } |
| 38 | + for handle in handles { |
| 39 | + if let Ok((link, LinkCheckResult::Invalid(message))) = handle.await { |
| 40 | + println!("유효하지 않은 링크: '{}', 실패 원인: {}", link, message); |
| 41 | + } |
| 42 | + } |
31 | 43 | } |
| 44 | + Err(e) => println!("Repository 처리 중 오류 발생: {}", e), |
32 | 45 | } |
| 46 | + println!("링크 확인 완료. 다음 간격 대기..."); |
| 47 | + }, |
| 48 | + // This branch listens for the `CancellationToken` to be triggered, |
| 49 | + // allowing the periodic check loop to terminate cleanly upon cancellation. |
| 50 | + _ = token.cancelled() => { |
| 51 | + println!("[{}] 체크 작업이 취소되었습니다.", repo_url); |
| 52 | + break; |
33 | 53 | } |
34 | | - Err(e) => println!("Repository 처리 중 오류 발생: {}", e), |
35 | 54 | } |
| 55 | + } |
| 56 | + let mut map = REPO_TASKS.lock().unwrap(); |
| 57 | + map.remove(repo_url); |
| 58 | +} |
36 | 59 |
|
37 | | - println!("링크 확인 완료. 다음 간격 대기..."); |
| 60 | +pub async fn cancel_repository_checker(repo_url: &str) { |
| 61 | + let token = { |
| 62 | + let mut map = REPO_TASKS.lock().unwrap(); |
| 63 | + map.remove(repo_url) |
| 64 | + }; |
| 65 | + if let Some(token) = token { |
| 66 | + token.cancel(); |
| 67 | + println!("[{}] 체크 작업 취소 요청됨.", repo_url); |
| 68 | + } else { |
| 69 | + println!("[{}] 체크 작업이 존재하지 않습니다.", repo_url); |
38 | 70 | } |
39 | 71 | } |
40 | 72 |
|
|
0 commit comments