Realtime Database tetikleyicileri


Cloud Functions ile istemci kodunu güncellemenize gerek kalmadan Firebase Realtime Database'teki etkinlikleri yönetebilirsiniz. Cloud Functions, Realtime Database işlemlerini tam yönetici ayrıcalıklarıyla çalıştırmanıza olanak tanır ve Realtime Database'da yapılan her değişikliğin ayrı ayrı işlenmesini sağlar. Firebase Realtime Database değişikliklerini DataSnapshot veya Admin SDK üzerinden yapabilirsiniz.

Tipik bir yaşam döngüsünde Firebase Realtime Database işlevi aşağıdakileri yapar:

  1. Belirli bir Realtime Database konumunda değişiklik yapılmasını bekler.
  2. Bir etkinlik gerçekleştiğinde tetiklenir ve görevlerini gerçekleştirir (Cloud Functions ile neler yapabilirim? başlıklı makaleyi inceleyin. kullanım alanı örnekleri için).
  3. Belirtilen dokümanda depolanan verilerin anlık görüntüsünü içeren bir veri nesnesi alır.

Realtime Database işlevini tetikleme

functions.database ile Realtime Database etkinlikleri için yeni işlevler oluşturun. Fonksiyonun ne zaman tetikleneceğini kontrol etmek için etkinlik işleyicilerden birini ve etkinlikleri dinleyeceği Realtime Database yolunu belirtin.

Etkinlik işleyiciyi ayarlama

İşlevler, Realtime Database etkinliklerini iki düzeyde işlemenize olanak tanır: Yalnızca oluşturma, güncelleme veya silme etkinliklerini dinleyebilir ya da bir yoldaki her türlü değişikliği dinleyebilirsiniz. Cloud Functions, Realtime Database için aşağıdaki etkinlik işleyicileri destekler:

  • Realtime Database alanında veri oluşturulduğunda, güncellendiğinde veya silindiğinde tetiklenen onWrite().
  • Realtime Database içinde yeni veri oluşturulduğunda tetiklenen onCreate().
  • Realtime Database kaynağında veriler güncellendiğinde tetiklenen onUpdate() .
  • Realtime Database kaynağından veri silindiğinde tetiklenen onDelete() .

Örneği ve yolu belirtin

İşlevinizin ne zaman ve nerede tetiklenmesi gerektiğini kontrol etmek için bir yol belirtmek üzere ref(path)'u çağırın ve isteğe bağlı olarak instance('INSTANCE_NAME') ile bir Realtime Database örneği belirtin. Bir örnek belirtmezseniz işlev, Firebase projesinin varsayılan Realtime Database örneğine dağıtılır. Örneğin:

  • Varsayılan Realtime Database örneği: functions.database.ref('/foo/bar')
  • "uygulama-veritabanı-2" adlı örnek: functions.database.instance('my-app-db-2').ref('/foo/bar')

Bu yöntemler, işlevinizi Realtime Database örneğindeki belirli bir yoldaki yazma işlemlerini gerçekleştirecek şekilde yönlendirir. Yol spesifikasyonları, bir yola dokunan tüm yazma işlemlerini (altındaki herhangi bir yerde gerçekleşen yazma işlemleri dahil) eşleştirir. İşlevinizin yolunu /foo/bar olarak ayarlarsanız bu işlev aşağıdaki iki konumdaki etkinliklerle eşleşir:

 /foo/bar
 /foo/bar/baz/really/deep/path

Her iki durumda da Firebase, etkinliğin /foo/bar tarihinde gerçekleştiğini yorumlar ve etkinlik verileri /foo/bar tarihindeki eski ve yeni verileri içerir. Etkinlik verileri büyük olabilirse veritabanınızın köküne yakın tek bir işlev yerine daha derin yollarda birden fazla işlev kullanmayı düşünebilirsiniz. En iyi performans için yalnızca mümkün olan en derin düzeyde veri isteyin.

Bir yol bileşenini, köşeli parantezle çevreleyerek joker karakter olarak belirtebilirsiniz; ref('foo/{bar}'), /foo'un herhangi bir alt öğesiyle eşleşir. Bu joker karakterli yol bileşenlerinin değerleri, işlevinizin EventContext.params nesnesinde kullanılabilir. Bu örnekte değer context.params.bar olarak kullanılabilir.

Joker karakter içeren yollar, tek bir yazma işleminden birden fazla etkinliği eşleştirebilir.

{
  "foo": {
    "hello": "world",
    "firebase": "functions"
  }
}

"/foo/{bar}" yolunu iki kez eşleştirir: bir kez "hello": "world" ile ve bir kez de "firebase": "functions" ile.

Etkinlik verilerini işleme

