Memperluas Datastore dengan Cloud Functions (generasi ke-2)

Dengan Cloud Run Functions dan Eventarc, Anda dapat men-deploy kode untuk menangani peristiwa yang dipicu oleh perubahan pada database Firestore dalam mode Datastore. Dengan begitu, Anda dapat menambahkan fungsionalitas sisi server tanpa harus menjalankan server Anda sendiri.

Pemicu mode Datastore

Eventarc mendukung pemicu peristiwa Firestore dalam mode Datastore berikut untuk memungkinkan Anda membuat handler Cloud Run Functions (generasi ke-2) yang terkait dengan peristiwa Firestore dalam mode Datastore:

Jenis Peristiwa Pemicu
google.cloud.datastore.entity.v1.created Dipicu saat entitas ditulis untuk pertama kalinya.
google.cloud.datastore.entity.v1.updated Dipicu saat entity sudah ada dan nilainya berubah.
google.cloud.datastore.entity.v1.deleted Dipicu saat entitas dihapus.
google.cloud.datastore.entity.v1.written Dipicu saat created, updated, atau deleted dipicu.
google.cloud.datastore.entity.v1.created.withAuthContext Sama seperti created, tetapi menambahkan informasi autentikasi.
google.cloud.datastore.entity.v1.updated.withAuthContext Sama seperti updated, tetapi menambahkan informasi autentikasi.
google.cloud.datastore.entity.v1.deleted.withAuthContext Sama seperti deleted, tetapi menambahkan informasi autentikasi.
google.cloud.datastore.entity.v1.written.withAuthContext Sama seperti written, tetapi menambahkan informasi autentikasi.

Pemicu peristiwa mode Datastore hanya merespons perubahan entity. Pembaruan terhadap entity mode Datastore yang tidak mengubah data (penulisan tanpa pengoperasian), tidak menghasilkan peristiwa penulisan atau pembaruan. Anda tidak dapat membuat peristiwa hanya untuk properti tertentu.

Menyertakan konteks autentikasi dalam acara

Untuk menyertakan informasi autentikasi tambahan tentang peristiwa, gunakan pemicu peristiwa dengan ekstensi withAuthContext. Ekstensi ini menambahkan informasi tambahan tentang principal yang memicu peristiwa tersebut. Peristiwa ini menambahkan atribut authtype dan authid selain informasi yang ditampilkan dalam peristiwa dasar. Lihat referensi authcontext untuk mengetahui informasi selengkapnya tentang nilai atribut.

Menulis fungsi yang dipicu entity

Untuk menulis fungsi yang merespons peristiwa Firestore dalam mode Datastore, bersiaplah untuk menentukan hal berikut selama deployment:

  • jenis peristiwa pemicu
  • filter peristiwa pemicu untuk memilih entitas yang terkait dengan fungsi
  • kode fungsi yang akan dijalankan

Filter peristiwa pemicu

Saat menentukan filter peristiwa, Anda dapat menentukan pencocokan entitas persis atau pola jalur. Gunakan pola jalur untuk mencocokkan beberapa entity dengan karakter pengganti * atau **.

Misalnya, Anda dapat menentukan pencocokan persis entitas untuk merespons perubahan pada entitas berikut:

users/marie

Gunakan karakter pengganti, * atau **, untuk merespons perubahan pada entitas yang cocok dengan pola. Karakter pengganti * cocok dengan satu segmen, dan karakter pengganti multi-segmen ** cocok dengan nol atau beberapa segmen dalam pola.

Untuk kecocokan segmen tunggal (*), Anda juga dapat menggunakan grup pengambilan bernama, seperti users/{userId}.

Tabel berikut menunjukkan pola jalur yang valid:

