您可以使用 Cloud Run 函式和 Eventarc,部署程式碼來處理因 Firestore (Datastore 模式) 資料庫變更而觸發的事件。這樣一來,您不必執行自己的伺服器,就能新增伺服器端功能。
Datastore 模式觸發條件
Eventarc 支援下列 Firestore (Datastore 模式) 事件觸發程序,可讓您建立與 Firestore (Datastore 模式) 事件相關聯的 Cloud Run 函式 (第 2 代) 處理常式:
事件類型 | 觸發條件 |
---|---|
google.cloud.datastore.entity.v1.created |
首次寫入實體時觸發。 |
google.cloud.datastore.entity.v1.updated |
當實體已存在且任何值有變更時觸發。 |
google.cloud.datastore.entity.v1.deleted |
在刪除實體時觸發。 |
google.cloud.datastore.entity.v1.written |
在觸發 created 、updated 或 deleted 時觸發。 |
google.cloud.datastore.entity.v1.created.withAuthContext |
與 created 相同,但會新增驗證資訊。 |
google.cloud.datastore.entity.v1.updated.withAuthContext |
與 updated 相同,但會新增驗證資訊。 |
google.cloud.datastore.entity.v1.deleted.withAuthContext |
與 deleted 相同,但會新增驗證資訊。 |
google.cloud.datastore.entity.v1.written.withAuthContext |
與 written 相同,但會新增驗證資訊。 |
Datastore 模式事件觸發程序只會回應實體變更。如果更新 Datastore 模式實體時資料未變更 (無作業寫入),系統不會產生更新或寫入事件。您無法只為特定資源產生事件。
在事件中加入驗證環境
如要加入事件的其他驗證資訊,請使用 withAuthContext
擴充功能的事件觸發程序。這個擴充功能會新增觸發事件的主體相關資訊。除了基本事件傳回的資訊外,還會新增 authtype
和 authid
屬性。如要進一步瞭解屬性值,請參閱 authcontext
參考資料。
編寫實體觸發函式
如要編寫函式來回應 Datastore 模式下的 Firestore 事件,請準備在部署期間指定下列項目:
- 觸發事件類型
- 觸發事件篩選器,用於選取與函式相關聯的實體
- 要執行的函式程式碼
觸發條件事件篩選器
指定事件篩選器時,您可以指定確切的實體比對或路徑模式。使用路徑模式,透過萬用字元 *
或 **
比對多個實體。
舉例來說,您可以指定完全比對實體,以便回應下列實體的變更:
users/marie
使用萬用字元 (*
或 **
) 回應符合模式的實體變更。*
萬用字元會比對單一區段,而 **
多區段萬用字元則會比對模式中的零或多個區段。
如果是單一區隔相符項目 (*
),您也可以使用具名擷取群組,例如 users/{userId}
。
下表列出有效的路徑模式:
模式 | 說明 |
---|---|
users/* 或users/{userId} |
比對種類為 users 的所有實體。與子代實體層級不符,例如 /users/marie/messages/33e2IxYBD9enzS50SJ68 |
users/** |
比對種類為 users 的所有實體,以及所有子系實體,例如 /users/marie/messages/33e2IxYBD9enzS50SJ68 |
如要進一步瞭解路徑模式,請參閱「Eventarc 路徑模式」。
即使使用萬用字元,觸發條件一律必須指向實體。 請參閱以下例子:
「
users/{userId=*}/{messages=*}
」無效,因為「{messages=*}
」是種類 ID。users/{userId=*}/{messages}/{messageId=*}
有效,因為{messageId=*}
一律會指向實體。
字元逸出
本節說明在種類 ID 和實體 ID 中逸出字元的情況。逸出字元可讓事件篩選器正確解讀 ID。
如果種類 ID 或實體 ID 包含
~
或/
字元,您必須在事件篩選器中逸出 ID。如要逸出 ID,請使用__escENCODED_ID__
格式。將 ENCODED_ID 替換為種類 ID 或實體 ID,並將所有~
和/
字元替換為編碼 ID,如下所示:~
:~0
/
:~1
舉例來說,種類 ID
user/profile
會變成__escusers~1profile__
。這類 ID 的路徑模式範例為__escusers~1profile__/{userId}
如果在事件篩選器中使用
.
或..
的種類 ID 或實體 ID,請務必按照下列方式逸出 ID:.
:__esc~2__
..
:__esc~2~2__
只有在 ID 剛好是
.
或..
時,才需要逸出.
字元。 舉例來說,種類 IDcustomers.info
不需要逸出。如果種類或實體 ID 是數值而非字串值,請務必使用
__idNUMERIC_VALUE__
逸出 ID。舉例來說,如果實體種類為111
,實體 ID 為222
,則路徑模式為__id111__/__id222__
。如果您從舊版 Cloud Datastore 遷移至 Datastore 模式的 Firestore,資料庫可能包含非 UTF-8 編碼的舊版 ID。您必須使用
__bytesBASE64_ENCODING__
逸出這些 ID。 將 BASE64_ENCODING 替換為 ID 的 Base64 編碼。舉例來說,路徑模式Task/{task}
(非 UTF8 類別 ID 的逸出字元為Task
) 會變成__bytesVGFzaw==__/{task}
。
函式範例
下列範例示範如何接收 Datastore 模式事件。如要使用事件中的資料,請查看 value
和 old_value
欄位。
value
:包含作業後實體快照的EntityResult
物件。刪除事件不會填入這個欄位。old_value
:包含前置作業實體快照的EntityResult
物件。這個欄位只會填入更新和刪除事件。
Java
如要瞭解如何安裝及使用 Datastore 模式的用戶端程式庫,請參閱這篇文章。 詳情請參閱 Datastore 模式 Java API 參考說明文件。
如要驗證 Datastore 模式,請設定應用程式預設憑證。 詳情請參閱「為本機開發環境設定驗證」。
在來源中加入 proto 依附元件
您必須在函式的來源目錄中加入 Datastore 模式 data.proto
檔案。這個檔案會匯入下列必須一併納入來源目錄的 Proto:
依附元件使用相同的目錄結構。例如,將 struct.proto
放在 google/protobuf
內。
解碼事件資料時需要這些檔案。如果函式來源不含這些檔案,執行時會傳回錯誤。
活動屬性
每個事件都包含資料屬性,內含事件相關資訊,例如事件觸發時間。Datastore 模式的 Firestore 會新增與事件相關的資料庫和實體資料。您可以透過下列方式存取這些屬性:
Java
logger.info("Event time " + event.getTime()); logger.info("Event project: " + event.getExtension("project")); logger.info("Event location: " + event.getExtension("location")); logger.info("Database name: " + event.getExtension("database")); logger.info("Database namespace: " + event.getExtension("namespace")); logger.info("Database entity: " + event.getExtension("entity")); // For withAuthContext events logger.info("Auth information: " + event.getExtension("authid")); logger.info("Auth information: " + event.getExtension("authtype"));
部署函式
部署 Cloud Run 函式的使用者必須具備「Cloud Run 函式開發人員」IAM 角色,或包含相同權限的角色。另請參閱部署作業的其他設定。
您可以使用 gcloud CLI 或 Google Cloud 控制台部署函式。以下範例說明如何使用 gcloud CLI 進行部署。如要瞭解如何使用 Google Cloud 控制台部署,請參閱部署 Cloud Run functions。
-
In the Google Cloud console, activate Cloud Shell.
At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.
使用
gcloud functions deploy
指令部署函式:gcloud functions deploy FUNCTION_NAME \ --gen2 \ --region=FUNCTION_LOCATION \ --trigger-location=TRIGGER_LOCATION \ --runtime=RUNTIME \ --source=SOURCE_LOCATION \ --entry-point=CODE_ENTRYPOINT \ --trigger-event-filters="type=EVENT_FILTER_TYPE" \ --trigger-event-filters="database=DATABASE" \ --trigger-event-filters="namespace=NAMESPACE" \ --trigger-event-filters-path-pattern="entity=ENTITY_OR_PATH" \
第一個引數 FUNCTION_NAME 是已部署函式的名稱。函式名稱開頭必須為英文字母,後面最多可接 62 個英文字母、數字、連字號或底線,且結尾必須為字母或數字。請將 FUNCTION_NAME 改成有效的函式名稱。然後新增下列旗標:
--gen2
旗標會指定您要部署至 Cloud Run functions (第 2 代)。如果省略這個旗標,系統會將函式部署至 Cloud Run functions (第 1 代)。--region=FUNCTION_LOCATION
標記會指定要部署函式的區域。為盡量縮短延遲時間,請將 FUNCTION_LOCATION 設為靠近 Firestore 資料庫的區域。如果 Firestore 資料庫位於多區域位置,請將
us-central1
中的資料庫值設為nam5
,並將eur3
中的資料庫值設為europe-west4
。如果是區域 Firestore 位置,請設為相同區域。--trigger-location=TRIGGER_LOCATION
標記會指定觸發條件的位置。您必須將 TRIGGER_LOCATION 設為 Datastore 模式資料庫的位置。--runtime=RUNTIME
標記會指定函式使用的語言執行階段。Cloud Run functions 支援多種執行階段。詳情請參閱「執行階段」。將 RUNTIME 設為支援的執行階段。--source=SOURCE_LOCATION
旗標會指定函式原始碼的位置。詳情請參閱下列說明:將 SOURCE_LOCATION 設為函式原始碼的位置。
--entry-point=CODE_ENTRYPOINT
標記會指定原始碼中函式的進入點。這是函式在執行時執行的程式碼。您必須將 CODE_ENTRYPOINT 設為原始碼中存在的函式名稱或完整類別名稱。詳情請參閱「函式進入點」。--trigger-event-filters
旗標定義事件篩選器,包括觸發條件類型和觸發事件的實體或路徑。 設定下列屬性值,定義事件篩選條件:type=EVENT_FILTER_TYPE
:Firestore 支援下列事件類型:google.cloud.datastore.entity.v1.created
:首次寫入實體時傳送的事件。google.cloud.datastore.entity.v1.updated
:當實體已存在且有任何值變更時,系統會傳送事件。google.cloud.datastore.entity.v1.deleted
:刪除實體時會傳送事件。google.cloud.datastore.entity.v1.written
:實體建立、更新或刪除時,系統會傳送事件。google.cloud.datastore.entity.v1.created.withAuthContext
:首次將文件寫入時傳送的事件,且事件包含額外的驗證資訊google.cloud.datastore.entity.v1.updated.withAuthContext
:如果文件已存在,且有任何值變更,系統就會傳送事件。包括其他驗證資訊google.cloud.datastore.entity.v1.deleted.withAuthContext
:刪除文件時會傳送事件。包含額外的驗證資訊google.cloud.datastore.entity.v1.written.withAuthContext
:事件會在建立、更新或刪除文件時傳送,且事件。包括其他驗證資訊
將 EVENT_FILTER_TYPE 設為下列其中一種事件類型。
database=DATABASE
:Firestore 資料庫。 將預設資料庫名稱的 DATABASE 設為(default)
。namespace=NAMESPACE
:資料庫 命名空間。如要使用預設資料庫名稱,請將 NAMESPACE 設為(default)
。移除旗標,即可比對任何命名空間。entity=ENTITY_OR_PATH
:資料庫路徑,當資料建立、更新或刪除時,會觸發事件。ENTITY_OR_PATH 的有效值如下:- 相等,例如
--trigger-event-filters="entity='users/marie'"
- 路徑模式,例如
--trigger-event-filters-path-pattern="entity='users/*'"
。詳情請參閱「瞭解路徑模式」。
- 相等,例如
如需部署指令及其標記的完整參考資料,請參閱
gcloud functions deploy
說明文件。
部署範例
以下範例示範如何使用 Google Cloud CLI 進行部署。
在 us-west2
區域中,為資料庫部署函式:
gcloud functions deploy gcfv2-trigger-datastore-node \
--gen2 \
--region=us-west2 \
--trigger-location=us-west2 \
--runtime=nodejs18 \
--source=gs://example_bucket-1/datastoreEventFunction.zip \
--entry-point=makeUpperCase \
--trigger-event-filters=type=google.cloud.datastore.entity.v1.written \
--trigger-event-filters=database='(default)' \
--trigger-event-filters-path-pattern="entity='messages/{pushId}'"
在 nam5
多地區部署資料庫的函式:
gcloud functions deploy gcfv2-trigger-datastore-python \
--gen2 \
--region=us-central1 \
--trigger-location=nam5 \
--runtime=python311 \
--source=gs://example_bucket-1/datastoreEventFunction.zip \
--entry-point=make_upper_case \
--trigger-event-filters=type=google.cloud.datastore.entity.v1.written.withAuthContext \
--trigger-event-filters=database='(default)' \
--trigger-event-filters-path-pattern="entity='messages/{pushId}'"
限制
請注意,Cloud Run 函式的 Firestore 觸發條件有下列限制:
- 如要使用 Cloud Run 函式 (第 1 代),必須先在 Firestore 原生模式中建立「(default)」資料庫。不支援 Firestore 已命名的資料庫或 Datastore 模式。在這種情況下,請使用 Cloud Run functions (第 2 代) 設定事件。
- 我們不保證排序。快速變更可能會以非預期的順序觸發函式呼叫。
- 系統至少會傳送一次事件,但單一事件可能會導致多次函式叫用。請避免依附於「只執行一次」機制,並編寫等冪函式。
- Firestore (Datastore 模式) 需要 Cloud Run 函式 (第 2 代)。Cloud Run 函式 (第 1 代) 不支援 Datastore 模式。
- 觸發條件會與單一資料庫建立關聯。您無法建立與多個資料庫相符的觸發程序。
- 刪除資料庫時,系統不會自動刪除該資料庫的任何觸發程序。觸發條件會停止傳送事件,但會繼續存在,直到您刪除觸發條件為止。
- 如果相符事件超過要求大小上限,事件可能無法傳送至 Cloud Run 函式 (第 1 代)。
- 如果事件因要求大小而未傳送,系統會記錄在平台記錄中, 並計入專案的記錄檔用量。
- 您可以在記錄檔探索器中找到這些記錄,訊息為「Event cannot deliver to Cloud function due to size exceeding the limit for 1st gen...」(事件無法傳送至 Cloud 函式,因為大小超出第 1 代的限制...),嚴重程度為
error
。您可以在「functionName
」欄位下方找到函式名稱。如果receiveTimestamp
欄位仍在一小時內,您可以讀取時間戳記前後的快照,推斷實際活動內容。 - 如要避免這種情況,可以採取下列做法:
- 遷移及升級至 Cloud Run functions (第 2 代)
- 縮小文件
- 刪除有問題的 Cloud Run 函式
- 您可以使用排除條件關閉記錄功能,但請注意,違規事件仍不會傳送。
Eventarc 和 Firestore (Datastore 模式) 位置
Eventarc 不支援 Firestore 事件觸發程序的多區域設定,但您仍可為多區域位置的 Firestore 資料庫建立觸發程序。Eventarc 會將 Firestore 多區域位置對應至下列 Eventarc 區域:
Firestore 多區域 | Eventarc 區域 |
---|---|
nam5 |
us-central1 |
eur3 |
europe-west4 |
後續步驟
- 瞭解事件導向架構。
- 請參閱 Datastore 模式的程式碼範例。