JavaScript User-Defined Function (UDF) 是一種 Single Message Transform (SMT)。使用者定義函式提供彈性的方式,可在 Pub/Sub 中實作自訂轉換邏輯,類似於 BigQuery JavaScript 使用者定義函式。
UDF 會接受單一訊息做為輸入內容,對輸入內容執行定義的動作,並傳回處理結果。
UDF 具有下列重要屬性:
程式碼:定義轉換邏輯的 JavaScript 程式碼。
函式名稱:Pub/Sub 會將提供的程式碼套用至訊息,這個欄位是程式碼中的 JavaScript 函式名稱。
建立 JavaScript 函式
UDF 程式碼必須包含具有下列簽章的函式:
/**
* Transforms a Pub/Sub message.
* @return {(Object<string, (string | Object<string, string>)>|* null)} - To
* filter a message, return `null`. To transform a message, return a map with
* the following keys:
* - (required) 'data' : {string}
* - (optional) 'attributes' : {Object<string, string>}
* Returning empty `attributes` will remove all attributes from the message.
*
* @param {(Object<string, (string | Object<string, string>)>} - Pub/Sub
* message. Keys:
* - (required) 'data' : {string}
* - (required) 'attributes' : {Object<string, string>}
*
* @param {Object<string, any>} metadata - Pub/Sub message metadata.
* Keys:
* - (optional) 'message_id' : {string}
* - (optional) 'publish_time': {string} YYYY-MM-DDTHH:MM:SSZ format
* - (optional) 'ordering_key': {string}
*/
function <function_name>(message, metadata) {
// Perform custom transformation logic
return message; // to filter a message instead, return `null`
}
輸入內容
這個函式會採用下列輸入內容:
message引數:代表 Pub/Sub 訊息的 JavaScript 物件。其中包含下列屬性:data:(String,必要) 訊息酬載。attributes:(Object<String, String>,選用) 代表訊息屬性的鍵值對應地圖。
metadata引數:包含 Pub/Sub 訊息不可變更中繼資料的 JavaScript 物件:
輸出內容
這個函式必須傳回下列其中一項:
如要轉換訊息,請編輯
message.data和message.attributes的內容,並傳回變更後的message物件。如要篩選訊息,請傳回
null。
輸入 / 輸出內容規定
- 如果 UDF 會轉換訊息酬載,則酬載輸入和輸出內容必須是 UTF-8 編碼的字串。
- 如果 UDF 未轉換訊息酬載,酬載可使用任何編碼。
- 屬性鍵/值組合必須是 UTF-8 編碼的字串。
UDF 如何轉換訊息
在郵件上執行 UDF 的結果可能是下列其中之一:
UDF 會轉換訊息。
UDF 會傳回
null。主題 SMT:Pub/Sub 會向發布者傳回成功訊息,並在篩選後訊息的回應中加入訊息 ID。Pub/Sub 不會儲存訊息,也不會傳送給任何訂閱端。
訂閱項目 SMT:Pub/Sub 會確認訊息已傳送,但不會將訊息傳送給訂閱者。
UDF 擲回錯誤。
主題 SMT:Pub/Sub 會將錯誤傳回給發布者,且不會發布任何訊息。
訂閱項目 SMT:Pub/Sub 會對訊息發出否定確認。
建立 UDF SMT
您可以在 Pub/Sub 主題或訂閱項目上設定 SMT。
- 主題 SMT 會在 Pub/Sub 儲存訊息前執行,且所有訂閱者都能取得結果。
訂閱項目 SMT 會在郵件傳送前執行,且結果只適用於該訂閱項目。
控制台
前往 Google Cloud 控制台的 Pub/Sub「主題」頁面。
建立主題或訂閱項目。
如要建立主題,請按一下「建立主題」。「建立主題」頁面隨即開啟。
如要建立訂閱:
按一下要建立訂閱項目的主題名稱。
按一下「建立訂閱項目」。「將訂閱項目新增至主題」頁面隨即開啟。
在「轉換」下方,按一下「新增轉換」。
在「轉換類型」部分,選取「JavaScript UDF」。
在「函式名稱」欄位中,輸入 SMT 呼叫的 JavaScript 函式名稱。範例:
redactSSN。在文字區域中輸入 UDF 的程式碼。範例:
function redactSSN(message, metadata) { const data = JSON.parse(message.data); delete data['ssn']; message.data = JSON.stringify(data); return message; }程式碼必須包含名稱與「函式名稱」欄位相符的函式。
如不想立即啟用 SMT,請選取「停用轉換」。選取這個選項後,系統會使用主題建立 SMT,但不會對內送郵件執行 SMT。建立主題後,您可以編輯主題來啟用 SMT。
如要建立主題或訂閱項目,請按一下「建立」。
gcloud
建立定義檔
建立定義 UDF SMT 的 YAML 或 JSON 檔案。
YAML
- javascriptUdf:
code: { FUNCTION_CODE }
functionName: FUNCTION_NAME
JSON
{
"javascriptUdf": {
"code": {
FUNCTION_CODE
}
"functionName": FUNCTION_NAME
}
}
更改下列內容:
FUNCTION_CODE:UDF 的 JavaScript 程式碼。程式碼必須包含名稱與
functionName欄位相符的函式。範例:function redactSSN(message, metadata) { const data = JSON.parse(message.data); delete data['ssn']; message.data = JSON.stringify(data); return message; }FUNCTION_NAME:SMT 呼叫的 JavaScript 函式名稱。範例:
redactSSN。
建立主題或訂閱項目
如要建立主題,請執行 gcloud pubsub topics create 指令。
gcloud pubsub topics create TOPIC_ID \
--message-transforms-file=TRANSFORMS_FILE
更改下列內容:
- TOPIC_ID:要建立的主題 ID 或名稱。
- TRANSFORMS_FILE:定義檔案的路徑。
如要建立訂閱項目,請執行 gcloud pubsub subscriptions create 指令。
gcloud pubsub subscriptions create SUBSCRIPTION_ID \
--topic=projects/PROJECT_ID/topics/TOPIC_ID \
--message-transforms-file=TRANSFORMS_FILE
更改下列內容:
SUBSCRIPTION_ID:要建立的訂閱項目 ID 或名稱。
PROJECT_ID:包含主題的專案 ID。
TOPIC_ID:要訂閱的主題 ID。
TRANSFORMS_FILE:定義檔案的路徑。
你也可以先驗證及測試 SMT,再建立 SMT。詳情請參閱下列頁面:
限制
Pub/Sub 會對 UDF 執行資源限制,確保轉換作業的效率。限制包括:
- 每個 UDF 的程式碼上限為 20 KB
- 每則訊息的執行時間上限為 500 毫秒
- 僅支援 ECMAScript 標準內建函式
- 不呼叫外部 API
- 不匯入外部程式庫
UDF 範例
以下列舉一些發布及訂閱的 UDF 範例。您可以在UDF 程式庫中找到其他範例。
函式:將星期幾的整數轉換為對應的字串
將下列 UDF 新增至主題或訂閱項目時,系統會在發布或傳送訊息期間進行下列變更:
Pub/Sub 會將函式套用至訊息。如果訊息沒有 JSON 酬載,UDF 會擲回錯誤。
使用者定義函式會尋找名為
dayOfWeek的欄位,如果這個欄位的值是介於 0 到 6 之間的數字,就會轉換為對應的星期幾,例如Monday。如果該欄位不存在,或數字不在 0 到 6 的範圍內,程式碼會將dayOfWeek欄位設為Unknown。UDF 會將修改後的酬載序列化回訊息。
Pub/Sub 會將更新後的訊息傳遞至管道的下一個步驟。
function intToString(message, metadata) {
const data = JSON.parse(message.data);
switch(`data["dayOfWeek"]`) {
case 0:
data["dayOfWeek"] = "Sunday";
break;
case 1:
data["dayOfWeek"] = "Monday";
break;
case 2:
data["dayOfWeek"] = "Tuesday";
break;
case 3:
data["dayOfWeek"] = "Wednesday";
break;
case 4:
data["dayOfWeek"] = "Thursday";
break;
case 5:
data["dayOfWeek"] = "Friday";
break;
case 6:
data["dayOfWeek"] = "Saturday";
break;
default:
data["dayOfWeek"] = "Unknown";
}
message.data = JSON.stringify(data);
return message;
}
功能:遮蓋身分證字號
將下列 UDF 新增至主題或訂閱項目時,系統會在發布或傳送訊息期間進行下列變更:
Pub/Sub 會將函式套用至訊息。如果訊息沒有 JSON 酬載,UDF 會擲回錯誤。
UDF 會從訊息酬載中移除欄位
ssn(如果存在)。UDF 會將修改後的酬載序列化回訊息。
Pub/Sub 會將更新後的訊息傳遞至管道的下一個步驟。
function redactSSN(message, metadata) {
const data = JSON.parse(message.data);
delete data['ssn'];
message.data = JSON.stringify(data);
return message;
}
功能:篩除特定訊息並自動確認
將下列 UDF 新增至主題或訂閱項目時,系統會在發布或傳送訊息期間進行下列變更:
Pub/Sub 會將函式套用至訊息。如果訊息沒有 JSON 酬載,UDF 會擲回錯誤。
UDF 會檢查酬載是否包含名為
region的欄位。如果
region欄位的值不是US,函式會傳回空值,導致 Pub/Sub 篩除訊息。如果
region欄位的值為US,Pub/Sub 會將原始訊息傳遞至管道的下一個步驟。
function filterForUSRegion(message, metadata) {
const data = JSON.parse(message.data);
if (data["region"] !== "US") {
return null;
}
return message;
}
函式:驗證訊息內容,確保金額不超過 100
將下列 UDF 新增至主題或訂閱項目時,系統會在發布或傳送訊息期間進行下列變更:
Pub/Sub 會將函式套用至訊息。如果訊息沒有 JSON 酬載,UDF 會擲回錯誤。
這項 UDF 會檢查訊息是否包含名為
amount的欄位。如果
amount欄位的值大於100,函式會擲回錯誤。如果
amount欄位的值不大於100,函式會傳回原始訊息。Pub/Sub 接著會將訊息標示為失敗,或將原始訊息傳遞至管道中的下一個步驟。
function validateAmount(message, metadata) {
const data = JSON.parse(message.data);
if (data["amount"] > 100) {
throw new Error("Amount is invalid");
}
return message;
}
後續步驟
在 UDF 程式庫中探索其他範例