2016-03-31 1 views
1

Как указано в документации, я сохраняю пользователей в списке. Пользователи могут регистрироваться как с паролем, так и с провайдерами Facebook. (другие поставщики могут прийти позже)знаете, что новые пользователи добавили в список Firebase, даже после перезагрузки.

Затем у меня есть приложение nodejs, которое прослушивает список пользователей и отправляет мне электронное письмо в случае новых элементов.

Это легко с помощью firebase, просто добавьте прослушиватель событий child_added. Но поскольку мое приложение может перезагружаться для обновления/сбоя или по любой другой причине, я не хочу получать электронное письмо с каждым пользователем при каждом повторном запуске приложения. Поэтому я просто сохраняю последний userId, который использовался для отправки электронной почты.

var retrieveLatestAccountNotified = function() { 
    ref.child("server-state").child("email-account").once("value", function (snapshot) { 
     user = snapshot.val(); 
     console.log("Latest User Id : " + user); 
     fetchUser(user); 
     //fakeUser(""); 
    }, function (errorObject) { 
     console.log("The read failed: " + errorObject.code); 
    }); 
}; 


var fetchUser = function (latestUserId) { 
    ref.child("users").orderByKey().startAt(latestUserId).on("child_added", function (snapshot, prevChildKey) { 
     if (snapshot.key() !== latestUserId) { 
      var newUser = snapshot.val(); 
      console.log(newUser); 
      sendEmail.newAccountEmail(ses, newUser, snapshot.key(), function (err, data) { 
       if (err) 
        throw err; 
       console.log('Email sent:'); 
       console.log(data); 
       ref.child("server-state").child("email-account").set(snapshot.key()); 
      }); 
     } 

    }, function (errorObject) { 
     console.log("The read failed: " + errorObject.code); 
    }); 
}; 

Проблема заключается в том, что FB генерирует другой тип USERID в зависимости от выбранного поставщика, поэтому мой механизм не будет работать.

Как с этим бороться?

  • Добавить приоритет, когда пользователь создаются => как многие клиенты могут добавлять пользователь, этот механизм должен использоваться в каждой клиентской реализации
  • Добавить ребенок (CREATION_DATE) в каждом пользователе => Добавление дополнительным Информация о пользователе в
  • Добавить еще один список, который сохраняет которые пользователи были уведомлены => требует, чтобы петли как на полный список

Любой образованный предложение приветствуется!

ответ

3

Общий подход, используемый для этого близко к # 3:

Добавить еще один список, который сохраняет которые пользователи были уведомлены => требуется в цикле как на полный список

Обычно вы добавляете очередь для отправки уведомлений по электронной почте. Эта очередь предназначена исключительно для отправки уведомлений, поэтому сервер удаляет элемент из него после его завершения.

В своей простейшей форме:

ref.child('emailNotificationQueue').on('child_added', function(snapshot) { 
    sendEmailToAnthony(snapshot.val(), function() { 
    snapshot.ref().remove(); 
    }); 
}); 

Для лучшей масштабируемости и многих других причин, вы можете захотеть использовать firebase-queue. Но это (красиво) сухая версия такой петли.

Вы можете взять два подхода к очереди:

  1. Вашего приложение записывает новый пользователь /users и уведомление /emailNotificationQueue. Обычно это работает, но имеет некоторые неприятные условия гонки/ошибки, если вредоносный клиент (или ошибки кодирования) пишет один, а не другой). Хотя вы можете защитить их, иногда существует более простой подход.

  2. Ваше приложение записывает новых пользователей в /newUserQueue. Сервер читает их оттуда, отправляет по электронной почте и добавляет их в /users.

+0

Я действительно знал о пожарной базе, это кажется мощным. Вы бы рекомендовали сделать отдельную очередь для каждой темы, добавив спецификацию в задачу? – Anthony

+0

Это действительно зависит от того, как вы предпочитаете структурировать свой внутренний код и достаточно ли разные задачи. У вас может даже быть начальная «createUser» задача, которая затем отгоняет другие «подзадачи». Но я обычно предпочитаю более простую систему. –

1

Вы можете попытаться сохранить отметку времени, когда последнее письмо было отправлено в самом объекте пользователя, а запрос - дочерним по типу времени. Этот подход имеет одну проблему, когда в первый раз он может повторно отправлять письма всем пользователям.

var fetchUser = function (last_email_sent_ts) { 
    // as email_sent_ts will only have valid value when email is sent 
    // if we query by email_sent_ts equals to null shall return all the 
    // values that are missed during the restart 
    ref.child("users") 
     .orderByChild("email_sent_ts") 
     .equalTo(null) 
     .on("child_added", success , error);  

    function success(snapshot, prevChildKey) {    
     var newUser = snapshot.val(); 

     if (newUser.email_sent_ts === last_email_sent_ts) return; 

     sendEmail.newAccountEmail(ses, newUser, snapshot.key(), emailCallback); 

     function emailCallback(err, data) { 
      if (err) throw err; 

      var email_sent_ts = new Date().getTime(); 

      ref.child("users") 
       .child(snapshot.key()) 
       .child('email_sent_ts').set(email_sent_ts); 

     }          
    } 
} 
Смежные вопросы