语境
有一个邮件管理器。
每封邮件都包含一个时间戳、一个发件人和一份收件人列表。
时间戳指定了新闻稿的发送时间,可以是:
- 一次性(2025/01/15 12:30)
- 定期(每 3 小时)
- 从某个日期开始定期更新(每月 3 日 15:30)
每个用户的收件人总数上限是有限制的(默认为 500)。
创建新邮件时,如果其创建日期在已创建日期的 24 小时内,则此新邮件的收件人数量将从用户的收件人限制中减去。也就是说,限制与日期以及在该日期创建邮件的用户相关。
24小时内最多可以发送用户收件人的数量限制。
问题
由于创建邮件时没有设置时间限制,用户可以一次创建多封邮件,这些邮件会在24小时内生效,突破了用户数量的限制。
例子:
假设我们同时安排了 2 封定期邮件。
然后在惰性计算期间第一次将限制考虑在内。如果我们将第二次邮寄的日期推迟 2 个月,由于我们一直在偷懒计算新日期并且它不断更新,因此限制仍然会被正确计算。
冲突检测算法
对于每封邮件,都会创建一个时间/数量事件序列。每一次邮寄时刻都对应两个事件:第一个事件是在邮寄那一刻,数量等于地址数量,第二个事件是在24小时后,数量等于地址数量带减号。序列不是一个列表,它是一个按时间顺序检索连续事件的生成器。
使用排序数组合并算法的泛化将所有序列组合成一个公共序列。不要注意“数组”这个词,合并算法从一组递增序列中生成单个递增序列。
让我们启动一个计数器,计算过去 24 小时内发送的信件数量。按照事件的顺序,我们将事件的数量添加到这个计数器中。通过监视计数器的变化,您可以检测何时超出了发送信件的限制。
如果邮件发送有时间限制,计数器会一直跟踪,直到事件序列结束。如果其中有无限多的邮件,则计数器会在有限的时间内进行跟踪,例如几年。
通过修改算法,我们可以估算出想要添加到现有邮件中的新邮件的数量。
例子
假设我们有20 个邮件列表,每个邮件列表每天发送一次信件。您将需要二十个生成器的内存,也就是说,需要的内存非常少。如果我们提前十年追踪冲突,事件总数将约为20 x 2 x 365 x 10 = 146,000。使用任何脚本语言,十四万六千个事件将在不到一秒的时间内被处理。