Realtime Database etkinliği işlenirken döndürülen veri nesnesi bir DataSnapshot olur. onWrite veya onUpdate etkinlikleri için ilk parametre, tetikleyici etkinlikten önceki ve sonraki veri durumunu temsil eden iki anlık görüntü içeren bir Change nesnesi olur. onCreate ve onDelete etkinlikleri için döndürülen veri nesnesi, oluşturulan veya silinen verilerin anlık görüntüsüdür.

Bu örnekte işlev, belirtilen yolun anlık görüntüsünü alır, bu konumdaki dizeyi büyük harfe dönüştürür ve değiştirilmiş dizeyi veritabanına yazar:

// Listens for new messages added to /messages/:pushId/original and creates an
// uppercase version of the message to /messages/:pushId/uppercase
exports.makeUppercase = functions.database.ref('/messages/{pushId}/original')
    .onCreate((snapshot, context) => {
      // Grab the current value of what was written to the Realtime Database.
      const original = snapshot.val();
      functions.logger.log('Uppercasing', context.params.pushId, original);
      const uppercase = original.toUpperCase();
      // You must return a Promise when performing asynchronous tasks inside a Functions such as
      // writing to the Firebase Realtime Database.
      // Setting an "uppercase" sibling in the Realtime Database returns a Promise.
      return snapshot.ref.parent.child('uppercase').set(uppercase);
    });

Kullanıcı kimlik doğrulama bilgilerine erişme

EventContext.auth ve EventContext.authType üzerinden, bir işlevi tetikleyen kullanıcının izinleri dahil kullanıcı bilgilerine erişebilirsiniz. Bu, güvenlik kurallarını zorunlu kılmak için yararlı olabilir. Böylece işlevinizin, kullanıcının izin düzeyine göre farklı işlemleri tamamlamasına izin verebilirsiniz:

const functions = require('firebase-functions/v1');
const admin = require('firebase-admin');

exports.simpleDbFunction = functions.database.ref('/path')
    .onCreate((snap, context) => {
      if (context.authType === 'ADMIN') {
        // do something
      } else if (context.authType === 'USER') {
        console.log(snap.val(), 'written by', context.auth.uid);
      }
    });

Ayrıca, bir kullanıcının "kimliğine bürünmek" ve kullanıcı adına yazma işlemleri gerçekleştirmek için kullanıcı kimlik doğrulama bilgilerinden yararlanabilirsiniz. Eşzamanlılık sorunlarını önlemek için uygulama örneğini aşağıda gösterildiği gibi sildiğinizden emin olun:

exports.impersonateMakeUpperCase = functions.database.ref('/messages/{pushId}/original')
    .onCreate((snap, context) => {
      const appOptions = JSON.parse(process.env.FIREBASE_CONFIG);
      appOptions.databaseAuthVariableOverride = context.auth;
      const app = admin.initializeApp(appOptions, 'app');
      const uppercase = snap.val().toUpperCase();
      const ref = snap.ref.parent.child('uppercase');

      const deleteApp = () => app.delete().catch(() => null);

      return app.database().ref(ref).set(uppercase).then(res => {
        // Deleting the app is necessary for preventing concurrency leaks
        return deleteApp().then(() => res);
      }).catch(err => {
        return deleteApp().then(() => Promise.reject(err));
      });
    });

Önceki değeri okuma

Change nesnesinde, etkinlikten önce Realtime Database nesnesine kaydedilenleri incelemenizi sağlayan bir before özelliği vardır. before mülkü, tüm yöntemlerin (örneğin, val() ve exists()) önceki değere atıfta bulunduğu bir DataSnapshot döndürür. Orijinal DataSnapshot özelliğini kullanarak veya after özelliğini okuyarak yeni değeri tekrar okuyabilirsiniz. Herhangi bir Change öğesindeki bu mülk, etkinliğin gerçekleşmesinden sonra verilerin durumunu temsil eden başka bir DataSnapshot öğesidir.

Örneğin, before mülkü, işlevin metni yalnızca ilk oluşturulduğunda büyük harf kullanmasını sağlamak için kullanılabilir:

exports.makeUppercase = functions.database.ref('/messages/{pushId}/original')
    .onWrite((change, context) => {
      // Only edit data when it is first created.
      if (change.before.exists()) {
        return null;
      }
      // Exit when the data is deleted.
      if (!change.after.exists()) {
        return null;
      }
      // Grab the current value of what was written to the Realtime Database.
      const original = change.after.val();
      console.log('Uppercasing', context.params.pushId, original);
      const uppercase = original.toUpperCase();
      // You must return a Promise when performing asynchronous tasks inside a Functions such as
      // writing to the Firebase Realtime Database.
      // Setting an "uppercase" sibling in the Realtime Database returns a Promise.
      return change.after.ref.parent.child('uppercase').set(uppercase);
    });