使用 Cloud Functions 擴充 SQL 連線

透過 Cloud Functions for Firebase,您可以在 Firebase SQL Connect 中處理事件。Cloud Functions 可讓您根據事件執行伺服器端程式碼,例如在 SQL Connect 服務中執行異動。這樣一來,您就能新增自訂邏輯,而不必部署自己的伺服器。

常見用途

  • 資料同步:發生異動後,與其他系統 (例如 Cloud Firestore、BigQuery 或外部 API) 複製或同步資料。

  • 非同步工作流程:在資料庫變更後,啟動長時間執行的程序,例如圖片處理或資料匯總。

  • 使用者參與度:在應用程式中發生特定變化事件 (例如建立帳戶) 後,向使用者傳送電子郵件或 Cloud Messaging 通知。

在 SQL Connect 變動時觸發函式

只要使用 onMutationExecuted 事件處理常式,就能在執行 SQL Connect 異動時觸發函式。執行異動時,就會觸發這項觸發條件。

基本變化事件函式

以下基本範例是一個函式,會記錄 SQL Connect 服務中執行的任何異動詳細資料:

Node.js

import { onMutationExecuted } from "firebase-functions/dataconnect";
import { logger } from "firebase-functions";

export const logMutation = onMutationExecuted(
  {
    /* Trigger on all mutations, spanning all services and connectors
       in us-central1 */
  },
  (event) => {
    logger.info("A mutation was executed!", {
      data: event.data,
    });
  }
);

Python

from firebase_functions import dataconnect_fn, logger

@dataconnect_fn.on_mutation_executed()
def log_mutation(event: dataconnect_fn.Event):
  logger.info("A mutation was executed!", event.data)

如果觸發條件是專案中的所有異動,請勿在觸發條件處理常式中執行任何異動,否則會導致無限迴圈。如要在事件觸發條件中執行變異,請使用下述篩選選項,並注意變異不會觸發自身。

設定函式位置

函式位置必須與 SQL Connect 服務位置一致,事件才能觸發函式。函式區域預設為 us-central1。

Node.js

import { onMutationExecuted } from "firebase-functions/dataconnect";

export const onMutationRegionOption = onMutationExecuted(
  {
    region: "europe-west1"  // Set if SQL Connect service location is not us-central1
  },
  (event) => { /* ... */ }
);

Python

@dataconnect_fn.on_mutation_executed(
  region="europe-west1"  # Set if SQL Connect service location is not us-central1
)
def mutation_executed_handler_region_option(event: dataconnect_fn.Event):
  pass

篩選事件

onMutationExecuted 處理常式可設定選項,根據特定屬性篩選事件。如果只想針對特定異動觸發函式,這個方法就很實用。

您可以依service、connector和operation篩選:

Node.js

import { onMutationExecuted } from "firebase-functions/dataconnect";
import { logger } from "firebase-functions";

// Trigger this function only for the CreateUser mutation
// in the users connector of the myAppService service.
export const onUserCreate = onMutationExecuted(
  {
    service: "myAppService",
    connector: "users",
    operation: "CreateUser",
  },
  (event) => {
    logger.info("A new user was created!", event.data);
    // Add logic here: for example, sending a welcome email.
  }
);

Python

from firebase_functions import dataconnect_fn, logger

@dataconnect_fn.on_mutation_executed(
  service="myAppService",
  connector="users",
  operation="CreateUser"
):
def on_user_create(event: dataconnect_fn.Event):
  logger.info("A new user was created!", event.data)

萬用字元和擷取群組

您可以使用萬用字元和擷取群組,依多個值篩選觸發條件。擷取的任何群組都可在 event.params 中使用。詳情請參閱「瞭解路徑模式」。

範例:

Node.js

import { onMutationExecuted } from "firebase-functions/dataconnect";

// Trigger on all operations that match the pattern `User*`, on any service and
// connector.
export const onMutationWildcards = onMutationExecuted(
  {
    operation: "User*",
  },
  (event) => {}
);

// Trigger on all operations that match the pattern `User*`, on any service and
// connector. Capture the operation name in the variable `op`.
export const onMutationCaptureWildcards = onMutationExecuted(
  {
    operation: "{op=User*}",
  },
  (event) => {
    // `event.params.op` contains the operation name.
  }
);

// Trigger on all operations on the service `myAppService`. Capture the
// operation name in the variable `operation`.
export const onMutationCaptures = onMutationExecuted(
  {
    service: "myAppService",
    operation: "{operation}",
  },
  (event) => {
    // `event.params.operation` contains the operation name.
  }
);

Python

from firebase_functions import dataconnect_fn

# Trigger on all operations that match the pattern `User*`, on any service and
# connector.
@dataconnect_fn.on_mutation_executed(
  operation="User*"
)
def on_mutation_wildcards(event: dataconnect_fn.Event):
  pass

# Trigger on all operations that match the pattern `User*`, on any service and
# connector. Capture the operation name in the variable `op`.
@dataconnect_fn.on_mutation_executed(
  operation="{op=User*}"
)
def on_mutation_capture_wildcards(event: dataconnect_fn.Event):
  # `event.params["op"]` contains the operation name.
  pass

