github.com/iron-io/functions@v0.0.0-20180820112432-d59d7d1c40b2/docs/hot-functions.md (about)

     1  # Hot functions
     2  
     3  IronFunctions is built on top of container technologies, for each incoming
     4  workload, it spins a new container, feed it with the payload and sends the
     5  answer back to the caller. You can expect an average start time of 300ms per
     6  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.
     7  
     8  In the case you need faster start times for your function, you may use a hot
     9  container instead.
    10  
    11  hot functions are started once and kept alive while there is incoming workload.
    12  Thus, it means that once you decide to use a hot function, you must be able to
    13  tell the moment it should reading from standard input to start writing to
    14  standard output.
    15  
    16  Currently, IronFunctions implements a HTTP-like protocol to operate hot
    17  containers, but instead of communication through a TCP/IP port, it uses standard
    18  input/output.
    19  
    20  ## Implementing a hot function
    21  
    22  In the [examples directory](https://github.com/iron-io/functions/blob/master/examples/hotfunctions/http/func.go), there is one simple implementation of a hot function
    23  which we are going to get in the details here.
    24  
    25  The basic cycle comprises three steps: read standard input up to a previosly
    26  known point, process the work, the write the output to stdout with some
    27  information about when functions daemon should stop reading from stdout.
    28  
    29  In the case at hand, we serve a loop, whose first part is plugging stdin to a
    30  HTTP request parser:
    31  
    32  ```go
    33  r := bufio.NewReader(os.Stdin)
    34  req, err := http.ReadRequest(r)
    35  
    36  // ...
    37  } else {
    38  	l, _ := strconv.Atoi(req.Header.Get("Content-Length"))
    39  	p := make([]byte, l)
    40  	r.Read(p)
    41  }
    42  ```
    43  
    44  Note how `Content-Length` is used to help determinate how far standard input
    45  must be read.
    46  
    47  The next step in the cycle is to do some processing:
    48  
    49  ```go
    50  	//...
    51  	var buf bytes.Buffer
    52  	fmt.Fprintf(&buf, "Hello %s\n", p)
    53  	for k, vs := range req.Header {
    54  		fmt.Fprintf(&buf, "ENV: %s %#v\n", k, vs)
    55  	}
    56  	//...
    57  ```
    58  
    59  And finally, we return the result with a `Content-Length` header, so
    60  IronFunctions daemon would know when to stop reading the gotten response.
    61  
    62  ```go
    63  res := http.Response{
    64  	Proto:      "HTTP/1.1",
    65  	ProtoMajor: 1,
    66  	ProtoMinor: 1,
    67  	StatusCode: 200,
    68  	Status:     "OK",
    69  }
    70  res.Body = ioutil.NopCloser(&buf)
    71  res.ContentLength = int64(buf.Len())
    72  res.Write(os.Stdout)
    73  ```
    74  
    75  Rinse and repeat for each incoming workload.
    76  
    77  
    78  ## Deploying a hot function
    79  
    80  Once your functions is adapted to be handled as hot function, you must tell
    81  IronFunctions daemon that this function is now ready to be reused across
    82  requests:
    83  
    84  ```json
    85  {
    86  	"route":{
    87  		"app_name": "myapp",
    88  		"path": "/hot",
    89  		"image": "USERNAME/hchttp",
    90  		"memory": 64,
    91  		"type": "sync",
    92  		"config": null,
    93  		"format": "http",
    94  		"max_concurrency": "1",
    95  		"idle_timeout": 30
    96  	}
    97  }
    98  ```
    99  
   100  `format` (mandatory) either "default" or "http". If "http", then it is a hot
   101  container.
   102  
   103  `max_concurrency` (optional) - the number of simultaneous hot functions for
   104  this functions. This is a per-node configuration option. Default: 1
   105  
   106  `idle_timeout` (optional) - idle timeout (in seconds) before function termination.