Pola Deskripsi
users/* atau users/{userId} Mencocokkan semua entity jenis users. Tidak cocok dengan tingkat entitas turunan seperti /users/marie/messages/33e2IxYBD9enzS50SJ68
users/** Mencocokkan semua entity jenis users dan semua entity turunan seperti /users/marie/messages/33e2IxYBD9enzS50SJ68

Untuk mempelajari pola jalur lebih lanjut, lihat Pola jalur Eventarc.

Pemicu Anda harus selalu menunjuk ke entitas, meskipun Anda menggunakan karakter pengganti. Lihat contoh berikut:

  • users/{userId=*}/{messages=*} tidak valid karena {messages=*} adalah ID jenis.

  • users/{userId=*}/{messages}/{messageId=*} valid karena {messageId=*} selalu mengarah ke entity.

Proses escape karakter

Bagian ini menjelaskan situasi yang mengharuskan Anda meng-escape karakter dalam ID jenis dan ID entity. Mengganti karakter memungkinkan filter peristiwa menafsirkan ID dengan benar.

  • Jika ID jenis atau ID entitas menyertakan karakter ~ atau /, Anda harus mengganti ID dalam filter peristiwa. Untuk meng-escape ID, gunakan format __escENCODED_ID__. Ganti ENCODED_ID dengan ID jenis atau ID entitas yang memiliki semua karakter ~ dan / yang diganti dengan ID encoding-nya, yaitu sebagai berikut:

    • ~: ~0
    • /: ~1

    Misalnya, ID jenis user/profile menjadi __escusers~1profile__. Contoh pola jalur dengan ID jenis ini adalah __escusers~1profile__/{userId}

  • Jika Anda menggunakan ID jenis atau ID entitas . atau .. dalam filter peristiwa, Anda harus melakukan escape ID sebagai berikut:

    • .: __esc~2__
    • ..: __esc~2~2__

    Anda hanya perlu meng-escape karakter . jika ID-nya persis . atau ... Misalnya, ID jenis customers.info tidak memerlukan escape.

  • Jika ID jenis atau entitas Anda adalah nilai numerik, bukan nilai string, Anda harus melakukan escape pada ID dengan __idNUMERIC_VALUE__. Misalnya, pola jalur untuk entity jenis 111 dan ID entity 222 adalah __id111__/__id222__.

  • Jika Anda bermigrasi dari Cloud Datastore Lama ke Firestore dalam mode Datastore, database Anda mungkin berisi ID lama dalam encoding non-UTF8. Anda harus meng-escape ID ini dengan __bytesBASE64_ENCODING__. Ganti BASE64_ENCODING dengan encoding base-64 dari ID. Misalnya, pola jalur Task/{task} dengan escaping untuk ID jenis non-UTF8 Task menjadi __bytesVGFzaw==__/{task}.

Contoh fungsi

Contoh berikut menunjukkan cara menerima peristiwa mode Datastore. Untuk menggunakan data yang terlibat dalam suatu peristiwa, lihat kolom value dan old_value.

  • value: Objek EntityResult yang berisi snapshot entity pasca-operasi. Kolom ini tidak diisi untuk peristiwa penghapusan.
  • old_value: Objek EntityResult yang berisi snapshot entity pra-operasi. Kolom ini hanya diisi untuk peristiwa update dan hapus.

Java

Untuk mempelajari cara menginstal dan menggunakan library klien untuk mode Datastore, lihat library klien mode Datastore. Untuk mengetahui informasi selengkapnya, lihat dokumentasi referensi Java API mode Datastore.

Untuk melakukan autentikasi ke mode Datastore, siapkan Kredensial Default Aplikasi. Untuk mengetahui informasi selengkapnya, lihat Menyiapkan autentikasi untuk lingkungan pengembangan lokal.

import com.google.cloud.functions.CloudEventsFunction;
import com.google.events.cloud.datastore.v1.EntityEventData;
import com.google.protobuf.InvalidProtocolBufferException;
import io.cloudevents.CloudEvent;
import java.util.logging.Logger;

public class Datastore implements CloudEventsFunction {
  private static final Logger logger = Logger.getLogger(Datastore.class.getName());

  @Override
  public void accept(CloudEvent event) throws InvalidProtocolBufferException {
    EntityEventData datastoreEventData = EntityEventData.parseFrom(event.getData().toBytes());

    logger.info("Function triggered by event on: " + event.getSource());
    logger.info("Event type: " + event.getType());

    logger.info("Old value:");
    logger.info(datastoreEventData.getOldValue().toString());

    logger.info("New value:");
    logger.info(datastoreEventData.getValue().toString());
  }
}

Sertakan dependensi proto dalam sumber Anda

Anda harus menyertakan file mode Datastore data.proto di direktori sumber untuk fungsi Anda. File ini mengimpor proto berikut yang juga harus Anda sertakan dalam direktori sumber:

Gunakan struktur direktori yang sama untuk dependensi. Misalnya, tempatkan struct.proto dalam google/protobuf.

File ini diperlukan untuk mendekode data peristiwa. Jika sumber fungsi Anda tidak menyertakan file ini, fungsi akan menampilkan error saat dijalankan.

Atribut peristiwa

Setiap peristiwa mencakup atribut data yang mencakup informasi tentang peristiwa seperti waktu pemicuan peristiwa. Firestore dalam mode Datastore menambahkan data tambahan tentang database dan entitas yang terlibat dalam peristiwa. Anda dapat mengakses atribut ini sebagai berikut:

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"));

Men-deploy fungsi

Pengguna yang men-deploy fungsi Cloud Run harus memiliki peran IAM Cloud Run Functions Developer atau peran yang mencakup izin yang sama. Lihat juga Konfigurasi tambahan untuk deployment.

Anda dapat men-deploy fungsi menggunakan gcloud CLI atau konsol Google Cloud . Contoh di bawah menunjukkan deployment dengan gcloud CLI. Untuk mengetahui detail tentang deployment dengan konsol Google Cloud , lihat Men-deploy fungsi Cloud Run.

  1. Di konsol Google Cloud , aktifkan Cloud Shell.

    Aktifkan Cloud Shell

    Di bagian bawah konsol Google Cloud , sesi Cloud Shell akan dimulai dan menampilkan perintah command line. Cloud Shell adalah lingkungan shell dengan Google Cloud CLI yang sudah terinstal, dan dengan nilai yang sudah ditetapkan untuk project Anda saat ini. Diperlukan waktu beberapa detik untuk melakukan inisialisasi pada sesi.

  2. Gunakan perintah gcloud functions deploy untuk men-deploy fungsi:

    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" \
    

    Argumen pertama, FUNCTION_NAME, adalah nama untuk fungsi yang di-deploy. Nama fungsi harus dimulai dengan huruf yang diikuti dengan maksimal 62 huruf, angka, tanda hubung, atau garis bawah dan harus diakhiri dengan huruf atau angka. Ganti FUNCTION_NAME dengan nama fungsi yang valid. Kemudian, tambahkan tanda berikut:

    • Flag --gen2 menentukan bahwa Anda ingin men-deploy ke Cloud Run Functions (generasi ke-2). Jika flag ini tidak ada, deployment akan dilakukan ke Cloud Run Functions (generasi ke-1).

    • Flag --region=FUNCTION_LOCATION menentukan region tempat men-deploy fungsi Anda.

      Untuk memaksimalkan kedekatan, tetapkan FUNCTION_LOCATION ke region di dekat database Firestore Anda. Jika database Firestore Anda berada di lokasi multi-region, tetapkan nilai ke us-central1 untuk database di nam5 dan ke europe-west4 untuk database di eur3. Untuk lokasi Firestore regional, tetapkan ke region yang sama.

    • Flag --trigger-location=TRIGGER_LOCATION menentukan lokasi pemicu. Anda harus menyetel TRIGGER_LOCATION ke lokasi database mode Datastore Anda.

    • Flag --runtime=RUNTIME menentukan runtime bahasa yang digunakan fungsi Anda. Cloud Run Functions mendukung beberapa runtime. Lihat Runtime untuk mengetahui informasi selengkapnya. Setel RUNTIME ke runtime yang didukung.

    • Flag --source=SOURCE_LOCATION menentukan lokasi kode sumber fungsi Anda. Lihat bagian berikut untuk mengetahui detailnya:

      Tetapkan SOURCE_LOCATION ke lokasi kode sumber fungsi Anda.

    • Flag --entry-point=CODE_ENTRYPOINT menentukan titik entri ke fungsi Anda dalam kode sumber. Ini adalah kode yang dieksekusi fungsi Anda saat dijalankan. Anda harus menetapkan CODE_ENTRYPOINT ke nama fungsi atau nama class yang sepenuhnya memenuhi syarat yang ada dalam kode sumber Anda. Lihat Titik entri fungsi untuk informasi selengkapnya.

    • Flag --trigger-event-filters menentukan filter peristiwa yang mencakup jenis pemicu dan entitas atau jalur yang memicu peristiwa. Tetapkan nilai atribut berikut untuk menentukan filter acara:

      • type=EVENT_FILTER_TYPE: Firestore mendukung jenis peristiwa berikut:

        • google.cloud.datastore.entity.v1.created: peristiwa dikirim saat entitas ditulis untuk pertama kalinya.
        • google.cloud.datastore.entity.v1.updated: peristiwa dikirim saat entitas sudah ada dan nilainya berubah.
        • google.cloud.datastore.entity.v1.deleted: peristiwa dikirim saat entitas dihapus.
        • google.cloud.datastore.entity.v1.written: peristiwa dikirim saat entitas dibuat, diperbarui, atau dihapus.
        • google.cloud.datastore.entity.v1.created.withAuthContext: peristiwa dikirim saat dokumen ditulis untuk pertama kalinya dan peristiwa tersebut mencakup informasi autentikasi tambahan
        • google.cloud.datastore.entity.v1.updated.withAuthContext: peristiwa dikirim saat dokumen sudah ada dan nilainya berubah. Mencakup informasi autentikasi tambahan
        • google.cloud.datastore.entity.v1.deleted.withAuthContext: event dikirim saat dokumen dihapus. Mencakup informasi autentikasi tambahan
        • google.cloud.datastore.entity.v1.written.withAuthContext: peristiwa dikirim saat dokumen dibuat, diupdate, atau dihapus dan peristiwa. Mencakup informasi autentikasi tambahan

        Tetapkan EVENT_FILTER_TYPE ke salah satu jenis peristiwa berikut.

      • database=DATABASE: database Firestore. Untuk nama database default, tetapkan DATABASE ke (default).

      • namespace=NAMESPACE: namespace database. Untuk nama database default, tetapkan NAMESPACE ke (default). Hapus tanda agar cocok dengan namespace apa pun.

      • entity=ENTITY_OR_PATH: jalur database yang memicu peristiwa saat data dibuat, diupdate, atau dihapus. Nilai yang diterima untuk ENTITY_OR_PATH adalah:

        • Sama dengan; misalnya, --trigger-event-filters="entity='users/marie'"
        • Pola jalur; misalnya, --trigger-event-filters-path-pattern="entity='users/*'". Untuk mengetahui informasi selengkapnya, lihat Memahami pola jalur.

      Secara opsional, Anda dapat menentukan opsi konfigurasi, jaringan, dan keamanan tambahan saat men-deploy fungsi.

      Untuk referensi lengkap tentang perintah deployment dan flag-nya, lihat dokumentasi gcloud functions deploy.

Contoh deployment

Contoh berikut menunjukkan deployment dengan Google Cloud CLI.

Deploy fungsi untuk database di region 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}'"

Deploy fungsi untuk database di multi-region 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}'"

Batasan

Perhatikan batasan berikut untuk pemicu Firestore untuk Cloud Run Functions:

  • Cloud Run Functions (generasi ke-1) menjadi prasyarat database "(default)" yang ada dalam mode native Firestore. Lingkungan ini tidak mendukung mode Datastore atau database bernama Firestore. Gunakan Cloud Run Functions (generasi ke-2) untuk mengonfigurasi peristiwa dalam kasus tersebut.
  • Penyiapan lintas project dengan Cloud Run Functions dan pemicu Firestore memiliki batasan. Untuk menyiapkan pemicu Firestore, Cloud Run Functions harus berada dalam project yang sama.
  • Pengurutan tidak dijamin. Perubahan cepat dapat memicu pemanggilan fungsi dalam urutan yang tidak terduga.
  • Peristiwa dikirim setidaknya satu kali, tetapi satu peristiwa dapat menghasilkan beberapa pemanggilan fungsi. Hindari mengandalkan mekanisme tepat satu kali, dan tulis fungsi idempoten.
  • Firestore dalam mode Datastore memerlukan Cloud Run Functions (generasi ke-2). Cloud Run Functions (generasi ke-1) tidak mendukung mode Datastore.
  • Pemicu dikaitkan dengan satu database. Anda tidak dapat membuat pemicu yang cocok dengan beberapa database.
  • Menghapus database tidak secara otomatis menghapus pemicu untuk database tersebut. Pemicu berhenti mengirim peristiwa, tetapi akan tetap ada sampai Anda menghapus pemicu.
  • Jika peristiwa yang cocok melebihi ukuran permintaan maksimum, peristiwa tersebut mungkin tidak akan dikirim ke Cloud Run Functions (generasi ke-1).
    • Peristiwa yang tidak terkirim karena ukuran permintaan akan dicatat dalam log platform dan diperhitungkan terhadap penggunaan log untuk project.
    • Anda dapat menemukan log ini di Logs Explorer dengan pesan "Event dapat mengirim ke Cloud function karena ukuran melebihi batas untuk generasi ke-1..." dengan tingkat keparahan error. Anda dapat menemukan nama fungsi di bawah kolom functionName. Jika kolom receiveTimestamp masih berada dalam waktu satu jam dari sekarang, Anda dapat menyimpulkan konten peristiwa yang sebenarnya dengan membaca dokumen yang dimaksud menggunakan snapshot sebelum dan setelah stempel waktu.
    • Untuk menghindari peristiwa seperti ini, Anda dapat:
      • Melakukan migrasi dan upgrade ke Cloud Run Functions (generasi ke-2)
      • Memperkecil dokumen
      • Menghapus Cloud Run Functions yang dimaksud
    • Anda dapat menonaktifkan logging itu sendiri menggunakan pengecualian, tetapi perhatikan bahwa peristiwa yang melanggar tidak akan dikirim.

Lokasi Eventarc dan Firestore dalam mode Datastore

Eventarc tidak mendukung multi-region untuk pemicu peristiwa Firestore, tetapi Anda tetap dapat membuat pemicu untuk database Firestore di lokasi multi-region. Eventarc memetakan lokasi multi-region Firestore ke region Eventarc berikut:

Firestore multi-region Wilayah Eventarc
nam5 us-central1
eur3 europe-west4

Langkah berikutnya