Skip to content

Commit 6ab2a75

Browse files
Merge pull request #33 from reddevilmidzy/api
링크 확인 작업 취소 API 추가 및 링크 확인 작업 비동기 처리
2 parents b3c635c + 316b20d commit 6ab2a75

File tree

4 files changed

+70
-23
lines changed

4 files changed

+70
-23
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ chrono = "0.4"
1313
regex = "1"
1414
reqwest = { version = "0.12", features = ["json"] }
1515
tokio = { version = "1", features = ["full"] }
16+
tokio-util = "0.7"
1617
git2 = "0.20"
1718
serde = { version = "1.0", features = ["derive"] }
1819
serde_json = "1.0"
20+
once_cell = "1.18"

src/main.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
use queensac::check_repository_links;
1+
use queensac::{cancel_repository_checker, check_repository_links};
22

33
use axum::{
44
Json, Router,
5-
routing::{get, post},
5+
routing::{delete, get, post},
66
serve,
77
};
88
use serde::Deserialize;
@@ -32,6 +32,16 @@ async fn check_handler(Json(payload): Json<CheckRequest>) -> &'static str {
3232
"Repository checker started"
3333
}
3434

35+
#[derive(Deserialize)]
36+
struct CancelRequest {
37+
repo_url: String,
38+
}
39+
40+
async fn cancel_handler(Json(payload): Json<CancelRequest>) -> &'static str {
41+
cancel_repository_checker(&payload.repo_url).await;
42+
"Repository checker cancelled"
43+
}
44+
3545
#[tokio::main]
3646
async fn main() {
3747
let app = app();
@@ -45,4 +55,5 @@ fn app() -> Router {
4555
.route("/", get(|| async { "Sacrifice the Queen!!" }))
4656
.route("/health", get(health_check))
4757
.route("/check", post(check_handler))
58+
.route("/cancel", delete(cancel_handler))
4859
}

src/schedule/mod.rs

Lines changed: 53 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,37 +4,69 @@
44
use crate::git;
55
use crate::link::{LinkCheckResult, check_link};
66
use chrono::Local;
7+
use once_cell::sync::Lazy;
8+
use std::collections::HashMap;
9+
use std::sync::Mutex;
710
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()));
815

916
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+
}
1022
let mut interval = tokio::time::interval(interval_duration);
11-
1223
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+
}
3143
}
44+
Err(e) => println!("Repository 처리 중 오류 발생: {}", e),
3245
}
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;
3353
}
34-
Err(e) => println!("Repository 처리 중 오류 발생: {}", e),
3554
}
55+
}
56+
let mut map = REPO_TASKS.lock().unwrap();
57+
map.remove(repo_url);
58+
}
3659

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);
3870
}
3971
}
4072

0 commit comments

Comments
 (0)