GoogleCloudPlatform / functions-framework

The Contract for Building New Function Frameworks
Apache License 2.0
123 stars 11 forks source link

Add a CloudEvent signature that allows replying with an Event #30

Closed cooperneil closed 2 years ago

cooperneil commented 4 years ago

In addition to supporting the a CloudEvents signature that receives a CloudEvent and processes it in the background (with essentially a void return), this issue to to support another CloudEvents signature that receives a CloudEvent and allows replying with a CloudEvent, potentially with a different event type than the input event.

In this way "transform functions" can be supported, i.e. a Function that accepts an event input and potentially produces an event output. The invoker is then responsible for delivering the new event, which a different function may receive and process. This functionality currently exists in Knative eventing.

Considering golang, the existing Functions Framework signature is like:

func myFunction(ctx context.Context, event cloudevents.Event)

whereas a transform, or event-reply signature may be like:

func eventReceiver(ctx context.Context, event cloudevents.Event) (*cloudevents.Event, error)

Here is an example of the reply type in the cloud events sdk samples, and here is a hello-world example from Knative eventing.

cooperneil commented 4 years ago

Note, per @grant this targets this area of the Functions Framework contract

grant commented 3 years ago

No matter what, we need to be a bit more specific in the contract with:

Spec:

Your function have must use the following signature:

1st parameter cloudevent The developer's function must either explicitly or implicitly signal that it has completed performing useful work. The function may explicitly signal this condition by explicitly returning. The function may implicitly signal this condition by simply evaluating until it reaches the end of the function's code block.

Any thoughts?: @grayside @bshaffer @dazuma @jskeet

jskeet commented 3 years ago

We've previously discussed this internally, and I believe it's more flexible to simply make it easy for any function to initiate an event. Benefits of this:

Once that is in place, it would be fairly easy to write a "helper" function signature which happens to conform to the constraints of "I'm receiving a CloudEvent, I want to produce exactly one CloudEvent to send, and I want to only send that when my function completes."

grayside commented 3 years ago

@grant I think it's useful to call out explicit vs. implicit action, but it seems like we should be more specific about what's expected in success & failure. The error codes are useful, but a couple things which seem missing:

  1. Uncaught exceptions should not trigger a crash, instead they should be translated to an HTTP 500 response and the exception logged.
  2. That the response should not be considered safe to carry private data even though a user doesn't directly receive the response.
  3. Is X-Google-Status: error expected on errors

@jskeet I agree, instead of the hard control setting it seems like some form of request content negotiation would make sense.

grant commented 3 years ago

Thanks for jogging my memory @jskeet. We should probably recommend this in the contract and close this issue then.

+1 to @grayside's comments too on documenting these cases too.

grant commented 2 years ago

We've previously discussed this internally, and I believe it's more flexible to simply make it easy for any function to initiate an event. Benefits of this:

  • HTTP functions can initiate events too
  • Functions can initiate multiple events
  • Functions can initiate events before completing

Once that is in place, it would be fairly easy to write a "helper" function signature which happens to conform to the constraints of "I'm receiving a CloudEvent, I want to produce exactly one CloudEvent to send, and I want to only send that when my function completes."

Yes. Per this discussion, let's close this issue as a developer can more flexibly initiate multiple events within a function. The more I think about this feature, the more I think it wouldn't be a good idea to allow for event responses. Events are self-contained and independent of the sender and receiver. If we allowed event responses, that would make an event contain state of the sender and wouldn't be agnostic of the sender – defeating the purpose of stateless events.

A developer can always use the HTTP signature and reply to events as a HTTP req/res.

Eventually, services like Eventarc will allow for custom events to be sent, making this use-case of replying with more events easier. As such, I'll close the request for replying with an event in the CE signatures in the FFs.

CC @anniefu working on error codes per @grayside's comment.