@cloudbase/manager-node 3.11.0 → 3.12.1

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.
@@ -628,6 +628,121 @@ class FunctionService {
628
628
  LayerVersion: version
629
629
  });
630
630
  }
631
+ /**
632
+ * 设置预置并发
633
+ * @private
634
+ * @param {IProvisionedConcurrencyConfig} concurrencyConfig
635
+ * @returns
636
+ * @memberof FunctionService
637
+ */
638
+ async setProvisionedConcurrencyConfig(concurrencyConfig) {
639
+ const { namespace } = this.getFunctionConfig();
640
+ const { functionName: FunctionName, qualifier: Qualifier, versionProvisionedConcurrencyNum: VersionProvisionedConcurrencyNum } = concurrencyConfig;
641
+ return this.scfService.request('PutProvisionedConcurrencyConfig', {
642
+ FunctionName,
643
+ Qualifier,
644
+ VersionProvisionedConcurrencyNum,
645
+ Namespace: namespace
646
+ });
647
+ }
648
+ /**
649
+ * 获取函数预置并发详情
650
+ * @private
651
+ * @param {IGetProvisionedConcurrencyConfig} concurrencyConfig
652
+ * @returns {Promise<IGetProvisionedConcurrencyRes>}
653
+ * @memberof FunctionService
654
+ */
655
+ async getProvisionedConcurrencyConfig(concurrencyConfig) {
656
+ const { namespace } = this.getFunctionConfig();
657
+ const { functionName: FunctionName, qualifier: Qualifier } = concurrencyConfig;
658
+ return this.scfService.request('GetProvisionedConcurrencyConfig', {
659
+ FunctionName,
660
+ Qualifier,
661
+ Namespace: namespace
662
+ });
663
+ }
664
+ /**
665
+ * 删除预置并发
666
+ * @private
667
+ * @param {IGetProvisionedConcurrencyConfig} concurrencyConfig
668
+ * @returns {Promise<IResponseInfo>}
669
+ * @memberof FunctionService
670
+ */
671
+ async deleteProvisionedConcurrencyConfig(concurrencyConfig) {
672
+ const { namespace } = this.getFunctionConfig();
673
+ const { functionName: FunctionName, qualifier: Qualifier } = concurrencyConfig;
674
+ return this.scfService.request('DeleteProvisionedConcurrencyConfig', {
675
+ FunctionName,
676
+ Qualifier,
677
+ Namespace: namespace
678
+ });
679
+ }
680
+ /**
681
+ * 发布新版本
682
+ * @param {IPublishVersionParams} publishParams
683
+ * @returns {Promise<IPublishVersionRes>}
684
+ * @memberof FunctionService
685
+ */
686
+ async publishVersion(publishParams) {
687
+ const { namespace } = this.getFunctionConfig();
688
+ const { functionName: FunctionName, description: Description } = publishParams;
689
+ return this.scfService.request('PublishVersion', {
690
+ FunctionName,
691
+ Description,
692
+ Namespace: namespace
693
+ });
694
+ }
695
+ /**
696
+ * 查询函数版本详情
697
+ * @param {IListFunctionVersionParams} listVersionParams
698
+ * @returns {Promise<IFunctionVersionsRes>}
699
+ * @memberof FunctionService
700
+ */
701
+ async listVersionByFunction(listVersionParams) {
702
+ const { namespace } = this.getFunctionConfig();
703
+ const { functionName: FunctionName, offset: Offset, limit: Limit, order: Order, orderBy: OrderBy } = listVersionParams;
704
+ return this.scfService.request('ListVersionByFunction', {
705
+ FunctionName,
706
+ Namespace: namespace,
707
+ Offset,
708
+ Limit,
709
+ Order,
710
+ OrderBy
711
+ });
712
+ }
713
+ /**
714
+ *
715
+ * @param {IUpdateFunctionAliasConfig} updateVersionConfigParams
716
+ * @returns {Promise<IResponseInfo>}
717
+ * @memberof FunctionService
718
+ */
719
+ async updateFunctionAliasConfig(updateVersionConfigParams) {
720
+ const { namespace } = this.getFunctionConfig();
721
+ const { functionName: FunctionName, name: Name, functionVersion: FunctionVersion, routingConfig: RoutingConfig, description: Description } = updateVersionConfigParams;
722
+ return this.scfService.request('UpdateAlias', {
723
+ FunctionName,
724
+ Name,
725
+ Namespace: namespace,
726
+ FunctionVersion,
727
+ RoutingConfig,
728
+ Description
729
+ });
730
+ }
731
+ /**
732
+ * 查询函数别名详情
733
+ * @param {IGetFunctionAlias} params
734
+ * @returns {Promise<IGetFunctionAliasRes>}
735
+ * @memberof FunctionService
736
+ */
737
+ async getFunctionAlias(params) {
738
+ const { namespace } = this.getFunctionConfig();
739
+ const { functionName: FunctionName, name: Name } = params;
740
+ return this.scfService.request('GetAlias', {
741
+ FunctionName,
742
+ Name,
743
+ Namespace: namespace
744
+ });
745
+ }
631
746
  async createAccessPath(name, path) {
632
747
  const access = this.environment.getAccessService();
633
748
  try {
@@ -856,6 +971,27 @@ __decorate([
856
971
  __decorate([
857
972
  utils_1.preLazy()
858
973
  ], FunctionService.prototype, "getLayerVersion", null);
974
+ __decorate([
975
+ utils_1.preLazy()
976
+ ], FunctionService.prototype, "setProvisionedConcurrencyConfig", null);
977
+ __decorate([
978
+ utils_1.preLazy()
979
+ ], FunctionService.prototype, "getProvisionedConcurrencyConfig", null);
980
+ __decorate([
981
+ utils_1.preLazy()
982
+ ], FunctionService.prototype, "deleteProvisionedConcurrencyConfig", null);
983
+ __decorate([
984
+ utils_1.preLazy()
985
+ ], FunctionService.prototype, "publishVersion", null);
986
+ __decorate([
987
+ utils_1.preLazy()
988
+ ], FunctionService.prototype, "listVersionByFunction", null);
989
+ __decorate([
990
+ utils_1.preLazy()
991
+ ], FunctionService.prototype, "updateFunctionAliasConfig", null);
992
+ __decorate([
993
+ utils_1.preLazy()
994
+ ], FunctionService.prototype, "getFunctionAlias", null);
859
995
  __decorate([
860
996
  utils_1.preLazy()
861
997
  ], FunctionService.prototype, "createAccessPath", null);
@@ -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
  * 列出文件夹下的文件
@@ -889,27 +894,73 @@ class StorageService {
889
894
  async uploadFilesWithRetry({ uploadFiles, options, times, interval, failedFiles }) {
890
895
  const { files, onFileFinish } = options;
891
896
  const tempFailedFiles = [];
897
+ let curError = null;
892
898
  const res = await uploadFiles(Object.assign(Object.assign({}, options), { files: failedFiles.length
893
899
  ? files.filter(file => failedFiles.includes(file.Key))
894
900
  : files, onFileFinish: (...args) => {
895
901
  const error = args[0];
896
902
  const fileInfo = args[2];
897
903
  if (error) {
904
+ curError = error;
898
905
  tempFailedFiles.push(fileInfo.Key);
899
906
  }
900
907
  onFileFinish === null || onFileFinish === void 0 ? void 0 : onFileFinish.apply(null, args);
901
908
  } }));
902
- if (!(tempFailedFiles === null || tempFailedFiles === void 0 ? void 0 : tempFailedFiles.length) || times <= 0)
909
+ // if (!tempFailedFiles?.length || times <= 0) return res
910
+ if (!(tempFailedFiles === null || tempFailedFiles === void 0 ? void 0 : tempFailedFiles.length)) {
903
911
  return res;
904
- if (times > 0) {
905
- setTimeout(() => this.uploadFilesWithRetry({
906
- uploadFiles,
907
- options,
908
- times: times - 1,
909
- interval,
910
- failedFiles: tempFailedFiles
911
- }), interval);
912
912
  }
913
+ else {
914
+ if (times > 0) {
915
+ return await new Promise((resolve, reject) => {
916
+ setTimeout(() => this.uploadFilesWithRetry({
917
+ uploadFiles,
918
+ options,
919
+ times: times - 1,
920
+ interval,
921
+ failedFiles: tempFailedFiles
922
+ }).then(res => resolve(res))
923
+ .catch(err => reject(err)), interval);
924
+ });
925
+ }
926
+ else {
927
+ if (curError) {
928
+ throw curError;
929
+ }
930
+ }
931
+ }
932
+ }
933
+ /**
934
+ * 拼接路径下载单文件
935
+ * @param file
936
+ * @param cloudDirectoryKey
937
+ * @param resolveLocalPath
938
+ * @returns
939
+ */
940
+ async downloadWithFilePath({ file, cloudDirectoryKey, resolveLocalPath }) {
941
+ const fileRelativePath = file.Key.replace(cloudDirectoryKey, '');
942
+ // 空路径和文件夹跳过
943
+ if (!fileRelativePath || /\/$/g.test(fileRelativePath)) {
944
+ return;
945
+ }
946
+ const localFilePath = path_1.default.join(resolveLocalPath, fileRelativePath);
947
+ // 创建文件的父文件夹
948
+ const fileDir = path_1.default.dirname(localFilePath);
949
+ await make_dir_1.default(fileDir);
950
+ return this.downloadFile({
951
+ cloudPath: file.Key,
952
+ localPath: localFilePath
953
+ });
954
+ }
955
+ /**
956
+ * 根据下载结果返回错误列表
957
+ * @param res
958
+ * @returns
959
+ */
960
+ determineDownLoadResultIsError(res) {
961
+ const resultErrorArr = [];
962
+ res.map(item => /Error/gi.test(Object.prototype.toString.call(item)) && resultErrorArr.push(item));
963
+ return resultErrorArr;
913
964
  }
914
965
  }
915
966
  __decorate([
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudbase/manager-node",
3
- "version": "3.11.0",
3
+ "version": "3.12.1",
4
4
  "description": "The node manage service api for cloudbase.",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {
@@ -126,6 +126,107 @@ export interface IGetLayerVersionRes extends IResponseInfo {
126
126
  Status: string // 层的具体版本当前状态
127
127
  }
128
128
 
129
+ export interface ISetProvisionedConcurrencyConfig {
130
+ functionName: string
131
+ qualifier: string
132
+ versionProvisionedConcurrencyNum: number
133
+ }
134
+
135
+ export interface IGetProvisionedConcurrencyConfig {
136
+ functionName: string
137
+ qualifier?: string
138
+ }
139
+
140
+ export interface IVersionProvisionedConcurrencyInfo {
141
+ AllocatedProvisionedConcurrencyNum: number // 设置的预置并发数。
142
+ AvailableProvisionedConcurrencyNum: number // 当前已完成预置的并发数。
143
+ Status: string // 预置任务状态,Done表示已完成,InProgress表示进行中,Failed表示部分或全部失败。
144
+ StatusReason: string // 对预置任务状态Status的说明。
145
+ Qualifier: string // 版本号
146
+ }
147
+ export interface IGetProvisionedConcurrencyRes extends IResponseInfo {
148
+ UnallocatedConcurrencyNum: number
149
+ Allocated: IVersionProvisionedConcurrencyInfo[]
150
+ }
151
+
152
+ export interface IPublishVersionParams {
153
+ functionName: string
154
+ description?: string
155
+ }
156
+
157
+ export interface IPublishVersionRes extends IResponseInfo {
158
+ FunctionVersion: string
159
+ CodeSize: number
160
+ MemorySize: number
161
+ Description: string
162
+ Handler: string
163
+ Timeout: number
164
+ Runtime: string
165
+ Namespace: string
166
+ }
167
+
168
+
169
+ export interface IListFunctionVersionParams {
170
+ functionName: string
171
+ offset?: number
172
+ limit?: number
173
+ order?: string
174
+ orderBy?: string
175
+ }
176
+
177
+ export interface IFunctionVersion {
178
+ Version: string
179
+ Description: string
180
+ AddTime: string
181
+ ModTime: string
182
+ Status: string //
183
+ }
184
+
185
+ export interface IFunctionVersionsRes extends IResponseInfo {
186
+ FunctionVersion: string[]
187
+ Versions: IFunctionVersion[]
188
+ TotalCount: number
189
+ }
190
+
191
+ export interface IVersionMatch {
192
+ Version: string // 函数版本名称
193
+ Key: string // 匹配规则的key,调用时通过传key来匹配规则路由到指定版本 header方式:key填写"invoke.headers.User",并在 invoke 调用函数时传参 RoutingKey:{"User":"value"}规则匹配调用
194
+ Method: string // 匹配方式。取值范围:range:范围匹配 exact:字符串精确匹配
195
+ Expression: string //
196
+ }
197
+
198
+ export interface IVersionWeight {
199
+ Version: string
200
+ Weight: number
201
+ }
202
+
203
+ export interface IRoutingConfig {
204
+ AdditionalVersionWeights?: IVersionWeight[]
205
+ AddtionVersionMatchs?: IVersionMatch[]
206
+ }
207
+
208
+ export interface IUpdateFunctionAliasConfig {
209
+ functionName: string // 函数名
210
+ name: string // 函数别名 如$DEFAULT
211
+ functionVersion: string // 函数版本
212
+ description?: string // 别名描述
213
+ routingConfig?: IRoutingConfig
214
+ }
215
+
216
+ export interface IGetFunctionAlias {
217
+ functionName: string // 函数名称
218
+ name: string // 别名
219
+ }
220
+
221
+ export interface IGetFunctionAliasRes extends IResponseInfo {
222
+ FunctionVersion: string
223
+ Name: string
224
+ RoutingConfig: IRoutingConfig
225
+ Description: string
226
+ AddTime: string
227
+ ModTime: string
228
+ }
229
+
129
230
  // 是否为 Node 函数
130
231
  function isNodeFunction(runtime: string) {
131
232
  // 不严格限制
@@ -913,6 +1014,142 @@ export class FunctionService {
913
1014
  })
914
1015
  }
915
1016
 
1017
+ /**
1018
+ * 设置预置并发
1019
+ * @private
1020
+ * @param {IProvisionedConcurrencyConfig} concurrencyConfig
1021
+ * @returns
1022
+ * @memberof FunctionService
1023
+ */
1024
+ @preLazy()
1025
+ public async setProvisionedConcurrencyConfig(concurrencyConfig: ISetProvisionedConcurrencyConfig): Promise<IResponseInfo> {
1026
+ const { namespace } = this.getFunctionConfig()
1027
+ const { functionName: FunctionName, qualifier: Qualifier, versionProvisionedConcurrencyNum: VersionProvisionedConcurrencyNum } = concurrencyConfig
1028
+
1029
+ return this.scfService.request('PutProvisionedConcurrencyConfig', {
1030
+ FunctionName,
1031
+ Qualifier,
1032
+ VersionProvisionedConcurrencyNum,
1033
+ Namespace: namespace
1034
+ })
1035
+ }
1036
+
1037
+ /**
1038
+ * 获取函数预置并发详情
1039
+ * @private
1040
+ * @param {IGetProvisionedConcurrencyConfig} concurrencyConfig
1041
+ * @returns {Promise<IGetProvisionedConcurrencyRes>}
1042
+ * @memberof FunctionService
1043
+ */
1044
+ @preLazy()
1045
+ public async getProvisionedConcurrencyConfig(concurrencyConfig: IGetProvisionedConcurrencyConfig): Promise<IGetProvisionedConcurrencyRes> {
1046
+ const { namespace } = this.getFunctionConfig()
1047
+ const { functionName: FunctionName, qualifier: Qualifier } = concurrencyConfig
1048
+
1049
+ return this.scfService.request('GetProvisionedConcurrencyConfig', {
1050
+ FunctionName,
1051
+ Qualifier,
1052
+ Namespace: namespace
1053
+ })
1054
+ }
1055
+
1056
+ /**
1057
+ * 删除预置并发
1058
+ * @private
1059
+ * @param {IGetProvisionedConcurrencyConfig} concurrencyConfig
1060
+ * @returns {Promise<IResponseInfo>}
1061
+ * @memberof FunctionService
1062
+ */
1063
+ @preLazy()
1064
+ public async deleteProvisionedConcurrencyConfig(concurrencyConfig: IGetProvisionedConcurrencyConfig): Promise<IResponseInfo> {
1065
+ const { namespace } = this.getFunctionConfig()
1066
+ const { functionName: FunctionName, qualifier: Qualifier } = concurrencyConfig
1067
+
1068
+ return this.scfService.request('DeleteProvisionedConcurrencyConfig', {
1069
+ FunctionName,
1070
+ Qualifier,
1071
+ Namespace: namespace
1072
+ })
1073
+ }
1074
+
1075
+ /**
1076
+ * 发布新版本
1077
+ * @param {IPublishVersionParams} publishParams
1078
+ * @returns {Promise<IPublishVersionRes>}
1079
+ * @memberof FunctionService
1080
+ */
1081
+ @preLazy()
1082
+ public async publishVersion(publishParams: IPublishVersionParams): Promise<IPublishVersionRes> {
1083
+ const { namespace } = this.getFunctionConfig()
1084
+ const { functionName: FunctionName, description: Description } = publishParams
1085
+
1086
+ return this.scfService.request('PublishVersion', {
1087
+ FunctionName,
1088
+ Description,
1089
+ Namespace: namespace
1090
+ })
1091
+ }
1092
+
1093
+ /**
1094
+ * 查询函数版本详情
1095
+ * @param {IListFunctionVersionParams} listVersionParams
1096
+ * @returns {Promise<IFunctionVersionsRes>}
1097
+ * @memberof FunctionService
1098
+ */
1099
+ @preLazy()
1100
+ public async listVersionByFunction(listVersionParams: IListFunctionVersionParams): Promise<IFunctionVersionsRes> {
1101
+ const { namespace } = this.getFunctionConfig()
1102
+ const { functionName: FunctionName, offset: Offset, limit: Limit, order: Order, orderBy: OrderBy } = listVersionParams
1103
+
1104
+ return this.scfService.request('ListVersionByFunction', {
1105
+ FunctionName,
1106
+ Namespace: namespace,
1107
+ Offset,
1108
+ Limit,
1109
+ Order,
1110
+ OrderBy
1111
+ })
1112
+ }
1113
+
1114
+ /**
1115
+ *
1116
+ * @param {IUpdateFunctionAliasConfig} updateVersionConfigParams
1117
+ * @returns {Promise<IResponseInfo>}
1118
+ * @memberof FunctionService
1119
+ */
1120
+ @preLazy()
1121
+ public async updateFunctionAliasConfig(updateVersionConfigParams: IUpdateFunctionAliasConfig): Promise<IResponseInfo> {
1122
+ const { namespace } = this.getFunctionConfig()
1123
+ const { functionName: FunctionName, name: Name, functionVersion: FunctionVersion, routingConfig: RoutingConfig, description: Description } = updateVersionConfigParams
1124
+
1125
+ return this.scfService.request('UpdateAlias', {
1126
+ FunctionName,
1127
+ Name,
1128
+ Namespace: namespace,
1129
+ FunctionVersion,
1130
+ RoutingConfig,
1131
+ Description
1132
+ })
1133
+ }
1134
+
1135
+ /**
1136
+ * 查询函数别名详情
1137
+ * @param {IGetFunctionAlias} params
1138
+ * @returns {Promise<IGetFunctionAliasRes>}
1139
+ * @memberof FunctionService
1140
+ */
1141
+ @preLazy()
1142
+ public async getFunctionAlias(params: IGetFunctionAlias): Promise<IGetFunctionAliasRes> {
1143
+ const { namespace } = this.getFunctionConfig()
1144
+ const { functionName: FunctionName, name: Name } = params
1145
+
1146
+ return this.scfService.request('GetAlias', {
1147
+ FunctionName,
1148
+ Name,
1149
+ Namespace: namespace
1150
+ })
1151
+ }
1152
+
916
1153
  @preLazy()
917
1154
  private async createAccessPath(name: string, path: string) {
918
1155
  const access = this.environment.getAccessService()
@@ -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
  /**
@@ -1190,6 +1198,7 @@ export class StorageService {
1190
1198
  private async uploadFilesWithRetry({ uploadFiles, options, times, interval, failedFiles }) {
1191
1199
  const { files, onFileFinish } = options
1192
1200
  const tempFailedFiles = []
1201
+ let curError: any = null
1193
1202
  const res = await uploadFiles({
1194
1203
  ...options,
1195
1204
  files: failedFiles.length
@@ -1199,24 +1208,74 @@ export class StorageService {
1199
1208
  const error = args[0]
1200
1209
  const fileInfo = (args as any)[2]
1201
1210
  if (error) {
1211
+ curError = error
1202
1212
  tempFailedFiles.push(fileInfo.Key)
1203
1213
  }
1204
1214
  onFileFinish?.apply(null, args)
1205
1215
  }
1206
1216
  })
1207
- if (!tempFailedFiles?.length || times <= 0) return res
1208
- if (times > 0) {
1209
- setTimeout(
1210
- () =>
1211
- this.uploadFilesWithRetry({
1212
- uploadFiles,
1213
- options,
1214
- times: times - 1,
1215
- interval,
1216
- failedFiles: tempFailedFiles
1217
- }),
1218
- interval
1219
- )
1217
+ // if (!tempFailedFiles?.length || times <= 0) return res
1218
+
1219
+ if (!tempFailedFiles?.length) {
1220
+ return res
1221
+ } else {
1222
+ if (times > 0) {
1223
+ return await new Promise((resolve, reject) => {
1224
+ setTimeout(
1225
+ () =>
1226
+ this.uploadFilesWithRetry({
1227
+ uploadFiles,
1228
+ options,
1229
+ times: times - 1,
1230
+ interval,
1231
+ failedFiles: tempFailedFiles
1232
+ }).then(res => resolve(res))
1233
+ .catch(err => reject(err)),
1234
+ interval
1235
+ )
1236
+ })
1237
+ } else {
1238
+ if (curError) {
1239
+ throw curError
1240
+ }
1241
+ }
1242
+ }
1243
+ }
1244
+
1245
+ /**
1246
+ * 拼接路径下载单文件
1247
+ * @param file
1248
+ * @param cloudDirectoryKey
1249
+ * @param resolveLocalPath
1250
+ * @returns
1251
+ */
1252
+ private async downloadWithFilePath({ file, cloudDirectoryKey, resolveLocalPath }) {
1253
+ const fileRelativePath = file.Key.replace(cloudDirectoryKey, '')
1254
+ // 空路径和文件夹跳过
1255
+ if (!fileRelativePath || /\/$/g.test(fileRelativePath)) {
1256
+ return
1220
1257
  }
1258
+ const localFilePath = path.join(resolveLocalPath, fileRelativePath)
1259
+ // 创建文件的父文件夹
1260
+ const fileDir = path.dirname(localFilePath)
1261
+ await makeDir(fileDir)
1262
+ return this.downloadFile({
1263
+ cloudPath: file.Key,
1264
+ localPath: localFilePath
1265
+ })
1266
+ }
1267
+
1268
+ /**
1269
+ * 根据下载结果返回错误列表
1270
+ * @param res
1271
+ * @returns
1272
+ */
1273
+ private determineDownLoadResultIsError(res) {
1274
+ const resultErrorArr = []
1275
+ res.map(
1276
+ item =>
1277
+ /Error/gi.test(Object.prototype.toString.call(item)) && resultErrorArr.push(item)
1278
+ )
1279
+ return resultErrorArr
1221
1280
  }
1222
1281
  }
@@ -87,6 +87,92 @@ export interface IGetLayerVersionRes extends IResponseInfo {
87
87
  LayerName: string;
88
88
  Status: string;
89
89
  }
90
+ export interface ISetProvisionedConcurrencyConfig {
91
+ functionName: string;
92
+ qualifier: string;
93
+ versionProvisionedConcurrencyNum: number;
94
+ }
95
+ export interface IGetProvisionedConcurrencyConfig {
96
+ functionName: string;
97
+ qualifier?: string;
98
+ }
99
+ export interface IVersionProvisionedConcurrencyInfo {
100
+ AllocatedProvisionedConcurrencyNum: number;
101
+ AvailableProvisionedConcurrencyNum: number;
102
+ Status: string;
103
+ StatusReason: string;
104
+ Qualifier: string;
105
+ }
106
+ export interface IGetProvisionedConcurrencyRes extends IResponseInfo {
107
+ UnallocatedConcurrencyNum: number;
108
+ Allocated: IVersionProvisionedConcurrencyInfo[];
109
+ }
110
+ export interface IPublishVersionParams {
111
+ functionName: string;
112
+ description?: string;
113
+ }
114
+ export interface IPublishVersionRes extends IResponseInfo {
115
+ FunctionVersion: string;
116
+ CodeSize: number;
117
+ MemorySize: number;
118
+ Description: string;
119
+ Handler: string;
120
+ Timeout: number;
121
+ Runtime: string;
122
+ Namespace: string;
123
+ }
124
+ export interface IListFunctionVersionParams {
125
+ functionName: string;
126
+ offset?: number;
127
+ limit?: number;
128
+ order?: string;
129
+ orderBy?: string;
130
+ }
131
+ export interface IFunctionVersion {
132
+ Version: string;
133
+ Description: string;
134
+ AddTime: string;
135
+ ModTime: string;
136
+ Status: string;
137
+ }
138
+ export interface IFunctionVersionsRes extends IResponseInfo {
139
+ FunctionVersion: string[];
140
+ Versions: IFunctionVersion[];
141
+ TotalCount: number;
142
+ }
143
+ export interface IVersionMatch {
144
+ Version: string;
145
+ Key: string;
146
+ Method: string;
147
+ Expression: string;
148
+ }
149
+ export interface IVersionWeight {
150
+ Version: string;
151
+ Weight: number;
152
+ }
153
+ export interface IRoutingConfig {
154
+ AdditionalVersionWeights?: IVersionWeight[];
155
+ AddtionVersionMatchs?: IVersionMatch[];
156
+ }
157
+ export interface IUpdateFunctionAliasConfig {
158
+ functionName: string;
159
+ name: string;
160
+ functionVersion: string;
161
+ description?: string;
162
+ routingConfig?: IRoutingConfig;
163
+ }
164
+ export interface IGetFunctionAlias {
165
+ functionName: string;
166
+ name: string;
167
+ }
168
+ export interface IGetFunctionAliasRes extends IResponseInfo {
169
+ FunctionVersion: string;
170
+ Name: string;
171
+ RoutingConfig: IRoutingConfig;
172
+ Description: string;
173
+ AddTime: string;
174
+ ModTime: string;
175
+ }
90
176
  export declare class FunctionService {
91
177
  private environment;
92
178
  private vpcService;
@@ -210,6 +296,58 @@ export declare class FunctionService {
210
296
  listLayerVersions(options: IVersionListOptions): Promise<IListLayerVersionsRes>;
211
297
  listLayers(options: ILayerListOptions): Promise<IListLayerRes>;
212
298
  getLayerVersion(options: ILayerOptions): Promise<IGetLayerVersionRes>;
299
+ /**
300
+ * 设置预置并发
301
+ * @private
302
+ * @param {IProvisionedConcurrencyConfig} concurrencyConfig
303
+ * @returns
304
+ * @memberof FunctionService
305
+ */
306
+ setProvisionedConcurrencyConfig(concurrencyConfig: ISetProvisionedConcurrencyConfig): Promise<IResponseInfo>;
307
+ /**
308
+ * 获取函数预置并发详情
309
+ * @private
310
+ * @param {IGetProvisionedConcurrencyConfig} concurrencyConfig
311
+ * @returns {Promise<IGetProvisionedConcurrencyRes>}
312
+ * @memberof FunctionService
313
+ */
314
+ getProvisionedConcurrencyConfig(concurrencyConfig: IGetProvisionedConcurrencyConfig): Promise<IGetProvisionedConcurrencyRes>;
315
+ /**
316
+ * 删除预置并发
317
+ * @private
318
+ * @param {IGetProvisionedConcurrencyConfig} concurrencyConfig
319
+ * @returns {Promise<IResponseInfo>}
320
+ * @memberof FunctionService
321
+ */
322
+ deleteProvisionedConcurrencyConfig(concurrencyConfig: IGetProvisionedConcurrencyConfig): Promise<IResponseInfo>;
323
+ /**
324
+ * 发布新版本
325
+ * @param {IPublishVersionParams} publishParams
326
+ * @returns {Promise<IPublishVersionRes>}
327
+ * @memberof FunctionService
328
+ */
329
+ publishVersion(publishParams: IPublishVersionParams): Promise<IPublishVersionRes>;
330
+ /**
331
+ * 查询函数版本详情
332
+ * @param {IListFunctionVersionParams} listVersionParams
333
+ * @returns {Promise<IFunctionVersionsRes>}
334
+ * @memberof FunctionService
335
+ */
336
+ listVersionByFunction(listVersionParams: IListFunctionVersionParams): Promise<IFunctionVersionsRes>;
337
+ /**
338
+ *
339
+ * @param {IUpdateFunctionAliasConfig} updateVersionConfigParams
340
+ * @returns {Promise<IResponseInfo>}
341
+ * @memberof FunctionService
342
+ */
343
+ updateFunctionAliasConfig(updateVersionConfigParams: IUpdateFunctionAliasConfig): Promise<IResponseInfo>;
344
+ /**
345
+ * 查询函数别名详情
346
+ * @param {IGetFunctionAlias} params
347
+ * @returns {Promise<IGetFunctionAliasRes>}
348
+ * @memberof FunctionService
349
+ */
350
+ getFunctionAlias(params: IGetFunctionAlias): Promise<IGetFunctionAliasRes>;
213
351
  private createAccessPath;
214
352
  private getCodeParams;
215
353
  private getTempCosInfo;
@@ -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 {};