问题描述
我有一个每三分钟运行一次的预定函数。
它应该查看数据库(firestore),查询相关用户,向他们发送电子邮件或执行其他数据库操作。
一旦它向用户发送电子邮件,它就会使用字段“sent_to_today:true”更新用户。
如果 sent_to_today == true,则该函数在大约 24 小时内不会触及该用户,这正是预期的。
但是,因为我有很多用户,而且该函数正在做很多工作,当它用 sent_to_today:true 更新用户时,另一个调用会事先到达该用户并处理他们以发送电子邮件。
这会导致一些用户收到两次相同的电子邮件。
我有哪些选择可以确保不会发生这种情况?
数据模型(简化):
users (Collection)
--- userId (document)
--- sent_to_today [Boolean]
--- NextUpdateTime [String representing a Timestamp in ISO String]
函数运行时,如果("Now" >= NextUpdateTime) && (sent_to_today==false),则处理用户,否则跳过。
如何确保用户每天只处理一次调用,而不是多次调用?
正如我所说,当它们被一个函数调用(将“sent_to_today”设置为 true)处理时,下一次调用就会到达该用户并处理它们。
在更好地构建数据或使用任何其他逻辑方法方面的任何帮助将不胜感激。
这是我正在考虑的一个想法:
- 每次调用都会在开始时设置一个全局文档的字段,“例如:busy_right_now : true”,完成后再次将其设置为 false。如果后续调用在当前调用完成之前运行,并且 busy_right_now 仍然是 true,则它什么都不做。
解决方法
选项 1。
您认为该函数可以每十分钟调用一次,而不是每三分钟调用一次吗?如果是 - 只需修改调度程序,并确保“最大实例”属性为“1”。由于函数超时只有 540 秒,因此 10 分钟(600 秒)足以避免重叠。
选项 2。
When a firestore document is chosen for processing,the cloud function modifies some attribute - i.e. __state
- and sets its value to IN_PROGRESS
for example.处理完成(发送电子邮件)后,该属性值将再次修改 - 例如,修改为 DONE
。因此,如果函数选择了一个文档,该文档在 IN_PROGRESS
属性中具有值 __state
- 它只是忽略并继续下一个。
缺点 - 如果函数崩溃 - 可能存在 IN_PROGRESS
状态的文档,并且应该有一些机制来监控和解决此类情况。
选项 3。
一个云函数通过 firestore 集合运行,并且对于每个要处理的文档 - 发送一个 pubsub 消息,触发另一个云函数。那个只适用于一个 firestore 文档。然而,“状态机”控制是必需的(如上面的选项 2)。选项 3 的好处 - 函数之间的专业化程度更高,并且可能有许多“第二”云函数并行运行。