@cloudbase/manager-node 3.11.0 → 3.11.1-beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -382,27 +382,32 @@ class StorageService {
382
382
  * @returns {Promise<(NodeJS.ReadableStream | string)[]>}
383
383
  */
384
384
  async downloadDirectory(options) {
385
- const { cloudPath, localPath } = options;
385
+ const { cloudPath, localPath, parallel = 20 } = options;
386
386
  const resolveLocalPath = path_1.default.resolve(localPath);
387
387
  utils_1.checkFullAccess(resolveLocalPath, true);
388
388
  const cloudDirectoryKey = this.getCloudKey(cloudPath);
389
389
  const files = await this.walkCloudDir(cloudDirectoryKey);
390
- const promises = files.map(async (file) => {
391
- const fileRelativePath = file.Key.replace(cloudDirectoryKey, '');
392
- // 空路径和文件夹跳过
393
- if (!fileRelativePath || /\/$/g.test(fileRelativePath)) {
394
- return;
395
- }
396
- const localFilePath = path_1.default.join(resolveLocalPath, fileRelativePath);
397
- // 创建文件的父文件夹
398
- const fileDir = path_1.default.dirname(localFilePath);
399
- await make_dir_1.default(fileDir);
400
- return this.downloadFile({
401
- cloudPath: file.Key,
402
- localPath: localFilePath
403
- });
390
+ const promises = files.map(file => async () => {
391
+ return this.downloadWithFilePath({ file, cloudDirectoryKey, resolveLocalPath });
404
392
  });
405
- return Promise.all(promises);
393
+ const asyncTaskController = new parallel_1.AsyncTaskParallelController(parallel, 50);
394
+ asyncTaskController.loadTasks(promises);
395
+ let res = await asyncTaskController.run();
396
+ const errorIndexArr = [];
397
+ res.map((item, index) => /Error/gi.test(Object.prototype.toString.call(item)) && errorIndexArr.push(index));
398
+ // 重试逻辑
399
+ if (errorIndexArr.length) {
400
+ const errorFiles = errorIndexArr.map(errorIndex => files[errorIndex]);
401
+ asyncTaskController.loadTasks(errorFiles.map(file => async () => {
402
+ return this.downloadWithFilePath({ file, cloudDirectoryKey, resolveLocalPath });
403
+ }));
404
+ res = await asyncTaskController.run();
405
+ }
406
+ const errorResultArr = this.determineDownLoadResultIsError(res);
407
+ if (errorResultArr.length) {
408
+ throw errorResultArr[0];
409
+ }
410
+ return res;
406
411
  }
407
412
  /**
408
413
  * 列出文件夹下的文件
@@ -911,6 +916,38 @@ class StorageService {
911
916
  }), interval);
912
917
  }
913
918
  }
919
+ /**
920
+ * 拼接路径下载单文件
921
+ * @param file
922
+ * @param cloudDirectoryKey
923
+ * @param resolveLocalPath
924
+ * @returns
925
+ */
926
+ async downloadWithFilePath({ file, cloudDirectoryKey, resolveLocalPath }) {
927
+ const fileRelativePath = file.Key.replace(cloudDirectoryKey, '');
928
+ // 空路径和文件夹跳过
929
+ if (!fileRelativePath || /\/$/g.test(fileRelativePath)) {
930
+ return;
931
+ }
932
+ const localFilePath = path_1.default.join(resolveLocalPath, fileRelativePath);
933
+ // 创建文件的父文件夹
934
+ const fileDir = path_1.default.dirname(localFilePath);
935
+ await make_dir_1.default(fileDir);
936
+ return this.downloadFile({
937
+ cloudPath: file.Key,
938
+ localPath: localFilePath
939
+ });
940
+ }
941
+ /**
942
+ * 根据下载结果返回错误列表
943
+ * @param res
944
+ * @returns
945
+ */
946
+ determineDownLoadResultIsError(res) {
947
+ const resultErrorArr = [];
948
+ res.map(item => /Error/gi.test(Object.prototype.toString.call(item)) && resultErrorArr.push(item));
949
+ return resultErrorArr;
950
+ }
914
951
  }
915
952
  __decorate([
916
953
  utils_1.preLazy()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudbase/manager-node",
3
- "version": "3.11.0",
3
+ "version": "3.11.1-beta",
4
4
  "description": "The node manage service api for cloudbase.",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {
@@ -62,7 +62,6 @@ export interface IFilesOptions extends IOptions {
62
62
  ignore?: string | string[]
63
63
  // 文件列表
64
64
  files: { localPath: string; cloudPath?: string }[]
65
-
66
65
  // 重试次数
67
66
  retryCount?: number
68
67
  // 重试时间间隔(毫秒)
@@ -146,8 +145,8 @@ export class StorageService {
146
145
  */
147
146
  @preLazy()
148
147
  public async uploadFiles(options: IFilesOptions): Promise<void> {
149
- const { files, onProgress, parallel, onFileFinish, ignore, retryCount,
150
- retryInterval } = options
148
+ const { files, onProgress, parallel, onFileFinish, ignore, retryCount, retryInterval } =
149
+ options
151
150
  const { bucket, region } = this.getStorageConfig()
152
151
 
153
152
  return this.uploadFilesCustom({
@@ -455,7 +454,6 @@ export class StorageService {
455
454
 
456
455
  const cos = this.getCos(parallel)
457
456
  const uploadFiles = Util.promisify(cos.uploadFiles).bind(cos)
458
-
459
457
  const params = {
460
458
  files: fileList,
461
459
  SliceSize: BIG_FILE_SIZE,
@@ -567,32 +565,42 @@ export class StorageService {
567
565
  public async downloadDirectory(options: {
568
566
  cloudPath: string
569
567
  localPath?: string
568
+ parallel?: number
570
569
  }): Promise<(NodeJS.ReadableStream | string)[]> {
571
- const { cloudPath, localPath } = options
570
+ const { cloudPath, localPath, parallel = 20 } = options
572
571
  const resolveLocalPath = path.resolve(localPath)
573
572
 
574
573
  checkFullAccess(resolveLocalPath, true)
575
574
 
576
575
  const cloudDirectoryKey = this.getCloudKey(cloudPath)
577
576
  const files = await this.walkCloudDir(cloudDirectoryKey)
578
-
579
- const promises = files.map(async file => {
580
- const fileRelativePath = file.Key.replace(cloudDirectoryKey, '')
581
- // 空路径和文件夹跳过
582
- if (!fileRelativePath || /\/$/g.test(fileRelativePath)) {
583
- return
584
- }
585
- const localFilePath = path.join(resolveLocalPath, fileRelativePath)
586
- // 创建文件的父文件夹
587
- const fileDir = path.dirname(localFilePath)
588
- await makeDir(fileDir)
589
- return this.downloadFile({
590
- cloudPath: file.Key,
591
- localPath: localFilePath
592
- })
577
+ const promises = files.map(file => async () => {
578
+ return this.downloadWithFilePath({ file, cloudDirectoryKey, resolveLocalPath })
593
579
  })
580
+ const asyncTaskController = new AsyncTaskParallelController(parallel, 50)
581
+ asyncTaskController.loadTasks(promises)
582
+ let res = await asyncTaskController.run()
583
+ const errorIndexArr = []
594
584
 
595
- return Promise.all(promises)
585
+ res.map(
586
+ (item, index) =>
587
+ /Error/gi.test(Object.prototype.toString.call(item)) && errorIndexArr.push(index)
588
+ )
589
+ // 重试逻辑
590
+ if (errorIndexArr.length) {
591
+ const errorFiles = errorIndexArr.map(errorIndex => files[errorIndex])
592
+ asyncTaskController.loadTasks(
593
+ errorFiles.map(file => async () => {
594
+ return this.downloadWithFilePath({ file, cloudDirectoryKey, resolveLocalPath })
595
+ })
596
+ )
597
+ res = await asyncTaskController.run()
598
+ }
599
+ const errorResultArr = this.determineDownLoadResultIsError(res)
600
+ if (errorResultArr.length) {
601
+ throw errorResultArr[0]
602
+ }
603
+ return res
596
604
  }
597
605
 
598
606
  /**
@@ -1219,4 +1227,41 @@ export class StorageService {
1219
1227
  )
1220
1228
  }
1221
1229
  }
1230
+
1231
+ /**
1232
+ * 拼接路径下载单文件
1233
+ * @param file
1234
+ * @param cloudDirectoryKey
1235
+ * @param resolveLocalPath
1236
+ * @returns
1237
+ */
1238
+ private async downloadWithFilePath({ file, cloudDirectoryKey, resolveLocalPath }) {
1239
+ const fileRelativePath = file.Key.replace(cloudDirectoryKey, '')
1240
+ // 空路径和文件夹跳过
1241
+ if (!fileRelativePath || /\/$/g.test(fileRelativePath)) {
1242
+ return
1243
+ }
1244
+ const localFilePath = path.join(resolveLocalPath, fileRelativePath)
1245
+ // 创建文件的父文件夹
1246
+ const fileDir = path.dirname(localFilePath)
1247
+ await makeDir(fileDir)
1248
+ return this.downloadFile({
1249
+ cloudPath: file.Key,
1250
+ localPath: localFilePath
1251
+ })
1252
+ }
1253
+
1254
+ /**
1255
+ * 根据下载结果返回错误列表
1256
+ * @param res
1257
+ * @returns
1258
+ */
1259
+ private determineDownLoadResultIsError(res) {
1260
+ const resultErrorArr = []
1261
+ res.map(
1262
+ item =>
1263
+ /Error/gi.test(Object.prototype.toString.call(item)) && resultErrorArr.push(item)
1264
+ )
1265
+ return resultErrorArr
1266
+ }
1222
1267
  }
@@ -151,6 +151,7 @@ export declare class StorageService {
151
151
  downloadDirectory(options: {
152
152
  cloudPath: string;
153
153
  localPath?: string;
154
+ parallel?: number;
154
155
  }): Promise<(NodeJS.ReadableStream | string)[]>;
155
156
  /**
156
157
  * 列出文件夹下的文件
@@ -305,5 +306,19 @@ export declare class StorageService {
305
306
  * @returns
306
307
  */
307
308
  private uploadFilesWithRetry;
309
+ /**
310
+ * 拼接路径下载单文件
311
+ * @param file
312
+ * @param cloudDirectoryKey
313
+ * @param resolveLocalPath
314
+ * @returns
315
+ */
316
+ private downloadWithFilePath;
317
+ /**
318
+ * 根据下载结果返回错误列表
319
+ * @param res
320
+ * @returns
321
+ */
322
+ private determineDownLoadResultIsError;
308
323
  }
309
324
  export {};