@@ -13,6 +13,8 @@ import { firstValueFrom } from 'rxjs';
1313@Injectable ( )
1414export class DownloadManagerService {
1515 private allDownloadStates : DownloadState [ ] = [ ] ;
16+ private abortControllers : Record < string , Record < string , AbortController > > =
17+ { } ;
1618
1719 constructor (
1820 private readonly httpService : HttpService ,
@@ -24,6 +26,19 @@ export class DownloadManagerService {
2426 } , 500 ) ;
2527 }
2628
29+ async abortDownload ( downloadId : string ) {
30+ if ( ! this . abortControllers [ downloadId ] ) {
31+ return ;
32+ }
33+ Object . keys ( this . abortControllers [ downloadId ] ) . forEach ( ( destination ) => {
34+ this . abortControllers [ downloadId ] [ destination ] . abort ( ) ;
35+ } ) ;
36+ delete this . abortControllers [ downloadId ] ;
37+ this . allDownloadStates = this . allDownloadStates . filter (
38+ ( downloadState ) => downloadState . id !== downloadId ,
39+ ) ;
40+ }
41+
2742 async submitDownloadRequest (
2843 downloadId : string ,
2944 title : string ,
@@ -67,6 +82,7 @@ export class DownloadManagerService {
6782 } ;
6883
6984 this . allDownloadStates . push ( downloadState ) ;
85+ this . abortControllers [ downloadId ] = { } ;
7086
7187 Object . keys ( urlToDestination ) . forEach ( ( url ) => {
7288 const destination = urlToDestination [ url ] ;
@@ -79,11 +95,17 @@ export class DownloadManagerService {
7995 url : string ,
8096 destination : string ,
8197 ) {
98+ const controller = new AbortController ( ) ;
99+ // adding to abort controllers
100+ this . abortControllers [ downloadId ] [ destination ] = controller ;
101+
82102 const response = await firstValueFrom (
83103 this . httpService . get ( url , {
84104 responseType : 'stream' ,
105+ signal : controller . signal ,
85106 } ) ,
86107 ) ;
108+
87109 // check if response is success
88110 if ( ! response ) {
89111 throw new Error ( 'Failed to download model' ) ;
@@ -93,7 +115,6 @@ export class DownloadManagerService {
93115 const totalBytes = response . headers [ 'content-length' ] ;
94116
95117 // update download state
96- // TODO: separte this duplicate code to a function
97118 const currentDownloadState = this . allDownloadStates . find (
98119 ( downloadState ) => downloadState . id === downloadId ,
99120 ) ;
@@ -110,6 +131,8 @@ export class DownloadManagerService {
110131 let transferredBytes = 0 ;
111132
112133 writer . on ( 'finish' , ( ) => {
134+ // delete the abort controller
135+ delete this . abortControllers [ downloadId ] [ destination ] ;
113136 const currentDownloadState = this . allDownloadStates . find (
114137 ( downloadState ) => downloadState . id === downloadId ,
115138 ) ;
@@ -130,8 +153,8 @@ export class DownloadManagerService {
130153 ) ;
131154
132155 if ( allChildrenDownloaded ) {
156+ delete this . abortControllers [ downloadId ] ;
133157 currentDownloadState . status = DownloadStatus . Downloaded ;
134- // TODO: notify if download success so that client can auto refresh
135158 // remove download state if all children is downloaded
136159 this . allDownloadStates = this . allDownloadStates . filter (
137160 ( downloadState ) => downloadState . id !== downloadId ,
@@ -140,6 +163,7 @@ export class DownloadManagerService {
140163 } ) ;
141164
142165 writer . on ( 'error' , ( error ) => {
166+ delete this . abortControllers [ downloadId ] [ destination ] ;
143167 const currentDownloadState = this . allDownloadStates . find (
144168 ( downloadState ) => downloadState . id === downloadId ,
145169 ) ;
@@ -158,7 +182,6 @@ export class DownloadManagerService {
158182 currentDownloadState . status = DownloadStatus . Error ;
159183 currentDownloadState . error = error . message ;
160184
161- // TODO: notify if download error
162185 // remove download state if all children is downloaded
163186 this . allDownloadStates = this . allDownloadStates . filter (
164187 ( downloadState ) => downloadState . id !== downloadId ,
0 commit comments