问题描述
在我的 Rails 应用程序中,用户可以取消订阅,这会触发一个函数,在他们的 current_billing_period_end
处降级他们的帐户(此变量由支付提供商的 API 提供)。例如,用户在 4 月 12 日取消订阅,但在 3 月 1 日之前的订阅有效。因此,数据库中该用户的 premium
条目应仅在 3 月 1 日设置为 false
。
我已经使用 Resque 和 Resque-Scheduler 实现了一个可行的解决方案,但现在想知道这是否有点矫枉过正?
我可以在订阅取消时为用户设置一个 subscription_end_date
数据库条目并将其设置为 current_billing_period_end
,然后每当用户进行身份验证时我都会运行
if user.premium != false && user.subscription_end_date == Time.Now.strftime("%Y-%m-%d")
user.premium = false
user.save
end
但是,这意味着每次用户进行身份验证/前端检查用户是否通过我的 API 登录时都运行该代码段。
我的问题是:实现该功能的更好方法是什么? Resque 解决方案似乎更干净,但我想知道它是否对我在这里尝试实现的目标来说太过分了。我以前从未与 Resque 合作过,如果这是我不必在生产中维护的另一件事,我会很高兴。
解决方法
不要那样做。
将许多工作安排在几天或几周后是一种糟糕的设计,尤其是在执行关键任务时。
为什么?
主要是因为计划作业的日期没有存储在您的应用程序数据库中,而是另一个,大部分时间存储在 Redis 中。在大多数情况下,它不包含在备份中。因此,在您需要恢复备份的那一天,您将丢失所有挂起的预定作业。在最后一个订阅期结束时处于待处理状态的所有帐户可能会保持打开状态。
最安全的解决方案是依靠保存订阅日期的实际结束日期的数据库字段。让我们将其命名为 subscription_ends_on
。如果您的用户在 4 月 12 日退订,请将 subscription_ends_on
设置为值“March 1rst”。
然后您创建一个每天午夜运行的后台作业,并取消订阅 subscription_ends_on
不为空且小于或等于今天的所有帐户。