所以你有任务模型.您可以创建任务,完成任务,销毁它们.然后你有重复的任务.它就像常规任务一样,但它附有一个重复规则.但是,任务可能无限期地复发 – 您可以在计划中提前一年,您应该看到任务显示.
所以当用户创建一个重复的任务时,你不想在将来建立数百年的任务,并将它们保存到数据库中,对吧?所以我开始思考 – 你如何创建它们?
一种方法是在查看计划时创建它们.因此,当用户正在移动一个月前,将会创建任何重复的任务.这当然意味着你不能简单地处理任务的数据库记录.您执行的任务上的每个SELECT操作必须位于特定日期范围的上下文中,以便触发该日期范围内的循环任务才能持续.这是维护和性能负担,但可行.
好的,但是原来的任务呢?每个复发任务都与创建它的循环规则相关联,并且每个重复规则需要知道开始重新发生的原始任务.后者是重要的,因为您需要在用户浏览其计划时将原始任务克隆到新的日期.我猜也可以.
但是如果原始任务更新会怎么样?这意味着现在,当我们浏览时间表时,我们将创建从修改的任务中克隆的定期任务.这是不可取的.所有隐含持续的重复性任务都应显示当添加重新执行时原始任务的样子.因此,我们需要分开存储原始任务的副本,并从中克隆,以便重复工作.
但是,当用户浏览计划中的任务时,我们如何知道在特定时刻是否需要创建新的重复任务?我们要求复发规则:“呃,我今天应该坚持一个任务吗?它说是或否.如果这一天已经有这种重复发生的任务,我们不会创建一个.除了用户之外,所有好的还可以简单地删除自动持续的一个循环任务.在这种情况下,按照我们的逻辑,系统将重新创建已被删除的任务.不好.所以这意味着我们需要继续存储任务,但将其标记为这种重复的删除任务.咩.
正如我刚才所说,我想知道其他人是否解决了这个问题,可以在这里提供建筑意见.它必须是这个凌乱吗?有没有什么更优雅我失踪了?
更新:由于这个问题难以完美回答,我将会对设计/架构最有帮助的认识,这对于这种类型的问题具有最佳的帮助/权衡比例.它不必包含所有的细节.
解决方法
我正在使用他所谓的“时间表达”来确定一个预订是否落在一个特定的日期范围内,而不是试图将无限数量的事件(或在你的情况下的任务)插入到数据库中.
实际上,对于您的用例,这可能意味着您使用称为schedule的“temporal expression”属性来存储Task. ice_cube recurrence gem具有将自身序列化为活动记录属性的能力like so:
class Task < ActiveRecord::Base include IceCube serialize :schedule,Hash def schedule=(new_schedule) write_attribute(:schedule,new_schedule.to_hash) end def schedule Schedule.from_hash(read_attribute(:schedule)) end end
冰块似乎非常灵活,甚至允许您指定循环规则的例外. (假设您只想删除一个任务,但不是全部删除).
问题是,您不能真正查询数据库中属于特定日期范围的任务,因为您只存储了用于执行任务的规则,而不是任务本身.对于我的情况,我正在考虑添加一个属性,如“next_recurrence_date”,将用于进行一些基本的排序/过滤.您甚至可以使用它来将任务放在队列上,以便在下一个周期性日期完成某项任务. (像检查该日期是否已经过去,然后重新生成,甚至在下一个周期日期过去之后,您甚至可以存储该任务的“存档”版本.)
这样可以解决您的问题,“如果任务更新,该怎么办”,因为任务直到过去都不会持续存在.
无论如何,我希望这有助于试图通过自己的应用来思考这个问题.