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.