@cloudbase/manager-node 3.9.5 → 3.12.0
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.
- package/lib/function/index.js +136 -0
- package/lib/hosting/index.js +7 -3
- package/lib/storage/index.js +128 -27
- package/package.json +1 -1
- package/src/function/index.ts +237 -0
- package/src/hosting/index.ts +17 -3
- package/src/storage/index.ts +180 -43
- package/types/function/index.d.ts +138 -0
- package/types/hosting/index.d.ts +4 -0
- package/types/storage/index.d.ts +36 -0
package/lib/function/index.js
CHANGED
|
@@ -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);
|
package/lib/hosting/index.js
CHANGED
|
@@ -131,7 +131,7 @@ class HostingService {
|
|
|
131
131
|
* @param options
|
|
132
132
|
*/
|
|
133
133
|
async uploadFiles(options) {
|
|
134
|
-
const { localPath, cloudPath, files = [], onProgress, onFileFinish, parallel = 20, ignore } = options;
|
|
134
|
+
const { localPath, cloudPath, files = [], onProgress, onFileFinish, parallel = 20, ignore, retryCount, retryInterval } = options;
|
|
135
135
|
const hosting = await this.checkStatus();
|
|
136
136
|
const { Bucket, Regoin } = hosting;
|
|
137
137
|
const storageService = await this.environment.getStorageService();
|
|
@@ -150,7 +150,9 @@ class HostingService {
|
|
|
150
150
|
onProgress,
|
|
151
151
|
onFileFinish,
|
|
152
152
|
fileId: false,
|
|
153
|
-
ignore
|
|
153
|
+
ignore,
|
|
154
|
+
retryCount,
|
|
155
|
+
retryInterval,
|
|
154
156
|
});
|
|
155
157
|
}
|
|
156
158
|
else {
|
|
@@ -171,7 +173,9 @@ class HostingService {
|
|
|
171
173
|
bucket: Bucket,
|
|
172
174
|
region: Regoin,
|
|
173
175
|
files: uploadFiles,
|
|
174
|
-
fileId: false
|
|
176
|
+
fileId: false,
|
|
177
|
+
retryCount,
|
|
178
|
+
retryInterval,
|
|
175
179
|
});
|
|
176
180
|
}
|
|
177
181
|
/**
|
package/lib/storage/index.js
CHANGED
|
@@ -49,7 +49,7 @@ class StorageService {
|
|
|
49
49
|
* @param options
|
|
50
50
|
*/
|
|
51
51
|
async uploadFiles(options) {
|
|
52
|
-
const { files, onProgress, parallel, onFileFinish, ignore } = options;
|
|
52
|
+
const { files, onProgress, parallel, onFileFinish, ignore, retryCount, retryInterval } = options;
|
|
53
53
|
const { bucket, region } = this.getStorageConfig();
|
|
54
54
|
return this.uploadFilesCustom({
|
|
55
55
|
files,
|
|
@@ -58,7 +58,9 @@ class StorageService {
|
|
|
58
58
|
ignore,
|
|
59
59
|
parallel,
|
|
60
60
|
onProgress,
|
|
61
|
-
onFileFinish
|
|
61
|
+
onFileFinish,
|
|
62
|
+
retryCount,
|
|
63
|
+
retryInterval
|
|
62
64
|
});
|
|
63
65
|
}
|
|
64
66
|
/**
|
|
@@ -134,18 +136,24 @@ class StorageService {
|
|
|
134
136
|
* 上传文件夹
|
|
135
137
|
* @param {string} localPath 本地文件夹路径
|
|
136
138
|
* @param {string} cloudPath 云端文件夹
|
|
139
|
+
* @param {number} parallel 并发量
|
|
140
|
+
* @param {number} retryCount 重试次数
|
|
141
|
+
* @param {number} retryInterval 重试时间间隔(毫秒)
|
|
137
142
|
* @param {(string | string[])} ignore
|
|
138
143
|
* @param {(string | string[])} ignore
|
|
139
144
|
* @returns {Promise<void>}
|
|
140
145
|
*/
|
|
141
146
|
async uploadDirectory(options) {
|
|
142
|
-
const { localPath, cloudPath = '', ignore, onProgress, onFileFinish } = options;
|
|
147
|
+
const { localPath, cloudPath = '', ignore, onProgress, onFileFinish, parallel, retryCount, retryInterval } = options;
|
|
143
148
|
// 此处不检查路径是否存在
|
|
144
149
|
// 绝对路径 /var/blog/xxxx
|
|
145
150
|
const { bucket, region } = this.getStorageConfig();
|
|
146
151
|
return this.uploadDirectoryCustom({
|
|
147
152
|
localPath,
|
|
148
153
|
cloudPath,
|
|
154
|
+
parallel,
|
|
155
|
+
retryCount,
|
|
156
|
+
retryInterval,
|
|
149
157
|
bucket,
|
|
150
158
|
region,
|
|
151
159
|
ignore,
|
|
@@ -157,13 +165,16 @@ class StorageService {
|
|
|
157
165
|
* 上传文件夹,支持自定义 Region 和 Bucket
|
|
158
166
|
* @param {string} localPath
|
|
159
167
|
* @param {string} cloudPath
|
|
168
|
+
* @param {number} parallel
|
|
169
|
+
* @param {number} retryCount
|
|
170
|
+
* @param {number} retryInterval
|
|
160
171
|
* @param {string} bucket
|
|
161
172
|
* @param {string} region
|
|
162
173
|
* @param {IOptions} options
|
|
163
174
|
* @returns {Promise<void>}
|
|
164
175
|
*/
|
|
165
176
|
async uploadDirectoryCustom(options) {
|
|
166
|
-
const { localPath, cloudPath, bucket, region, onProgress, onFileFinish, ignore, fileId = true, parallel = 20 } = options;
|
|
177
|
+
const { localPath, cloudPath, bucket, region, onProgress, onFileFinish, ignore, fileId = true, parallel = 20, retryCount = 0, retryInterval = 500 } = options;
|
|
167
178
|
// 此处不检查路径是否存在
|
|
168
179
|
// 绝对路径 /var/blog/xxxx
|
|
169
180
|
const resolvePath = path_1.default.resolve(localPath);
|
|
@@ -229,11 +240,18 @@ class StorageService {
|
|
|
229
240
|
// 对文件上传进行处理
|
|
230
241
|
const cos = this.getCos(parallel);
|
|
231
242
|
const uploadFiles = util_1.default.promisify(cos.uploadFiles).bind(cos);
|
|
232
|
-
|
|
243
|
+
const params = {
|
|
233
244
|
files,
|
|
234
245
|
SliceSize: BIG_FILE_SIZE,
|
|
235
246
|
onProgress,
|
|
236
247
|
onFileFinish
|
|
248
|
+
};
|
|
249
|
+
return this.uploadFilesWithRetry({
|
|
250
|
+
uploadFiles,
|
|
251
|
+
options: params,
|
|
252
|
+
times: retryCount,
|
|
253
|
+
interval: retryInterval,
|
|
254
|
+
failedFiles: []
|
|
237
255
|
});
|
|
238
256
|
}
|
|
239
257
|
/**
|
|
@@ -241,7 +259,7 @@ class StorageService {
|
|
|
241
259
|
* @param options
|
|
242
260
|
*/
|
|
243
261
|
async uploadFilesCustom(options) {
|
|
244
|
-
const { files, bucket, region, ignore, onProgress, onFileFinish, fileId = true, parallel = 20 } = options;
|
|
262
|
+
const { files, bucket, region, ignore, onProgress, onFileFinish, fileId = true, parallel = 20, retryCount = 0, retryInterval = 500 } = options;
|
|
245
263
|
if (!files || !files.length) {
|
|
246
264
|
return;
|
|
247
265
|
}
|
|
@@ -275,11 +293,24 @@ class StorageService {
|
|
|
275
293
|
fileList = await asyncTaskController.run();
|
|
276
294
|
const cos = this.getCos(parallel);
|
|
277
295
|
const uploadFiles = util_1.default.promisify(cos.uploadFiles).bind(cos);
|
|
278
|
-
|
|
279
|
-
onProgress,
|
|
280
|
-
onFileFinish,
|
|
296
|
+
const params = {
|
|
281
297
|
files: fileList,
|
|
282
|
-
SliceSize: BIG_FILE_SIZE
|
|
298
|
+
SliceSize: BIG_FILE_SIZE,
|
|
299
|
+
onProgress,
|
|
300
|
+
onFileFinish
|
|
301
|
+
};
|
|
302
|
+
// return uploadFiles({
|
|
303
|
+
// onProgress,
|
|
304
|
+
// onFileFinish,
|
|
305
|
+
// files: fileList,
|
|
306
|
+
// SliceSize: BIG_FILE_SIZE
|
|
307
|
+
// })
|
|
308
|
+
return this.uploadFilesWithRetry({
|
|
309
|
+
uploadFiles,
|
|
310
|
+
options: params,
|
|
311
|
+
times: retryCount,
|
|
312
|
+
interval: retryInterval,
|
|
313
|
+
failedFiles: []
|
|
283
314
|
});
|
|
284
315
|
}
|
|
285
316
|
/**
|
|
@@ -351,27 +382,32 @@ class StorageService {
|
|
|
351
382
|
* @returns {Promise<(NodeJS.ReadableStream | string)[]>}
|
|
352
383
|
*/
|
|
353
384
|
async downloadDirectory(options) {
|
|
354
|
-
const { cloudPath, localPath } = options;
|
|
385
|
+
const { cloudPath, localPath, parallel = 20 } = options;
|
|
355
386
|
const resolveLocalPath = path_1.default.resolve(localPath);
|
|
356
387
|
utils_1.checkFullAccess(resolveLocalPath, true);
|
|
357
388
|
const cloudDirectoryKey = this.getCloudKey(cloudPath);
|
|
358
389
|
const files = await this.walkCloudDir(cloudDirectoryKey);
|
|
359
|
-
const promises = files.map(async (
|
|
360
|
-
|
|
361
|
-
// 空路径和文件夹跳过
|
|
362
|
-
if (!fileRelativePath || /\/$/g.test(fileRelativePath)) {
|
|
363
|
-
return;
|
|
364
|
-
}
|
|
365
|
-
const localFilePath = path_1.default.join(resolveLocalPath, fileRelativePath);
|
|
366
|
-
// 创建文件的父文件夹
|
|
367
|
-
const fileDir = path_1.default.dirname(localFilePath);
|
|
368
|
-
await make_dir_1.default(fileDir);
|
|
369
|
-
return this.downloadFile({
|
|
370
|
-
cloudPath: file.Key,
|
|
371
|
-
localPath: localFilePath
|
|
372
|
-
});
|
|
390
|
+
const promises = files.map(file => async () => {
|
|
391
|
+
return this.downloadWithFilePath({ file, cloudDirectoryKey, resolveLocalPath });
|
|
373
392
|
});
|
|
374
|
-
|
|
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;
|
|
375
411
|
}
|
|
376
412
|
/**
|
|
377
413
|
* 列出文件夹下的文件
|
|
@@ -774,7 +810,6 @@ class StorageService {
|
|
|
774
810
|
params.WebsiteConfiguration.RoutingRules.push(routeItem);
|
|
775
811
|
}
|
|
776
812
|
}
|
|
777
|
-
console.log('params:', JSON.stringify(params));
|
|
778
813
|
const res = await putBucketWebsite(params);
|
|
779
814
|
return res;
|
|
780
815
|
}
|
|
@@ -847,6 +882,72 @@ class StorageService {
|
|
|
847
882
|
env: envConfig.EnvId
|
|
848
883
|
};
|
|
849
884
|
}
|
|
885
|
+
/**
|
|
886
|
+
* 带重试功能的上传多文件函数
|
|
887
|
+
* @param uploadFiles sdk上传函数
|
|
888
|
+
* @param options sdk上传函数参数
|
|
889
|
+
* @param times 重试次数
|
|
890
|
+
* @param interval 重试时间间隔(毫秒)
|
|
891
|
+
* @param failedFiles 失败文件列表
|
|
892
|
+
* @returns
|
|
893
|
+
*/
|
|
894
|
+
async uploadFilesWithRetry({ uploadFiles, options, times, interval, failedFiles }) {
|
|
895
|
+
const { files, onFileFinish } = options;
|
|
896
|
+
const tempFailedFiles = [];
|
|
897
|
+
const res = await uploadFiles(Object.assign(Object.assign({}, options), { files: failedFiles.length
|
|
898
|
+
? files.filter(file => failedFiles.includes(file.Key))
|
|
899
|
+
: files, onFileFinish: (...args) => {
|
|
900
|
+
const error = args[0];
|
|
901
|
+
const fileInfo = args[2];
|
|
902
|
+
if (error) {
|
|
903
|
+
tempFailedFiles.push(fileInfo.Key);
|
|
904
|
+
}
|
|
905
|
+
onFileFinish === null || onFileFinish === void 0 ? void 0 : onFileFinish.apply(null, args);
|
|
906
|
+
} }));
|
|
907
|
+
if (!(tempFailedFiles === null || tempFailedFiles === void 0 ? void 0 : tempFailedFiles.length) || times <= 0)
|
|
908
|
+
return res;
|
|
909
|
+
if (times > 0) {
|
|
910
|
+
setTimeout(() => this.uploadFilesWithRetry({
|
|
911
|
+
uploadFiles,
|
|
912
|
+
options,
|
|
913
|
+
times: times - 1,
|
|
914
|
+
interval,
|
|
915
|
+
failedFiles: tempFailedFiles
|
|
916
|
+
}), interval);
|
|
917
|
+
}
|
|
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
|
+
}
|
|
850
951
|
}
|
|
851
952
|
__decorate([
|
|
852
953
|
utils_1.preLazy()
|
package/package.json
CHANGED
package/src/function/index.ts
CHANGED
|
@@ -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()
|
package/src/hosting/index.ts
CHANGED
|
@@ -38,6 +38,10 @@ export interface IHostingFileOptions {
|
|
|
38
38
|
onProgress?: OnProgress
|
|
39
39
|
onFileFinish?: OnFileFinish
|
|
40
40
|
ignore?: string | string[]
|
|
41
|
+
// 重试次数
|
|
42
|
+
retryCount?: number
|
|
43
|
+
// 重试时间间隔(毫秒)
|
|
44
|
+
retryInterval?: number
|
|
41
45
|
}
|
|
42
46
|
|
|
43
47
|
export interface IHostingFilesOptions {
|
|
@@ -52,6 +56,10 @@ export interface IHostingFilesOptions {
|
|
|
52
56
|
onProgress?: OnProgress
|
|
53
57
|
onFileFinish?: OnFileFinish
|
|
54
58
|
ignore?: string | string[]
|
|
59
|
+
// 重试次数
|
|
60
|
+
retryCount?: number
|
|
61
|
+
// 重试时间间隔(毫秒)
|
|
62
|
+
retryInterval?: number
|
|
55
63
|
}
|
|
56
64
|
|
|
57
65
|
export type IHostingOptions = IHostingFileOptions | IHostingFilesOptions
|
|
@@ -331,7 +339,9 @@ export class HostingService {
|
|
|
331
339
|
onProgress,
|
|
332
340
|
onFileFinish,
|
|
333
341
|
parallel = 20,
|
|
334
|
-
ignore
|
|
342
|
+
ignore,
|
|
343
|
+
retryCount,
|
|
344
|
+
retryInterval
|
|
335
345
|
} = options
|
|
336
346
|
|
|
337
347
|
const hosting = await this.checkStatus()
|
|
@@ -355,7 +365,9 @@ export class HostingService {
|
|
|
355
365
|
onProgress,
|
|
356
366
|
onFileFinish,
|
|
357
367
|
fileId: false,
|
|
358
|
-
ignore
|
|
368
|
+
ignore,
|
|
369
|
+
retryCount,
|
|
370
|
+
retryInterval,
|
|
359
371
|
})
|
|
360
372
|
} else {
|
|
361
373
|
// 文件上传统一通过批量上传接口
|
|
@@ -376,7 +388,9 @@ export class HostingService {
|
|
|
376
388
|
bucket: Bucket,
|
|
377
389
|
region: Regoin,
|
|
378
390
|
files: uploadFiles,
|
|
379
|
-
fileId: false
|
|
391
|
+
fileId: false,
|
|
392
|
+
retryCount,
|
|
393
|
+
retryInterval,
|
|
380
394
|
})
|
|
381
395
|
}
|
|
382
396
|
|
package/src/storage/index.ts
CHANGED
|
@@ -49,6 +49,12 @@ export interface IFileOptions extends IOptions {
|
|
|
49
49
|
localPath: string
|
|
50
50
|
// cloudPath 可以为空
|
|
51
51
|
cloudPath?: string
|
|
52
|
+
// 并发数量
|
|
53
|
+
parallel?: number
|
|
54
|
+
// 重试次数
|
|
55
|
+
retryCount?: number
|
|
56
|
+
// 重试时间间隔(毫秒)
|
|
57
|
+
retryInterval?: number
|
|
52
58
|
}
|
|
53
59
|
|
|
54
60
|
export interface IFilesOptions extends IOptions {
|
|
@@ -56,6 +62,10 @@ export interface IFilesOptions extends IOptions {
|
|
|
56
62
|
ignore?: string | string[]
|
|
57
63
|
// 文件列表
|
|
58
64
|
files: { localPath: string; cloudPath?: string }[]
|
|
65
|
+
// 重试次数
|
|
66
|
+
retryCount?: number
|
|
67
|
+
// 重试时间间隔(毫秒)
|
|
68
|
+
retryInterval?: number
|
|
59
69
|
}
|
|
60
70
|
|
|
61
71
|
export interface ICustomOptions {
|
|
@@ -135,7 +145,8 @@ export class StorageService {
|
|
|
135
145
|
*/
|
|
136
146
|
@preLazy()
|
|
137
147
|
public async uploadFiles(options: IFilesOptions): Promise<void> {
|
|
138
|
-
const { files, onProgress, parallel, onFileFinish, ignore } =
|
|
148
|
+
const { files, onProgress, parallel, onFileFinish, ignore, retryCount, retryInterval } =
|
|
149
|
+
options
|
|
139
150
|
const { bucket, region } = this.getStorageConfig()
|
|
140
151
|
|
|
141
152
|
return this.uploadFilesCustom({
|
|
@@ -145,7 +156,9 @@ export class StorageService {
|
|
|
145
156
|
ignore,
|
|
146
157
|
parallel,
|
|
147
158
|
onProgress,
|
|
148
|
-
onFileFinish
|
|
159
|
+
onFileFinish,
|
|
160
|
+
retryCount,
|
|
161
|
+
retryInterval
|
|
149
162
|
})
|
|
150
163
|
}
|
|
151
164
|
|
|
@@ -230,19 +243,34 @@ export class StorageService {
|
|
|
230
243
|
* 上传文件夹
|
|
231
244
|
* @param {string} localPath 本地文件夹路径
|
|
232
245
|
* @param {string} cloudPath 云端文件夹
|
|
246
|
+
* @param {number} parallel 并发量
|
|
247
|
+
* @param {number} retryCount 重试次数
|
|
248
|
+
* @param {number} retryInterval 重试时间间隔(毫秒)
|
|
233
249
|
* @param {(string | string[])} ignore
|
|
234
250
|
* @param {(string | string[])} ignore
|
|
235
251
|
* @returns {Promise<void>}
|
|
236
252
|
*/
|
|
237
253
|
@preLazy()
|
|
238
254
|
public async uploadDirectory(options: IFileOptions): Promise<void> {
|
|
239
|
-
const {
|
|
255
|
+
const {
|
|
256
|
+
localPath,
|
|
257
|
+
cloudPath = '',
|
|
258
|
+
ignore,
|
|
259
|
+
onProgress,
|
|
260
|
+
onFileFinish,
|
|
261
|
+
parallel,
|
|
262
|
+
retryCount,
|
|
263
|
+
retryInterval
|
|
264
|
+
} = options
|
|
240
265
|
// 此处不检查路径是否存在
|
|
241
266
|
// 绝对路径 /var/blog/xxxx
|
|
242
267
|
const { bucket, region } = this.getStorageConfig()
|
|
243
268
|
return this.uploadDirectoryCustom({
|
|
244
269
|
localPath,
|
|
245
270
|
cloudPath,
|
|
271
|
+
parallel,
|
|
272
|
+
retryCount,
|
|
273
|
+
retryInterval,
|
|
246
274
|
bucket,
|
|
247
275
|
region,
|
|
248
276
|
ignore,
|
|
@@ -255,6 +283,9 @@ export class StorageService {
|
|
|
255
283
|
* 上传文件夹,支持自定义 Region 和 Bucket
|
|
256
284
|
* @param {string} localPath
|
|
257
285
|
* @param {string} cloudPath
|
|
286
|
+
* @param {number} parallel
|
|
287
|
+
* @param {number} retryCount
|
|
288
|
+
* @param {number} retryInterval
|
|
258
289
|
* @param {string} bucket
|
|
259
290
|
* @param {string} region
|
|
260
291
|
* @param {IOptions} options
|
|
@@ -271,7 +302,9 @@ export class StorageService {
|
|
|
271
302
|
onFileFinish,
|
|
272
303
|
ignore,
|
|
273
304
|
fileId = true,
|
|
274
|
-
parallel = 20
|
|
305
|
+
parallel = 20,
|
|
306
|
+
retryCount = 0,
|
|
307
|
+
retryInterval = 500
|
|
275
308
|
} = options
|
|
276
309
|
// 此处不检查路径是否存在
|
|
277
310
|
// 绝对路径 /var/blog/xxxx
|
|
@@ -310,12 +343,13 @@ export class StorageService {
|
|
|
310
343
|
const creatingDirController = new AsyncTaskParallelController(parallel, 50)
|
|
311
344
|
const creatingDirTasks = fileStatsList
|
|
312
345
|
.filter(info => info.isDir)
|
|
313
|
-
.map(
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
346
|
+
.map(
|
|
347
|
+
info => () =>
|
|
348
|
+
this.createCloudDirectroyCustom({
|
|
349
|
+
cloudPath: info.cloudFileKey,
|
|
350
|
+
bucket,
|
|
351
|
+
region
|
|
352
|
+
})
|
|
319
353
|
)
|
|
320
354
|
|
|
321
355
|
creatingDirController.loadTasks(creatingDirTasks)
|
|
@@ -348,15 +382,20 @@ export class StorageService {
|
|
|
348
382
|
// 对文件上传进行处理
|
|
349
383
|
const cos = this.getCos(parallel)
|
|
350
384
|
const uploadFiles = Util.promisify(cos.uploadFiles).bind(cos)
|
|
351
|
-
|
|
352
|
-
return uploadFiles({
|
|
385
|
+
const params = {
|
|
353
386
|
files,
|
|
354
387
|
SliceSize: BIG_FILE_SIZE,
|
|
355
388
|
onProgress,
|
|
356
389
|
onFileFinish
|
|
390
|
+
}
|
|
391
|
+
return this.uploadFilesWithRetry({
|
|
392
|
+
uploadFiles,
|
|
393
|
+
options: params,
|
|
394
|
+
times: retryCount,
|
|
395
|
+
interval: retryInterval,
|
|
396
|
+
failedFiles: []
|
|
357
397
|
})
|
|
358
398
|
}
|
|
359
|
-
|
|
360
399
|
/**
|
|
361
400
|
* 批量上传文件
|
|
362
401
|
* @param options
|
|
@@ -371,7 +410,9 @@ export class StorageService {
|
|
|
371
410
|
onProgress,
|
|
372
411
|
onFileFinish,
|
|
373
412
|
fileId = true,
|
|
374
|
-
parallel = 20
|
|
413
|
+
parallel = 20,
|
|
414
|
+
retryCount = 0,
|
|
415
|
+
retryInterval = 500
|
|
375
416
|
} = options
|
|
376
417
|
|
|
377
418
|
if (!files || !files.length) {
|
|
@@ -413,12 +454,25 @@ export class StorageService {
|
|
|
413
454
|
|
|
414
455
|
const cos = this.getCos(parallel)
|
|
415
456
|
const uploadFiles = Util.promisify(cos.uploadFiles).bind(cos)
|
|
416
|
-
|
|
417
|
-
return uploadFiles({
|
|
418
|
-
onProgress,
|
|
419
|
-
onFileFinish,
|
|
457
|
+
const params = {
|
|
420
458
|
files: fileList,
|
|
421
|
-
SliceSize: BIG_FILE_SIZE
|
|
459
|
+
SliceSize: BIG_FILE_SIZE,
|
|
460
|
+
onProgress,
|
|
461
|
+
onFileFinish
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
// return uploadFiles({
|
|
465
|
+
// onProgress,
|
|
466
|
+
// onFileFinish,
|
|
467
|
+
// files: fileList,
|
|
468
|
+
// SliceSize: BIG_FILE_SIZE
|
|
469
|
+
// })
|
|
470
|
+
return this.uploadFilesWithRetry({
|
|
471
|
+
uploadFiles,
|
|
472
|
+
options: params,
|
|
473
|
+
times: retryCount,
|
|
474
|
+
interval: retryInterval,
|
|
475
|
+
failedFiles: []
|
|
422
476
|
})
|
|
423
477
|
}
|
|
424
478
|
|
|
@@ -511,32 +565,42 @@ export class StorageService {
|
|
|
511
565
|
public async downloadDirectory(options: {
|
|
512
566
|
cloudPath: string
|
|
513
567
|
localPath?: string
|
|
568
|
+
parallel?: number
|
|
514
569
|
}): Promise<(NodeJS.ReadableStream | string)[]> {
|
|
515
|
-
const { cloudPath, localPath } = options
|
|
570
|
+
const { cloudPath, localPath, parallel = 20 } = options
|
|
516
571
|
const resolveLocalPath = path.resolve(localPath)
|
|
517
572
|
|
|
518
573
|
checkFullAccess(resolveLocalPath, true)
|
|
519
574
|
|
|
520
575
|
const cloudDirectoryKey = this.getCloudKey(cloudPath)
|
|
521
576
|
const files = await this.walkCloudDir(cloudDirectoryKey)
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
const fileRelativePath = file.Key.replace(cloudDirectoryKey, '')
|
|
525
|
-
// 空路径和文件夹跳过
|
|
526
|
-
if (!fileRelativePath || /\/$/g.test(fileRelativePath)) {
|
|
527
|
-
return
|
|
528
|
-
}
|
|
529
|
-
const localFilePath = path.join(resolveLocalPath, fileRelativePath)
|
|
530
|
-
// 创建文件的父文件夹
|
|
531
|
-
const fileDir = path.dirname(localFilePath)
|
|
532
|
-
await makeDir(fileDir)
|
|
533
|
-
return this.downloadFile({
|
|
534
|
-
cloudPath: file.Key,
|
|
535
|
-
localPath: localFilePath
|
|
536
|
-
})
|
|
577
|
+
const promises = files.map(file => async () => {
|
|
578
|
+
return this.downloadWithFilePath({ file, cloudDirectoryKey, resolveLocalPath })
|
|
537
579
|
})
|
|
580
|
+
const asyncTaskController = new AsyncTaskParallelController(parallel, 50)
|
|
581
|
+
asyncTaskController.loadTasks(promises)
|
|
582
|
+
let res = await asyncTaskController.run()
|
|
583
|
+
const errorIndexArr = []
|
|
538
584
|
|
|
539
|
-
|
|
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
|
|
540
604
|
}
|
|
541
605
|
|
|
542
606
|
/**
|
|
@@ -735,9 +799,7 @@ export class StorageService {
|
|
|
735
799
|
* @returns {Promise<void>}
|
|
736
800
|
*/
|
|
737
801
|
@preLazy()
|
|
738
|
-
public async deleteDirectory(
|
|
739
|
-
cloudPath: string
|
|
740
|
-
): Promise<{
|
|
802
|
+
public async deleteDirectory(cloudPath: string): Promise<{
|
|
741
803
|
Deleted: { Key: string }[]
|
|
742
804
|
Error: Object[]
|
|
743
805
|
}> {
|
|
@@ -758,9 +820,7 @@ export class StorageService {
|
|
|
758
820
|
* @returns {Promise<void>}
|
|
759
821
|
*/
|
|
760
822
|
@preLazy()
|
|
761
|
-
public async deleteDirectoryCustom(
|
|
762
|
-
options: { cloudPath: string } & ICustomOptions
|
|
763
|
-
): Promise<{
|
|
823
|
+
public async deleteDirectoryCustom(options: { cloudPath: string } & ICustomOptions): Promise<{
|
|
764
824
|
Deleted: { Key: string }[]
|
|
765
825
|
Error: Object[]
|
|
766
826
|
}> {
|
|
@@ -1040,7 +1100,6 @@ export class StorageService {
|
|
|
1040
1100
|
}
|
|
1041
1101
|
}
|
|
1042
1102
|
|
|
1043
|
-
console.log('params:', JSON.stringify(params))
|
|
1044
1103
|
const res = await putBucketWebsite(params)
|
|
1045
1104
|
|
|
1046
1105
|
return res
|
|
@@ -1127,4 +1186,82 @@ export class StorageService {
|
|
|
1127
1186
|
env: envConfig.EnvId
|
|
1128
1187
|
}
|
|
1129
1188
|
}
|
|
1189
|
+
/**
|
|
1190
|
+
* 带重试功能的上传多文件函数
|
|
1191
|
+
* @param uploadFiles sdk上传函数
|
|
1192
|
+
* @param options sdk上传函数参数
|
|
1193
|
+
* @param times 重试次数
|
|
1194
|
+
* @param interval 重试时间间隔(毫秒)
|
|
1195
|
+
* @param failedFiles 失败文件列表
|
|
1196
|
+
* @returns
|
|
1197
|
+
*/
|
|
1198
|
+
private async uploadFilesWithRetry({ uploadFiles, options, times, interval, failedFiles }) {
|
|
1199
|
+
const { files, onFileFinish } = options
|
|
1200
|
+
const tempFailedFiles = []
|
|
1201
|
+
const res = await uploadFiles({
|
|
1202
|
+
...options,
|
|
1203
|
+
files: failedFiles.length
|
|
1204
|
+
? files.filter(file => failedFiles.includes(file.Key))
|
|
1205
|
+
: files,
|
|
1206
|
+
onFileFinish: (...args) => {
|
|
1207
|
+
const error = args[0]
|
|
1208
|
+
const fileInfo = (args as any)[2]
|
|
1209
|
+
if (error) {
|
|
1210
|
+
tempFailedFiles.push(fileInfo.Key)
|
|
1211
|
+
}
|
|
1212
|
+
onFileFinish?.apply(null, args)
|
|
1213
|
+
}
|
|
1214
|
+
})
|
|
1215
|
+
if (!tempFailedFiles?.length || times <= 0) return res
|
|
1216
|
+
if (times > 0) {
|
|
1217
|
+
setTimeout(
|
|
1218
|
+
() =>
|
|
1219
|
+
this.uploadFilesWithRetry({
|
|
1220
|
+
uploadFiles,
|
|
1221
|
+
options,
|
|
1222
|
+
times: times - 1,
|
|
1223
|
+
interval,
|
|
1224
|
+
failedFiles: tempFailedFiles
|
|
1225
|
+
}),
|
|
1226
|
+
interval
|
|
1227
|
+
)
|
|
1228
|
+
}
|
|
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
|
+
}
|
|
1130
1267
|
}
|
|
@@ -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;
|
package/types/hosting/index.d.ts
CHANGED
|
@@ -20,6 +20,8 @@ export interface IHostingFileOptions {
|
|
|
20
20
|
onProgress?: OnProgress;
|
|
21
21
|
onFileFinish?: OnFileFinish;
|
|
22
22
|
ignore?: string | string[];
|
|
23
|
+
retryCount?: number;
|
|
24
|
+
retryInterval?: number;
|
|
23
25
|
}
|
|
24
26
|
export interface IHostingFilesOptions {
|
|
25
27
|
localPath?: string;
|
|
@@ -32,6 +34,8 @@ export interface IHostingFilesOptions {
|
|
|
32
34
|
onProgress?: OnProgress;
|
|
33
35
|
onFileFinish?: OnFileFinish;
|
|
34
36
|
ignore?: string | string[];
|
|
37
|
+
retryCount?: number;
|
|
38
|
+
retryInterval?: number;
|
|
35
39
|
}
|
|
36
40
|
export declare type IHostingOptions = IHostingFileOptions | IHostingFilesOptions;
|
|
37
41
|
export interface IHostingCloudOptions {
|
package/types/storage/index.d.ts
CHANGED
|
@@ -17,6 +17,9 @@ export interface IOptions {
|
|
|
17
17
|
export interface IFileOptions extends IOptions {
|
|
18
18
|
localPath: string;
|
|
19
19
|
cloudPath?: string;
|
|
20
|
+
parallel?: number;
|
|
21
|
+
retryCount?: number;
|
|
22
|
+
retryInterval?: number;
|
|
20
23
|
}
|
|
21
24
|
export interface IFilesOptions extends IOptions {
|
|
22
25
|
ignore?: string | string[];
|
|
@@ -24,6 +27,8 @@ export interface IFilesOptions extends IOptions {
|
|
|
24
27
|
localPath: string;
|
|
25
28
|
cloudPath?: string;
|
|
26
29
|
}[];
|
|
30
|
+
retryCount?: number;
|
|
31
|
+
retryInterval?: number;
|
|
27
32
|
}
|
|
28
33
|
export interface ICustomOptions {
|
|
29
34
|
bucket: string;
|
|
@@ -87,6 +92,9 @@ export declare class StorageService {
|
|
|
87
92
|
* 上传文件夹
|
|
88
93
|
* @param {string} localPath 本地文件夹路径
|
|
89
94
|
* @param {string} cloudPath 云端文件夹
|
|
95
|
+
* @param {number} parallel 并发量
|
|
96
|
+
* @param {number} retryCount 重试次数
|
|
97
|
+
* @param {number} retryInterval 重试时间间隔(毫秒)
|
|
90
98
|
* @param {(string | string[])} ignore
|
|
91
99
|
* @param {(string | string[])} ignore
|
|
92
100
|
* @returns {Promise<void>}
|
|
@@ -96,6 +104,9 @@ export declare class StorageService {
|
|
|
96
104
|
* 上传文件夹,支持自定义 Region 和 Bucket
|
|
97
105
|
* @param {string} localPath
|
|
98
106
|
* @param {string} cloudPath
|
|
107
|
+
* @param {number} parallel
|
|
108
|
+
* @param {number} retryCount
|
|
109
|
+
* @param {number} retryInterval
|
|
99
110
|
* @param {string} bucket
|
|
100
111
|
* @param {string} region
|
|
101
112
|
* @param {IOptions} options
|
|
@@ -140,6 +151,7 @@ export declare class StorageService {
|
|
|
140
151
|
downloadDirectory(options: {
|
|
141
152
|
cloudPath: string;
|
|
142
153
|
localPath?: string;
|
|
154
|
+
parallel?: number;
|
|
143
155
|
}): Promise<(NodeJS.ReadableStream | string)[]>;
|
|
144
156
|
/**
|
|
145
157
|
* 列出文件夹下的文件
|
|
@@ -284,5 +296,29 @@ export declare class StorageService {
|
|
|
284
296
|
* 获取存储桶配置
|
|
285
297
|
*/
|
|
286
298
|
private getStorageConfig;
|
|
299
|
+
/**
|
|
300
|
+
* 带重试功能的上传多文件函数
|
|
301
|
+
* @param uploadFiles sdk上传函数
|
|
302
|
+
* @param options sdk上传函数参数
|
|
303
|
+
* @param times 重试次数
|
|
304
|
+
* @param interval 重试时间间隔(毫秒)
|
|
305
|
+
* @param failedFiles 失败文件列表
|
|
306
|
+
* @returns
|
|
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;
|
|
287
323
|
}
|
|
288
324
|
export {};
|