mirror of
https://github.com/fnproject/fn.git
synced 2022-10-28 21:29:17 +03:00
Feature/acksync response writer (#1267)
This implements a "detached" mechanism to get an ack from the runner once it actually starts to run a function. In this scenario the response returned back is just a 202 if we placed the function in a specific time-frame. If we hit some errors or we fail to place the fn in time we return back different errors.
This commit is contained in:
committed by
Tolga Ceylan
parent
2df6c8d349
commit
182db94fad
@@ -19,6 +19,12 @@ var (
|
||||
bufPool = &sync.Pool{New: func() interface{} { return new(bytes.Buffer) }}
|
||||
)
|
||||
|
||||
// ResponseBuffer implements http.ResponseWriter
|
||||
type ResponseBuffer interface {
|
||||
http.ResponseWriter
|
||||
Status() int
|
||||
}
|
||||
|
||||
// implements http.ResponseWriter
|
||||
// this little guy buffers responses from user containers and lets them still
|
||||
// set headers and such without us risking writing partial output [as much, the
|
||||
@@ -34,6 +40,7 @@ var _ http.ResponseWriter = new(syncResponseWriter) // nice compiler errors
|
||||
|
||||
func (s *syncResponseWriter) Header() http.Header { return s.headers }
|
||||
func (s *syncResponseWriter) WriteHeader(code int) { s.status = code }
|
||||
func (s *syncResponseWriter) Status() int { return s.status }
|
||||
|
||||
// handleFnInvokeCall executes the function, for router handlers
|
||||
func (s *Server) handleFnInvokeCall(c *gin.Context) {
|
||||
@@ -49,8 +56,6 @@ func (s *Server) handleFnInvokeCall(c *gin.Context) {
|
||||
// handleTriggerHTTPFunctionCall2 executes the function and returns an error
|
||||
// Requires the following in the context:
|
||||
func (s *Server) handleFnInvokeCall2(c *gin.Context) error {
|
||||
// log := common.Logger(c.Request.Context())
|
||||
|
||||
fn, err := s.lbReadAccess.GetFnByID(c, c.Param(api.ParamFnID))
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -73,19 +78,19 @@ func (s *Server) fnInvoke(resp http.ResponseWriter, req *http.Request, app *mode
|
||||
// buffer the response before writing it out to client to prevent partials from trying to stream
|
||||
buf := bufPool.Get().(*bytes.Buffer)
|
||||
buf.Reset()
|
||||
writer := syncResponseWriter{
|
||||
headers: resp.Header(),
|
||||
status: 200,
|
||||
Buffer: buf,
|
||||
}
|
||||
var writer ResponseBuffer
|
||||
|
||||
opts := []agent.CallOpt{
|
||||
agent.WithWriter(&writer), // XXX (reed): order matters [for now]
|
||||
agent.FromHTTPFnRequest(app, fn, req),
|
||||
}
|
||||
if trig != nil {
|
||||
opts = append(opts, agent.WithTrigger(trig))
|
||||
isDetached := req.Header.Get("Fn-Invoke-Type") == models.TypeDetached
|
||||
if isDetached {
|
||||
writer = agent.NewDetachedResponseWriter(resp.Header(), 202)
|
||||
} else {
|
||||
writer = &syncResponseWriter{
|
||||
headers: resp.Header(),
|
||||
status: 200,
|
||||
Buffer: buf,
|
||||
}
|
||||
}
|
||||
opts := getCallOptions(req, app, fn, trig, writer)
|
||||
|
||||
call, err := s.agent.GetCall(opts...)
|
||||
if err != nil {
|
||||
@@ -102,11 +107,30 @@ func (s *Server) fnInvoke(resp http.ResponseWriter, req *http.Request, app *mode
|
||||
writer.Header().Add("Fn-Call-Id", call.Model().ID) // XXX(reed): move to before Submit when adding streaming
|
||||
|
||||
// buffered response writer traps status (so we can add headers), we need to write it still
|
||||
if writer.status > 0 {
|
||||
resp.WriteHeader(writer.status)
|
||||
if writer.Status() > 0 {
|
||||
resp.WriteHeader(writer.Status())
|
||||
}
|
||||
|
||||
if isDetached {
|
||||
return nil
|
||||
}
|
||||
|
||||
io.Copy(resp, buf)
|
||||
bufPool.Put(buf) // at this point, submit returned without timing out, so we can re-use this one
|
||||
return nil
|
||||
}
|
||||
|
||||
func getCallOptions(req *http.Request, app *models.App, fn *models.Fn, trig *models.Trigger, rw http.ResponseWriter) []agent.CallOpt {
|
||||
var opts []agent.CallOpt
|
||||
opts = append(opts, agent.WithWriter(rw)) // XXX (reed): order matters [for now]
|
||||
opts = append(opts, agent.FromHTTPFnRequest(app, fn, req))
|
||||
|
||||
if req.Header.Get("Fn-Invoke-Type") == models.TypeDetached {
|
||||
opts = append(opts, agent.InvokeDetached())
|
||||
}
|
||||
|
||||
if trig != nil {
|
||||
opts = append(opts, agent.WithTrigger(trig))
|
||||
}
|
||||
return opts
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user