OpenFunction / functions-framework-go

Go functions framework for OpenFunction
18 stars 20 forks source link

Support Dapr gRPC #6

Closed tpiperatgod closed 3 years ago

tpiperatgod commented 3 years ago

What this PR do

  1. Modify the OpenFunction Context Refer to types.go

    The latest Context is as follows.

    type OpenFunctionContext struct {
    Name      string      `json:"name"`
    Version   string      `json:"version"`
    RequestID string      `json:"request_id,omitempty"`
    Input     *Input      `json:"input,omitempty"`
    Outputs   *Outputs    `json:"outputs,omitempty"`
    Runtime   Runtime     `json:"runtime"`
    State     interface{} `json:"state,omitempty"`
    Out       interface{} `json:"out,omitempty"`
    }

    The Input has been changed to: Name indicates the Dapr Component name Enabled indicates whether the input source should use Pattern indicates the topic name when using pubsub aslo the url path when using protocol of HTTP Port indicates the listening port Kind indicates the protocol, HTTP or gRPC InType indicates the Dapr Component type, such as "bindings", "pubsub", "invoke"

    type Input struct {
    Name    string       `json:"name"`
    Enabled *bool        `json:"enabled"`
    Pattern string       `json:"pattern"`
    Port    string       `json:"port"`
    Kind    Kind         `json:"kind"`
    InType  ResourceType `json:"in_type,omitempty"`
    }
  2. Support Dapr gRPC protocol The function registerOpenFunction can now support to register Dapr gRPC methods via dapr/go-sdk.

    func registerOpenFunction(fn func(*ofctx.OpenFunctionContext, interface{}) int, h *http.ServeMux) error {
        ctx, err := ofctx.GetOpenFunctionContext()
        if err != nil {
            return err
        }
    
        if *ctx.Input.Enabled {
            if ctx.Input.Kind == ofctx.HTTP {
                h.HandleFunc(ctx.Input.Pattern, func(w http.ResponseWriter, r *http.Request) {
                    defer recoverPanicHTTP(w, "Function panic")
                    code := fn(ctx, r)
                    w.WriteHeader(code)
                })
            }
    
            if ctx.Input.Kind == ofctx.GRPC && ctx.Runtime == ofctx.Dapr {
                grpcHandler, err = daprd.NewService(fmt.Sprintf(":%s", ctx.Input.Port))
                if err != nil {
                    return err
                }
                switch ctx.Input.InType {
                case ofctx.DaprBinding:
                    err = grpcHandler.AddBindingInvocationHandler(ctx.Input.Pattern, func(c context.Context, in *dapr.BindingEvent) (out []byte, err error) {
                        code := fn(ctx, in)
                        if code == 200 {
                            return nil, nil
                        } else {
                            return nil, errors.New("error")
    
                        }
                    })
                case ofctx.DaprTopic:
                    sub := &dapr.Subscription{
                        PubsubName: ctx.Input.Name,
                        Topic:      ctx.Input.Pattern,
                    }
                    err = grpcHandler.AddTopicEventHandler(sub, func(c context.Context, e *dapr.TopicEvent) (retry bool, err error) {
                        code := fn(ctx, e)
                        if code == 200 {
                            return false, nil
                        } else {
                            return true, errors.New("error")
                        }
                    })
                case ofctx.DaprService:
                    err = grpcHandler.AddServiceInvocationHandler(ctx.Input.Pattern, func(c context.Context, in *dapr.InvocationEvent) (out *dapr.Content, err error) {
                        code := fn(ctx, in)
                        if code == 200 {
                            return ctx.Out.(*dapr.Content), nil
                        } else {
                            return nil, errors.New("error")
                        }
                    })
                default:
                    return errors.New("invalid input type")
                }
            }
    
            if err != nil {
                return err
            }
        }
    
        return nil
    }
  3. Add examples Added function examples and README for the Dapr gRPC methods.

Follow up

Signed-off-by: laminar fangtian@kubesphere.io

tpiperatgod commented 3 years ago

Follow up