@@ -2,6 +2,8 @@ import { Service } from '@volcengine/openapi';
22import type { VefaasFunctionConfig , VefaasFunctionInfo } from './types' ;
33import { logger } from '../../common/logger' ;
44import { lang } from '../../lang' ;
5+ import { pollUntil , PollingTimeoutError } from '../polling' ;
6+ import { SCF_STATUS_POLL_INTERVAL_MS , SCF_STATUS_POLL_MAX_ATTEMPTS } from '../constants' ;
57import * as fs from 'node:fs' ;
68
79type VefaasSdkClient = Service ;
@@ -132,7 +134,48 @@ export const createVefaasOperations = (client: VefaasSdkClient) => {
132134 region : ( client as unknown as { region : string } ) . region ,
133135 } ) ;
134136
135- return {
137+ const operations = {
138+ waitForFunctionActive : async ( functionName : string ) : Promise < VefaasFunctionInfo | null > => {
139+ try {
140+ return await pollUntil ( {
141+ description : `veFaaS function ${ functionName } to become Active` ,
142+ fetch : ( ) => operations . getFunction ( functionName ) ,
143+ isDone : ( info ) => info ?. status === 'Active' ,
144+ intervalMs : SCF_STATUS_POLL_INTERVAL_MS ,
145+ maxAttempts : SCF_STATUS_POLL_MAX_ATTEMPTS ,
146+ } ) ;
147+ } catch ( e ) {
148+ if ( e instanceof PollingTimeoutError ) {
149+ throw new Error (
150+ `Timed out waiting for veFaaS function ${ functionName } to become Active` ,
151+ {
152+ cause : e ,
153+ } ,
154+ ) ;
155+ }
156+ throw e ;
157+ }
158+ } ,
159+
160+ waitForFunctionDeleted : async ( functionName : string ) : Promise < void > => {
161+ try {
162+ await pollUntil ( {
163+ description : `veFaaS function ${ functionName } to be deleted` ,
164+ fetch : ( ) => operations . getFunction ( functionName ) ,
165+ isDone : ( info ) => info === null ,
166+ intervalMs : SCF_STATUS_POLL_INTERVAL_MS ,
167+ maxAttempts : SCF_STATUS_POLL_MAX_ATTEMPTS ,
168+ } ) ;
169+ } catch ( e ) {
170+ if ( e instanceof PollingTimeoutError ) {
171+ throw new Error ( `Timed out waiting for veFaaS function ${ functionName } to be deleted` , {
172+ cause : e ,
173+ } ) ;
174+ }
175+ throw e ;
176+ }
177+ } ,
178+
136179 createFunction : async ( config : VefaasFunctionConfig , codePath : string ) : Promise < void > => {
137180 const { size, sizeMB } = await validateCodePackage ( codePath ) ;
138181
@@ -228,6 +271,11 @@ export const createVefaasOperations = (client: VefaasSdkClient) => {
228271 data : params ,
229272 } ) ;
230273
274+ // CreateFunction is async on veFaaS — the function stays non-Active until
275+ // the platform finishes provisioning. Follow-up calls (e.g. update or
276+ // trigger setup) fail if issued too early, so poll until Active.
277+ await operations . waitForFunctionActive ( config . functionName ) ;
278+
231279 logger . info ( lang . __ ( 'FUNCTION_CREATED' , { functionName : config . functionName } ) ) ;
232280 } ,
233281
@@ -325,6 +373,7 @@ export const createVefaasOperations = (client: VefaasSdkClient) => {
325373 } ) ,
326374 } ;
327375
376+ await operations . waitForFunctionActive ( config . functionName ) ;
328377 await client . fetchOpenAPI ( {
329378 Action : 'UpdateFunction' ,
330379 Version : '2024-06-06' ,
@@ -378,6 +427,7 @@ export const createVefaasOperations = (client: VefaasSdkClient) => {
378427 } ;
379428 }
380429
430+ await operations . waitForFunctionActive ( functionName ) ;
381431 await client . fetchOpenAPI ( {
382432 Action : 'UpdateFunction' ,
383433 Version : '2024-06-06' ,
@@ -401,6 +451,10 @@ export const createVefaasOperations = (client: VefaasSdkClient) => {
401451 data : { FunctionName : functionName } ,
402452 } ) ;
403453
454+ // DeleteFunction returns immediately — wait for the function to be gone so
455+ // a subsequent create (retry) does not collide with a still-deleting function.
456+ await operations . waitForFunctionDeleted ( functionName ) ;
457+
404458 logger . info ( lang . __ ( 'FUNCTION_DELETED' , { functionName } ) ) ;
405459 } ,
406460
@@ -430,4 +484,6 @@ export const createVefaasOperations = (client: VefaasSdkClient) => {
430484 } ) ) ;
431485 } ,
432486 } ;
487+
488+ return operations ;
433489} ;
0 commit comments