You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从Solid Queue中删除指定的定时任务?

解决Solid Queue中重复生日提醒定时任务的问题

核心思路

更新亲友生日时,先清理对应未执行的旧定时任务,再创建新的任务,避免重复投递邮件。

具体实现方案

方案1:记录任务ID到关联模型(推荐)

在亲友模型中新增reminder_job_id字段,存储对应定时任务的ID,更新时直接通过ID定位删除旧任务:

  1. 生成迁移添加字段:
rails generate migration AddReminderJobIdToRelatives reminder_job_id:string
rails db:migrate
  1. 创建任务时记录ID:
# 亲友模型的创建/更新回调中
def schedule_birthday_reminder
  # 删除旧任务(如果存在)
  if reminder_job_id.present?
    SolidQueue::Job.find_by(id: reminder_job_id)&.destroy
  end

  # 计算用户时区下的生日午夜时间
  reminder_time = user.timezone.local_to_utc(Date.today.change(month: birthdate.month, day: birthdate.day).beginning_of_day)
  # 调度新任务并记录ID
  job = BirthdayReminderJob.set(wait_until: reminder_time).perform_later(user, self)
  update(reminder_job_id: job.job_id)
end
  1. 在亲友模型中设置回调触发:
class Relative < ApplicationRecord
  belongs_to :user
  after_save :schedule_birthday_reminder, if: :birthdate_changed?
end

方案2:通过任务参数查询删除

如果不想新增字段,可以通过Solid Queue的任务参数查询定位对应任务,适合数据库支持JSON查询的场景(如PostgreSQL):

def schedule_birthday_reminder
  # 查询并删除未执行的旧任务
  old_jobs = SolidQueue::Job.where(queue_name: 'default') # 替换为你的队列名
                            .where("arguments ->> 'relative_id' = ?", id.to_s)
                            .where("arguments ->> 'user_id' = ?", user.id.to_s)
                            .where(status: [:pending, :scheduled]) # 只清理未执行的任务
  old_jobs.destroy_all

  # 创建新任务
  reminder_time = user.timezone.local_to_utc(Date.today.change(month: birthdate.month, day: birthdate.day).beginning_of_day)
  BirthdayReminderJob.set(wait_until: reminder_time).perform_later(user, self)
end

注意:如果是MySQL,JSON查询语法略有不同,可使用JSON_EXTRACT(arguments, '$.relative_id') = ?替代。

额外注意事项

  • 确保只删除未执行的任务(pending或scheduled状态),已执行的任务无需处理。
  • 如果生日是每年重复提醒,需要考虑每年重新调度任务的逻辑(比如每年年初重新生成下一年的任务),避免任务过期后无法触发。

内容的提问来源于stack exchange,提问作者Juzer Shakir

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 04:57:06