Realtime Database tetikleyicileri


Cloud Functions ile istemci kodunu güncellemenize gerek kalmadan Firebase Realtime Database'deki etkinlikleri işleyebilirsiniz. Cloud Functions, Realtime Database işlemlerini tam yönetim ayrıcalıklarıyla çalıştırmanızı ve Realtime Database'de yapılan her değişikliğin ayrı ayrı işlenmesini sağlar. Firebase Realtime Database'de değişiklik yapmak için DataSnapshot veya Admin SDK'yı kullanabilirsiniz.

Firebase Realtime Database işlevi tipik bir yaşam döngüsünde şu işlemleri yapar:

  1. Belirli bir Realtime Database konumunda yapılan değişiklikleri bekler.
  2. Bir etkinlik gerçekleştiğinde tetiklenir ve görevlerini yerine getirir (kullanım alanı örnekleri için Cloud Functions ile neler yapabilirim? bölümüne bakın).
  3. Belirtilen belgede 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. İşlevin ne zaman tetikleneceğini kontrol etmek için etkinlik işleyicilerden birini belirtin ve etkinlikleri dinleyeceği Realtime Database yolunu belirtin.

Etkinlik işleyiciyi ayarlama

Functions, Realtime Database etkinliklerini iki belirlilik düzeyinde yönetmenizi sağlar. Yalnızca oluşturma, güncelleme veya silme etkinliklerini dinleyebilir veya bir yolda yapılan herhangi bir değişikliği dinleyebilirsiniz. Cloud Functions, Realtime Database için şu etkinlik işleyicileri destekler:

  • onWrite(), Realtime Database'de veri oluşturulduğunda, güncellendiğinde veya silindiğinde tetiklenir.
  • onCreate(), Realtime Database'de yeni veri oluşturulduğunda tetiklenir.
  • onUpdate(), Realtime Database'de veriler güncellendiğinde tetiklenir .
  • onDelete(), veriler Realtime Database'den silindiğinde tetiklenir .

Örneği ve yolu belirtin

İşlevinizin ne zaman ve nerede tetikleneceğini kontrol etmek için ref(path) çağrısıyla yol belirtin. İsteğe bağlı olarak instance('INSTANCE_NAME') ile bir Realtime Database örneği belirtin. Örnek belirtmezseniz işlev, Firebase projesi için varsayılan Realtime Database örneğine dağıtılır. Örneğin:

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

Bu yöntemler, işlevinizi Realtime Database örneği içinde belirli bir yoldaki yazma işlemlerini işlemesi için yönlendirir. Yol özellikleri, bir yola dokunan tüm yazmalarla (bu yolun altında herhangi bir yerde gerçekleşen yazmalar dahil) eşleşir. İşlevinizin yolunu /foo/bar olarak ayarlarsanız şu iki konumun ikisindeki etkinliklerle eşleşir:

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

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

Bir yol bileşenini süslü parantez içine alarak joker karakter olarak belirtebilirsiniz. ref('foo/{bar}'), /foo öğesinin herhangi bir alt öğesiyle eşleşir. Bu joker karakter yol bileşenlerinin değerleri, işlevinizin EventContext.params nesnesinde bulunur. Bu örnekte değer context.params.bar olarak kullanılabilir.

Joker karakter içeren yollar, tek bir yazma işleminde birden fazla etkinlikle eşleşebilir. Ek

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

"/foo/{bar}" yolu ile bir kez "hello": "world" ve bir kez "firebase": "functions" ile olmak üzere iki kez eşleşir.

Etkinlik verilerini işleme

Bir Realtime Database etkinliği işlenirken döndürülen veri nesnesi bir DataSnapshot olur. onWrite veya onUpdate etkinlikleri için ilk parametre, tetikleme etkinliğinden önceki ve sonraki veri durumunu temsil eden iki anlık görüntü içeren bir Change nesnesidir. 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, ilgili konumdaki dizeyi büyük harfe dönüştürür ve değiştirilen 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ıya ait izinler de dahil olmak üzere kullanıcı bilgilerine erişebilirsiniz. Bu, güvenlik kurallarının zorunlu kılınması açısından faydalı olabilir ve işlevinizin, kullanıcının izin düzeyine bağlı olarak farklı işlemler tamamlamasına olanak tanır:

const functions = require('firebase-functions');
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 aşağıda gösterildiği gibi uygulama örneğini 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ğer okunuyor

Change nesnesi, etkinlikten önce Realtime Database'e kaydedilen bilgileri incelemenizi sağlayan bir before özelliğine sahiptir. before özelliği, tüm yöntemlerin (örneğin, val() ve exists()) önceki değere referans verdiği bir DataSnapshot döndürür. Orijinal DataSnapshot değerini kullanarak veya after özelliğini okuyarak yeni değeri tekrar okuyabilirsiniz. Herhangi bir Change üzerindeki bu özellik, verilerin etkinlik gerçekleştikten sonra durumunu temsil eden başka bir DataSnapshot öğesidir.

Örneğin, before özelliği, işlevin metnin yalnızca ilk oluşturulduğu zaman büyük harflerle yazılması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);
    });