-
Notifications
You must be signed in to change notification settings - Fork 125
feat: Add async and streaming examples #393
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
taeold
merged 6 commits into
GoogleCloudPlatform:main
from
taeold:add-async-and-streaming-examples
Aug 4, 2025
Merged
Changes from 1 commit
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
ad40680
feat: Add async and streaming examples
taeold 6cdcc1f
feat: address PR feedback
taeold e96742c
Fix deploy instruction.
taeold 172e339
nit.
taeold 594df2d
fix small typos.
taeold 666c3a8
Merge remote-tracking branch 'upstream/main' into add-async-and-strea…
taeold File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| # Deploying async functions to Cloud Run | ||
|
|
||
| This sample shows how to deploy asynchronous functions to [Cloud Run](http://cloud.google.com/run) with the Functions Framework. It includes examples for both HTTP and CloudEvent functions, which can be found in the `main.py` file. | ||
taeold marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| ## Dependencies | ||
| Install the dependencies for this example: | ||
| ```sh | ||
| pip install -r requirements.txt | ||
| ``` | ||
|
|
||
| ## Running locally | ||
|
|
||
| ### HTTP Function | ||
| To run the HTTP function locally, use the `functions-framework` command: | ||
| ```sh | ||
| functions-framework --target=hello_async_http | ||
| ``` | ||
| Then, send a request to it from another terminal: | ||
| ```sh | ||
| curl localhost:8080 | ||
| # Output: Hello, async world! | ||
| ``` | ||
|
|
||
| ### CloudEvent Function | ||
| To run the CloudEvent function, specify the target and set the signature type: | ||
| ```sh | ||
| functions-framework --target=hello_async_cloudevent --signature-type=cloudevent | ||
| ``` | ||
| Then, in another terminal, send a sample CloudEvent using the provided script: | ||
| ```sh | ||
| python send_cloud_event.py | ||
| ``` | ||
|
|
||
| ## Deploying to Cloud Run | ||
| You can deploy these functions to Cloud Run using the `gcloud` CLI. | ||
|
|
||
| ### HTTP Function | ||
| ```sh | ||
| gcloud run deploy async-http-function \ | ||
| --source . \ | ||
| --function hello_async_http \ | ||
| --base-image python312 \ | ||
| --region <YOUR_REGION> \ | ||
| --allow-unauthenticated | ||
| ``` | ||
|
|
||
| ### CloudEvent Function | ||
| ```sh | ||
| gcloud run deploy async-cloudevent-function \ | ||
| --source . \ | ||
| --function hello_async_cloudevent \ | ||
| --base-image python312 \ | ||
| --region <YOUR_REGION> \ | ||
| --set-env-vars=FUNCTION_SIGNATURE_TYPE=cloudevent \ | ||
taeold marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| --allow-unauthenticated | ||
| ``` | ||
| After deploying, you can invoke the CloudEvent function by sending an HTTP POST request with a CloudEvent payload to its URL. | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| # Copyright 2025 Google LLC | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| import functions_framework.aio | ||
|
|
||
| @functions_framework.aio.http | ||
| async def hello_async_http(request): | ||
| """ | ||
| An async HTTP function. | ||
| Args: | ||
| request (starlette.requests.Request): The request object. | ||
| Returns: | ||
| The response text, or an instance of any Starlette response class | ||
| (e.g. `starlette.responses.Response`). | ||
| """ | ||
| return "Hello, async world!" | ||
|
|
||
| @functions_framework.aio.cloud_event | ||
| async def hello_async_cloudevent(cloud_event): | ||
| """ | ||
| An async CloudEvent function. | ||
| Args: | ||
| cloud_event (cloudevents.http.CloudEvent): The CloudEvent object. | ||
| """ | ||
| print(f"Received event with ID: {cloud_event['id']} and data {cloud_event.data}") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| # Function dependencies | ||
| functions-framework | ||
|
|
||
| # For testing | ||
| httpx |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| #!/usr/local/bin/python | ||
|
|
||
| # Copyright 2025 Google LLC | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
| import asyncio | ||
| import httpx | ||
|
|
||
| from cloudevents.http import CloudEvent, to_structured | ||
|
|
||
| async def main(): | ||
| # Create a cloudevent | ||
| attributes = { | ||
| "Content-Type": "application/json", | ||
| "source": "from-galaxy-far-far-away", | ||
| "type": "cloudevent.greet.you", | ||
| } | ||
| data = {"name": "john"} | ||
|
|
||
| event = CloudEvent(attributes, data) | ||
|
|
||
| # Send the event to the local functions-framework server | ||
| headers, data = to_structured(event) | ||
|
|
||
| async with httpx.AsyncClient() as client: | ||
| await client.post("http://localhost:8080/", headers=headers, data=data) | ||
|
|
||
| if __name__ == "__main__": | ||
| asyncio.run(main()) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| # Deploying streaming functions to Cloud Run | ||
|
|
||
| This sample shows how to deploy streaming functions to [Cloud Run](http://cloud.google.com/run) with the Functions Framework. The `main.py` file contains examples for both synchronous and asynchronous streaming. | ||
|
|
||
| ## Dependencies | ||
| Install the dependencies for this example: | ||
| ```sh | ||
| pip install -r requirements.txt | ||
| ``` | ||
|
|
||
| ## Running locally | ||
|
|
||
| ### Synchronous Streaming | ||
| To run the synchronous streaming function locally: | ||
| ```sh | ||
| functions-framework --target=hello_stream | ||
| ``` | ||
| Then, send a request to it from another terminal: | ||
| ```sh | ||
| curl localhost:8080 | ||
| ``` | ||
|
|
||
| ### Asynchronous Streaming | ||
| To run the asynchronous streaming function locally: | ||
| ```sh | ||
| functions-framework --target=hello_stream_async | ||
| ``` | ||
| Then, send a request to it from another terminal: | ||
| ```sh | ||
| curl localhost:8080 | ||
| ``` | ||
|
|
||
| ## Deploying to Cloud Run | ||
| You can deploy these functions to Cloud Run using the `gcloud` CLI. | ||
|
|
||
| ### Synchronous Streaming | ||
| ```sh | ||
| gcloud run deploy streaming-function \ | ||
| --source . \ | ||
| --function hello_stream \ | ||
| --base-image python312 \ | ||
| --region <YOUR_REGION> \ | ||
| --allow-unauthenticated | ||
taeold marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| ``` | ||
|
|
||
| ### Asynchronous Streaming | ||
| ```sh | ||
| gcloud run deploy streaming-async-function \ | ||
| --source . \ | ||
| --function hello_stream_async \ | ||
| --base-image python312 \ | ||
| --region <YOUR_REGION> \ | ||
| --allow-unauthenticated | ||
| ``` | ||
|
|
||
| ``` | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| # Copyright 2025 Google LLC | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| import time | ||
| import asyncio | ||
| import functions_framework | ||
| import functions_framework.aio | ||
| from starlette.responses import StreamingResponse | ||
|
|
||
| # Helper function for the synchronous streaming example. | ||
| def slow_numbers(minimum, maximum): | ||
| yield '<html><body><ul>' | ||
| for number in range(minimum, maximum + 1): | ||
| yield '<li>%d</li>' % number | ||
| time.sleep(0.5) | ||
| yield '</ul></body></html>' | ||
|
|
||
| @functions_framework.http | ||
| def hello_stream(request): | ||
| """ | ||
| A synchronous HTTP function that streams a response. | ||
| Args: | ||
| request (flask.Request): The request object. | ||
| Returns: | ||
| A generator, which will be streamed as the response. | ||
| """ | ||
| generator = slow_numbers(1, 10) | ||
| return generator, {'Content-Type': 'text/html'} | ||
|
|
||
| # Helper function for the asynchronous streaming example. | ||
| async def slow_numbers_async(minimum, maximum): | ||
| yield '<html><body><ul>' | ||
| for number in range(minimum, maximum + 1): | ||
| yield '<li>%d</li>' % number | ||
| await asyncio.sleep(0.5) | ||
| yield '</ul></body></html>' | ||
|
|
||
| @functions_framework.aio.http | ||
| async def hello_stream_async(request): | ||
| """ | ||
| An asynchronous HTTP function that streams a response. | ||
| Args: | ||
| request (starlette.requests.Request): The request object. | ||
| Returns: | ||
| A starlette.responses.StreamingResponse. | ||
| """ | ||
| generator = slow_numbers_async(1, 10) | ||
| return StreamingResponse(generator, media_type='text/html') |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| # Function dependencies | ||
| functions-framework | ||
taeold marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.