@@ -56,7 +56,7 @@ public async Task<OperationSummary> CompressAsync(CompressOption option)
5656 _logger . LogInformation ( "Starting compression job" ) ;
5757 var po = ParallelizeOption ( option ) ;
5858
59- IRemoteStorage uploader = await option . GetRemoteStorageAsync ( _logger , _cancellationTokenSource . Token ) ;
59+ IEnumerable < IRemoteStorage > uploaders = await option . GetRemoteStoragesAsync ( _logger , _cancellationTokenSource . Token ) ;
6060
6161 var operationBlocks = await buffer
6262 . AsAsyncStream ( _cancellationTokenSource . Token )
@@ -81,90 +81,93 @@ public async Task<OperationSummary> CompressAsync(CompressOption option)
8181 return opb ;
8282 } , po )
8383 // Upload loop
84- . ParallelizeStreamAsync ( ( block , token ) => UploadBlockInternal ( uploader , option , block , token ) , new ParallelizeOption { FailMode = Fail . Smart , MaxDegreeOfParallelism = option . AzThread ?? 1 } )
84+ . ParallelizeStreamAsync ( ( block , token ) => UploadBlockInternal ( uploaders , option , block , token ) , new ParallelizeOption { FailMode = Fail . Smart , MaxDegreeOfParallelism = option . AzThread ?? 1 } )
8585 . AsReadOnlyCollectionAsync ( ) ;
8686
8787 sw . Stop ( ) ;
8888 return new OperationSummary ( operationBlocks , option . Threads , sw , option . SourceDirOrFile ) ;
8989 }
9090
91- private async Task < OperationCompressionBlock > UploadBlockInternal ( IRemoteStorage uploader , CompressOption option , OperationCompressionBlock block , CancellationToken token )
92- {
93- if ( uploader is NoneRemoteStorage )
94- {
95- return block ;
91+ private async Task < OperationCompressionBlock > UploadBlockInternal ( IEnumerable < IRemoteStorage > uploaders , CompressOption option , OperationCompressionBlock block , CancellationToken token )
92+ {
93+ foreach ( var uploader in uploaders )
94+ {
95+ if ( uploader is NoneRemoteStorage )
96+ {
97+ continue ;
98+ }
99+
100+ int count = Interlocked . Increment ( ref _uploadCounter ) ;
101+ string progress = $ "{ count } /{ _totalCounter } ";
102+
103+ var file = block . CompressionBlock . DestinationArchiveFileInfo ;
104+ var name = file . Name ;
105+ RetryContext ctx = null ;
106+ while ( true )
107+ {
108+ bool hasError ;
109+ try
110+ {
111+ var sw = Stopwatch . StartNew ( ) ;
112+
113+ var result = await uploader . UploadAsync ( file , block . CompressionBlock . FolderProvider . RootFolder , token ) ;
114+ hasError = ! result . IsSuccess ;
115+
116+ sw . Stop ( ) ;
117+ double speed = file . Length / sw . Elapsed . TotalSeconds ;
118+
119+ block . BlockResult . StepResults . Add ( new StepResult
120+ {
121+ Type = StepType . Upload ,
122+ UploadMode = uploader . GetMode ( ) ,
123+ Errors = result . IsSuccess ? null : result . ErrorMessage ,
124+ Infos = result . IsSuccess ? result . ErrorMessage : null ,
125+ Duration = sw . Elapsed ,
126+ ArchiveFileSize = file . Length ,
127+ } ) ;
128+
129+
130+ if ( ! hasError )
131+ {
132+ _logger . LogInformation ( $ "{ progress } Uploaded \" { file . Name } \" in { sw . Elapsed . HumanizedTimeSpan ( ) } at { speed . HumanizedBandwidth ( ) } ") ;
133+ }
134+ else
135+ {
136+ if ( ctx == null && option . RetryPeriodInSeconds . HasValue )
137+ {
138+ ctx = new RetryContext ( option . RetryPeriodInSeconds . Value ) ;
139+ }
140+ _logger . LogError ( $ "{ progress } Uploaded { file . Name } with errors. { result . ErrorMessage } ") ;
141+ }
142+ }
143+ catch ( Exception e )
144+ {
145+ hasError = true ;
146+ if ( ctx == null && option . RetryPeriodInSeconds . HasValue )
147+ {
148+ ctx = new RetryContext ( option . RetryPeriodInSeconds . Value ) ;
149+ }
150+ _logger . LogCritical ( e , $ "{ progress } Error uploading { name } ") ;
151+ }
152+
153+ if ( hasError )
154+ {
155+ if ( ctx != null && await ctx . WaitForNextRetry ( ) )
156+ {
157+ _logger . LogWarning ( $ "{ progress } Retrying uploading { name } , attempt #{ ctx . Retries } ") ;
158+ }
159+ else
160+ {
161+ break ;
162+ }
163+ }
164+ else
165+ {
166+ break ;
167+ }
168+ }
96169 }
97-
98- int count = Interlocked . Increment ( ref _uploadCounter ) ;
99- string progress = $ "{ count } /{ _totalCounter } ";
100-
101- var file = block . CompressionBlock . DestinationArchiveFileInfo ;
102- var name = file . Name ;
103- RetryContext ctx = null ;
104- while ( true )
105- {
106- bool hasError ;
107- try
108- {
109- var sw = Stopwatch . StartNew ( ) ;
110-
111- var result = await uploader . UploadAsync ( file , block . CompressionBlock . FolderProvider . RootFolder , token ) ;
112- hasError = ! result . IsSuccess ;
113-
114- sw . Stop ( ) ;
115- double speed = file . Length / sw . Elapsed . TotalSeconds ;
116-
117- block . BlockResult . StepResults . Add ( new StepResult
118- {
119- Type = StepType . Upload ,
120- Errors = result . IsSuccess ? null : result . ErrorMessage ,
121- Infos = result . IsSuccess ? result . ErrorMessage : null ,
122- Duration = sw . Elapsed ,
123- ArchiveFileSize = file . Length ,
124- } ) ;
125-
126-
127- if ( ! hasError )
128- {
129- _logger . LogInformation ( $ "{ progress } Uploaded \" { file . Name } \" in { sw . Elapsed . HumanizedTimeSpan ( ) } at { speed . HumanizedBandwidth ( ) } ") ;
130- }
131- else
132- {
133- if ( ctx == null && option . RetryPeriodInSeconds . HasValue )
134- {
135- ctx = new RetryContext ( option . RetryPeriodInSeconds . Value ) ;
136- }
137- _logger . LogError ( $ "{ progress } Uploaded { file . Name } with errors. { result . ErrorMessage } ") ;
138- }
139- }
140- catch ( Exception e )
141- {
142- hasError = true ;
143- if ( ctx == null && option . RetryPeriodInSeconds . HasValue )
144- {
145- ctx = new RetryContext ( option . RetryPeriodInSeconds . Value ) ;
146- }
147- _logger . LogCritical ( e , $ "{ progress } Error uploading { name } ") ;
148- }
149-
150- if ( hasError )
151- {
152- if ( ctx != null && await ctx . WaitForNextRetry ( ) )
153- {
154- _logger . LogWarning ( $ "{ progress } Retrying uploading { name } , attempt #{ ctx . Retries } ") ;
155- }
156- else
157- {
158- break ;
159- }
160- }
161- else
162- {
163- break ;
164- }
165- }
166-
167- return block ;
170+ return block ;
168171 }
169172
170173 private async Task CleanupOldFiles ( OperationCompressionBlock opb )
0 commit comments