Skip to content

feat: initialize openfunction knative and async runtime #4

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Apr 14, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
node_modules/
build/
.coverage/
.history/
npm-debug.log
.nyc_output
.vscode
Expand Down
29 changes: 15 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ for writing portable Node.js functions
The Functions Framework lets you write lightweight functions that run in many
different environments, including:

* [Google Cloud Functions](https://cloud.google.com/functions/)
* Your local development machine
* [Cloud Run](https://cloud.google.com/run/) and [Cloud Run for Anthos](https://cloud.google.com/anthos/run)
* [Knative](https://github.com/knative/)-based environments
* [OpenFunction](https://github.com/OpenFunction/OpenFunction)
* [Google Cloud Functions](https://cloud.google.com/functions/)
* Your local development machine
* [Cloud Run](https://cloud.google.com/run/) and [Cloud Run for Anthos](https://cloud.google.com/anthos/run)
* [Knative](https://github.com/knative/)-based environments
* [Dapr](https://dapr.io/)-based environments
* [OpenFunction](https://github.com/OpenFunction/OpenFunction)

The framework allows you to go from:

Expand Down Expand Up @@ -45,11 +46,11 @@ handling logic.

## Features

- Spin up a local development server for quick testing
- Invoke a function in response to a request
- Automatically unmarshal events conforming to the
* Spin up a local development server for quick testing
* Invoke a function in response to a request
* Automatically unmarshal events conforming to the
[CloudEvents](https://cloudevents.io/) spec
- Portable between serverless platforms
* Portable between serverless platforms

## Installation

Expand Down Expand Up @@ -77,7 +78,7 @@ npm install @openfunction/functions-framework
npx @openfunction/functions-framework --target=helloWorld
```

1. Open http://localhost:8080/ in your browser and see _Hello, World_.
1. Open <http://localhost:8080/> in your browser and see _Hello, World_.

### Quickstart: Set up a new project

Expand Down Expand Up @@ -132,7 +133,7 @@ command-line arguments:
1. Install [Docker](https://store.docker.com/search?type=edition&offering=community) and the [`pack` tool](https://buildpacks.io/docs/install-pack/).

1. Build a container from your function using the Functions [buildpacks](https://github.com/GoogleCloudPlatform/buildpacks):

```sh
pack build \
--builder openfunction/builder-node:v2-16.13 \
Expand All @@ -142,14 +143,14 @@ command-line arguments:
```

1. Start the built container:

```sh
docker run --rm -p 8080:8080 my-first-function
# Output: Serving function...
```

1. Send requests to this function using `curl` from another terminal window:

```sh
curl localhost:8080
# Output: Hello, World!
Expand Down Expand Up @@ -249,7 +250,7 @@ To enable the CloudEvent functions, you must list the Functions Framework as a d
```json
{
"dependencies": {
"@openfunction/functions-framework": "~0.3.6"
"@openfunction/functions-framework": "~0.4.0"
}
}
```
Expand Down
61 changes: 61 additions & 0 deletions docs/async-server.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
@startuml Async Server

box Function Process in Local Environment or Container
control ENTRYPOINT
participant Main
participant AsyncServer
participant DaprServer
participant Restana [
Web Server
----
""Restana""
]
end box

entity "Dapr Sidecar " as DaprSidecar

== OpenFunction Serving ==

ENTRYPOINT -> Main ** : execute
note over ENTRYPOINT, Main: Pass through __CLI arguments__ and \ncontainer __environment variables__

Main -> Main : load user function file
note left: ""function (ctx, data) {}""

Main -> AsyncServer ** : create
note over Main, AsyncServer: Hand over __user function__ and __context__

AsyncServer -> DaprServer ** : ""new""
note over AsyncServer, DaprServer: Extract __port__ from __context__ and pass down

DaprServer -> Restana ** : ""new""
note over Restana: Super fast and minimalist framework \nfor building REST micro-services
|||
DaprServer --> DaprSidecar : Waiting till Dapr sidecar started
note over DaprServer, DaprSidecar #FFAAAA: Using HTTP channel due to lack of good support of gRPC in Dapr Node.js SDK
...
AsyncServer -> DaprServer : register __user function__ as handler \nfor each of __inputs__ in __context__
DaprServer -> Restana : add routes for Dapr style \nsubscriptions and input bindings

...

== OpenFunction Triggering ==

DaprSidecar <--] : sub / input data

DaprSidecar -> Restana ++ : Dapr request with "data"

Restana -> Restana ++ : invoke user function

alt
Restana -> DaprSidecar ++ : publish data or invoke output binding
DaprSidecar --> Restana -- : execution result
end

return

return server app response

...

@enduml
76 changes: 76 additions & 0 deletions docs/http-binding.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
@startuml HTTP Binding

box Function Process in Local Environment or Container
control ENTRYPOINT
participant Main
participant Server
participant Express [
Web Server
----
""Express""
]
participant Interceptor
participant "User Function" as UserFunction
participant DaprClient
end box

entity "Dapr Sidecar " as DaprSidecar

== OpenFunction Serving ==

ENTRYPOINT -> Main ** : execute
note over ENTRYPOINT, Main: Pass through __CLI arguments__ and \ncontainer __environment variables__

Main -> Main : load user function file
note left: ""function (req, res) {}""

Main -> Server ** : create
note over Main, Server: Hand over __user function__, __function type__ \nand __context__ parsed from env variables

Server -> Express ** : new

Server -> Express : use init middleware
note over Server, Express: Store context in ""res.locals.context""

Server -> Interceptor ** : new
Server -> Express : use interceptor
|||
Server -> Express : use others middlewares
|||
Server -> UserFunction ** : wrap user function
note over Server, UserFunction: Use Node.js ""Domain"" to run function and catch exceptions
Server -> Express : bind wrapper to "/*" route

...

== OpenFunction Invocation ==

[-> Express ++ : HTTP request to "/"

Express -> UserFunction ++ : execute user function
UserFunction --> Express -- : return execution result "data"

alt ""runtime"" = ""knative"" and ""outputs"" is not empty
Express -> Interceptor ++ : invoke interceptor

Interceptor -> Interceptor : load context
Interceptor -> DaprClient ** : new

loop each OpenFunction Output
Interceptor -> DaprClient ++ : send "data"

DaprClient -> DaprSidecar ++ : invoke binding or publication with "data"
DaprSidecar --> DaprClient -- : return result

DaprClient --> Interceptor -- : forward result
end

Interceptor -> DaprClient !!
Interceptor --> Express -- : return "data" as response
end

[<- Express -- : send response

...

@enduml
Loading