Callback memungkinkan eksekusi alur kerja menunggu layanan lain membuat permintaan ke endpoint callback; permintaan tersebut akan melanjutkan eksekusi alur kerja.
Dengan callback, Anda dapat memberi sinyal ke alur kerja bahwa peristiwa tertentu telah terjadi, dan menunggu peristiwa tersebut tanpa melakukan polling. Misalnya, Anda dapat membuat alur kerja yang memberi tahu Anda saat produk kembali tersedia atau saat item telah dikirim; atau yang menunggu untuk memungkinkan interaksi manusia seperti meninjau pesanan atau memvalidasi terjemahan.
Halaman ini menunjukkan cara membuat alur kerja yang mendukung endpoint callback, dan yang menunggu permintaan HTTP dari proses eksternal tiba di endpoint tersebut. Anda juga dapat menunggu peristiwa menggunakan callback dan pemicu Eventarc.
Callback memerlukan penggunaan dua fungsi bawaan library standar:
events.create_callback_endpoint—Membuat endpoint callback yang mengharapkan metode HTTP yang ditentukanevents.await_callback—Menunggu callback diterima di endpoint yang diberikan
Membuat endpoint yang menerima permintaan callback
Buat endpoint callback yang dapat menerima permintaan HTTP untuk tiba di endpoint tersebut.
- Ikuti langkah-langkah untuk membuat alur kerja baru, atau pilih alur kerja yang ada untuk diperbarui tetapi jangan deploy alur kerja tersebut terlebih dahulu.
- Dalam definisi alur kerja, tambahkan langkah untuk membuat endpoint callback:
YAML
- create_callback: call: events.create_callback_endpoint args: http_callback_method: "METHOD" result: callback_details
JSON
[ { "create_callback": { "call": "events.create_callback_endpoint", "args": { "http_callback_method": "METHOD" }, "result": "callback_details" } } ]
Ganti
METHODdengan metode HTTP yang diharapkan, salah satu dariGET,HEAD,POST,PUT,DELETE,OPTIONS, atauPATCH. Nilai defaultnya adalahPOST.Hasilnya adalah peta,
callback_details, dengan aurlkolom yang menyimpan URL endpoint yang dibuat.Endpoint callback kini siap menerima permintaan masuk dengan metode HTTP yang ditentukan. URL endpoint yang dibuat dapat digunakan untuk memicu callback dari proses eksternal ke alur kerja; misalnya, dengan meneruskan URL ke Cloud Run Functions.
- Dalam definisi alur kerja, tambahkan langkah untuk menunggu permintaan callback:
YAML
- await_callback: call: events.await_callback args: callback: ${callback_details} timeout: TIMEOUT result: callback_request
JSON
[ { "await_callback": { "call": "events.await_callback", "args": { "callback": "${callback_details}", "timeout": TIMEOUT }, "result": "callback_request" } } ]
Ganti
TIMEOUTdengan jumlah maksimum detik yang harus ditunggu alur kerja untuk permintaan. Nilai defaultnya adalah 43200 (12 jam). Jika waktu berlalu sebelum permintaan diterima, aTimeoutErrorakan muncul.Perhatikan bahwa ada durasi eksekusi maksimum. Untuk mengetahui informasi selengkapnya, lihat batas permintaan.
Peta
callback_detailsdari langkah sebelumnyacreate_callbackditeruskan sebagai argumen. - Deploy alur kerja Anda untuk menyelesaikan pembuatan atau pembaruannya.
Saat permintaan diterima, semua detail permintaan akan disimpan dalam peta
callback_request. Kemudian, Anda akan memiliki akses ke seluruh permintaan HTTP, termasuk header, isi, dan petaqueryuntuk parameter kueri apa pun. Contoh:YAML
http_request: body: headers: {...} method: GET query: {} url: "/v1/projects/350446661175/locations/us-central1/workflows/workflow-1/executions/46804f42-dc83-46d6-87e4-93962866ed81/callbacks/49c80102-74d2-49cd-a70e-805a9fded94f_2de9b413-6332-412d-99c3-d7e9b6eeeda2" received_time: 2021-06-24 12:49:16.988072651 -0700 PDT m=+742581.005780667 type: HTTP
JSON
{ "http_request":{ "body":null, "headers":{ ... }, "method":"GET", "query":{ }, "url":"/v1/projects/350446661175/locations/us-central1/workflows/workflow-1/executions/46804f42-dc83-46d6-87e4-93962866ed81/callbacks/49c80102-74d2-49cd-a70e-805a9fded94f_2de9b413-6332-412d-99c3-d7e9b6eeeda2" }, "received_time":"2021-06-24 12:49:16.988072651 -0700 PDT m=+742581.005780667", "type":"HTTP" }
Jika isi HTTP adalah teks atau JSON, Workflows akan mencoba mendekode isi; jika tidak, byte mentah akan ditampilkan.
Mengotorisasi permintaan ke endpoint callback
Untuk mengirim permintaan ke endpoint callback, Google Cloud layanan seperti
Cloud Run dan Cloud Run Functions, serta layanan pihak ketiga
harus diotorisasi untuk melakukannya dengan memiliki izin
Identity and Access Management (IAM) yang sesuai; khususnya, workflows.callbacks.send
(termasuk dalam peran Workflows Invoker).
Membuat permintaan langsung
Cara paling sederhana untuk membuat kredensial berjangka pendek untuk akun layanan adalah dengan membuat permintaan langsung. Dua identitas terlibat dalam alur ini: pemanggil, dan akun layanan tempat kredensial dibuat. Panggilan ke alur kerja dasar di halaman ini adalah contoh permintaan langsung. Untuk mengetahui informasi selengkapnya, lihat Menggunakan IAM untuk mengontrol akses dan Izin permintaan langsung.
Membuat token akses OAuth 2.0
Untuk mengotorisasi aplikasi memanggil endpoint callback, Anda dapat membuat token akses OAuth 2.0 untuk akun layanan yang terkait dengan alur kerja.
Dengan asumsi Anda memiliki izin yang diperlukan (untuk peran Workflows Editor atau
Workflows Admin, dan Service Account Token Creator), Anda juga dapat
membuat token sendiri dengan
menjalankan metode generateAccessToken.
Jika permintaan generateAccessToken berhasil, isi respons yang ditampilkan akan berisi token akses OAuth 2.0 dan waktu habis masa berlaku. (Secara default, token akses OAuth 2.0 berlaku selama maksimum 1 jam.) Contoh:
{ "accessToken": "eyJ0eXAi...NiJ9", "expireTime": "2020-04-07T15:01:23.045123456Z" }
accessToken kemudian dapat digunakan dalam panggilan curl ke URL endpoint callback seperti dalam contoh berikut:
curl -X GET -H "Authorization: Bearer ACCESS_TOKEN_STRING" CALLBACK_URL
curl -X POST -H "Content-Type: application/json" -H "Authorization: Bearer ACCESS_TOKEN_STRING" -d '{"foo" : "bar"}' CALLBACK_URL
Membuat token OAuth untuk Cloud Run Functions
Jika Anda memanggil callback dari Cloud Run Functions menggunakan akun layanan yang sama dengan alur kerja dan dalam project yang sama, Anda dapat membuat token akses OAuth di fungsi itu sendiri. Contoh:
Untuk konteks selengkapnya, lihat tutorial Membuat alur kerja yang memerlukan interaksi manusia menggunakan callback.
Meminta akses offline
Token akses akan habis masa berlakunya secara berkala dan menjadi kredensial yang tidak valid untuk permintaan API terkait. Anda dapat memperbarui token akses tanpa meminta izin pengguna jika Anda meminta akses offline ke cakupan yang terkait dengan token. Meminta akses offline adalah persyaratan untuk aplikasi apa pun yang perlu mengakses Google API saat pengguna tidak ada. Untuk mengetahui informasi selengkapnya, lihat Memperbarui token akses (akses offline).
Memanggil alur kerja tepat satu kali menggunakan callback
Callback sepenuhnya idempotent yang berarti Anda dapat mencoba kembali callback jika gagal tanpa menghasilkan hasil atau efek samping yang tidak terduga.
Setelah Anda membuat endpoint callback, URL akan siap menerima permintaan masuk, dan biasanya ditampilkan ke pemanggil sebelum panggilan yang sesuai ke await_callback dilakukan. Namun, jika URL callback belum diterima saat langkah await_callback dieksekusi, eksekusi alur kerja akan diblokir hingga endpoint diterima (atau terjadi waktu tunggu). Setelah diterima, eksekusi alur kerja akan dilanjutkan, dan callback akan diproses.
Setelah Anda menjalankan langkah create_callback_endpoint dan membuat endpoint callback, satu slot callback akan tersedia untuk alur kerja. Saat permintaan callback diterima, slot ini akan diisi dengan payload callback hingga callback dapat diproses. Saat langkah await_callback dieksekusi, callback akan diproses, dan slot akan dikosongkan serta tersedia untuk callback lain. Kemudian, Anda dapat menggunakan kembali endpoint callback dan memanggil await_callback lagi.
Jika await_callback hanya dipanggil satu kali, tetapi callback kedua diterima, salah satu skenario berikut akan terjadi dan kode status HTTP yang sesuai akan ditampilkan:
HTTP
429: Too Many Requestsmenunjukkan bahwa callback pertama berhasil diterima, tetapi belum diproses; callback tersebut tetap menunggu untuk diproses. Callback kedua ditolak oleh alur kerja.HTTP
200: Successmenunjukkan bahwa callback pertama berhasil diterima dan respons ditampilkan. Callback kedua disimpan dan mungkin tidak akan pernah diproses kecuali jikaawait_callbackdipanggil untuk kedua kalinya. Jika alur kerja berakhir sebelum hal itu terjadi, permintaan callback kedua tidak akan pernah diproses dan akan dihapus.HTTP
404: Page Not Foundmenunjukkan bahwa alur kerja tidak lagi berjalan. Callback pertama diproses dan alur kerja telah selesai, atau alur kerja gagal. Untuk menentukannya, Anda harus membuat kueri status eksekusi alur kerja.
Callback paralel
Saat langkah-langkah dieksekusi secara paralel, dan callback dibuat oleh thread induk dan ditunggu di langkah turunan, pola yang sama seperti yang dijelaskan sebelumnya akan diikuti.
Pada contoh berikut, saat langkah create_callback_endpoint dieksekusi, satu slot callback akan dibuat. Setiap panggilan berikutnya ke await_callback akan membuka slot callback baru. Sepuluh callback dapat dilakukan secara serentak, jika semua thread berjalan dan menunggu sebelum permintaan callback dibuat. Callback tambahan dapat dibuat, tetapi akan disimpan dan tidak pernah diproses.
YAML
- createCallbackInParent: call: events.create_callback_endpoint args: http_callback_method: "POST" result: callback_details - parallelStep: parallel: for: range: [1, 10] value: loopValue steps: - waitForCallbackInChild: call: events.await_callback args: callback: ${callback_details}
JSON
[ { "createCallbackInParent": { "call": "events.create_callback_endpoint", "args": { "http_callback_method": "POST" }, "result": "callback_details" } }, { "parallelStep": { "parallel": { "for": { "range": [ 1, 10 ], "value": "loopValue", "steps": [ { "waitForCallbackInChild": { "call": "events.await_callback", "args": { "callback": "${callback_details}" } } } ] } } } } ]
Perhatikan bahwa callback diproses dalam urutan yang sama dengan setiap panggilan yang dibuat oleh cabang ke await_callback. Namun, urutan eksekusi cabang bersifat non-deterministik dan dapat mencapai hasil menggunakan berbagai jalur. Untuk mengetahui informasi selengkapnya, lihat
Langkah paralel.
Mencoba alur kerja callback dasar
Anda dapat membuat alur kerja dasar, lalu menguji panggilan ke endpoint callback alur kerja tersebut menggunakan curl. Anda harus memiliki izin Workflows Editor atau Workflows Admin yang diperlukan untuk project tempat alur kerja berada.
-
Buat dan deploy alur kerja berikut, lalu
jalankan.
YAML
- create_callback: call: events.create_callback_endpoint args: http_callback_method: "GET" result: callback_details - print_callback_details: call: sys.log args: severity: "INFO" text: ${"Listening for callbacks on " + callback_details.url} - await_callback: call: events.await_callback args: callback: ${callback_details} timeout: 3600 result: callback_request - print_callback_request: call: sys.log args: severity: "INFO" text: ${"Received " + json.encode_to_string(callback_request.http_request)} - return_callback_result: return: ${callback_request.http_request}
JSON
[ { "create_callback": { "call": "events.create_callback_endpoint", "args": { "http_callback_method": "GET" }, "result": "callback_details" } }, { "print_callback_details": { "call": "sys.log", "args": { "severity": "INFO", "text": "${\"Listening for callbacks on \" + callback_details.url}" } } }, { "await_callback": { "call": "events.await_callback", "args": { "callback": "${callback_details}", "timeout": 3600 }, "result": "callback_request" } }, { "print_callback_request": { "call": "sys.log", "args": { "severity": "INFO", "text": "${\\"Received \\" + json.encode_to_string(callback_request.http_request)}" } } }, { "return_callback_result": { "return": "${callback_request.http_request}" } } ]
Setelah menjalankan alur kerja, status eksekusi alur kerja adalah
ACTIVEhingga permintaan callback diterima atau waktu tunggu berlalu. - Konfirmasi status eksekusi dan ambil URL callback:
Konsol
-
Di Google Cloud konsol, buka halaman Workflows:
Buka Workflows -
Klik nama alur kerja yang baru saja Anda jalankan.
Status eksekusi alur kerja akan ditampilkan.
- Klik tab Logs.
Cari entri log yang mirip dengan berikut ini:
Listening for callbacks on https://workflowexecutions.googleapis.com/v1/projects/...
- Salin URL callback untuk digunakan di perintah berikutnya.
gcloud
- Pertama, ambil ID eksekusi:
Gantigcloud logging read "Listening for callbacks" --freshness=DURATION
DURATIONdengan jumlah waktu yang sesuai untuk membatasi entri log yang ditampilkan (jika Anda telah menjalankan alur kerja beberapa kali).Misalnya,
--freshness=t10mmenampilkan entri log yang tidak lebih lama dari 10 menit. Untuk mengetahui detailnya, lihatgcloud topic datetimes.ID eksekusi akan ditampilkan. Perhatikan bahwa URL callback juga ditampilkan di kolom
textPayloadSalin kedua nilai tersebut untuk digunakan pada langkah-langkah berikut. - Jalankan perintah berikut:
Status eksekusi alur kerja akan ditampilkan.gcloud workflows executions describe WORKFLOW_EXECUTION_ID --workflow=WORKFLOW_NAME
-
- Sekarang Anda dapat memanggil endpoint callback menggunakan perintah curl:
curl -X GET -H "Authorization: Bearer $(gcloud auth print-access-token)" CALLBACK_URL
Perhatikan bahwa untuk endpoint
POST, Anda harus menggunakan header representasiContent-Type. Contoh:curl -X POST -H "Content-Type: application/json" -H "Authorization: Bearer $(gcloud auth print-access-token)" -d '{"foo" : "bar"}' CALLBACK_URL
Ganti
CALLBACK_URLdengan URL yang Anda salin pada langkah sebelumnya. - Melalui Google Cloud konsol atau menggunakan Google Cloud CLI,
konfirmasi bahwa status eksekusi alur kerja kini adalah
SUCCEEDED. - Cari entri log dengan
textPayloadyang ditampilkan yang menyerupai berikut ini:Received {"body":null,"headers":...
Sampel
Sampel ini menunjukkan sintaksis.
Menangkap error waktu tunggu
Sampel ini menambahkan ke sampel sebelumnya dengan menangkap error waktu tunggu, dan menulis error ke log sistem.
YAML
main: steps: - create_callback: call: events.create_callback_endpoint args: http_callback_method: "GET" result: callback_details - print_callback_details: call: sys.log args: severity: "INFO" text: ${"Listening for callbacks on " + callback_details.url} - await_callback: try: call: events.await_callback args: callback: ${callback_details} timeout: 3600 result: callback_request except: as: e steps: - log_error: call: sys.log args: severity: "ERROR" text: ${"Received error " + e.message} next: end - print_callback_result: call: sys.log args: severity: "INFO" text: ${"Received " + json.encode_to_string(callback_request.http_request)}
JSON
{ "main": { "steps": [ { "create_callback": { "call": "events.create_callback_endpoint", "args": { "http_callback_method": "GET" }, "result": "callback_details" } }, { "print_callback_details": { "call": "sys.log", "args": { "severity": "INFO", "text": "${\"Listening for callbacks on \" + callback_details.url}" } } }, { "await_callback": { "try": { "call": "events.await_callback", "args": { "callback": "${callback_details}", "timeout": 3600 }, "result": "callback_request" }, "except": { "as": "e", "steps": [ { "log_error": { "call": "sys.log", "args": { "severity": "ERROR", "text": "${\"Received error \" + e.message}" }, "next": "end" } } ] } } }, { "print_callback_result": { "call": "sys.log", "args": { "severity": "INFO", "text": "${\"Received \" + json.encode_to_string(callback_request.http_request)}" } } } ] } }
Menunggu callback dalam loop percobaan ulang
Sampel ini mengubah sampel sebelumnya dengan menerapkan langkah percobaan ulang. Menggunakan predikat percobaan ulang kustom, alur kerja mencatat peringatan saat waktu tunggu terjadi, lalu mencoba kembali menunggu endpoint callback, hingga lima kali. Jika kuota percobaan ulang habis sebelum callback diterima, error waktu tunggu akhir akan menyebabkan alur kerja gagal.
YAML
main: steps: - create_callback: call: events.create_callback_endpoint args: http_callback_method: "GET" result: callback_details - print_callback_details: call: sys.log args: severity: "INFO" text: ${"Listening for callbacks on " + callback_details.url} - await_callback: try: call: events.await_callback args: callback: ${callback_details} timeout: 60.0 result: callback_request retry: predicate: ${log_timeout} max_retries: 5 backoff: initial_delay: 1 max_delay: 10 multiplier: 2 - print_callback_result: call: sys.log args: severity: "INFO" text: ${"Received " + json.encode_to_string(callback_request.http_request)} log_timeout: params: [e] steps: - when_to_repeat: switch: - condition: ${"TimeoutError" in e.tags} steps: - log_error_and_retry: call: sys.log args: severity: "WARNING" text: "Timed out waiting for callback, retrying" - exit_predicate: return: true - otherwise: return: false
JSON
{ "main": { "steps": [ { "create_callback": { "call": "events.create_callback_endpoint", "args": { "http_callback_method": "GET" }, "result": "callback_details" } }, { "print_callback_details": { "call": "sys.log", "args": { "severity": "INFO", "text": "${\"Listening for callbacks on \" + callback_details.url}" } } }, { "await_callback": { "try": { "call": "events.await_callback", "args": { "callback": "${callback_details}", "timeout": 60 }, "result": "callback_request" }, "retry": { "predicate": "${log_timeout}", "max_retries": 5, "backoff": { "initial_delay": 1, "max_delay": 10, "multiplier": 2 } } } }, { "print_callback_result": { "call": "sys.log", "args": { "severity": "INFO", "text": "${\"Received \" + json.encode_to_string(callback_request.http_request)}" } } } ] }, "log_timeout": { "params": [ "e" ], "steps": [ { "when_to_repeat": { "switch": [ { "condition": "${\"TimeoutError\" in e.tags}", "steps": [ { "log_error_and_retry": { "call": "sys.log", "args": { "severity": "WARNING", "text": "Timed out waiting for callback, retrying" } } }, { "exit_predicate": { "return": true } } ] } ] } }, { "otherwise": { "return": false } } ] } }