Python 中有一个云函数,当文件上传到 firebase 的存储桶时,它会处理一些数据:
@storage_fn.on_object_finalized(bucket = "my-bucket", timeout_sec = timeout_sec, memory = memory, cpu = cpu, region='us-central1')
def validate_file_upload(event: storage_fn.CloudEvent[storage_fn.StorageObjectData]):
process(event)
当通过 firebase cli 部署时,该功能可以正常工作
firebase deploy --only functions:validate_file_upload
但是,当通过 gcloud 部署相同的功能时
gcloud functions deploy validate_file_upload
--gen2
--region=us-central1
.......
--entry-point=validate_file_upload
--trigger-event-filters="type=google.cloud.storage.object.v1.finalized"
--trigger-event-filters="bucket=my-bucket"
当函数被触发时,它失败并显示
TypeError:validate_file_upload() 需要 1 个位置参数,但给出了 2 个
原因是,当通过
firebase
部署函数时,GCP将“Eventarc”对象作为单个参数发送给云函数,但如果通过gcloud
部署,它会发送两个:(数据,上下文),自然会导致异常
即使在文档中也指出应该只有 1 个参数:
Cloud Storage 触发器作为 CloudEvent 函数实现,其中 Cloud Storage 事件数据以 CloudEvents 格式传递到您的函数
https://cloud.google.com/functions/docs/calling/storage
如何确保
gcloud
部署使用正确的函数原型?
答案是使用双装饰器:
import functions_framework
from cloudevents.http import CloudEvent
from firebase_functions import storage_fn, options
@functions_framework.cloud_event
@storage_fn.on_object_finalized(bucket = "my-bucket", timeout_sec = timeout_sec, memory = memory, cpu = cpu, region='us-central1')
def decode_and_process_metrics_fsdb_us(event: CloudEvent):
process(event)
这样,无论是通过 gcloud 还是 firebase 部署,它都可以工作。
我还注意到,如果该函数最初是使用 HTTP 触发器而不是“存储桶”触发器部署的,那么它在 GCP 中会保持标记为 HTTP,直到您删除它并重新部署。简单的重新部署会将此函数标记为 HTTP(尽管在“触发器”选项卡中,它将按预期显示存储桶的事件)