doc-exports/docs/fg/umn/functiongraph_01_0406.html
Chen, Junjie dac566cf2f FG UMN 20230725 version
Reviewed-by: Eotvos, Oliver <oliver.eotvos@t-systems.com>
Co-authored-by: Chen, Junjie <chenjunjie@huawei.com>
Co-committed-by: Chen, Junjie <chenjunjie@huawei.com>
2024-04-03 10:30:56 +00:00

361 lines
28 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<a name="functiongraph_01_0406"></a><a name="functiongraph_01_0406"></a>
<h1 class="topictitle1">Custom Runtime</h1>
<div id="body32001227"><div class="section" id="functiongraph_01_0406__en-us_topic_0000001298786845_section1386041552612"><h4 class="sectiontitle">Scenarios</h4><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p1804104513282">A runtime runs the code of a function, reads the handler name from an environment variable, and reads invocation events from the runtime APIs of FunctionGraph. The runtime passes event data to the function handler and returns the response from the handler to FunctionGraph.</p>
<p id="functiongraph_01_0406__en-us_topic_0000001298786845_p38401633142619">FunctionGraph supports custom runtimes. You can use an executable file named <strong id="functiongraph_01_0406__en-us_topic_0000001298786845_b4605181516714">bootstrap</strong> to include a runtime in your function deployment package. The runtime runs the function's handler method when the function is invoked.</p>
<p id="functiongraph_01_0406__en-us_topic_0000001298786845_p18840733202613">Your runtime runs in the FunctionGraph execution environment. It can be a shell script or a binary executable file that is compiled in Linux.</p>
<div class="note" id="functiongraph_01_0406__en-us_topic_0000001298786845_note3917101515122"><img src="public_sys-resources/note_3.0-en-us.png"><span class="notetitle"> </span><div class="notebody"><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p8121218111213">After programming, simply package your code into a ZIP file (Java, Node.js, Python, and Go) or JAR file (Java), and upload the file to FunctionGraph for execution. When creating a ZIP file, place the handler file under the <strong id="functiongraph_01_0406__en-us_topic_0000001298786845_b1582143103816">root</strong> directory to ensure that your code can run normally after being decompressed.</p>
<p id="functiongraph_01_0406__en-us_topic_0000001298786845_p1713111813121">If you edit code in Go, zip the compiled file, and ensure that the name of the dynamic library file is consistent with the plug-in name of the handler. For example, if the name of the dynamic library file is <strong id="functiongraph_01_0406__en-us_topic_0000001298786845_b1885453663820">testplugin.so</strong>, set the handler name to <strong id="functiongraph_01_0406__en-us_topic_0000001298786845_b188541936133819">testplugin.Handler</strong>.</p>
</div></div>
</div>
<div class="section" id="functiongraph_01_0406__en-us_topic_0000001298786845_section144561842183111"><h4 class="sectiontitle">Runtime File bootstrap</h4><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p1553158145612">If there is a file named <strong id="functiongraph_01_0406__en-us_topic_0000001298786845_b424461817440">bootstrap</strong> in your function deployment package, FunctionGraph executes that file. If the <strong id="functiongraph_01_0406__en-us_topic_0000001298786845_b2218519164516">bootstrap</strong> file is not found or not executable, your function will return an error when invoked.</p>
<p id="functiongraph_01_0406__en-us_topic_0000001298786845_p1376873115577">The runtime code is responsible for completing initialization tasks. It processes invocation events in a loop until it is terminated.</p>
<p id="functiongraph_01_0406__en-us_topic_0000001298786845_p182091510183218">The initialization tasks run once for each instance of the function to prepare the environment for handling invocations.</p>
</div>
<div class="section" id="functiongraph_01_0406__en-us_topic_0000001298786845_section236572019466"><h4 class="sectiontitle">Runtime APIs</h4><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p166193664615">FunctionGraph provides HTTP runtime APIs to receive function invocation events and returns response data in the execution environment.</p>
<ul id="functiongraph_01_0406__en-us_topic_0000001298786845_ul1441510517481"><li id="functiongraph_01_0406__en-us_topic_0000001298786845_li11415115164813"><strong id="functiongraph_01_0406__en-us_topic_0000001298786845_b14836182345117">Obtaining Invocation Event</strong><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p145531014185016"><strong id="functiongraph_01_0406__en-us_topic_0000001298786845_b1899514455102">Method</strong> Get</p>
<p id="functiongraph_01_0406__en-us_topic_0000001298786845_p17553201405017"><strong id="functiongraph_01_0406__en-us_topic_0000001298786845_b3553111418509">Path</strong> http://$RUNTIME_API_ADDR/v1/runtime/invocation/request</p>
<p id="functiongraph_01_0406__en-us_topic_0000001298786845_p1496475854915">This API is used to retrieve an invocation event. The response body contains the event data. The following table describes additional data about the invocation contained in the response header.</p>
<div class="tablenoborder"><a name="functiongraph_01_0406__en-us_topic_0000001298786845_table9387122910529"></a><a name="en-us_topic_0000001298786845_table9387122910529"></a><table cellpadding="4" cellspacing="0" summary="" id="functiongraph_01_0406__en-us_topic_0000001298786845_table9387122910529" frame="border" border="1" rules="all"><caption><b>Table 1 </b>Response header information</caption><thead align="left"><tr id="functiongraph_01_0406__en-us_topic_0000001298786845_row20387729165211"><th align="left" class="cellrowborder" valign="top" width="50%" id="mcps1.3.3.3.1.5.2.3.1.1"><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p14387529165210">Parameter</p>
</th>
<th align="left" class="cellrowborder" valign="top" width="50%" id="mcps1.3.3.3.1.5.2.3.1.2"><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p153881629165212">Description</p>
</th>
</tr>
</thead>
<tbody><tr id="functiongraph_01_0406__en-us_topic_0000001298786845_row13881929135213"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.3.3.3.1.5.2.3.1.1 "><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p19388112945214">X-Cff-Request-Id</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.3.3.3.1.5.2.3.1.2 "><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p143881329145211">Request ID.</p>
</td>
</tr>
<tr id="functiongraph_01_0406__en-us_topic_0000001298786845_row15388112917524"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.3.3.3.1.5.2.3.1.1 "><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p1438816290521">X-CFF-Access-Key</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.3.3.3.1.5.2.3.1.2 "><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p03881929175219">AK of the account. An agency must be configured for the function if this variable is used.</p>
</td>
</tr>
<tr id="functiongraph_01_0406__en-us_topic_0000001298786845_row14388529105215"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.3.3.3.1.5.2.3.1.1 "><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p15389172935210">X-CFF-Auth-Token</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.3.3.3.1.5.2.3.1.2 "><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p9389429125213">Token of the account. An agency must be configured for the function if this variable is used.</p>
</td>
</tr>
<tr id="functiongraph_01_0406__en-us_topic_0000001298786845_row1389102975220"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.3.3.3.1.5.2.3.1.1 "><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p33891829175218">X-CFF-Invoke-Type</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.3.3.3.1.5.2.3.1.2 "><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p10389929165212">Invocation type of the function.</p>
</td>
</tr>
<tr id="functiongraph_01_0406__en-us_topic_0000001298786845_row1738992915213"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.3.3.3.1.5.2.3.1.1 "><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p20389142917525">X-CFF-Secret-Key</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.3.3.3.1.5.2.3.1.2 "><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p13389162955215">SK of the account. An agency must be configured for the function if this variable is used.</p>
</td>
</tr>
<tr id="functiongraph_01_0406__en-us_topic_0000001298786845_row8389929195216"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.3.3.3.1.5.2.3.1.1 "><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p1338952985210">X-CFF-Security-Token</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.3.3.3.1.5.2.3.1.2 "><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p18389152915218">Security token of the account. An agency must be configured for the function if this variable is used.</p>
</td>
</tr>
</tbody>
</table>
</div>
</li><li id="functiongraph_01_0406__en-us_topic_0000001298786845_li1985614327535"><strong id="functiongraph_01_0406__en-us_topic_0000001298786845_b4628451974">Invocation Response</strong><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p6856532105317"><strong id="functiongraph_01_0406__en-us_topic_0000001298786845_b540576171">Method</strong> POST</p>
<p id="functiongraph_01_0406__en-us_topic_0000001298786845_p8856832165310"><strong id="functiongraph_01_0406__en-us_topic_0000001298786845_b158569329535">Path</strong> http://$RUNTIME_API_ADDR/v1/runtime/invocation/response/$REQUEST_ID</p>
<p id="functiongraph_01_0406__en-us_topic_0000001298786845_p15856143215537">This API is used to send a successful invocation response to FunctionGraph. After the runtime invokes the function handler, it publishes the response from the function to the invocation response path.</p>
</li><li id="functiongraph_01_0406__en-us_topic_0000001298786845_li1836644364810"><strong id="functiongraph_01_0406__en-us_topic_0000001298786845_b1221291151218">Invocation Error</strong><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p8799325145619"><strong id="functiongraph_01_0406__en-us_topic_0000001298786845_b815313210127">Method</strong> POST</p>
<p id="functiongraph_01_0406__en-us_topic_0000001298786845_p1479972595615"><strong id="functiongraph_01_0406__en-us_topic_0000001298786845_b4799325155620">Path</strong> http://$RUNTIME_API_ADDR/v1/runtime/invocation/error/$REQUEST_ID</p>
<p id="functiongraph_01_0406__en-us_topic_0000001298786845_p841045791420"><strong id="functiongraph_01_0406__en-us_topic_0000001298786845_b184716261275">$REQUEST_ID</strong> is the value of variable <strong id="functiongraph_01_0406__en-us_topic_0000001298786845_b17388171710813">X-Cff-Request-Id</strong> in the header of an event retrieval response. For more information, see <a href="#functiongraph_01_0406__en-us_topic_0000001298786845_table9387122910529">Table 1</a>.</p>
<p id="functiongraph_01_0406__en-us_topic_0000001298786845_p166615161676"><strong id="functiongraph_01_0406__en-us_topic_0000001298786845_b13916183717105">$RUNTIME_API_ADDR</strong> is a system environment variable. For more information, see <a href="#functiongraph_01_0406__en-us_topic_0000001298786845_table11731825111317">Table 2</a>.</p>
<p id="functiongraph_01_0406__en-us_topic_0000001298786845_p5799152511568">This API is used to send an error invocation response to FunctionGraph. After the runtime invokes the function handler, it publishes the response from the function to the invocation response path.</p>
</li></ul>
</div>
<div class="section" id="functiongraph_01_0406__en-us_topic_0000001298786845_section519742719101"><h4 class="sectiontitle">Runtime Environment Variables</h4><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p124001941171019">You can use both custom and runtime environment variables in function code. The following table lists the runtime environment variables that are used in the FunctionGraph execution environment.</p>
<div class="tablenoborder"><a name="functiongraph_01_0406__en-us_topic_0000001298786845_table11731825111317"></a><a name="en-us_topic_0000001298786845_table11731825111317"></a><table cellpadding="4" cellspacing="0" summary="" id="functiongraph_01_0406__en-us_topic_0000001298786845_table11731825111317" frame="border" border="1" rules="all"><caption><b>Table 2 </b>Environment variables</caption><thead align="left"><tr id="functiongraph_01_0406__en-us_topic_0000001298786845_row6731251134"><th align="left" class="cellrowborder" valign="top" width="50.480000000000004%" id="mcps1.3.4.3.2.3.1.1"><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p77319257136">Key</p>
</th>
<th align="left" class="cellrowborder" valign="top" width="49.519999999999996%" id="mcps1.3.4.3.2.3.1.2"><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p773125191317">Description</p>
</th>
</tr>
</thead>
<tbody><tr id="functiongraph_01_0406__en-us_topic_0000001298786845_row473125181317"><td class="cellrowborder" valign="top" width="50.480000000000004%" headers="mcps1.3.4.3.2.3.1.1 "><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p490910286133">RUNTIME_PROJECT_ID</p>
</td>
<td class="cellrowborder" valign="top" width="49.519999999999996%" headers="mcps1.3.4.3.2.3.1.2 "><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p97382514135">Project ID</p>
</td>
</tr>
<tr id="functiongraph_01_0406__en-us_topic_0000001298786845_row1073162551313"><td class="cellrowborder" valign="top" width="50.480000000000004%" headers="mcps1.3.4.3.2.3.1.1 "><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p7265153671320">RUNTIME_FUNC_NAME</p>
</td>
<td class="cellrowborder" valign="top" width="49.519999999999996%" headers="mcps1.3.4.3.2.3.1.2 "><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p173425171312">Function name</p>
</td>
</tr>
<tr id="functiongraph_01_0406__en-us_topic_0000001298786845_row1873325101311"><td class="cellrowborder" valign="top" width="50.480000000000004%" headers="mcps1.3.4.3.2.3.1.1 "><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p8876154014132">RUNTIME_FUNC_VERSION</p>
</td>
<td class="cellrowborder" valign="top" width="49.519999999999996%" headers="mcps1.3.4.3.2.3.1.2 "><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p11737257132">Function version</p>
</td>
</tr>
<tr id="functiongraph_01_0406__en-us_topic_0000001298786845_row8731325111316"><td class="cellrowborder" valign="top" width="50.480000000000004%" headers="mcps1.3.4.3.2.3.1.1 "><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p102991146171316">RUNTIME_PACKAGE</p>
</td>
<td class="cellrowborder" valign="top" width="49.519999999999996%" headers="mcps1.3.4.3.2.3.1.2 "><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p473825131312">App to which the function belongs</p>
</td>
</tr>
<tr id="functiongraph_01_0406__en-us_topic_0000001298786845_row177322515133"><td class="cellrowborder" valign="top" width="50.480000000000004%" headers="mcps1.3.4.3.2.3.1.1 "><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p577014512138">RUNTIME_HANDLER</p>
</td>
<td class="cellrowborder" valign="top" width="49.519999999999996%" headers="mcps1.3.4.3.2.3.1.2 "><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p167422518139">Function handler</p>
</td>
</tr>
<tr id="functiongraph_01_0406__en-us_topic_0000001298786845_row674112512137"><td class="cellrowborder" valign="top" width="50.480000000000004%" headers="mcps1.3.4.3.2.3.1.1 "><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p1486457141311">RUNTIME_TIMEOUT</p>
</td>
<td class="cellrowborder" valign="top" width="49.519999999999996%" headers="mcps1.3.4.3.2.3.1.2 "><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p15335125821620">Function timeout duration</p>
</td>
</tr>
<tr id="functiongraph_01_0406__en-us_topic_0000001298786845_row19741125151311"><td class="cellrowborder" valign="top" width="50.480000000000004%" headers="mcps1.3.4.3.2.3.1.1 "><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p13325622143">RUNTIME_USERDATA</p>
</td>
<td class="cellrowborder" valign="top" width="49.519999999999996%" headers="mcps1.3.4.3.2.3.1.2 "><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p263716871710">Value passed through an environment variable</p>
</td>
</tr>
<tr id="functiongraph_01_0406__en-us_topic_0000001298786845_row1074025101319"><td class="cellrowborder" valign="top" width="50.480000000000004%" headers="mcps1.3.4.3.2.3.1.1 "><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p18669095145">RUNTIME_CPU</p>
</td>
<td class="cellrowborder" valign="top" width="49.519999999999996%" headers="mcps1.3.4.3.2.3.1.2 "><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p28641716121717">Number of allocated CPU cores</p>
</td>
</tr>
<tr id="functiongraph_01_0406__en-us_topic_0000001298786845_row174132510133"><td class="cellrowborder" valign="top" width="50.480000000000004%" headers="mcps1.3.4.3.2.3.1.1 "><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p2038932011147">RUNTIME_MEMORY</p>
</td>
<td class="cellrowborder" valign="top" width="49.519999999999996%" headers="mcps1.3.4.3.2.3.1.2 "><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p974182519139">Allocated memory</p>
</td>
</tr>
<tr id="functiongraph_01_0406__en-us_topic_0000001298786845_row647315121418"><td class="cellrowborder" valign="top" width="50.480000000000004%" headers="mcps1.3.4.3.2.3.1.1 "><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p14057244147">RUNTIME_CODE_ROOT</p>
</td>
<td class="cellrowborder" valign="top" width="49.519999999999996%" headers="mcps1.3.4.3.2.3.1.2 "><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p15471115121420">Directory that stores the function code</p>
</td>
</tr>
<tr id="functiongraph_01_0406__en-us_topic_0000001298786845_row194751561414"><td class="cellrowborder" valign="top" width="50.480000000000004%" headers="mcps1.3.4.3.2.3.1.1 "><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p1148111518148">RUNTIME_API_ADDR</p>
</td>
<td class="cellrowborder" valign="top" width="49.519999999999996%" headers="mcps1.3.4.3.2.3.1.2 "><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p5983151918913">Host IP address and port of a custom runtime API</p>
</td>
</tr>
</tbody>
</table>
</div>
<p id="functiongraph_01_0406__en-us_topic_0000001298786845_p14925131491814">The value of a custom environment variable can be retrieved in the same way as the value of a FunctionGraph environment variable.</p>
</div>
<div class="section" id="functiongraph_01_0406__en-us_topic_0000001298786845_section1326081833712"><h4 class="sectiontitle">Example</h4><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p117141551161816">This example contains one file called <strong id="functiongraph_01_0406__en-us_topic_0000001298786845_b182111438112318">bootstrap</strong>. The file is implemented in Bash.</p>
<p id="functiongraph_01_0406__en-us_topic_0000001298786845_p6715175161812">The runtime loads the function script from the deployment package by using two variables.</p>
<p id="functiongraph_01_0406__en-us_topic_0000001298786845_p16715351171810">The <strong id="functiongraph_01_0406__en-us_topic_0000001298786845_b144045833314">bootstrap</strong> file is as follows:</p>
<pre class="screen" id="functiongraph_01_0406__en-us_topic_0000001298786845_screen65009157459">#!/bin/sh
set -o pipefail
#Processing requests loop
while true
do
HEADERS="$(mktemp)"
# Get an event
EVENT_DATA=$(curl -sS -LD "$HEADERS" -X GET "http://$RUNTIME_API_ADDR/v1/runtime/invocation/request")
# Get request id from response header
REQUEST_ID=$(grep -Fi x-cff-request-id "$HEADERS" | tr -d '[:space:]' | cut -d: -f2)
if [ -z "$REQUEST_ID" ]; then
continue
fi
# Process request data
RESPONSE="Echoing request: hello world!"
# Put response
curl -X POST "http://$RUNTIME_API_ADDR/v1/runtime/invocation/response/$REQUEST_ID" -d "$RESPONSE"
done</pre>
<p id="functiongraph_01_0406__en-us_topic_0000001298786845_p187262142217">After loading the script, the runtime processes invocation events in a loop until it is terminated. It uses the API to retrieve invocation events from FunctionGraph, passes the events to the handler, and then sends responses back to FunctionGraph.</p>
<p id="functiongraph_01_0406__en-us_topic_0000001298786845_p18630163274019">To obtain the request ID, the runtime saves the API response header in a temporary file, and then reads the request ID from the <strong id="functiongraph_01_0406__en-us_topic_0000001298786845_b142444374394">x-cff-request-id</strong> header field. The runtime processes the retrieved event data and sends a response back to FunctionGraph.</p>
<p id="functiongraph_01_0406__en-us_topic_0000001298786845_p4747124472410">The following is an example of source code in Go. It can be executed only after compilation.</p>
<pre class="codeblock" id="functiongraph_01_0406__en-us_topic_0000001298786845_codeblock1957122002516">package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"log"
"net"
"net/http"
"os"
"strings"
"time"
)
var (
getRequestUrl = os.ExpandEnv("http://${RUNTIME_API_ADDR}/v1/runtime/invocation/request")
putResponseUrl = os.ExpandEnv("http://${RUNTIME_API_ADDR}/v1/runtime/invocation/response/{REQUEST_ID}")
putErrorResponseUrl = os.ExpandEnv("http://${RUNTIME_API_ADDR}/v1/runtime/invocation/error/{REQUEST_ID}")
requestIdInvalidError = fmt.Errorf("request id invalid")
noRequestAvailableError = fmt.Errorf("no request available")
putResponseFailedError = fmt.Errorf("put response failed")
functionPackage = os.Getenv("RUNTIME_PACKAGE")
functionName = os.Getenv("RUNTIME_FUNC_NAME")
functionVersion = os.Getenv("RUNTIME_FUNC_VERSION")
client = http.Client{
Transport: &amp;http.Transport{
DialContext: (&amp;net.Dialer{
Timeout: 3 * time.Second,
}).DialContext,
},
}
)
func main() {
// main loop for processing requests.
for {
requestId, header, payload, err := getRequest()
if err != nil {
time.Sleep(50 * time.Millisecond)
continue
}
result, err := processRequestEvent(requestId, header, payload)
err = putResponse(requestId, result, err)
if err != nil {
log.Printf("put response failed, err: %s.", err.Error())
}
}
}
// event processing function
func processRequestEvent(requestId string, header http.Header, evtBytes []byte) ([]byte, error) {
log.Printf("processing request '%s'.", requestId)
result := fmt.Sprintf("function: %s:%s:%s, request id: %s, headers: %+v, payload: %s", functionPackage, functionName,
functionVersion, requestId, header, string(evtBytes))
var event FunctionEvent
err := json.Unmarshal(evtBytes, &amp;event)
if err != nil {
return (&amp;ErrorMessage{ErrorType: "invalid event", ErrorMessage: "invalid json formated event"}).toJsonBytes(), err
}
return (&amp;APIGFormatResult{StatusCode: 200, Body: result}).toJsonBytes(), nil
}
func getRequest() (string, http.Header, []byte, error) {
resp, err := client.Get(getRequestUrl)
if err != nil {
log.Printf("get request error, err: %s.", err.Error())
return "", nil, nil, err
}
defer resp.Body.Close()
// get request id from response header
requestId := resp.Header.Get("X-CFF-Request-Id")
if requestId == "" {
log.Printf("request id not found.")
return "", nil, nil, requestIdInvalidError
}
payload, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Printf("read request body error, err: %s.", err.Error())
return "", nil, nil, err
}
if resp.StatusCode != 200 {
log.Printf("get request failed, status: %d, message: %s.", resp.StatusCode, string(payload))
return "", nil, nil, noRequestAvailableError
}
log.Printf("get request ok.")
return requestId, resp.Header, payload, nil
}
func putResponse(requestId string, payload []byte, err error) error {
var body io.Reader
if payload != nil &amp;&amp; len(payload) &gt; 0 {
body = bytes.NewBuffer(payload)
}
url := ""
if err == nil {
url = strings.Replace(putResponseUrl, "{REQUEST_ID}", requestId, -1)
} else {
url = strings.Replace(putErrorResponseUrl, "{REQUEST_ID}", requestId, -1)
}
resp, err := client.Post(strings.Replace(url, "{REQUEST_ID}", requestId, -1), "", body)
if err != nil {
log.Printf("put response error, err: %s.", err.Error())
return err
}
defer resp.Body.Close()
responsePayload, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Printf("read request body error, err: %s.", err.Error())
return err
}
if resp.StatusCode != 200 {
log.Printf("put response failed, status: %d, message: %s.", resp.StatusCode, string(responsePayload))
return putResponseFailedError
}
return nil
}
type FunctionEvent struct {
Type string `json:"type"`
Name string `json:"name"`
}
type APIGFormatResult struct {
StatusCode int `json:"statusCode"`
IsBase64Encoded bool `json:"isBase64Encoded"`
Headers map[string]string `json:"headers,omitempty"`
Body string `json:"body,omitempty"`
}
func (result *APIGFormatResult) toJsonBytes() []byte {
data, err := json.MarshalIndent(result, "", " ")
if err != nil {
return nil
}
return data
}
type ErrorMessage struct {
ErrorType string `json:"errorType"`
ErrorMessage string `json:"errorMessage"`
}
func (errMsg *ErrorMessage) toJsonBytes() []byte {
data, err := json.MarshalIndent(errMsg, "", " ")
if err != nil {
return nil
}
return data
}</pre>
<p id="functiongraph_01_0406__en-us_topic_0000001298786845_p63347172913"><a href="#functiongraph_01_0406__en-us_topic_0000001298786845_table122572411113">Table 3</a> describes the environment variables used in the preceding code.</p>
<div class="tablenoborder"><a name="functiongraph_01_0406__en-us_topic_0000001298786845_table122572411113"></a><a name="en-us_topic_0000001298786845_table122572411113"></a><table cellpadding="4" cellspacing="0" summary="" id="functiongraph_01_0406__en-us_topic_0000001298786845_table122572411113" frame="border" border="1" rules="all"><caption><b>Table 3 </b>Environment variables</caption><thead align="left"><tr id="functiongraph_01_0406__en-us_topic_0000001298786845_row11258648119"><th align="left" class="cellrowborder" valign="top" width="50%" id="mcps1.3.5.11.2.3.1.1"><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p52583412112">Environment Variable</p>
</th>
<th align="left" class="cellrowborder" valign="top" width="50%" id="mcps1.3.5.11.2.3.1.2"><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p1625820420116">Description</p>
</th>
</tr>
</thead>
<tbody><tr id="functiongraph_01_0406__en-us_topic_0000001298786845_row0258114191117"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.3.5.11.2.3.1.1 "><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p2701163610115">RUNTIME_FUNC_NAME</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.3.5.11.2.3.1.2 "><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p12701133611119">Function name</p>
</td>
</tr>
<tr id="functiongraph_01_0406__en-us_topic_0000001298786845_row142581443112"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.3.5.11.2.3.1.1 "><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p19701133616115">RUNTIME_FUNC_VERSION</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.3.5.11.2.3.1.2 "><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p1270123681112">Function version</p>
</td>
</tr>
<tr id="functiongraph_01_0406__en-us_topic_0000001298786845_row102588413114"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.3.5.11.2.3.1.1 "><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p177011836151112">RUNTIME_PACKAGE</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.3.5.11.2.3.1.2 "><p id="functiongraph_01_0406__en-us_topic_0000001298786845_p17701103611115">App to which the function belongs</p>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div>
<div class="familylinks">
<div class="parentlink"><strong>Parent topic:</strong> <a href="functiongraph_01_0151.html">Supported Programming Languages</a></div>
</div>
</div>