Cloud Functionの基本ソースを追加しました
Some checks failed
Python Test / python-test (push) Failing after 11s

This commit is contained in:
ry.yamafuji 2025-12-06 01:56:18 +09:00
parent 0c2390c569
commit ce5bc639fe
7 changed files with 219 additions and 6 deletions

23
examples/example_event.py Normal file
View File

@ -0,0 +1,23 @@
import functions_framework
from utils.custom_logger import get_logger
logger = get_logger(__name__)
@functions_framework.cloud_event
def hello_pubsub(cloud_event):
logger.info("Cloud Function triggered")
data = cloud_event.data
logger.info(f"Received data: {data}")
if __name__ == "__main__":
# For local testing purposes
class DummyCloudEvent:
"""デバッグ用のダミークラウドイベントクラス"""
def __init__(self, data):
self.data = data
test_event = DummyCloudEvent(data={"message": "Hello from local test"})
hello_pubsub(test_event)

48
examples/example_http.py Normal file
View File

@ -0,0 +1,48 @@
from flask import Request
import functions_framework
from utils.custom_logger import get_logger
logger = get_logger(__name__)
@functions_framework.http
def hello_request(request: Request):
"""HTTPリクエストを処理するエンドポイント"""
logger.info("Cloud Function triggered start")
# Headerを取得する
ua = request.headers.get("User-Agent", "Unknown")
logger.info(f"User-Agent: {ua}")
if request.method == "GET":
logger.info("Processing GET request")
return _get(request)
elif request.method == "POST":
logger.info("Processing POST request")
return _post(request)
else:
logger.warning(f"Unsupported HTTP method: {request.method}")
return {"error": "Unsupported HTTP method"}, 405
def _get(request: Request):
"""GETリクエストの処理"""
params = request.args
name = params.get("name", "World")
message = f"Hello, {name}!"
logger.info(f"Greeting generated: {message}")
return {"message": message}
def _post(request: Request):
"""POSTリクエストの処理"""
data = request.get_json(silent=True)
if not data or "name" not in data:
logger.warning("Invalid POST request: 'name' not found in JSON body")
return {"error": "Please provide a 'name' in the JSON body."}, 400
name = data["name"]
message = f"Hello, {name}!"
logger.info(f"Greeting generated: {message}")
return {"message": message}

104
readme/cloud_functions.md Normal file
View File

@ -0,0 +1,104 @@
# Cloud Functionsについて
## Dev
### リクエストをトリガーにする場合
**関数のエントリポインの定義**
```py
@functions_framework.http
def hello_request(request: Request):
...
```
**Cloud FUnctionsを起動する**
```sh
functions-framework \
--source=src/main.py \
--target=hello_request \
--signature-type=http \
--port=8080
```
ローカルでリクエストを送信する(ローカル)
**GET**
```sh
curl -X GET -H "Content-Type: application/json" \
'http://localhost:8080?name=python'
```
**POST**
```sh
curl -X POST -H "Content-Type: application/json" \
-d '{"name": "python"}' \
http://localhost:8080
```
**PUT**
```sh
curl -X PUT -H "Content-Type: application/json" \
-d '{"name": "python"}' \
http://localhost:8080
```
### Eventをトリガーにする場合
ローカルで実行するにはイベントをHTTPにラップして Functions Frameworkで動かすのが基本です。
本番ではPub/Sub / Storage / Firestore / Eventarc などのイベントトリガでCloud Functionsを起動します。
* **ユースケース**:
* Pub/Sub: Pub/Subイベントにより実行する
* Storage: GCSにファイルのアップロードなどがあった場合
* Firestore: Firestoreのデータに変更等が生じた場合
* Eventarc: イベントログなどをトリガーにする(BQにデータが登録された場合)
[サンプルイベントソース](../examples/example_event.py)
**関数のエントリポインの定義**
```py
@functions_framework.cloud_event
def main(cloud_event):
...
```
第1世代 (1st Gen)では以下のエントリポイントになる
```py
def main(event, context)
```
**Cloud FUnctionsを起動する**
```sh
functions-framework \
--source=src/main.py \
--target=hello_pubsub \
--signature-type=cloudevent \
--port=8080
```
ローカルでイベントを送信する(ローカル)
```sh
curl -X POST \
-H "Content-Type: application/json" \
-H "Ce-Specversion: 1.0" \
-H "Ce-Type: google.cloud.pubsub.topic.v1.messagePublished" \
-H "Ce-Source: //pubsub.googleapis.com/projects/test-project/topics/test-topic" \
-H "Ce-Id: 1234567890" \
-H "Ce-Time: 2025-12-06T00:00:00Z" \
-d '{
"message": {
"data": "'$(echo -n "hello-local" | base64)'"
}
}' \
http://localhost:8080
```

View File

@ -0,0 +1 @@
functions-framework==3.*

View File

@ -8,5 +8,5 @@ line-length = 79
# BXXバグの可能性 # BXXバグの可能性
[lint] [lint]
select = ["F", "E", "W", "D101", "B"] select = ["F", "E", "W", "D101", "D102", "D103", "B"]
ignore = [] ignore = []

View File

@ -1,12 +1,48 @@
from flask import Request
import functions_framework
from utils.custom_logger import get_logger from utils.custom_logger import get_logger
logger = get_logger(__name__) logger = get_logger(__name__)
@functions_framework.http
def main(request: Request):
"""HTTPリクエストを処理するエンドポイント"""
def main(): logger.info("Cloud Function triggered start")
logger.info("Application started")
print("Hello, World!") # Headerを取得する
ua = request.headers.get("User-Agent", "Unknown")
logger.info(f"User-Agent: {ua}")
if request.method == "GET":
logger.info("Processing GET request")
return _get(request)
elif request.method == "POST":
logger.info("Processing POST request")
return _post(request)
else:
logger.warning(f"Unsupported HTTP method: {request.method}")
return {"error": "Unsupported HTTP method"}, 405
if __name__ == "__main__": def _get(request: Request):
main() """GETリクエストの処理"""
params = request.args
name = params.get("name", "World")
message = f"Hello, {name}!"
logger.info(f"Greeting generated: {message}")
return {"message": message}
def _post(request: Request):
"""POSTリクエストの処理"""
data = request.get_json(silent=True)
if not data or "name" not in data:
logger.warning("Invalid POST request: 'name' not found in JSON body")
return {"error": "Please provide a 'name' in the JSON body."}, 400
name = data["name"]
message = f"Hello, {name}!"
logger.info(f"Greeting generated: {message}")
return {"message": message}

1
src/requirements.txt Normal file
View File

@ -0,0 +1 @@
functions-framework==3.*