# Trigger on all operations on the service `myAppService`. Capture the
# operation name in the variable `operation`.
@dataconnect_fn.on_mutation_executed(
  service="myAppService",
  operation="{operation}"
)
def on_mutation_captures(event: dataconnect_fn.Event):
  # `event.params["operation"]` contains the operation name.
  pass

存取使用者驗證資訊

您可以存取觸發事件的主體使用者驗證資訊。如要進一步瞭解驗證資訊中可用的資料,請參閱「驗證資訊」。

以下範例說明如何擷取驗證資訊:

Node.js

import { onMutationExecuted } from "firebase-functions/dataconnect";

export const onMutation = onMutationExecuted(
  { operation: "MyMutation" },
  (event) => {
    // mutationExecuted event provides authType and authId:
    // event.authType
    // event.authId
  }
);

Python

from firebase_functions import dataconnect_fn

@dataconnect_fn.on_mutation_executed(operation="MyMutation")
def mutation_executed_handler(event: dataconnect_fn.Event):
  # mutationExecuted event provides auth_type and auth_id, which are accessed as follows
  # event.auth_type
  # event.auth_id
  pass

系統會填入驗證類型和驗證 ID,如下所示:

異動啟動者 authtype authid
通過驗證的使用者 app_user Firebase 驗證權杖 UID
未經驗證的使用者 unauthenticated 空白
Admin SDK 模擬使用者 app_user 模擬使用者的 Firebase 驗證權杖 UID
Admin SDK 模擬未經驗證的要求 unauthenticated 空白
具備完整權限的 Admin SDK admin 空白

存取事件資料

傳遞至函式的 CloudEvent 物件包含觸發函式的事件相關資訊。

事件屬性

屬性 類型 說明
id string 事件的專屬 ID。
source string 產生事件的連接器資源 (例如 //firebasedataconnect.googleapis.com/projects/*/locations/*/services/*/connectors/*)。
specversion string CloudEvents 規格版本 (例如「1.0」)。
type string 事件類型:google.firebase.dataconnect.connector.v1.mutationExecuted。
time string 事件產生時的時間戳記 (ISO 8601 格式)。
subject string 選用。事件背景資訊的額外資訊,例如作業名稱。
params object 擷取路徑模式的地圖。
authType string 列舉,代表觸發事件的主體類型。
authId string 觸發事件的主體專屬 ID。
data MutationEventData SQL Connect 事件的酬載。請參閱下一節。

資料酬載

MutationEventData 物件包含 SQL Connect 事件的酬載:

{
  // ...
  "authType": // ...
  "data": {
    "payload": {
      "variables": {
        "userId": "user123",
        "updateData": {
          "displayName": "New Name"
        }
      },
      "data": {
        "updateUser": {
          "id": "user123",
          "displayName": "New Name",
          "email": "user@example.com"
        }
      },
      "errors": []
    }
  }
}
  • payload.variables:包含傳遞至變異的變數的物件。
  • payload.data:包含異動傳回資料的物件。
  • payload.errors:陣列,包含異動執行期間發生的任何錯誤。如果變動成功,這個陣列會是空的。

範例

存取變動變數和傳回資料的方法如下:

Node.js

import { onMutationExecuted } from "firebase-functions/dataconnect";
import { logger } from "firebase-functions";

export const processNewUserData = onMutationExecuted(
  {
    "service": "myAppService",
    "connector": "users",
    "operation": "CreateUser",
  },
  (event) => {
    // The variables passed to the mutation
    const mutationVariables = event.data.payload.variables;

    // The data returned by the mutation
    const returnedData = event.data.payload.data;

    logger.info("Processing mutation with variables:", mutationVariables);
    logger.info("Mutation returned:", returnedData);

    // ... your custom logic here
  }
);

Python

from firebase_functions import dataconnect_fn, logger

@dataconnect_fn.on_mutation_executed(
  service="myAppService",
  connector="users",
  operation="CreateUser"
):
def process_new_user_data(event: dataconnect_fn.Event):
  # The variables passed to the mutation
  mutation_vars = event.data.payload.variables
  # The data returned by the mutation
  returned_data = event.data.payload.data

  logger.info("Processing mutation with variables:", mutationVariables)
  logger.info("Mutation returned", returnedData)

  # ... your custom logic here

請注意,與 Cloud Firestore 或 Realtime Database 等其他資料庫觸發條件不同,SQL Connect 事件不會提供資料的「之前」快照。由於 SQL Connect 會將要求代理至基礎資料庫,因此無法透過交易取得資料的「之前」快照。而是可以存取傳送至異動的引數,以及異動傳回的資料。

這會導致您無法使用比較「之前」和「之後」快照的策略,避免事件觸發條件觸發相同事件的無限迴圈。如果必須從由變化事件觸發的函式執行變化,請使用事件篩選器,並確保任何變化都不會觸發自身,即使是間接觸發也不行。