33require_once __DIR__ . '/../vendor/autoload.php ' ;
44
55use Appwrite \Runtimes \Runtimes ;
6+ use OpenRuntimes \Executor \Validator \TCP ;
67use OpenRuntimes \Executor \Usage ;
78use Swoole \Process ;
89use Swoole \Runtime ;
@@ -412,6 +413,7 @@ function removeAllRuntimes(Table $activeRuntimes, Orchestration $orchestration):
412413 $ secret = \bin2hex (\random_bytes (16 ));
413414
414415 $ activeRuntimes ->set ($ runtimeName , [
416+ 'listening ' => false ,
415417 'name ' => $ runtimeName ,
416418 'hostname ' => $ runtimeHostname ,
417419 'created ' => $ startTime ,
@@ -570,14 +572,10 @@ function removeAllRuntimes(Table $activeRuntimes, Orchestration $orchestration):
570572 'duration ' => $ duration ,
571573 ]);
572574
573- $ activeRuntimes ->set ($ runtimeName , [
574- 'name ' => $ runtimeName ,
575- 'hostname ' => $ runtimeHostname ,
576- 'created ' => $ startTime ,
577- 'updated ' => \microtime (true ),
578- 'status ' => 'Up ' . \round ($ duration , 2 ) . 's ' ,
579- 'key ' => $ secret ,
580- ]);
575+ $ activeRuntime = $ activeRuntimes ->get ($ runtimeName );
576+ $ activeRuntime ['updated ' ] = \microtime (true );
577+ $ activeRuntime ['status ' ] = 'Up ' . \round ($ duration , 2 ) . 's ' ;
578+ $ activeRuntimes ->set ($ runtimeName , $ activeRuntime );
581579 } catch (Throwable $ th ) {
582580 $ error = $ th ->getMessage () . $ output ;
583581
@@ -734,7 +732,7 @@ function (string $runtimeId, ?string $payload, string $path, string $method, arr
734732 'INERNAL_EXECUTOR_HOSTNAME ' => System::getHostname ()
735733 ]);
736734
737- $ coldStartDuration = 0 ;
735+ $ prepareStart = \microtime ( true ) ;
738736
739737 // Prepare runtime
740738 if (!$ activeRuntimes ->exists ($ runtimeName )) {
@@ -793,7 +791,12 @@ function (string $runtimeId, ?string $payload, string $path, string $method, arr
793791 };
794792
795793 // Prepare runtime
796- for ($ i = 0 ; $ i < 10 ; $ i ++) {
794+ while (true ) {
795+ // If timeout is passed, stop and return error
796+ if (\microtime (true ) - $ prepareStart >= $ timeout ) {
797+ throw new Exception ('Function timed out during preparation. ' , 400 );
798+ }
799+
797800 ['errNo ' => $ errNo , 'error ' => $ error , 'statusCode ' => $ statusCode , 'executorResponse ' => $ executorResponse ] = \call_user_func ($ sendCreateRuntimeRequest );
798801
799802 if ($ errNo === 0 ) {
@@ -806,39 +809,44 @@ function (string $runtimeId, ?string $payload, string $path, string $method, arr
806809 $ error = $ body ['message ' ];
807810 throw new Exception ('An internal curl error has occurred while starting runtime! Error Msg: ' . $ error , 500 );
808811 } else {
809- $ coldStartDuration = \floatval ($ body ['duration ' ]);
810812 break ;
811813 }
812814 } elseif ($ errNo !== 111 ) { // Connection Refused - see https://openswoole.com/docs/swoole-error-code
813815 throw new Exception ('An internal curl error has occurred while starting runtime! Error Msg: ' . $ error , 500 );
814816 }
815817
816- if ($ i === 9 ) {
817- throw new Exception ('An internal curl error has occurred while starting runtime! Error Msg: ' . $ error , 500 );
818- }
819-
818+ // Wait 0.5s and check again
820819 \usleep (500000 );
821820 }
822821 }
823822
823+ // Lower timeout by time it took to prepare container
824+ $ timeout -= (\microtime (true ) - $ prepareStart );
825+
824826 // Update swoole table
825827 $ runtime = $ activeRuntimes ->get ($ runtimeName ) ?? [];
826828 $ runtime ['updated ' ] = \time ();
827829 $ activeRuntimes ->set ($ runtimeName , $ runtime );
828830
829831 // Ensure runtime started
830- for ($ i = 0 ; $ i < 10 ; $ i ++) {
831- if ($ activeRuntimes ->get ($ runtimeName )['status ' ] !== 'pending ' ) {
832- break ;
832+ $ launchStart = \microtime (true );
833+ while (true ) {
834+ // If timeout is passed, stop and return error
835+ if (\microtime (true ) - $ launchStart >= $ timeout ) {
836+ throw new Exception ('Function timed out during launch. ' , 400 );
833837 }
834838
835- if ($ i === 9 ) {
836- throw new Exception ( ' Runtime failed to launch in allocated time. ' , 500 ) ;
839+ if ($ activeRuntimes -> get ( $ runtimeName )[ ' status ' ] !== ' pending ' ) {
840+ break ;
837841 }
838842
843+ // Wait 0.5s and check again
839844 \usleep (500000 );
840845 }
841846
847+ // Lower timeout by time it took to launch container
848+ $ timeout -= (\microtime (true ) - $ launchStart );
849+
842850 // Ensure we have secret
843851 $ runtime = $ activeRuntimes ->get ($ runtimeName );
844852 $ hostname = $ runtime ['hostname ' ];
@@ -847,12 +855,7 @@ function (string $runtimeId, ?string $payload, string $path, string $method, arr
847855 throw new Exception ('Runtime secret not found. Please re-create the runtime. ' , 500 );
848856 }
849857
850- $ startTime = \microtime (true );
851-
852- $ executeV2 = function () use ($ variables , $ payload , $ secret , $ hostname , &$ startTime , $ timeout ): array {
853- // Restart execution timer to not could failed attempts
854- $ startTime = \microtime (true );
855-
858+ $ executeV2 = function () use ($ variables , $ payload , $ secret , $ hostname , $ timeout ): array {
856859 $ statusCode = 0 ;
857860 $ errNo = -1 ;
858861 $ executorResponse = '' ;
@@ -925,10 +928,7 @@ function (string $runtimeId, ?string $payload, string $path, string $method, arr
925928 ];
926929 };
927930
928- $ executeV3 = function () use ($ path , $ method , $ headers , $ payload , $ secret , $ hostname , &$ startTime , $ timeout ): array {
929- // Restart execution timer to not could failed attempts
930- $ startTime = \microtime (true );
931-
931+ $ executeV3 = function () use ($ path , $ method , $ headers , $ payload , $ secret , $ hostname , $ timeout ): array {
932932 $ statusCode = 0 ;
933933 $ errNo = -1 ;
934934 $ executorResponse = '' ;
@@ -959,11 +959,11 @@ function (string $runtimeId, ?string $payload, string $path, string $method, arr
959959
960960 return $ len ;
961961 });
962- \curl_setopt ($ ch , CURLOPT_TIMEOUT , $ timeout + 1 ); // Gives extra 1s after safe timeout to recieve response
963- \curl_setopt ($ ch , CURLOPT_CONNECTTIMEOUT , 10 );
962+ \curl_setopt ($ ch , CURLOPT_TIMEOUT , $ timeout + 5 ); // Gives extra 5s after safe timeout to recieve response
963+ \curl_setopt ($ ch , CURLOPT_CONNECTTIMEOUT , 5 );
964964
965965 $ headers ['x-open-runtimes-secret ' ] = $ secret ;
966- $ headers ['x-open-runtimes-timeout ' ] = $ timeout ;
966+ $ headers ['x-open-runtimes-timeout ' ] = \max ( \intval ( $ timeout), 1 ) ;
967967 $ headersArr = [];
968968 foreach ($ headers as $ key => $ value ) {
969969 $ headersArr [] = $ key . ': ' . $ value ;
@@ -1017,6 +1017,40 @@ function (string $runtimeId, ?string $payload, string $path, string $method, arr
10171017 ];
10181018 };
10191019
1020+ // From here we calculate billable duration of execution
1021+ $ startTime = \microtime (true );
1022+
1023+ $ listening = $ runtime ['listening ' ];
1024+
1025+ if (!$ listening ) {
1026+ // Wait for cold-start to finish (app listening on port)
1027+ $ pingStart = \microtime (true );
1028+ $ validator = new TCP ();
1029+ while (true ) {
1030+ // If timeout is passed, stop and return error
1031+ if (\microtime (true ) - $ pingStart >= $ timeout ) {
1032+ throw new Exception ('Function timed out during cold start. ' , 400 );
1033+ }
1034+
1035+ $ online = $ validator ->isValid ($ hostname . ': ' . 3000 );
1036+ if ($ online ) {
1037+ break ;
1038+ }
1039+
1040+ // Wait 0.5s and check again
1041+ \usleep (500000 );
1042+ }
1043+
1044+ // Update swoole table
1045+ $ runtime = $ activeRuntimes ->get ($ runtimeName );
1046+ $ runtime ['listening ' ] = true ;
1047+ $ activeRuntimes ->set ($ runtimeName , $ runtime );
1048+
1049+ // Lower timeout by time it took to cold-start
1050+ $ timeout -= (\microtime (true ) - $ pingStart );
1051+ }
1052+
1053+
10201054 // Execute function
10211055 for ($ i = 0 ; $ i < 10 ; $ i ++) {
10221056 $ executionRequest = $ version === 'v3 ' ? $ executeV3 : $ executeV2 ;
@@ -1056,7 +1090,7 @@ function (string $runtimeId, ?string $payload, string $path, string $method, arr
10561090 'body ' => $ body ,
10571091 'logs ' => \mb_strcut ($ logs , 0 , 1000000 ), // Limit to 1MB
10581092 'errors ' => \mb_strcut ($ errors , 0 , 1000000 ), // Limit to 1MB
1059- 'duration ' => $ duration + $ coldStartDuration ,
1093+ 'duration ' => $ duration ,
10601094 'startTime ' => $ startTime ,
10611095 ];
10621096
0 commit comments