Skip to content

Commit

Permalink
feat: add getting started for SQS triggers (#46)
Browse files Browse the repository at this point in the history
* feat: add triggers getting started for all langages

* docs: add README

* fix: add missing new lines

* fix: left comment for cc/cv

* fix: unecessary blank line

Co-authored-by: norbjd <[email protected]>

* docs: improve docs about retry policy and body handlind

---------

Co-authored-by: norbjd <[email protected]>
  • Loading branch information
cyclimse and norbjd authored Sep 11, 2023
1 parent deac9c3 commit 57dc57d
Show file tree
Hide file tree
Showing 28 changed files with 1,679 additions and 6 deletions.
96 changes: 96 additions & 0 deletions .github/workflows/triggers-functions-offline-testing.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
---
name: triggers-offline-testing

on:
push:
branches: [main]
pull_request:
branches: [main]

env:
TRIGGERS_GETTING_STARTED_FOLDER: functions/triggers-getting-started
OFFLINE_SERVER_URL: http://localhost:8080

jobs:
trigger-node:
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v3

- name: Install node
uses: actions/setup-node@v3
with:
node-version: 20

- name: Install node dev requirements
run: |
cd ${{ env.TRIGGERS_GETTING_STARTED_FOLDER }}/node
npm install
- name: Install python
uses: actions/setup-python@v4
with:
python-version: "3.11"

- name: Install testing requirements
run: pip install -r ${{ env.TRIGGERS_GETTING_STARTED_FOLDER }}/tests/requirements.txt

- name: Run node offline testing
uses: BerniWittmann/background-server-action@v1
with:
# The wait-on directive doesn't work with 405 on / with GETs
command: python ${{ env.TRIGGERS_GETTING_STARTED_FOLDER }}/tests/test_handler.py
start: npm start --prefix ${{ env.TRIGGERS_GETTING_STARTED_FOLDER }}/node

trigger-go:
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v3

- name: Install go
uses: actions/setup-go@v4
with:
go-version: "1.20"

- name: Install python
uses: actions/setup-python@v4
with:
python-version: "3.11"

- name: Install testing requirements
run: pip install -r ${{ env.TRIGGERS_GETTING_STARTED_FOLDER }}/tests/requirements.txt

- name: Run go offline testing
uses: BerniWittmann/background-server-action@v1
with:
# The wait-on directive doesn't work with 405 on / with GETs
command: python ${{ env.TRIGGERS_GETTING_STARTED_FOLDER }}/tests/test_handler.py
start: >
cd ${{ env.TRIGGERS_GETTING_STARTED_FOLDER }}/go &&
go run ./cmd
trigger-python:
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v3

- name: Install python
uses: actions/setup-python@v4
with:
python-version: "3.11"

- name: Install python dev requirements
run: pip install -r ${{ env.TRIGGERS_GETTING_STARTED_FOLDER }}/python/requirements-dev.txt

- name: Install testing requirements
run: pip install -r ${{ env.TRIGGERS_GETTING_STARTED_FOLDER }}/tests/requirements.txt

- name: Run python offline testing
uses: BerniWittmann/background-server-action@v1
with:
# The wait-on directive doesn't work with 405 on / with GETs
command: python ${{ env.TRIGGERS_GETTING_STARTED_FOLDER }}/tests/test_handler.py
start: python ${{ env.TRIGGERS_GETTING_STARTED_FOLDER }}/python/handler.py
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,22 +43,23 @@ Table of Contents:
| **[Python ChatBot](functions/python-dependencies/README.md)** <br/> A chatbot example with ChatterBot. | python310 | [Serverless Framework] |
| **[Python Dependencies](functions/python-chatbot/README.md)** <br/> Example showing how to use Python requirements with Serverless Framework. | python310 | [Serverless Framework] |
| **[Python MultiPart Upload to S3](functions/python-upload-file-s3-multipart/README.md)** <br/> A function to upload file from form-data to S3. | python311 | [Python API Framework] |
| **[Python SQS Trigger Hello World](functions/python-sqs-trigger-hello-world/README.md)** <br/> Trigger a function by sending a message to a SQS queue. | python311 | [Terraform] |
| **[Python SQS Trigger Async Worker](functions/python-sqs-trigger-async-worker/README.md)** <br/> Use SQS queues and function triggers to scheule an async task from another function. | python311 | [Terraform] |
| **[Python SQS Trigger Hello World](functions/python-sqs-trigger-hello-world/README.md)** <br/> Trigger a function by sending a message to a SQS queue. | python311 | [Terraform] |
| **[Python SQS Trigger Async Worker](functions/python-sqs-trigger-async-worker/README.md)** <br/> Use SQS queues and function triggers to scheule an async task from another function. | python311 | [Terraform] |
| **[Redis TLS](functions/redis-tls/README.md)** <br/> How to connect a function to a Scaleway Redis cluster with TLS enabled. | python310 | [Terraform] |
| **[Rust MNIST](functions/rust-mnist/README.md)** <br/> A Rust function to recognize hand-written digits with a simple neural network. | rust165 | [Serverless Framework] |
| **[PostgreSQL Python](functions/postgre-sql-python/README.md)** <br/> A Python function to perform a query on a PostgreSQL managed database. | python310 | [Serverless Framework] |
| **[Terraform Python](functions/terraform-python-example/README.md)** <br/> A Python function deployed with Terraform. | python310 | [Terraform] |
| **[Triggers Getting Started](functions/triggers-getting-started/README.md)** <br/> Simple SQS trigger example for all runtimes. | all | [Terraform] |
| **[Typescript with Node runtime](functions/typescript-with-node/README.md)** <br/> A Typescript function using Node runtime. | node18 | [Serverless Framework] |
| **[Serverless Gateway Python Example](functions/serverless-gateway-python/README.md)** <br/> A Python serverless API using Serverless Gateway. | python310 | [Python API Framework] |
| **[Serverless Gateway Python Example](functions/serverless-gateway-python/README.md)** <br/> A Python serverless API using Serverless Gateway. | python310 | [Python API Framework] |

### 📦 Containers

| Example | Language | Deployment |
|----------------------------------------------------------------------------------------------------------------------------------------------|--------------|------------------------|
| **[Container Bash Script](containers/bash-scheduled-job/README.md)** <br/> A Bash script runnning on a schedule using serverless containers. | Bash | [Serverless Framework] |
| **[Function Handler Java](containers/function-handler-java/README.md)** <br/> A Java function handler deployed on CaaS. | Java | [Serverless Framework] |
| **[Nginx CORS Private](containers/nginx-cors-private-python/README.md)** <br/> A Nginx proxy to allow CORS requests to a private container. | Python Flask | [Terraform] |
| **[Function Handler Java](containers/function-handler-java/README.md)** <br/> A Java function handler deployed on CaaS. | Java | [Serverless Framework] |
| **[Nginx CORS Private](containers/nginx-cors-private-python/README.md)** <br/> A Nginx proxy to allow CORS requests to a private container. | Python Flask | [Terraform] |

### 💜 Projects

Expand Down
2 changes: 1 addition & 1 deletion functions/redis-tls/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Everything is managed with Terraform. The terraform config files will also creat

```sh
terraform init
terraform deploy
terraform apply
```

You should be able to see your function in the Scaleway console.
Expand Down
13 changes: 13 additions & 0 deletions functions/triggers-getting-started/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Local .terraform directories
**/.terraform/*

# Generated files
*.zip

# .tfstate files
*.tfstate
*.tfstate.*

# Crash log files
crash.log
crash.*.log
44 changes: 44 additions & 0 deletions functions/triggers-getting-started/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

58 changes: 58 additions & 0 deletions functions/triggers-getting-started/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Triggers Getting Started

Simple starter examples that showcase using SQS triggers in all Scaleway Functions supported languages.

In each example, a function is triggered by a SQS queue with a message containing a number. The function will then print the factorial of this number to the logs.

## Requirements

This example requires [Terraform](https://www.scaleway.com/en/docs/tutorials/terraform-quickstart/).

## Setup

The Terraform configuration will deploy a function for each language, showing how to use triggers with each language.

It will also create a SQS queue per function to trigger it.

```console
terraform init
terraform apply
```

You should be able to see your functions in the Scaleway console.

## Running

You can use the `tests/send_messages.py` script to send a message to the SQS queue of each function.

```console
export AWS_ACCESS_KEY_ID=$(terraform output -raw sqs_access_key)
export AWS_SECRET_ACCESS_KEY=$(terraform output -raw sqs_secret_key)
python tests/send_messages.py
```

In Cockpit, you should see the functions being triggered and the result of the factorial being printed in the logs.

```console
...
DEBUG - php: factorial of 17 is 355687428096000 source=user stream=stdout
2023-09-11 10:36:19.994 DEBUG - Function Triggered: / source=core
2023-09-11 10:36:19.993 DEBUG - php: factorial of 13 is 6227020800 source=user stream=stdout
2023-09-11 10:36:19.991 DEBUG - Function Triggered: / source=core
2023-09-11 10:36:19.977 DEBUG - php: factorial of 12 is 479001600 source=user stream=stdout
2023-09-11 10:36:19.976 DEBUG - php: factorial of 11 is 39916800 source=user stream=stdout
2023-09-11 10:36:19.975 DEBUG - php: factorial of 10 is 3628800 source=user stream=stdout
2023-09-11 10:36:19.964 DEBUG - Function Triggered: / source=core
2023-09-11 10:36:19.954 DEBUG - php: factorial of 3 is 6 source=user stream=stdout
2023-09-11 10:36:19.954 DEBUG - php: factorial of 4 is 24 source=user stream=stdout
2023-09-11 10:36:19.948 DEBUG - php: factorial of 0 is 1 source=user stream=stdout
... (truncated)
```

Configuring and managing triggers is free, you only pay for the execution of your functions. For more information, please consult the [Scaleway Serverless pricing](https://www.scaleway.com/en/pricing/?tags=serverless). You will also be billed for the SQS queue usage when sending messages to it.

## Cleanup

```console
terraform destroy
```
11 changes: 11 additions & 0 deletions functions/triggers-getting-started/go/cmd/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package main

import (
"triggers-getting-started/go"
"github.com/scaleway/serverless-functions-go/local"
)

func main() {
// Replace "Handle" with your function handler name if necessary
local.ServeHandler(handler.Handle, local.WithPort(8080))
}
7 changes: 7 additions & 0 deletions functions/triggers-getting-started/go/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module triggers-getting-started/go

go 1.19

require github.com/scaleway/serverless-functions-go v0.1.2

require github.com/google/uuid v1.3.0 // indirect
8 changes: 8 additions & 0 deletions functions/triggers-getting-started/go/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/scaleway/serverless-functions-go v0.1.2 h1:UUToB+XXpLDG9l6c9c0ALhAs1jvb6rV2Lkyj2kZEYCo=
github.com/scaleway/serverless-functions-go v0.1.2/go.mod h1:23Hj74DYzTsVY3QgvsM0MGnx0+0OAAabTC06BOMJE58=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
53 changes: 53 additions & 0 deletions functions/triggers-getting-started/go/handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package handler

import (
"fmt"
"io"
"math/big"
"net/http"
"strconv"
)

func factorial(n int) *big.Int {
var f big.Int
f.MulRange(1, int64(n))
return &f
}

func Handle(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
// SQS triggers are sent as POST requests.
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}

// The SQS trigger sends the message content in the body.
body, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

n, err := strconv.Atoi(string(body))
if err != nil {
// Setting the status code to 200 will mark the message as processed.
http.Error(w, err.Error(), http.StatusOK)
return
}

result := factorial(n)
fmt.Printf("go: factorial of %d is %s\n", n, result.String())

// Because triggers are asynchronous, the response body is ignored.
// It's kept here when testing locally.
_, err = io.WriteString(w, result.String())
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

// If the status code is not in the 2XX range, the message is considered
// failed and is retried. In total, there are 3 retries.
w.WriteHeader(http.StatusOK)
w.Header().Set("Content-Type", "text/plain")
}
Loading

0 comments on commit 57dc57d

Please sign in to comment.