@@ -31,13 +31,12 @@ class Scf {
3131 return result ;
3232 }
3333
34- // 绑定默认策略
34+ // bind SCF_QcsRole role
3535 async bindScfQCSRole ( ) {
3636 console . log ( `Creating and binding SCF_QcsRole` ) ;
3737 const camClient = new Cam ( this . credentials ) ;
3838 const roleName = 'SCF_QcsRole' ;
3939 const policyId = 28341895 ;
40- // 创建默认角色
4140 try {
4241 await camClient . request ( {
4342 Action : 'CreateRole' ,
@@ -58,7 +57,6 @@ class Scf {
5857 } ) ,
5958 } ) ;
6059 } catch ( e ) { }
61- // 绑定默认策略
6260 try {
6361 await camClient . request ( {
6462 Action : 'AttachRolePolicy' ,
@@ -99,21 +97,27 @@ class Scf {
9997 // because creating/upadting function is asynchronous
10098 // if not become Active in 120 * 1000 miniseconds, return request result, and throw error
10199 async checkStatus ( namespace = 'default' , functionName , qualifier = '$LATEST' ) {
102- console . log ( `Checking function ${ functionName } status` ) ;
103100 let initialInfo = await this . getFunction ( namespace , functionName , qualifier ) ;
104- let status = initialInfo ;
101+ let { Status } = initialInfo ;
105102 let times = 120 ;
106- while ( CONFIGS . waitStatus . indexOf ( status ) !== - 1 && times > 0 ) {
103+ while ( CONFIGS . waitStatus . indexOf ( Status ) !== - 1 && times > 0 ) {
107104 initialInfo = await this . getFunction ( namespace , functionName , qualifier ) ;
108- status = initialInfo . Status ;
105+ if ( ! initialInfo ) {
106+ return true ;
107+ }
108+ ( { Status } = initialInfo ) ;
109+ // if change to failed status break loop
110+ if ( CONFIGS . failStatus . indexOf ( Status ) !== - 1 ) {
111+ break ;
112+ }
109113 await sleep ( 1000 ) ;
110114 times = times - 1 ;
111115 }
112116 const { StatusReasons } = initialInfo ;
113- return status !== 'Active'
117+ return Status !== 'Active'
114118 ? StatusReasons && StatusReasons . length > 0
115119 ? `函数状态异常, ${ StatusReasons [ 0 ] . ErrorMessage } `
116- : `函数状态异常, ${ status } `
120+ : `函数状态异常, ${ Status } `
117121 : true ;
118122 }
119123
@@ -237,7 +241,7 @@ class Scf {
237241 }
238242
239243 // 删除函数
240- async deleteFunction ( functionName , namespace ) {
244+ async deleteFunction ( namespace , functionName ) {
241245 await this . request ( {
242246 Action : 'DeleteFunction' ,
243247 FunctionName : functionName ,
@@ -315,7 +319,7 @@ class Scf {
315319 }
316320
317321 /**
318- * check whether function status is operational
322+ * check whether function status is operational, mostly for asynchronous operation
319323 * @param {string } namespace
320324 * @param {string } functionName funcitn name
321325 */
@@ -328,15 +332,63 @@ class Scf {
328332 throw new TypeError ( 'API_SCF_isOperationalStatus' , res ) ;
329333 }
330334
335+ async tryToDeleteFunction ( namespace , functionName ) {
336+ try {
337+ console . log ( `正在尝试删除创建失败的函数,命令空间:${ namespace } ,函数名称:${ functionName } ` ) ;
338+ await this . deleteFunction ( namespace , functionName ) ;
339+ await this . isOperationalStatus ( namespace , functionName ) ;
340+ } catch ( e ) { }
341+ }
342+
343+ // check whether scf is operational
344+ async isOperational ( namespace , functionName , qualifier = '$LATEST' ) {
345+ const funcInfo = await this . getFunction ( namespace , functionName , qualifier ) ;
346+ if ( funcInfo ) {
347+ const { Status, StatusReasons } = funcInfo ;
348+ const reason = StatusReasons && StatusReasons . length > 0 ? StatusReasons [ 0 ] . ErrorMessage : '' ;
349+ if ( Status === 'Active' ) {
350+ return true ;
351+ }
352+ let errorMsg = '' ;
353+ switch ( Status ) {
354+ case 'Creating' :
355+ errorMsg = '当前函数正在创建中,无法更新代码,请稍后再试' ;
356+ break ;
357+ case 'Updating' :
358+ errorMsg = '当前函数正在更新中,无法更新代码,请稍后再试' ;
359+ break ;
360+ case 'Publishing' :
361+ errorMsg = '当前函数正在版本发布中,无法更新代码,请稍后再试' ;
362+ break ;
363+ case 'Deleting' :
364+ errorMsg = '当前函数正在删除中,无法更新代码,请稍后再试' ;
365+ break ;
366+ case 'CreateFailed' :
367+ console . log ( `函数创建失败,${ reason || Status } ` ) ;
368+ await this . tryToDeleteFunction ( namespace , functionName ) ;
369+ break ;
370+ case 'DeleteFailed' :
371+ errorMsg = `函数删除失败,${ reason || Status } ` ;
372+ break ;
373+ }
374+ if ( errorMsg ) {
375+ throw new TypeError ( 'API_SCF_isOperational' , errorMsg ) ;
376+ }
377+ }
378+ }
379+
331380 // deploy SCF flow
332381 async deploy ( inputs = { } ) {
382+ const namespace = inputs . namespace || CONFIGS . defaultNamespace ;
383+
384+ // before deploy a scf, we should check whether
385+ // if is CreateFailed, try to remove it
386+ await this . isOperational ( namespace , inputs . name ) ;
387+
333388 // whether auto create/bind role
334389 if ( inputs . enableRoleAuth ) {
335390 await this . bindScfQCSRole ( ) ;
336391 }
337-
338- const namespace = inputs . namespace || CONFIGS . defaultNamespace ;
339-
340392 // check SCF exist
341393 // exist: update it, not: create it
342394 let funcInfo = await this . getFunction ( namespace , inputs . name ) ;
@@ -452,7 +504,7 @@ class Scf {
452504 return ;
453505 }
454506
455- await this . deleteFunction ( functionName , namespace ) ;
507+ await this . deleteFunction ( namespace , functionName ) ;
456508
457509 if ( inputs . Triggers ) {
458510 for ( let i = 0 ; i < inputs . Triggers . length ; i ++ ) {
0 commit comments