mirror of
https://github.com/fnproject/fn.git
synced 2022-10-28 21:29:17 +03:00
WIP: working on hot lambda functions.
This commit is contained in:
@@ -152,10 +152,10 @@ func (s *Server) loadroutes(ctx context.Context, filter models.RouteFilter) ([]*
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Should remove *gin.Context from these functions, should use only context.Context
|
// TODO: Should remove *gin.Context from these functions, should use only context.Context
|
||||||
func (s *Server) serve(ctx context.Context, c *gin.Context, appName string, found *models.Route, app *models.App, route, reqID string, payload io.Reader, enqueue models.Enqueue) (ok bool) {
|
func (s *Server) serve(ctx context.Context, c *gin.Context, appName string, route *models.Route, app *models.App, path, reqID string, payload io.Reader, enqueue models.Enqueue) (ok bool) {
|
||||||
ctx, log := common.LoggerWithFields(ctx, logrus.Fields{"app": appName, "route": found.Path, "image": found.Image})
|
ctx, log := common.LoggerWithFields(ctx, logrus.Fields{"app": appName, "route": route.Path, "image": route.Image})
|
||||||
|
|
||||||
params, match := matchRoute(found.Path, route)
|
params, match := matchRoute(route.Path, path)
|
||||||
if !match {
|
if !match {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -165,7 +165,7 @@ func (s *Server) serve(ctx context.Context, c *gin.Context, appName string, foun
|
|||||||
envVars := map[string]string{
|
envVars := map[string]string{
|
||||||
"METHOD": c.Request.Method,
|
"METHOD": c.Request.Method,
|
||||||
"APP_NAME": appName,
|
"APP_NAME": appName,
|
||||||
"ROUTE": found.Path,
|
"ROUTE": route.Path,
|
||||||
"REQUEST_URL": fmt.Sprintf("%v//%v%v", func() string {
|
"REQUEST_URL": fmt.Sprintf("%v//%v%v", func() string {
|
||||||
if c.Request.TLS == nil {
|
if c.Request.TLS == nil {
|
||||||
return "http"
|
return "http"
|
||||||
@@ -173,13 +173,14 @@ func (s *Server) serve(ctx context.Context, c *gin.Context, appName string, foun
|
|||||||
return "https"
|
return "https"
|
||||||
}(), c.Request.Host, c.Request.URL.String()),
|
}(), c.Request.Host, c.Request.URL.String()),
|
||||||
"CALL_ID": reqID,
|
"CALL_ID": reqID,
|
||||||
|
"FORMAT": route.Format,
|
||||||
}
|
}
|
||||||
|
|
||||||
// app config
|
// app config
|
||||||
for k, v := range app.Config {
|
for k, v := range app.Config {
|
||||||
envVars[toEnvName("", k)] = v
|
envVars[toEnvName("", k)] = v
|
||||||
}
|
}
|
||||||
for k, v := range found.Config {
|
for k, v := range route.Config {
|
||||||
envVars[toEnvName("", k)] = v
|
envVars[toEnvName("", k)] = v
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,16 +196,16 @@ func (s *Server) serve(ctx context.Context, c *gin.Context, appName string, foun
|
|||||||
|
|
||||||
cfg := &task.Config{
|
cfg := &task.Config{
|
||||||
AppName: appName,
|
AppName: appName,
|
||||||
Path: found.Path,
|
Path: route.Path,
|
||||||
Env: envVars,
|
Env: envVars,
|
||||||
Format: found.Format,
|
Format: route.Format,
|
||||||
ID: reqID,
|
ID: reqID,
|
||||||
Image: found.Image,
|
Image: route.Image,
|
||||||
Memory: found.Memory,
|
Memory: route.Memory,
|
||||||
Stdin: payload,
|
Stdin: payload,
|
||||||
Stdout: &stdout,
|
Stdout: &stdout,
|
||||||
Timeout: time.Duration(found.Timeout) * time.Second,
|
Timeout: time.Duration(route.Timeout) * time.Second,
|
||||||
IdleTimeout: time.Duration(found.IdleTimeout) * time.Second,
|
IdleTimeout: time.Duration(route.IdleTimeout) * time.Second,
|
||||||
ReceivedTime: time.Now(),
|
ReceivedTime: time.Now(),
|
||||||
Ready: make(chan struct{}),
|
Ready: make(chan struct{}),
|
||||||
}
|
}
|
||||||
@@ -223,11 +224,11 @@ func (s *Server) serve(ctx context.Context, c *gin.Context, appName string, foun
|
|||||||
newTask.Image = &cfg.Image
|
newTask.Image = &cfg.Image
|
||||||
newTask.ID = cfg.ID
|
newTask.ID = cfg.ID
|
||||||
newTask.CreatedAt = createdAt
|
newTask.CreatedAt = createdAt
|
||||||
newTask.Path = found.Path
|
newTask.Path = route.Path
|
||||||
newTask.EnvVars = cfg.Env
|
newTask.EnvVars = cfg.Env
|
||||||
newTask.AppName = cfg.AppName
|
newTask.AppName = cfg.AppName
|
||||||
|
|
||||||
switch found.Type {
|
switch route.Type {
|
||||||
case "async":
|
case "async":
|
||||||
// Read payload
|
// Read payload
|
||||||
pl, err := ioutil.ReadAll(cfg.Stdin)
|
pl, err := ioutil.ReadAll(cfg.Stdin)
|
||||||
@@ -263,7 +264,7 @@ func (s *Server) serve(ctx context.Context, c *gin.Context, appName string, foun
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
for k, v := range found.Headers {
|
for k, v := range route.Headers {
|
||||||
c.Header(k, v[0])
|
c.Header(k, v[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ You will also have access to a set of environment variables.
|
|||||||
* APP_NAME - the name of the application that matched this route, eg: `myapp`
|
* APP_NAME - the name of the application that matched this route, eg: `myapp`
|
||||||
* ROUTE - the matched route, eg: `/hello`
|
* ROUTE - the matched route, eg: `/hello`
|
||||||
* METHOD - the HTTP method for the request, eg: `GET` or `POST`
|
* METHOD - the HTTP method for the request, eg: `GET` or `POST`
|
||||||
|
* CALL_ID - a unique ID for each function execution.
|
||||||
|
* FORMAT - a string representing one of the [function formats](function-format.md), currently either `default` or `http`. Default is `default`.
|
||||||
* 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.
|
* 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 - any [configuration values](https://gitlab.oracledx.com/odx/functions/blob/master/fn/README.md#application-level-configuration) you've set
|
* X - any [configuration values](https://gitlab.oracledx.com/odx/functions/blob/master/fn/README.md#application-level-configuration) you've set
|
||||||
for the Application or the Route. Replace X with the upper cased name of the config variable you set. Ex: `minio_secret=secret` will be exposed via MINIO_SECRET env var.
|
for the Application or the Route. Replace X with the upper cased name of the config variable you set. Ex: `minio_secret=secret` will be exposed via MINIO_SECRET env var.
|
||||||
|
|||||||
63
fn/lambda/node-4/bootstrap.js
vendored
63
fn/lambda/node-4/bootstrap.js
vendored
@@ -1,6 +1,10 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
|
var net = require('net');
|
||||||
|
var http = require('http');
|
||||||
|
var events = require('events');
|
||||||
|
var HTTPParser = process.binding('http_parser').HTTPParser;
|
||||||
|
|
||||||
var oldlog = console.log
|
var oldlog = console.log
|
||||||
console.log = console.error
|
console.log = console.error
|
||||||
@@ -239,8 +243,67 @@ var setEnvFromHeader = function () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for http hot functions
|
||||||
|
function freeParser(parser){
|
||||||
|
if (parser) {
|
||||||
|
parser.onIncoming = null;
|
||||||
|
parser.socket = null;
|
||||||
|
http.parsers.free(parser);
|
||||||
|
parser = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// parses http requests
|
||||||
|
function parse(socket){
|
||||||
|
var emitter = new events.EventEmitter();
|
||||||
|
var parser = http.parsers.alloc();
|
||||||
|
|
||||||
|
parser.reinitialize(HTTPParser.REQUEST);
|
||||||
|
parser.socket = socket;
|
||||||
|
parser.maxHeaderPairs = 2000;
|
||||||
|
|
||||||
|
parser.onIncoming = function(req){
|
||||||
|
emitter.emit('request', req);
|
||||||
|
};
|
||||||
|
|
||||||
|
socket.on('data', function(buffer){
|
||||||
|
var ret = parser.execute(buffer, 0, buffer.length);
|
||||||
|
if(ret instanceof Error){
|
||||||
|
emitter.emit('error');
|
||||||
|
|
||||||
|
freeParser(parser);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.once('close', function(){
|
||||||
|
freeParser(parser);
|
||||||
|
});
|
||||||
|
|
||||||
|
return emitter;
|
||||||
|
};
|
||||||
|
|
||||||
function run() {
|
function run() {
|
||||||
|
|
||||||
|
// First, check format (ie: hot functions)
|
||||||
|
var format = process.env.FORMAT;
|
||||||
|
if (format == "http"){
|
||||||
|
// init parser
|
||||||
|
var parser = http.parsers.alloc();
|
||||||
|
parser.reinitialize(HTTPParser.REQUEST);
|
||||||
|
parser.socket = process.stdin;
|
||||||
|
parser.maxHeaderPairs = 2000;
|
||||||
|
|
||||||
|
parser.onIncoming = function(req){
|
||||||
|
emitter.emit('request', req);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var parser = parse(socket);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
setEnvFromHeader();
|
setEnvFromHeader();
|
||||||
// FIXME(nikhil): Check for file existence and allow non-payload.
|
// FIXME(nikhil): Check for file existence and allow non-payload.
|
||||||
var path = process.env["PAYLOAD_FILE"];
|
var path = process.env["PAYLOAD_FILE"];
|
||||||
|
|||||||
Reference in New Issue
Block a user