2

I would like to implement a restart job in my rails app. First, My app is very simple. It just plays song form db using a Job and I perform the song playing n the job using loop for endless playback. I have Playlists controller. In which in this controller there is this play method definition. Code is below:

def play
        if @playlist
            system "redis-cli flushall"
            @playlist.update(current: true)
            Playlist.where.not(id: @playlist.id).update_all(current: false)

            PlaylistJob.perform_later(@playlist)

            @http_status = 200
            @http_response = Playlist.all
            @http_message = "#{@playlist.name} is now playing...."
        else
            @http_status = 404
            @http_error = { playlist: 'not found' }
            @http_message = "Playlist not found"
        end

        render :json => api_format(0, @http_response , @http_error ,@http_message) , :status => @http_status
end

My logic is, in Playlist model, there can be only 1 row of songs which can be only set in true and others will be false. so after updating the record into current: true, the ActiveJob which handles the playback will perform_later(). The job has this code:

class PlaylistJob < ApplicationJob
  queue_as :default

  def perform(data)# Do something later
    system "redis-cli flushall"

    ActionCable.server.broadcast 'PlaylistChannel', data
#data is the playlist passed from `PlaylistController`



    loop do # endless loop to peform streaming

        current_playlist.songs.order('created_at ASC').each do |song|
          File.open("public/#{song.track_data.url}") do |file| # open the public URL
            m = ShoutMetadata.new # add metadata
            m.add 'filename', song.track_data.url
            m.add 'title', song.title
            m.add 'artist', song.singer
            $s.metadata = m

            while data = file.read(16384) # read the portions of the file
              $s.send data # send portion of the file to Icecast
              $s.sync
            end
          end
          prev_song = song # the song has finished playing
        end
    end # end of the endless loop
end

As you can see, I am using ActionCable to get the passed playlist in realtime and update the currently playlist playing but every time it is executed, The playlist does not stop and only continue playing. How do I stop the active job here? I have read that once Job is already performing and is not enqueued, It cant be stop. Help Please. Or there is a better logic that can be implemented? Thank you.

PS: The ActionCable is performing well so I did not include the code in this post. I am asking on how to stop the job so that the next playlist which the user clicks on the frontend button will play and the current playlist playing(using background job sidekiq) will stop. thank you.

Welp
  • 357
  • 1
  • 5
  • 17
  • what does this line exactly do/mean? `while data = file.read(16384)` – lacostenycoder Mar 25 '18 at 08:04
  • 1
    If you're running an endless loop, you have to implement some code to break the loop and/or kill the job. If you use Sidekiq they give examples of how to implement this here: https://github.com/mperham/sidekiq/wiki/FAQ#how-do-i-cancel-a-sidekiq-job also see https://stackoverflow.com/questions/24180899/rails-cancelling-a-scheduled-job-in-sidekiq#24189112 – lacostenycoder Mar 25 '18 at 08:14

0 Answers0