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

点击按钮重启Rails ActiveJob/Sidekiq的实现方案咨询

搞定Rails播放任务的重启功能

嘿,我明白你想要实现的是——让正在循环播放歌曲的PlaylistJob能被重启,对吧?毕竟直接重复调用play方法的话,很可能会同时跑多个无限循环的Job,那可就乱套了。下面给你一套实用的方案:

第一步:给Job加个“停止开关”

Rails的Active Job本身没有直接终止运行中Job的方法,所以我们用Redis做个简单的信号标识,让Job自己检测要不要停止循环。修改你的PlaylistJob:

class PlaylistJob < ApplicationJob
  queue_as :default

  def perform(playlist)
    loop do
      # 检查有没有停止信号,有的话立刻退出循环
      break if Redis.current.get("playlist_stop:#{playlist.id}")

      # 这里放你原来的播放逻辑——比如从playlist里取歌播放的代码
      play_next_track(playlist)

      # 假设每首歌播放间隔5秒,根据你的实际情况调整
      sleep 5
    end

    # 任务结束后记得把停止信号删掉,避免影响下次启动
    Redis.current.del("playlist_stop:#{playlist.id}")
  end

  private

  def play_next_track(playlist)
    # 你的播放逻辑实现,比如从playlist.songs里取下一首播放
  end
end

第二步:在控制器加restart动作

接下来写一个restart方法,先给当前运行的Job发停止信号,等它退出后再启动新的播放任务:

class PlaylistsController < ApplicationController
  # 你现有的play方法...
  def play
    if @playlist
      # 注意:flushall会清空整个Redis!如果你的Redis还有其他用途,换成只删相关键
      # 比如改成 Redis.current.del("playlist_stop:*")
      system "redis-cli flushall"
      @playlist.update(current: true)
      Playlist.where.not(id: @playlist.id).update_all(current: false)
      PlaylistJob.perform_later(@playlist)
      # 这里加你的响应逻辑,比如redirect或者render
    end
  end

  def restart
    @playlist = Playlist.find(params[:id])
    # 给当前播放任务发停止信号
    Redis.current.set("playlist_stop:#{@playlist.id}", "1")

    # 稍微等一下,让旧Job有时间退出(时间根据你的循环间隔调整)
    sleep 2

    # 调用play方法启动新任务,或者直接把play里的逻辑复制过来也行
    play
    redirect_to playlists_path, notice: "播放任务已经重启啦!"
  end
end

第三步:配置路由

最后在config/routes.rb里加上restart的路由,这样前端就能调用了:

resources :playlists do
  member do
    post :play
    post :restart
  end
end

几个小提醒

  • 关于redis-cli flushall:这个操作会清空整个Redis数据库,如果你的应用还用Redis存缓存、其他Job数据之类的,一定要改成精准删除相关键,比如Redis.current.del("playlist_stop:*"),别把其他数据搞丢了。
  • 如果你的后台用的是Sidekiq,也可以用Sidekiq的API直接终止Job,但用Redis信号的方式更通用,不管你用什么Active Job适配器都能生效。
  • 前端可以给重启按钮加个确认提示,比如<%= button_to "重启播放", restart_playlist_path(@playlist), data: { confirm: "确定要重启吗?" } %>,避免误操作。

这样操作之后,点击重启按钮,就能先停掉当前的播放循环,再重新启动新的播放任务啦~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 04:05:10