1+ use crate :: core:: state:: AppState ;
12use crate :: core:: utils:: download:: { download, DownloadEvent , DownloadEventType } ;
23use std:: path:: Path ;
34use std:: sync:: { Arc , Mutex } ;
4- use tauri:: { AppHandle , Emitter } ;
5+ use tauri:: { AppHandle , Emitter , State } ;
6+ use tokio_util:: sync:: CancellationToken ;
57
68// task_id is only for compatibility with current Jan+Cortex we can remove it later
79// should we disallow custom save_dir? i.e. all HF models will be downloaded to
@@ -10,12 +12,22 @@ use tauri::{AppHandle, Emitter};
1012#[ tauri:: command]
1113pub async fn download_hf_repo (
1214 app : AppHandle ,
15+ state : State < ' _ , AppState > ,
1316 task_id : & str ,
1417 repo_id : & str ,
1518 branch : & str ,
1619 save_dir : & Path ,
1720) -> Result < ( ) , String > {
18- // TODO: check if it has been downloaded
21+ // TODO: check if it has been/is being downloaded
22+
23+ // check if task_id already exists
24+ {
25+ let download_manager = state. download_manager . lock ( ) . await ;
26+ if download_manager. cancel_tokens . contains_key ( task_id) {
27+ return Err ( format ! ( "Task ID {} already exists" , task_id) ) ;
28+ }
29+ }
30+
1931 let files = list_files ( repo_id, branch)
2032 . await
2133 . map_err ( |e| format ! ( "Failed to list files {}" , e) ) ?;
@@ -33,6 +45,15 @@ pub async fn download_hf_repo(
3345 app. emit ( "download" , info_arc. lock ( ) . unwrap ( ) . clone ( ) )
3446 . unwrap ( ) ;
3547
48+ // insert cancel tokens
49+ let cancel_token = CancellationToken :: new ( ) ;
50+ {
51+ let mut download_manager = state. download_manager . lock ( ) . await ;
52+ download_manager
53+ . cancel_tokens
54+ . insert ( task_id. to_string ( ) , cancel_token. clone ( ) ) ;
55+ }
56+
3657 let download_result = async {
3758 // NOTE: currently we are downloading sequentially. we can spawn tokio tasks
3859 // to download files in parallel.
@@ -55,13 +76,27 @@ pub async fn download_hf_repo(
5576 app. emit ( "download" , info. clone ( ) ) . unwrap ( ) ;
5677 }
5778 } ;
58- download ( & url, & full_path, Some ( callback) )
79+ download ( & url, & full_path, Some ( cancel_token . clone ( ) ) , Some ( callback) )
5980 . await
6081 . map_err ( |e| format ! ( "Failed to download file {}: {}" , file. path, e) ) ?;
6182 }
6283 Ok ( ( ) )
6384 }
6485 . await ;
86+
87+ // cleanup
88+ {
89+ let mut download_manager = state. download_manager . lock ( ) . await ;
90+ download_manager. cancel_tokens . remove ( task_id) ;
91+
92+ if cancel_token. is_cancelled ( ) && save_dir. exists ( ) {
93+ // NOTE: we don't check error here
94+ let _ = std:: fs:: remove_dir_all ( save_dir) ;
95+ }
96+ }
97+
98+ // report results
99+ // TODO: what if it is cancelled? do we still emit success?
65100 match download_result {
66101 Ok ( _) => {
67102 let mut info = info_arc. lock ( ) . unwrap ( ) ;
0 commit comments