我正在尝试创建一个侦听Firebase以添加/更改特定集合的工作进程。在任何一种情况下,都应该运行一个进程,最终根据它在那里找到的内容将一些额外的数据写回集合。我遇到的问题是这会导致无限循环,因为child_changed将再次触发回调,因为我正在更改它正在侦听的同一个树中的模型。此外,第一次通过child_added触发child_changed还有一个初步的重复工作。
我提出的唯一解决方案是以某种方式将数据放入Firebase,以指示不应发生更新(is_dirty: false
,或类似的事情)。我对这个解决方案并不是特别满意,因为这需要客户端在添加/更改应触发服务器处理的内容时参与翻转标志或其他内容。我希望他们不会那么耦合。我当然喜欢保持某种缓存集合以比较更改的想法,因为这会复制大量数据。
我还考虑在更新之前以某种方式使用off
(之后重新开启),但我担心这会让我错过在那段时间内可能出现的变化。也许这是交易的情况?
这里的最佳做法是什么?目前,我的代码如下所示:
collectionRef.on('child_added', processModel);
collectionRef.on('child_changed', processModel);
var processModel = function (modelSnapshot) {
// do some stuff that updates model
}
答案 0 :(得分:2)
您的主进程和工作进程(默认情况下)非常松散地绑定 - 仅通过修改数据而另一个被告知数据被更改的事实链接。
添加队列或信号量是一种更紧密地绑定它们的方法。
但是,我首选的模型通常是将它们绑得更紧......
不要考虑事件,而应考虑数据的状态。
设计您的工作进程以获取脏数据库并使其清理。然后在更新时对待'呼叫作为优化 - 有效地为您的工作流程提供一个线索'至于数据库的哪一部分可能需要清理。
使用此模式意味着无法无限更新'问题一旦清理,没有执行其他更新,并且它的可扩展性 - 您可以在数据库的不同部分使用多个工作进程,或以不同方式清理不同的元素。
不利的一面是数据的结构必须符合“状态”的要求。并且必须设计使用数据的程序,使其读取的数据可能变脏。虽然如果这非常重要,我会让客户端读取数据以检查它是否脏,并在继续之前触发清洁......
答案 1 :(得分:1)
[不知道你的用例,有点难以回答这个问题,但我会提供一些普遍的想法。]
重要的是要记住Firebase会同步数据,而不是"事件。"因此,每次重新启动工作进程时,它都会为所有现有数据获取child_added事件。
此外,如果您的工作进程已经停止了一个小时并且用户对模型中的项目进行了大量更改,那么当您的工作进程再次启动时,它仍然只会获得一堆child_added事件,而不是脱机更改的单个child_changed事件。
所以你通常想做两件事之一:
存储"工作人员队列"在Firebase中让您的工作进程从队列中抓取项目,处理它们,然后丢弃它们(或标记它们已完成或将它们移动到其他位置或其他任何位置)。
存储"州"在每个模型对象中,它指示它所处的状态以指示需要发生的处理(类似于您的脏想法)。用户可以将项目添加为" initial"并且您的工作流程会将其拾取,进行处理,然后将其写回"处理"或类似的东西。如果客户进行了修改,则将其标记为“脏”#34;再次,您的工作流程将进行修改并将状态更新为“已处理”"
如果您遵循其中一种方法,您的工作流程应该很容易知道它需要处理哪些项目,并且应该正确地处理重启/停机时间等,正确地处理"拾取"它停止了。