Skip to content

Commit a9b6224

Browse files
authored
Merge pull request #4 from webup/master
feat: initialize openfunction knative and async runtime
2 parents dca4132 + b2373e0 commit a9b6224

30 files changed

+4029
-495
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
node_modules/
22
build/
33
.coverage/
4+
.history/
45
npm-debug.log
56
.nyc_output
67
.vscode

README.md

Lines changed: 53 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,19 @@
77
> This is OpenFunction's nodejs functions-framework forked from [GCP functions-framework-nodejs](https://github.com/GoogleCloudPlatform/functions-framework-nodejs)
88
99
An open source FaaS (Function as a Service) framework based on [Express](https://expressjs.com/)
10-
for writing portable Node.js functions
10+
and [Restana](https://github.com/BackendStack21/restana) for writing portable sync and async Node.js functions.
1111

1212
The Functions Framework lets you write lightweight functions that run in many
1313
different environments, including:
1414

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

21-
The framework allows you to go from:
22+
Generally speaking, the framework allows you to go from:
2223

2324
```js
2425
/**
@@ -38,18 +39,17 @@ curl http://my-url
3839
# Output: Hello, World!
3940
```
4041

41-
All without needing to worry about writing an HTTP server or complicated request
42-
handling logic.
42+
All without needing to worry about writing an HTTP server or complicated request handling logic.
4343

4444
> Watch [this video](https://youtu.be/yMEcyAkTliU?t=912) to learn more about the Node Functions Framework.
4545
4646
## Features
4747

48-
- Spin up a local development server for quick testing
49-
- Invoke a function in response to a request
50-
- Automatically unmarshal events conforming to the
51-
[CloudEvents](https://cloudevents.io/) spec
52-
- Portable between serverless platforms
48+
* Spin up a local development server for quick testing
49+
* Invoke a function in response to a request
50+
* Listen and respond to the events bridged from Dapr system
51+
* Automatically unmarshal events conforming to the [CloudEvents](https://cloudevents.io/) spec
52+
* Portable between serverless platforms
5353

5454
## Installation
5555

@@ -61,7 +61,7 @@ npm install @openfunction/functions-framework
6161

6262
## Quickstarts
6363

64-
### Quickstart: Hello, World on your local machine
64+
### Quickstart: "Hello, World" on your local machine
6565

6666
1. Create an `index.js` file with the following contents:
6767

@@ -77,7 +77,7 @@ npm install @openfunction/functions-framework
7777
npx @openfunction/functions-framework --target=helloWorld
7878
```
7979

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

8282
### Quickstart: Set up a new project
8383

@@ -117,6 +117,7 @@ command-line arguments:
117117
...
118118
Serving function...
119119
Function: helloWorld
120+
Signature type: http
120121
URL: http://localhost:8080/
121122
```
122123

@@ -129,10 +130,10 @@ command-line arguments:
129130

130131
### Quickstart: Build a Deployable Container
131132

132-
1. Install [Docker](https://store.docker.com/search?type=edition&offering=community) and the [`pack` tool](https://buildpacks.io/docs/install-pack/).
133+
1. Install [Docker](https://store.docker.com/search?type=edition&offering=community) and the [pack](https://buildpacks.io/docs/install-pack/) tool.
134+
135+
2. Build a container from your function using the [Cloud Native Buildpacks](https://buildpacks.io/):
133136

134-
1. Build a container from your function using the Functions [buildpacks](https://github.com/GoogleCloudPlatform/buildpacks):
135-
136137
```sh
137138
pack build \
138139
--builder openfunction/builder-node:v2-16.13 \
@@ -141,44 +142,22 @@ command-line arguments:
141142
my-first-function
142143
```
143144

144-
1. Start the built container:
145-
145+
3. Start the built function container:
146+
146147
```sh
147-
docker run --rm -p 8080:8080 my-first-function
148+
docker run --rm -p 8080:8080 -e NODE_ENV=dev my-first-function
148149
# Output: Serving function...
149150
```
150151

151-
1. Send requests to this function using `curl` from another terminal window:
152-
152+
> NOTICE: `-e NODE_ENV=dev` is required to display "Serving function...", and you can also append `-e DEBUG=*` to display Express internal debug messages.
153+
154+
4. Send requests to this function using `curl` from another terminal window:
155+
153156
```sh
154157
curl localhost:8080
155158
# Output: Hello, World!
156159
```
157160

158-
## Run your function on serverless platforms
159-
160-
### Google Cloud Functions
161-
162-
The
163-
[Node.js 10 runtime on Google Cloud Functions](https://cloud.google.com/functions/docs/concepts/nodejs-10-runtime)
164-
is based on the Functions Framework. On Cloud Functions, the Functions Framework
165-
is completely optional: if you don't add it to your `package.json`, it will be
166-
installed automatically.
167-
168-
After you've written your function, you can simply deploy it from your local
169-
machine using the `gcloud` command-line tool.
170-
[Check out the Cloud Functions quickstart](https://cloud.google.com/functions/docs/quickstart).
171-
172-
### Cloud Run / Cloud Run for Anthos
173-
174-
After you've written your function, added the Functions Framework and updated your `start` script in `package.json`, deploy it to Cloud Run with `gcloud run deploy`. Check out the [Cloud Run quickstart for Node.js](https://cloud.google.com/run/docs/quickstarts/build-and-deploy/nodejs).
175-
176-
If you want even more control over the environment, you can [deploy to Cloud Run for Anthos](https://cloud.google.com/anthos/run/docs/quickstarts/prebuilt-deploy-gke). With Cloud Run for Anthos, you can run your function on a GKE cluster, which gives you additional control over the environment (including use of GPU-based instances, longer timeouts and more).
177-
178-
### Container environments based on Knative
179-
180-
Cloud Run and Cloud Run for Anthos both implement the [Knative Serving API](https://www.knative.dev/docs/). The Functions Framework is designed to be compatible with Knative environments. Just build and deploy your container to a Knative environment.
181-
182161
## Configure the Functions Framework
183162

184163
You can configure the Functions Framework using command-line flags or
@@ -201,34 +180,39 @@ For example:
201180
}
202181
```
203182
204-
## Enable Google Cloud Functions Events
183+
## Run your function on Serverless platforms
205184
206-
The Functions Framework can unmarshall incoming
207-
Google Cloud Functions [event](https://cloud.google.com/functions/docs/concepts/events-triggers#events) payloads to `data` and `context` objects.
208-
These will be passed as arguments to your function when it receives a request.
209-
Note that your function must use the `event`-style function signature:
185+
### Container environments based on Knative
210186
211-
```js
212-
exports.helloEvents = (data, context) => {
213-
console.log(data);
214-
console.log(context);
215-
};
216-
```
187+
The Functions Framework is designed to be compatible with Knative environments. Build and deploy your container to a Knative environment.
188+
189+
### OpenFunction
190+
191+
![OpenFunction Platform Overview](https://openfunction.dev/openfunction-0.5-architecture.png)
192+
193+
Besides Knative function support, one notable feature of OpenFunction is embracing Dapr system, so far Dapr pub/sub and bindings have been support.
194+
195+
Dapr bindings allows you to trigger your applications or services with events coming in from external systems, or interface with external systems. OpenFunction [0.6.0 release](https://openfunction.dev/blog/2022/03/25/announcing-openfunction-0.6.0-faas-observability-http-trigger-and-more/) adds Dapr output bindings to its synchronous functions which enables HTTP triggers for asynchronous functions. For example, synchronous functions backed by the Knative runtime can now interact with middlewares defined by Dapr output binding or pub/sub, and an asynchronous function will be triggered by the events sent from the synchronous function.
196+
197+
Asynchronous function introduces Dapr pub/sub to provide a platform-agnostic API to send and receive messages. A typical use case is that you can leverage synchronous functions to receive an event in plain JSON or Cloud Events format, and then send the received event to a Dapr output binding or pub/sub component, most likely a message queue (e.g. Kafka, NATS Streaming, GCP PubSub, MQTT). Finally, the asynchronous function could be triggered from the message queue.
198+
199+
More details would be brought up to you in some quickstart samples, stay tuned.
200+
201+
### Google Cloud Functions
217202
218-
To enable automatic unmarshalling, set the function signature type to `event`
219-
using a command-line flag or an environment variable. By default, the HTTP
220-
signature will be used and automatic event unmarshalling will be disabled.
203+
The [Node.js 10 runtime on Google Cloud Functions](https://cloud.google.com/functions/docs/concepts/nodejs-10-runtime) is based on the Functions Framework. On Cloud Functions, the Functions Framework is completely optional: if you don't add it to your `package.json`, it will be installed automatically.
221204
222-
For more details on this signature type, check out the Google Cloud Functions
223-
documentation on
224-
[background functions](https://cloud.google.com/functions/docs/writing/background#cloud_pubsub_example).
205+
After you've written your function, you can deploy it from your local machine using the `gcloud` command-line tool. [Check out the Cloud Functions quickstart](https://cloud.google.com/functions/docs/quickstart).
206+
207+
### Cloud Run / Cloud Run for Anthos
208+
209+
After you've written your function, added the Functions Framework and updated your `start` script in `package.json`, deploy it to Cloud Run with `gcloud run deploy`. Check out the [Cloud Run quickstart for Node.js](https://cloud.google.com/run/docs/quickstarts/build-and-deploy/nodejs).
210+
211+
If you want even more control over the environment, you can [deploy to Cloud Run for Anthos](https://cloud.google.com/anthos/run/docs/quickstarts/prebuilt-deploy-gke). With Cloud Run for Anthos, you can run your function on a GKE cluster, which gives you additional control over the environment (including use of GPU-based instances, longer timeouts and more).
225212
226213
## Enable CloudEvents
227214
228-
The Functions Framework can unmarshall incoming
229-
[CloudEvents](http://cloudevents.io) payloads to a `cloudevent` object.
230-
It will be passed as an argument to your function when it receives a request.
231-
Note that your function must use the `cloudevent`-style function signature:
215+
The Functions Framework can unmarshall incoming [CloudEvents](http://cloudevents.io) payloads to a `cloudevent` object. It will be passed as an argument to your function when it receives a request. Note that your function must use the `cloudevent`-style function signature:
232216
233217
```js
234218
const functions = require('@openfunction/functions-framework');
@@ -244,16 +228,6 @@ functions.cloudEvent('helloCloudEvents', (cloudevent) => {
244228
});
245229
```
246230
247-
To enable the CloudEvent functions, you must list the Functions Framework as a dependency in your `package.json`:
248-
249-
```json
250-
{
251-
"dependencies": {
252-
"@openfunction/functions-framework": "~0.3.6"
253-
}
254-
}
255-
```
256-
257231
Learn how to use CloudEvents in this [guide](docs/cloudevents.md).
258232
259233
## Advanced Docs

docs/async-server.puml

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
@startuml Async Server
2+
3+
box Function Process in Local Environment or Container
4+
control ENTRYPOINT
5+
participant Main
6+
participant AsyncServer
7+
participant DaprServer
8+
participant Restana [
9+
Web Server
10+
----
11+
""Restana""
12+
]
13+
end box
14+
15+
entity "Dapr Sidecar " as DaprSidecar
16+
17+
== OpenFunction Serving ==
18+
19+
ENTRYPOINT -> Main ** : execute
20+
note over ENTRYPOINT, Main: Pass through __CLI arguments__ and \ncontainer __environment variables__
21+
22+
Main -> Main : load user function file
23+
note left: ""function (ctx, data) {}""
24+
25+
Main -> AsyncServer ** : create
26+
note over Main, AsyncServer: Hand over __user function__ and __context__
27+
28+
AsyncServer -> DaprServer ** : ""new""
29+
note over AsyncServer, DaprServer: Extract __port__ from __context__ and pass down
30+
31+
DaprServer -> Restana ** : ""new""
32+
note over Restana: Super fast and minimalist framework \nfor building REST micro-services
33+
|||
34+
DaprServer --> DaprSidecar : Waiting till Dapr sidecar started
35+
note over DaprServer, DaprSidecar #FFAAAA: Using HTTP channel due to lack of good support of gRPC in Dapr Node.js SDK
36+
...
37+
AsyncServer -> DaprServer : register __user function__ as handler \nfor each of __inputs__ in __context__
38+
DaprServer -> Restana : add routes for Dapr style \nsubscriptions and input bindings
39+
40+
...
41+
42+
== OpenFunction Triggering ==
43+
44+
DaprSidecar <--] : sub / input data
45+
46+
DaprSidecar -> Restana ++ : Dapr request with "data"
47+
48+
Restana -> Restana ++ : invoke user function
49+
50+
alt
51+
Restana -> DaprSidecar ++ : publish data or invoke output binding
52+
DaprSidecar --> Restana -- : execution result
53+
end
54+
55+
return
56+
57+
return server app response
58+
59+
...
60+
61+
@enduml

0 commit comments

Comments
 (0)