知道在 Firebase 列表中添加了哪些新用户,即使在重启后也是如此
know what are new users added on a Firebase list, even after a restart
如文档中所述,我将用户保存在列表中。用户可以使用密码和 Facebook 提供商登录。 (其他提供者可能会稍后出现)
然后,我有一个 nodejs 应用程序可以侦听用户列表并在有新项目时向我发送电子邮件。
使用 firebase 很容易,只需添加一个 child_added 事件监听器。但是由于我的应用程序可能会因 update/crash 或任何其他原因而重新启动,因此我不想在每次重新启动应用程序时都收到一封电子邮件给每个用户。所以我只保存最近一次发邮件用过的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 类型,因此我的机制将不起作用。
如何处理?
- 创建用户时添加优先级
=> 由于许多客户端可能会添加用户,因此必须在每个客户端实现中使用此机制
- 在每个用户中添加一个child (creation_date)
=> 在用户中添加额外信息
- 添加另一个列表来保存哪些用户已收到通知
=> 需要在两个完整列表上循环
欢迎任何有根据的提议!
您可以尝试将邮件最后一次发送的时间戳存储在用户object 本身中,并通过child 和时间戳属性 进行查询。这种方法有一个问题,即第一次可能会为所有用户重新发送邮件。
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);
}
}
}
用于此的常用方法接近您的 #3:
Add another list that saves which users have been notified => require to loop on both full list
通常您会添加一个队列来发送电子邮件通知。此队列纯粹用于发送通知,因此服务器会在完成后从中删除该项目。
最简单的形式:
ref.child('emailNotificationQueue').on('child_added', function(snapshot) {
sendEmailToAnthony(snapshot.val(), function() {
snapshot.ref().remove();
});
});
出于更好的可伸缩性和许多其他原因,您可能想要使用 firebase-queue。但它是这种循环的(漂亮的)强化版本。
您可以采用两种方法来排队:
您的应用将新用户写入 /users
并将通知写入 /emailNotificationQueue
。这通常有效,但如果恶意客户端(或编码错误)写了一个而不是另一个,则会出现一些令人讨厌的 race/error 情况)。虽然您可以防范这些,但有时有更简单的方法。
您的应用将新用户写入 /newUserQueue
。服务器从那里读取它们,发送电子邮件 并 将它们添加到 /users
.
如文档中所述,我将用户保存在列表中。用户可以使用密码和 Facebook 提供商登录。 (其他提供者可能会稍后出现)
然后,我有一个 nodejs 应用程序可以侦听用户列表并在有新项目时向我发送电子邮件。
使用 firebase 很容易,只需添加一个 child_added 事件监听器。但是由于我的应用程序可能会因 update/crash 或任何其他原因而重新启动,因此我不想在每次重新启动应用程序时都收到一封电子邮件给每个用户。所以我只保存最近一次发邮件用过的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 类型,因此我的机制将不起作用。
如何处理?
- 创建用户时添加优先级 => 由于许多客户端可能会添加用户,因此必须在每个客户端实现中使用此机制
- 在每个用户中添加一个child (creation_date) => 在用户中添加额外信息
- 添加另一个列表来保存哪些用户已收到通知 => 需要在两个完整列表上循环
欢迎任何有根据的提议!
您可以尝试将邮件最后一次发送的时间戳存储在用户object 本身中,并通过child 和时间戳属性 进行查询。这种方法有一个问题,即第一次可能会为所有用户重新发送邮件。
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);
}
}
}
用于此的常用方法接近您的 #3:
Add another list that saves which users have been notified => require to loop on both full list
通常您会添加一个队列来发送电子邮件通知。此队列纯粹用于发送通知,因此服务器会在完成后从中删除该项目。
最简单的形式:
ref.child('emailNotificationQueue').on('child_added', function(snapshot) {
sendEmailToAnthony(snapshot.val(), function() {
snapshot.ref().remove();
});
});
出于更好的可伸缩性和许多其他原因,您可能想要使用 firebase-queue。但它是这种循环的(漂亮的)强化版本。
您可以采用两种方法来排队:
您的应用将新用户写入
/users
并将通知写入/emailNotificationQueue
。这通常有效,但如果恶意客户端(或编码错误)写了一个而不是另一个,则会出现一些令人讨厌的 race/error 情况)。虽然您可以防范这些,但有时有更简单的方法。您的应用将新用户写入
/newUserQueue
。服务器从那里读取它们,发送电子邮件 并 将它们添加到/users
.