openfaas / faasd

A lightweight & portable faas engine
https://store.openfaas.com/l/serverless-for-everyone-else
MIT License
2.97k stars 213 forks source link

Inter-function Communication Feature Asking #316

Closed DanielLee343 closed 1 year ago

DanielLee343 commented 1 year ago

Hi, Alex. Thanks for the clear guide on faasd!

I'm wondering if there's a feature for payload/data be transferred between functions, similar to OpenWhisk’s Action Sequence, Fn flow, or AWS Step Functions?

Say I have a stack.yml as follows

provider:
  name: openfaas
  gateway: http://127.0.0.1:8080

functions:
  fn1:
    lang: go
    handler: ./fn1
    image: fn1:latest
  fn2:
    lang: go
    handler: ./fn2
    image: fn2:latest

And each function is invoked by curl. I would like to feed fn2 with fn1's response body, or even send http request during function runtime (although not a best practice). I haven't found such feature in OpenFaaS documents. If any, is it relative to the architecture (Kubernetes/faasd)? Could you suggest any general best practices for multi-function communication in OpenFaaS? I appreciate that!

Due diligence

My actions before raising this issue

Before you ask for help or support, make sure that you've consulted the manual for faasd. We can't answer questions that are already covered by the manual.

Why do you need this?

Who is this for?

What company is this for? Are you listed in the ADOPTERS.md file?

Expected Behaviour

Current Behaviour

Are you a GitHub Sponsor (Yes/No?)

Check at: https://github.com/sponsors/openfaas

List All Possible Solutions and Workarounds

Which Solution Do You Recommend?

Steps to Reproduce (for bugs)

1. 2. 3. 4.

Your Environment

go version

containerd -version

uname -a

cat /etc/os-release

faasd version
alexellis commented 1 year ago

Hi @DanielLee343 thanks for your interest.

Unfortunately, you've deleted the issue template which has some important questions.

For sending data between functions, we recommend calling via the gateway and/or using async.

This is covered in detail in the docs and the eBook - https://gumroad.com/l/serverless-for-everyone-else

You don't say whether you have a copy, but you should find everything you need there.

Alex

DanielLee343 commented 1 year ago

Hi @alexellis I read the eBook and tried to setup an async call within a function. There is some "vendor" problem whenever I want to re-build the image.

To reproduce

faas-cli template store pull golang-http
faas-cli new --lang golang-http fn1 --prefix lyuze
mv f1.yml stack.yml
faas-cli new --lang golang-http fn2 --prefix lyuze --append stack.yml 
faas-cli up -f stack.yml

Everything is fine here, then I change the function code to

package function

import (
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
    "net/url"

    handler "github.com/openfaas/templates-sdk/go-http"
)

func Handle(req handler.Request) (handler.Response, error) {
    reqBody := url.Values{
        "name":       {"John Doe"},
        "occupation": {"gardener"},
    }
    resp, err := http.PostForm("http://gateway.openfaas.svc.cluster.local:8080/function/fn2", reqBody)
    if err != nil {
        log.Fatal(err)
        return handler.Response{}, err
    }
    defer resp.Body.Close()
    bodyByte, err := ioutil.ReadAll(resp.Body)
    fmt.Print("Body: %s", bodyByte)

    // message := fmt.Sprintf("Body: %s", string(req.Body))

    return handler.Response{
        Body:       bodyByte,
        StatusCode: http.StatusOK,
    }, err
}

I tried to re-build the image but it shows (no matter what changes I made to the code):

$ faas-cli up -f fn1.yml 
...
Step 18/37 : RUN test -z "$(gofmt -l $(find . -type f -name '*.go' -not -path "./vendor/*" -not -path "./function/vendor/*"))" || { echo "Run \"gofmt -s -w\" on your Golang code"; exit 1; }
 ---> Running in e14ea422864c
Run "gofmt -s -w" on your Golang code
The command '/bin/sh -c test -z "$(gofmt -l $(find . -type f -name '*.go' -not -path "./vendor/*" -not -path "./function/vendor/*"))" || { echo "Run \"gofmt -s -w\" on your Golang code"; exit 1; }' returned a non-zero code: 1
[0] < Building fn1 done in 8.82s.
[0] Worker done.

Total build time: 8.82s
Errors received during build:
- [fn1] received non-zero exit code from build, error: The command '/bin/sh -c test -z "$(gofmt -l $(find . -type f -name '*.go' -not -path "./vendor/*" -not -path "./function/vendor/*"))" || { echo "Run \"gofmt -s -w\" on your Golang code"; exit 1; }' returned a non-zero code: 1

Attempts I Tried

I tried to build with faas-cli build --build-arg GO111MODULE=on, or go mod tidy before build, neither worked. I also saw this merge but didn't get anything from it. I also changed to use template golang-middleware, didn't work either.

alexellis commented 1 year ago

Hi, this example is not part of Serverless For Everyone Else, this is a Go example.

Where did you get it from?

DanielLee343 commented 1 year ago

This is not from the eBook, but another issue with golang-middleware/golang-http template. I simply changed the original template code of golang-middleware to the following, which is from your youtube video (or the go-http-template example):

package function

import (
    "net/http"
)

//handles a request
func Handle(w http.ResponseWriter, r *http.Request) {
    if r.Method == http.MethodGet {
        w.WriteHeader(http.StatusOK)
        w.Write([]byte("Access granted!"))
        return
    }
    w.WriteHeader(http.StatusMethodNotAllowed)
    w.Write([]byte("Access not allowed!"))

}

And faas-cli build -f fn1.yml throws the above error. A temp fix is commenting out the following line in the template Dockerfile:

RUN test -z "$(gofmt -l $(find . -type f -name '*.go' -not -path "./vendor/*" -not -path "./function/vendor/*"))" || { echo "Run \"gofmt -s -w\" on your Golang code"; exit 1; }
alexellis commented 1 year ago

The example repo should be working out of the box. If not can you create a separate issue in the template's repo?

We will get this closed since the two are not connected.

Thanks