mirror of
https://github.com/fnproject/fn.git
synced 2022-10-28 21:29:17 +03:00
Updated docs, cleaned things up, DRY's up function format stuff. (#688)
* Updated docs, cleaned things up, DRY's up function format stuff. * deleted files * updated bad link
This commit is contained in:
@@ -7,30 +7,29 @@ If you are a developer using Fn through the API, this section is for you.
|
||||
### Getting Started
|
||||
|
||||
* [Quickstart](https://github.com/fnproject/fn#quickstart)
|
||||
* [API Reference](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/fnproject/fn/master/docs/swagger.yml)
|
||||
* [Function file (func.yaml)](developers/function-file.md)
|
||||
* [FDKs](developers/fdks.md)
|
||||
* [Config Vars for Functions](developers/configs.md)
|
||||
* [Hot functions](developers/hot-functions.md)
|
||||
* [Testing functions](developers/testing.md)
|
||||
* [Applications - groups of functions](developers/apps.md)
|
||||
* [Async functions](developers/async.md)
|
||||
* [FAQ](faq.md)
|
||||
* [Object Model](developers/model.md)
|
||||
* [Configuration](developers/configs.md)
|
||||
* [FDKs](developers/clients.md)
|
||||
* [Function file (func.yaml)](function-file.md)
|
||||
* [Hot functions](hot-functions.md)
|
||||
* [Testing functions](testing.md)
|
||||
* [Writing functions](writing.md)
|
||||
|
||||
### Advanced
|
||||
|
||||
* [Open Function Format](function-format.md)
|
||||
* [Packaging functions](packaging.md)
|
||||
* [CLI Source](https://github.com/fnproject/cli/)
|
||||
* [Async functions](async.md)
|
||||
* [Organizing functions into an application](developers/apps.md)
|
||||
|
||||
### Learn More
|
||||
### Examples and Tutorials
|
||||
|
||||
* [Examples](../examples)
|
||||
* [Getting Started Series](../examples/tutorial)
|
||||
* [Tutorials](https://github.com/fnproject/tutorials)
|
||||
|
||||
### Advanced
|
||||
|
||||
* [API Reference](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/fnproject/fn/master/docs/swagger.yml)
|
||||
* [API Clients](developers/clients.md)
|
||||
* [Open Function Format](developers/function-format.md)
|
||||
* [Packaging functions](developers/packaging.md)
|
||||
* [CLI Source](https://github.com/fnproject/cli/)
|
||||
|
||||
## For Operators
|
||||
|
||||
If you are operating Fn, this section is for you.
|
||||
@@ -50,8 +49,7 @@ If you are operating Fn, this section is for you.
|
||||
|
||||
* [Extending Fn](operating/extending.md)
|
||||
* [Kubernetes Helm Chart for Fn](https://github.com/fnproject/fn-helm/)
|
||||
* [Setting up development environment with Docker compose](./operating/compose.md)
|
||||
* [OpenStack Triggers](operating/triggers.md)
|
||||
* [Setting up development environment with Docker compose](operating/compose.md)
|
||||
* [Docker Configuration](operating/docker.md)
|
||||
|
||||
## For Contributors
|
||||
|
||||
@@ -1,15 +1,4 @@
|
||||
# Client Libraries
|
||||
|
||||
## Function Developer Kits - FDKs
|
||||
|
||||
Language wrappers to help write functions:
|
||||
|
||||
* [Go](https://github.com/fnproject/fdk-go)
|
||||
* [Java](https://github.com/fnproject/fdk-java)
|
||||
* [Python](https://github.com/fnproject/fdk-python)
|
||||
* [Ruby](https://github.com/fnproject/fdk-ruby)
|
||||
|
||||
## Client libraries for using the API
|
||||
# Client Libraries for the API
|
||||
|
||||
* [Elixir](https://github.com/fnproject/fn_elixir)
|
||||
* [Go](https://github.com/fnproject/fn_go)
|
||||
|
||||
@@ -11,7 +11,7 @@ fn apps config set myapp LOG_LEVEL debug
|
||||
|
||||
## 2. Function configuration from func.yaml
|
||||
|
||||
See [Function file](../function-file.md) for more info.
|
||||
See [Function file](function-file.md) for more info.
|
||||
|
||||
## 3. Route level configuration
|
||||
|
||||
|
||||
8
docs/developers/fdks.md
Normal file
8
docs/developers/fdks.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# Function Developer Kits - FDKs
|
||||
|
||||
FDKs helps make writing functions easier.
|
||||
|
||||
* [Go](https://github.com/fnproject/fdk-go)
|
||||
* [Java](https://github.com/fnproject/fdk-java)
|
||||
* [Python](https://github.com/fnproject/fdk-python)
|
||||
* [Ruby](https://github.com/fnproject/fdk-ruby)
|
||||
@@ -2,11 +2,6 @@
|
||||
|
||||
Functions files are used to assist fn to help you when creating functions.
|
||||
|
||||
The files can be named as:
|
||||
|
||||
- func.yaml
|
||||
- func.json
|
||||
|
||||
An example of a function file:
|
||||
|
||||
```yaml
|
||||
@@ -14,7 +9,6 @@ name: fnproject/hello
|
||||
version: 0.0.1
|
||||
type: sync
|
||||
memory: 128
|
||||
cpus: 100m
|
||||
config:
|
||||
key: value
|
||||
key2: value2
|
||||
@@ -58,9 +52,9 @@ function. If this function exceeds this limit during execution, it is stopped
|
||||
and error message is logged. Default: `128`.
|
||||
|
||||
`cpus` (optional) is the amount of available CPU cores for this function. For example, `100m` or `0.1`
|
||||
will allow the function to consume at most 1/10 of a CPU core on the running machine. It
|
||||
expects to be a string in MilliCPUs format ('100m') or floating-point number ('0.5').
|
||||
Default: unlimited.
|
||||
+will allow the function to consume at most 1/10 of a CPU core on the running machine. It
|
||||
+expects to be a string in MilliCPUs format ('100m') or floating-point number ('0.5').
|
||||
+Default: unlimited.
|
||||
|
||||
`timeout` (optional) is the maximum time a function will be allowed to run. Default is 30 seconds.
|
||||
|
||||
@@ -68,7 +62,7 @@ Default: unlimited.
|
||||
this function calls.
|
||||
|
||||
`config` (optional) is a set of configuration variables to be passed onto the function as environment variables.
|
||||
These configuration options shall override application configuration during functions execution. See [Configuration](developers/configs.md)
|
||||
These configuration options shall override application configuration during functions execution. See [Configuration](configs.md)
|
||||
for more information.
|
||||
|
||||
`expects` (optional) a list of config/env vars that are required to run this function. These vars will be used when running/testing locally,
|
||||
@@ -10,7 +10,7 @@ While wanting to keep things simple, flexible and expandable, we decided to go b
|
||||
|
||||
Configuration values, environment information and other things will be passed in through environment variables.
|
||||
|
||||
The goals of the I/O format are the following:
|
||||
The goals of the I/O formats are the following:
|
||||
|
||||
* Very easy to use and parse
|
||||
* Supports hot for increasing performance (more than one call per container execution)
|
||||
@@ -18,12 +18,36 @@ The goals of the I/O format are the following:
|
||||
|
||||
The format is still up for discussion and in order to move forward and remain flexible, it's likely we will just allow different I/O formats and the function creator can decide what they want, on a per function basis. Default being the simplest format to use.
|
||||
|
||||
TODO: Put common env vars here, that show up in all formats.
|
||||
The way that input data is supplied to functions depends on the input format (as specified in `func.yml`) that your function is using.
|
||||
|
||||
#### Environment Variables used by All Formats
|
||||
|
||||
Your function has access to a set of environment variables, independent of
|
||||
the function's format:
|
||||
|
||||
* `FN_APP_NAME` - the name of the application that matched this route, eg: `myapp`
|
||||
* `FN_PATH` - the matched route, eg: `/hello`
|
||||
* `FN_METHOD` - the HTTP method for the request, eg: `GET` or `POST`
|
||||
* `FN_FORMAT` - a string representing one of the [function formats](function-format.md), currently either `default` or `http`. Default is `default`.
|
||||
* `FN_TYPE` - the type for this call, currently 'sync' or 'async'
|
||||
* `FN_MEMORY` - a number representing the amount of memory available to the call, in MB
|
||||
* `FN_CPUS` - a string representing the amount of CPU available to the call, in MilliCPUs or floating-point number, eg. `100m` or `0.1`. Header is present only if `cpus` is set for the route.
|
||||
|
||||
### Default I/O Format
|
||||
|
||||
The default format is simply the request body itself plus some environment variables. For instance, if someone were to post a JSON body, the unmodified body would be sent in via STDIN. The result comes via STDOUT. When task is done, pipes are closed and the container running the function is terminated.
|
||||
|
||||
#### Default Format Env Vars
|
||||
|
||||
For `default` format, the following environment variables will be available:
|
||||
|
||||
* `FN_DEADLINE` - RFC3339 time stamp of the expiration (deadline) date of function execution.
|
||||
* `FN_REQUEST_URL` - the full URL for the request ([parsing example](https://github.com/fnproject/fn/tree/master/examples/tutorial/params))
|
||||
* `FN_CALL_ID` - a unique ID for each function execution.
|
||||
* `FN_METHOD` - http method used to invoke this function
|
||||
* `FN_HEADER_$X` - the HTTP headers that were set for this request. Replace $X with the upper cased name of the header and replace dashes in the header with underscores.
|
||||
* `$X` - $X is the header that came in the http request that invoked this function.
|
||||
|
||||
#### Pros/Cons
|
||||
|
||||
Pros:
|
||||
@@ -32,65 +56,7 @@ Pros:
|
||||
|
||||
Cons:
|
||||
|
||||
* Not very efficient resource utilization - one function for one event.
|
||||
|
||||
### HTTP I/O Format
|
||||
|
||||
`format: http`
|
||||
|
||||
HTTP format could be a good option as it is in very common use obviously, most languages have some semi-easy way to parse it, and it supports hot format. The response will look like a HTTP response. The communication is still done via stdin/stdout, but these pipes are never closed unless the container is explicitly terminated. The basic format is:
|
||||
|
||||
#### Request
|
||||
|
||||
```text
|
||||
GET / HTTP/1.1
|
||||
Content-Length: 5
|
||||
|
||||
world
|
||||
```
|
||||
|
||||
#### Response
|
||||
|
||||
```text
|
||||
HTTP/1.1 200 OK
|
||||
Content-Length: 11
|
||||
|
||||
hello world
|
||||
```
|
||||
|
||||
The header keys and values will be populated with information about the
|
||||
function call such as the request URL and query parameters, in addition to any
|
||||
headers sent in the request to invoke the function itself. The additional
|
||||
headers are:
|
||||
|
||||
* `Fn_deadline` - RFC3339 time stamp of the expiration (deadline) date of function execution.
|
||||
* `Fn_request_url` - the full URL for the request ([parsing example](https://github.com/fnproject/fn/tree/master/examples/tutorial/params))
|
||||
* `Fn_call_id` - a unique ID for each function execution.
|
||||
* `Fn_method` - the HTTP method used to invoke
|
||||
* `$X` - the HTTP headers that were set for this request, exactly as they were sent in the request.
|
||||
|
||||
HTTP Headers will not be populated with app config, route config or any of the
|
||||
following, that may be found in the environment instead:
|
||||
|
||||
* `FN_APP_NAME`
|
||||
* `FN_PATH`
|
||||
* `FN_METHOD`
|
||||
* `FN_FORMAT`
|
||||
* `FN_MEMORY`
|
||||
* `FN_CPUS` (present only if `cpus` is set for the route)
|
||||
* `FN_TYPE`
|
||||
|
||||
#### Pros/Cons
|
||||
|
||||
Pros:
|
||||
|
||||
* Supports streaming
|
||||
* Common format
|
||||
|
||||
Cons:
|
||||
|
||||
* Requires a parsing library or fair amount of code to parse headers properly
|
||||
* Double parsing - headers + body (if body is to be parsed, such as json)
|
||||
* Not very efficient resource utilization - one new container execution per event.
|
||||
|
||||
### JSON I/O Format
|
||||
|
||||
@@ -98,7 +64,7 @@ Cons:
|
||||
|
||||
The JSON format is a nice hot format as it is easy to parse in most languages.
|
||||
|
||||
If a request comes in like this:
|
||||
If a request comes in with the following body:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -106,6 +72,8 @@ If a request comes in like this:
|
||||
}
|
||||
```
|
||||
|
||||
then, the input will be:
|
||||
|
||||
#### Input
|
||||
|
||||
Internally functions receive data in the example format below:
|
||||
@@ -134,7 +102,9 @@ BLANK LINE
|
||||
* content_type - format of the `body` parameter.
|
||||
* protocol - arbitrary map of protocol specific data. The above example shows what the HTTP protocol handler passes in. Subject to change and reduces reusability of your functions. **USE AT YOUR OWN RISK**.
|
||||
|
||||
Under `protocol`, `headers` contain Default format environment variables listed in [Inputs](writing.md)
|
||||
TODO: Add config map
|
||||
|
||||
Under `protocol`, `headers` contains all of the HTTP headers exactly as defined in the incoming request.
|
||||
|
||||
Each request will be separated by a blank line.
|
||||
|
||||
@@ -163,7 +133,7 @@ BLANK LINE
|
||||
* content_type - optional - format of `body`. Default is application/json.
|
||||
* protocol - optional - protocol specific response options. Entirely optional. Contents defined by each protocol.
|
||||
|
||||
#### Pros/Cons
|
||||
#### Pros/Cons of JSON format
|
||||
|
||||
Pros:
|
||||
|
||||
@@ -174,7 +144,79 @@ Cons:
|
||||
|
||||
* Not streamable
|
||||
|
||||
### HTTP I/O Format
|
||||
|
||||
`format: http`
|
||||
|
||||
HTTP format could be a good option as it is in very common use obviously, most languages have some semi-easy way to parse it, and it supports hot format. The response will look like a HTTP response. The communication is still done via stdin/stdout, but these pipes are never closed unless the container is explicitly terminated.
|
||||
|
||||
#### Request
|
||||
|
||||
```text
|
||||
GET / HTTP/1.1
|
||||
Content-Length: 5
|
||||
|
||||
world
|
||||
```
|
||||
|
||||
#### Input
|
||||
|
||||
The input to the function will be in standard HTTP format, similar to the incoming request, but with the
|
||||
following additional headers:
|
||||
|
||||
* `Fn_deadline` - RFC3339 time stamp of the expiration (deadline) date of function execution.
|
||||
* `Fn_request_url` - the full URL for the request ([parsing example](https://github.com/fnproject/fn/tree/master/examples/tutorial/params))
|
||||
* `Fn_call_id` - a unique ID for each function execution.
|
||||
* `Fn_method` - the HTTP method used to invoke
|
||||
* `$X` - the HTTP headers that were set for this request, exactly as they were sent in the request.
|
||||
|
||||
#### Output
|
||||
|
||||
Your function should output the exact response in HTTP format you'd like to be returned to the client:
|
||||
|
||||
```text
|
||||
HTTP/1.1 200 OK
|
||||
Content-Length: 11
|
||||
|
||||
hello world
|
||||
```
|
||||
|
||||
#### Pros/Cons of HTTP Format
|
||||
|
||||
Pros:
|
||||
|
||||
* Supports streaming
|
||||
* Common format
|
||||
|
||||
Cons:
|
||||
|
||||
* Requires a parsing library or fair amount of code to parse headers properly
|
||||
* Double parsing - headers + body (if body is to be parsed, such as json)
|
||||
|
||||
## Logging
|
||||
|
||||
Standard error is reserved for logging, like it was meant to be. Anything you output to STDERR will show up in the logs. And if you use a log
|
||||
collector like logspout, you can collect those logs in a central location. See [logging](logging.md).
|
||||
Standard out is where you should write response data for synchronous functions. Standard error
|
||||
is where you should write for logging, as [it was intended](http://www.jstorimer.com/blogs/workingwithcode/7766119-when-to-use-stderr-instead-of-stdout).
|
||||
And if you use a log collector like logspout, you can collect those logs in a central location. See [logging](../operating/logging.md).
|
||||
|
||||
So to write output to logs, simply log to STDERR. Here are some examples in a few languages.
|
||||
|
||||
In Go, simply use the [log](https://golang.org/pkg/log/) package, it writes to STDERR by default.
|
||||
|
||||
```go
|
||||
log.Println("hi")
|
||||
```
|
||||
|
||||
In Node.js:
|
||||
|
||||
```node
|
||||
console.error("hi");
|
||||
```
|
||||
|
||||
[More details for Node.js here](http://stackoverflow.com/a/27576486/105562).
|
||||
|
||||
In Ruby:
|
||||
|
||||
```ruby
|
||||
STDERR.puts("hi")
|
||||
```
|
||||
@@ -34,7 +34,7 @@ This type of timeout defines for how long should hot function hang around before
|
||||
}
|
||||
```
|
||||
|
||||
This timeout parameter is valid for hot functions, see what [hot functions](hot-functions.md) is. By default this parameter equals to 30 seconds.
|
||||
This timeout parameter is valid for hot functions, see what [hot functions](developers/hot-functions.md) is. By default this parameter equals to 30 seconds.
|
||||
It starts after last request being processed by hot function.
|
||||
|
||||
## Correlation between idle and regular timeout
|
||||
15
docs/developers/hot-functions.md
Normal file
15
docs/developers/hot-functions.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# Hot functions
|
||||
|
||||
By default, Fn uses "cold functions" where every request starts up a new container, feeds it with the payload then sends the
|
||||
answer back to the caller. You can expect an average start time of [300ms per execution]((https://medium.com/travis-on-docker/the-overhead-of-docker-run-f2f06d47c9f3#.96tj75ugb)) to start the function/container.
|
||||
|
||||
Hot functions improve performance by starting a function then keeping it alive to handle additional requests. This
|
||||
makes it a bit trickier to use because you'll have to parse a stream of requests, but if you use an [FDK](fdks.md) it's
|
||||
all taken care of for you, so you should probably use an FDK in most cases.
|
||||
|
||||
## Making a hot function
|
||||
|
||||
In your `func.yaml`, add `format: json`.
|
||||
|
||||
From there, we recommend using one of our [FDKs](fdks.md) to handle all the parsing and formatting. But if you'd like to learn
|
||||
about the nitty gritty details, [check here](function-format.md).
|
||||
@@ -18,7 +18,7 @@ curl -H "Content-Type: application/json" -X POST -d '{
|
||||
}' http://localhost:8080/v1/apps
|
||||
```
|
||||
|
||||
[More on apps](docs/apps.md).
|
||||
[More on apps](apps.md).
|
||||
|
||||
Now that we have an app, we can route endpoints to functions.
|
||||
|
||||
@@ -26,8 +26,7 @@ Now that we have an app, we can route endpoints to functions.
|
||||
|
||||
A route is a way to define a path in your application that maps to a function. In this example, we'll map
|
||||
`/hello` to a simple `Hello World!` function called `fnproject/hello` which is a function we already made that you
|
||||
can use -- yes, you can share functions! The source code for this function is in the [examples directory](examples/hello/go).
|
||||
You can read more about [writing your own functions here](docs/writing.md).
|
||||
can use -- yes, you can share functions! The source code for this function is in the [examples directory](/examples/hello/go).
|
||||
|
||||
```sh
|
||||
fn routes create myapp /hello -i fnproject/hello
|
||||
@@ -44,7 +43,7 @@ curl -H "Content-Type: application/json" -X POST -d '{
|
||||
}' http://localhost:8080/v1/apps/myapp/routes
|
||||
```
|
||||
|
||||
[More on routes](docs/routes.md).
|
||||
[More on routes](../operating/routes.md).
|
||||
|
||||
### Calling your Function
|
||||
|
||||
@@ -124,6 +123,6 @@ You will get a `call_id` in the response:
|
||||
|
||||
If you watch the logs, you will see the function actually runs in the background:
|
||||
|
||||

|
||||

|
||||
|
||||
Read more on [logging](docs/logging.md).
|
||||
Read more on [logging](../operating/logging.md).
|
||||
@@ -89,7 +89,7 @@ Yes, as Fn packages and deploys all functions as Docker containers it’s possib
|
||||
|
||||
### What is the lifecycle of a function?
|
||||
|
||||
Functions are packaged as Docker images and by default individual containers are created to handle a function request and are then destroyed. However, [Hot Functions](hot-functions.md) are not disposed of after handling a single request.
|
||||
Functions are packaged as Docker images and by default individual containers are created to handle a function request and are then destroyed. However, [Hot Functions](developers/hot-functions.md) are not disposed of after handling a single request.
|
||||
|
||||
Hot functions are started once and kept alive while there is an incoming workload. A hot function hangs around based on an idle timeout. By default this parameter is set to 30 seconds. The timer starts after the last request is processed by the hot function.
|
||||
|
||||
@@ -154,7 +154,7 @@ We currently don't yet offer Fn as a managed service which would manage network
|
||||
|
||||
We support 'hot functions' (see the end of [this tutorial](https://github.com/fnproject/tutorials/blob/master/JavaFDKIntroduction/README.md) for an example). Hot functions will continue to live if they are used but, if not, will eventually be cleaned up.
|
||||
|
||||
Function timeout is configurable. Please see <https://github.com/fnproject/fn/blob/master/docs/function-file.md>. Note though configurable, timeouts do have limits. For example, sync functions have a maximum upper limit of 120 seconds.
|
||||
Function timeout is configurable. Please see <https://github.com/fnproject/fn/blob/master/docs/developers/function-file.md>. Note though configurable, timeouts do have limits. For example, sync functions have a maximum upper limit of 120 seconds.
|
||||
|
||||
### How does the service trace the liveliness of the function? If my function dies/crashes will the service provision it again?
|
||||
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
# Hot functions
|
||||
|
||||
Fn is built on top of container technologies. For each incoming
|
||||
workload, it spins a new container, feed it with the payload and sends the
|
||||
answer back to the caller. You can expect an average start time of 300ms per
|
||||
container. You may refer to [this blog](https://medium.com/travis-on-docker/the-overhead-of-docker-run-f2f06d47c9f3#.96tj75ugb) post to understand the details better.
|
||||
|
||||
In the case you need faster start times for your function, you may use a hot
|
||||
container instead.
|
||||
|
||||
Hot functions are started once and kept alive while there is incoming workload.
|
||||
Thus, it means that once you decide to use a hot function, you must be able to
|
||||
tell the moment it should reading from standard input to start writing to
|
||||
standard output.
|
||||
|
||||
Currently, Fn implements a HTTP-like protocol to operate hot
|
||||
containers, but instead of communication through a TCP/IP port, it uses standard
|
||||
input/output.
|
||||
|
||||
## Implementing a hot function
|
||||
|
||||
Let's look at a simple hot function. The examples directory contains a [simple example of a hot function written in go](/examples/tutorial/hotfunctions/http/go). Here's [func.go](/examples/tutorial/hotfunctions/http/go/func.go) from that example.
|
||||
|
||||
The basic cycle comprises three steps: read standard input up to a previously
|
||||
known point, process the work, the write the output to stdout with some
|
||||
information about when functions daemon should stop reading from stdout.
|
||||
|
||||
In the case at hand, we serve a loop, whose first part is plugging stdin to a
|
||||
HTTP request parser:
|
||||
|
||||
```go
|
||||
r := bufio.NewReader(os.Stdin)
|
||||
req, err := http.ReadRequest(r)
|
||||
|
||||
// ...
|
||||
} else {
|
||||
l, _ := strconv.Atoi(req.Header.Get("Content-Length"))
|
||||
p := make([]byte, l)
|
||||
r.Read(p)
|
||||
}
|
||||
```
|
||||
|
||||
Note how `Content-Length` is used to help determinate how far standard input
|
||||
must be read.
|
||||
|
||||
The next step in the cycle is to do some processing:
|
||||
|
||||
```go
|
||||
//...
|
||||
var buf bytes.Buffer
|
||||
fmt.Fprintf(&buf, "Hello %s\n", p)
|
||||
for k, vs := range req.Header {
|
||||
fmt.Fprintf(&buf, "ENV: %s %#v\n", k, vs)
|
||||
}
|
||||
//...
|
||||
```
|
||||
|
||||
And finally, we return the result with a `Content-Length` header, so
|
||||
Fn would know when to stop reading the gotten response.
|
||||
|
||||
```go
|
||||
res := http.Response{
|
||||
Proto: "HTTP/1.1",
|
||||
ProtoMajor: 1,
|
||||
ProtoMinor: 1,
|
||||
StatusCode: 200,
|
||||
Status: "OK",
|
||||
}
|
||||
res.Body = ioutil.NopCloser(&buf)
|
||||
res.ContentLength = int64(buf.Len())
|
||||
res.Write(os.Stdout)
|
||||
```
|
||||
|
||||
Rinse and repeat for each incoming workload.
|
||||
|
||||
|
||||
## Enabling a hot function
|
||||
|
||||
In your func.yaml, add "format: http". That's it.
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
|
||||
Once your functions is adapted to be handled as hot function, you must tell
|
||||
Fn that this function is now ready to be reused across
|
||||
requests:
|
||||
|
||||
```json
|
||||
{
|
||||
"route":{
|
||||
"app_name": "myapp",
|
||||
"path": "/hot",
|
||||
"image": "USERNAME/hchttp",
|
||||
"memory": 64,
|
||||
"cpus": "100m",
|
||||
"type": "sync",
|
||||
"config": null,
|
||||
"format": "http",
|
||||
"idle_timeout": 30
|
||||
}
|
||||
}
|
||||
```
|
||||
-->
|
||||
|
||||
|
||||
`format` (mandatory) either "default" or "http". If "http", then it is a hot
|
||||
function.
|
||||
|
||||
`idle_timeout` (optional) - idle timeout (in seconds) before function termination, default 30 seconds.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Fn Routes
|
||||
|
||||
Routes have a many-to-one mapping to an [app](apps.md).
|
||||
Routes have a many-to-one mapping to an [app](../developers/apps.md).
|
||||
|
||||
A good practice to get the best performance on your Fn API is define
|
||||
the required memory as well as CPU limits for each function.
|
||||
|
||||
122
docs/writing.md
122
docs/writing.md
@@ -1,122 +0,0 @@
|
||||
# Writing Functions
|
||||
|
||||
This will give you the basic overview of writing base level functions. You can also use higher level
|
||||
abstractions that make it easier such as [lambda](lambda/README.md).
|
||||
|
||||
Also, for complete examples in various languages, see the [examples directory](/examples).
|
||||
|
||||
## Code
|
||||
|
||||
The most basic code layout in any language is as follows, this is pseudo code and is not meant to run.
|
||||
|
||||
```ruby
|
||||
# Read and parse from STDIN
|
||||
body = JSON.parse(STDIN)
|
||||
|
||||
# Do something
|
||||
return_struct = doSomething(body)
|
||||
|
||||
# If sync, respond:
|
||||
STDOUT.write(JSON.generate(return_struct))
|
||||
# If async, update something:
|
||||
db.update(return_struct)
|
||||
```
|
||||
|
||||
## Inputs
|
||||
|
||||
Inputs are provided through standard input and environment variables.
|
||||
|
||||
The way that input data is supplied to functions depends on the input format (as specified in `func.yml`) that your function is using.
|
||||
|
||||
If you're using `default` format then you can simply read the function input from STDIN. For more information and to find out about other input formats see [Open Function Format](function-format.md).
|
||||
|
||||
Your function also has access to a set of environment variables, independent of
|
||||
the function's format:
|
||||
|
||||
* `FN_APP_NAME` - the name of the application that matched this route, eg: `myapp`
|
||||
* `FN_PATH` - the matched route, eg: `/hello`
|
||||
* `FN_METHOD` - the HTTP method for the request, eg: `GET` or `POST`
|
||||
* `FN_FORMAT` - a string representing one of the [function formats](function-format.md), currently either `default` or `http`. Default is `default`.
|
||||
* `FN_MEMORY` - a number representing the amount of memory available to the call, in MB
|
||||
* `FN_CPUS` - a string representing the amount of CPU available to the call, in MilliCPUs or floating-point number, eg. `100m` or `0.1`. Header is present only if `cpus` is set for the route.
|
||||
* `FN_TYPE` - the type for this call, currently 'sync' or 'async'
|
||||
|
||||
Dependent upon the function's format, additional variables that change on a
|
||||
per invocation basis will be in a certain location.
|
||||
|
||||
For `default` format, these will be in environment variables as well:
|
||||
|
||||
* `FN_DEADLINE` - RFC3339 time stamp of the expiration (deadline) date of function execution.
|
||||
* `FN_REQUEST_URL` - the full URL for the request ([parsing example](https://github.com/fnproject/fn/tree/master/examples/tutorial/params))
|
||||
* `FN_CALL_ID` - a unique ID for each function execution.
|
||||
* `FN_METHOD` - http method used to invoke this function
|
||||
* `FN_HEADER_$X` - the HTTP headers that were set for this request. Replace $X with the upper cased name of the header and replace dashes in the header with underscores.
|
||||
* `$X` - $X is the header that came in the http request that invoked this function.
|
||||
|
||||
For `http` format these will be in http headers:
|
||||
|
||||
* `Fn_deadline` - RFC3339 time stamp of the expiration (deadline) date of function execution.
|
||||
* `Fn_request_url` - the full URL for the request ([parsing example](https://github.com/fnproject/fn/tree/master/examples/tutorial/params))
|
||||
* `Fn_call_id` - a unique ID for each function execution.
|
||||
* `Fn_method` - the HTTP method used to invoke
|
||||
* `$X` - the HTTP headers that were set for this request, exactly as they were sent in the request.
|
||||
|
||||
If you're implementing your function using a fdk this will provide an API to obtain the http headers.
|
||||
|
||||
For `json` format, these will be fields in the json object (see
|
||||
[format](functions-format.md)):
|
||||
|
||||
* `call_id`
|
||||
* `protocol: { "headers": { "$X": [ "$Y" ] } }` where `$X:$Y` is each http
|
||||
header exactly as it was sent in the request
|
||||
|
||||
Warning: these may change before release.
|
||||
|
||||
## Logging
|
||||
|
||||
Standard out is where you should write response data for synchronous functions. Standard error
|
||||
is where you should write for logging, as [it was intended](http://www.jstorimer.com/blogs/workingwithcode/7766119-when-to-use-stderr-instead-of-stdout).
|
||||
|
||||
So to write output to logs, simply log to STDERR. Here are some examples in a few languages.
|
||||
|
||||
In Go, simply use the [log](https://golang.org/pkg/log/) package, it writes to STDERR by default.
|
||||
|
||||
```go
|
||||
log.Println("hi")
|
||||
```
|
||||
|
||||
In Node.js:
|
||||
|
||||
```node
|
||||
console.error("hi");
|
||||
```
|
||||
|
||||
[More details for Node.js here](http://stackoverflow.com/a/27576486/105562).
|
||||
|
||||
In Ruby:
|
||||
|
||||
```ruby
|
||||
STDERR.puts("hi")
|
||||
```
|
||||
|
||||
## Using Lambda Functions
|
||||
|
||||
### Lambda everywhere
|
||||
|
||||
Lambda support for Fn enables you to take your AWS Lambda functions and run them
|
||||
anywhere. You should be able to take your code and run them without any changes.
|
||||
|
||||
Creating Lambda functions is not much different than using regular functions, just use
|
||||
the `lambda-node` runtime.
|
||||
|
||||
```sh
|
||||
fn init --runtime lambda-node --name lambda-node
|
||||
```
|
||||
|
||||
Be sure the filename for your main handler is `func.js`.
|
||||
|
||||
TODO: Make Java and Python use the new workflow too.
|
||||
|
||||
## Next Steps
|
||||
|
||||
* [Packaging your function](packaging.md)
|
||||
@@ -28,7 +28,7 @@ Learn the basics about sending data into your function. Choose your language:
|
||||
## Key Examples
|
||||
|
||||
* Learn how to get parameters from a web request. [Click here](params)
|
||||
* Write your first HotFunction (stays alive to minimize latency between requests). [Click here](../../docs/hot-functions.md)
|
||||
* Write your first HotFunction (stays alive to minimize latency between requests). [Click here](../../docs/developers/hot-functions.md)
|
||||
|
||||
## Learn More
|
||||
|
||||
|
||||
Reference in New Issue
Block a user