From 50595d155c79708394b4b88aa3cbb911153d0ff4 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Mon, 13 Jan 2014 13:44:28 +0000 Subject: [PATCH] * VRFS-801 - closer to all fixes required for mixing --- ruby/lib/jam_ruby/models/icecast_limit.rb | 1 - ruby/lib/jam_ruby/models/mix.rb | 27 +++++++---- ruby/lib/jam_ruby/models/recorded_track.rb | 14 +++--- ruby/lib/jam_ruby/resque/audiomixer.rb | 48 +++++++++++-------- .../jam_ruby/models/icecast_limit_spec.rb | 2 - .../jam_ruby/models/recorded_track_spec.rb | 2 +- ruby/spec/jam_ruby/resque/audiomixer_spec.rb | 16 +++++++ web/app/controllers/api_mixes_controller.rb | 4 +- web/config/initializers/eventmachine.rb | 4 +- 9 files changed, 75 insertions(+), 43 deletions(-) diff --git a/ruby/lib/jam_ruby/models/icecast_limit.rb b/ruby/lib/jam_ruby/models/icecast_limit.rb index 2e006c7e1..02251b794 100644 --- a/ruby/lib/jam_ruby/models/icecast_limit.rb +++ b/ruby/lib/jam_ruby/models/icecast_limit.rb @@ -14,7 +14,6 @@ module JamRuby def init - puts "Init self.client #{self.clients}" self.clients ||= 10000 self.sources ||= 1000 self.queue_size ||= 102400 diff --git a/ruby/lib/jam_ruby/models/mix.rb b/ruby/lib/jam_ruby/models/mix.rb index 8ab73473d..71824cdb5 100644 --- a/ruby/lib/jam_ruby/models/mix.rb +++ b/ruby/lib/jam_ruby/models/mix.rb @@ -17,14 +17,23 @@ module JamRuby mix.recording = recording mix.manifest = manifest.to_json mix.save - mix.url = construct_filename(recording.id, mix.id) + mix.url = construct_filename(mix.created_at, recording.id, mix.id) if mix.save - Resque.enqueue(AudioMixer, mix.id, mix.sign_put) + mix.enqueue end mix end + def enqueue + Resque.enqueue(AudioMixer, self.id, self.sign_put) + end + + def can_download?(some_user) + !ClaimedRecording.find_by_user_id_and_recording_id(some_user.id, recording_id).nil? + end + + def errored(reason, detail) self.error_reason = reason self.error_detail = detail @@ -45,7 +54,7 @@ module JamRuby end def s3_url - s3_manager.s3_url(filename) + s3_manager.s3_url(url) end def is_completed @@ -54,11 +63,11 @@ module JamRuby def sign_url(expiration_time = 120) # expire link in 1 minute--the expectation is that a client is immediately following this link - s3_manager.sign_url(filename, {:expires => expiration_time, :response_content_type => 'audio/ogg', :secure => false}) + s3_manager.sign_url(self.url, {:expires => expiration_time, :response_content_type => 'audio/ogg', :secure => false}) end def sign_put(expiration_time = 3600 * 24) - s3_manager.sign_url(filename, {:expires => expiration_time, :content_type => 'audio/ogg', :secure => false}, :put) + s3_manager.sign_url(self.url, {:expires => expiration_time, :content_type => 'audio/ogg', :secure => false}, :put) end private @@ -69,14 +78,12 @@ module JamRuby def filename # construct a path for s3 - Mix.construct_filename(self.recording.id, self.id) + Mix.construct_filename(self.created_at, self.recording.id, self.id) end - def self.construct_filename(recording_id, id) + def self.construct_filename(created_at, recording_id, id) raise "unknown ID" unless id - "recordings/#{recording_id}/mix-#{id}.ogg" + "recordings/#{created_at.strftime('%m-%d-%Y')}/#{recording_id}/mix-#{id}.ogg" end - - end end diff --git a/ruby/lib/jam_ruby/models/recorded_track.rb b/ruby/lib/jam_ruby/models/recorded_track.rb index 90731961a..b67ec410d 100644 --- a/ruby/lib/jam_ruby/models/recorded_track.rb +++ b/ruby/lib/jam_ruby/models/recorded_track.rb @@ -86,13 +86,13 @@ module JamRuby recorded_track.next_part_to_upload = 0 recorded_track.file_offset = 0 recorded_track.save - recorded_track.url = construct_filename(recording.id, track.client_track_id) + recorded_track.url = construct_filename(recorded_track.created_at, recording.id, track.client_track_id) recorded_track.save recorded_track end def sign_url(expiration_time = 120) - s3_manager.sign_url(url, {:expires => expiration_time, :response_content_type => 'audio/ogg', :secure => false}) + s3_manager.sign_url(self.url, {:expires => expiration_time, :response_content_type => 'audio/ogg', :secure => false}) end def upload_start(length, md5) @@ -128,7 +128,7 @@ module JamRuby end def upload_sign(content_md5) - s3_manager.upload_sign(filename, content_md5, next_part_to_upload, upload_id) + s3_manager.upload_sign(url, content_md5, next_part_to_upload, upload_id) end def upload_part_complete(part, offset) @@ -154,17 +154,17 @@ module JamRuby private def delete_s3_files - s3_manager.delete(filename) + s3_manager.delete(url) end def filename # construct a path for s3 - RecordedTrack.construct_filename(self.recording.id, self.client_track_id) + RecordedTrack.construct_filename(self.created_at, self.recording.id, self.client_track_id) end - def self.construct_filename(recording_id, client_track_id) + def self.construct_filename(created_at, recording_id, client_track_id) raise "unknown ID" unless client_track_id - "recordings/#{recording_id}/track-#{client_track_id}.ogg" + "recordings/#{created_at.strftime('%m-%d-%Y')}/#{recording_id}/track-#{client_track_id}.ogg" end end end diff --git a/ruby/lib/jam_ruby/resque/audiomixer.rb b/ruby/lib/jam_ruby/resque/audiomixer.rb index a8fedade0..ce5033caa 100644 --- a/ruby/lib/jam_ruby/resque/audiomixer.rb +++ b/ruby/lib/jam_ruby/resque/audiomixer.rb @@ -49,6 +49,7 @@ module JamRuby raise "no timeline specified" unless @manifest[:timeline] raise "no recording_id specified" unless @manifest[:recording_id] raise "no mix_id specified" unless @manifest[:mix_id] + end @@ -79,9 +80,9 @@ module JamRuby @error_detail = "url #{filename}, error=#{e}" raise e end - end + @@log.debug("downloaded #{download_filename}") filename = download_filename file[:filename] = download_filename end @@ -103,7 +104,7 @@ module JamRuby # write the manifest object to file, to pass into audiomixer def prepare_manifest - @manifest_file = Dir::Tmpname.make_tmpname( ["#{Dir.tmpdir}/audiomixer-manifest-#{@manifest['recording_id']}", '.json'], nil) + @manifest_file = Dir::Tmpname.make_tmpname( ["#{Dir.tmpdir}/audiomixer-manifest-#{@manifest[:recording_id]}", '.json'], nil) File.open(@manifest_file,"w") do |f| f.write(@manifest.to_json) end @@ -113,7 +114,7 @@ module JamRuby # make a suitable location to store the output mix, and pass the chosen filepath into the manifest def prepare_output - @output_filename = Dir::Tmpname.make_tmpname( ["#{Dir.tmpdir}/audiomixer-output-#{@manifest['recording_id']}", '.ogg'], nil) + @output_filename = Dir::Tmpname.make_tmpname( ["#{Dir.tmpdir}/audiomixer-output-#{@manifest[:recording_id]}", '.ogg'], nil) # update manifest so that audiomixer writes here @manifest[:output][:filename] = @output_filename @@ -123,7 +124,7 @@ module JamRuby # make a suitable location to store an output error file, which will be populated on failure to help diagnose problems. def prepare_error_out - @error_out_filename = Dir::Tmpname.make_tmpname( ["#{Dir.tmpdir}/audiomixer-error-out-#{@manifest['recording_id']}", '.ogg'], nil) + @error_out_filename = Dir::Tmpname.make_tmpname( ["#{Dir.tmpdir}/audiomixer-error-out-#{@manifest[:recording_id]}", '.ogg'], nil) # update manifest so that audiomixer writes here @manifest[:error_out] = @error_out_filename @@ -203,6 +204,12 @@ module JamRuby mix = Mix.find(mix_id) begin + # bailout check + if mix.completed + @@log.debug("mix is already completed. bailing") + return + end + @manifest = symbolize_keys(JSON.parse(mix.manifest)) @manifest[:mix_id] = mix_id # slip in the mix_id so that the job can add it to the ogg comments @@ -215,25 +222,16 @@ module JamRuby # write the manifest to file, so that it can be passed to audiomixer as an filepath argument prepare - result = execute(@manifest_file) + execute(@manifest_file) - if result - if $? == 0 - postback - post_success(mix) - @@log.info("audiomixer job successful. mix_id #{mix_id}") - else - parse_error_out - error_msg = "audiomixer job failed status=#{$?} error_reason=#{error_reason} error_detail=#{error_detail}" - @@log.info(error_msg) - raise error_msg - end + if $? == 0 + postback + post_success(mix) + @@log.info("audiomixer job successful. mix_id #{mix_id}") else - @@log.error("unable to find audiomixer") + parse_error_out error_msg = "audiomixer job failed status=#{$?} error_reason=#{error_reason} error_detail=#{error_detail}" @@log.info(error_msg) - @error_reason = "unable-find-appmixer" - @error_detail = APP_CONFIG.audiomixer_path raise error_msg end rescue Exception => e @@ -250,8 +248,20 @@ module JamRuby private def execute(manifest_file) + + unless File.exist? APP_CONFIG.audiomixer_path + @@log.error("unable to find audiomixer") + error_msg = "audiomixer job failed status=#{$?} error_reason=#{error_reason} error_detail=#{error_detail}" + @@log.info(error_msg) + @error_reason = "unable-find-appmixer" + @error_detail = APP_CONFIG.audiomixer_path + raise error_msg + end + + audiomixer_cmd = "#{APP_CONFIG.audiomixer_path} #{manifest_file}" + @@log.debug("executing #{audiomixer_cmd}") system(audiomixer_cmd) diff --git a/ruby/spec/jam_ruby/models/icecast_limit_spec.rb b/ruby/spec/jam_ruby/models/icecast_limit_spec.rb index f23378430..ca100f8b8 100644 --- a/ruby/spec/jam_ruby/models/icecast_limit_spec.rb +++ b/ruby/spec/jam_ruby/models/icecast_limit_spec.rb @@ -11,11 +11,9 @@ describe IcecastLimit do it "save" do limit.clients = 9999 limit.save - puts limit.inspect #limit.dumpXml limit.errors.any?.should be_false v = IcecastLimit.find(limit.id) - puts v.inspect end =begin diff --git a/ruby/spec/jam_ruby/models/recorded_track_spec.rb b/ruby/spec/jam_ruby/models/recorded_track_spec.rb index ed2b74701..c8e3b2c8a 100644 --- a/ruby/spec/jam_ruby/models/recorded_track_spec.rb +++ b/ruby/spec/jam_ruby/models/recorded_track_spec.rb @@ -42,7 +42,7 @@ describe RecordedTrack do it "gets a url for the track" do @recorded_track = RecordedTrack.create_from_track(@track, @recording) @recorded_track.save.should be_true - @recorded_track.url.should == "recordings/#{@recording.id}/track-#{@track.client_track_id}.ogg" + @recorded_track.url.should == "recordings/#{@recorded_track.created_at.strftime('%m-%d-%Y')}/#{@recording.id}/track-#{@track.client_track_id}.ogg" end it "signs url" do diff --git a/ruby/spec/jam_ruby/resque/audiomixer_spec.rb b/ruby/spec/jam_ruby/resque/audiomixer_spec.rb index c74f18dc3..a4058e780 100644 --- a/ruby/spec/jam_ruby/resque/audiomixer_spec.rb +++ b/ruby/spec/jam_ruby/resque/audiomixer_spec.rb @@ -222,6 +222,22 @@ describe AudioMixer do @mix.length.should == 0 @mix.md5.should == 'd41d8cd98f00b204e9800998ecf8427e' # that's the md5 of a touched file, which is what the stubbed :execute does end + + it "bails out with no error if already completed" do + with_resque do + @mix = Mix.schedule(@recording, local_files_manifest) + end + + @mix.reload + @mix.completed.should be_true + + with_resque do + @mix.enqueue + end + + @mix.reload + @mix.completed.should be_true + end end end diff --git a/web/app/controllers/api_mixes_controller.rb b/web/app/controllers/api_mixes_controller.rb index a04687fb0..816968e8f 100644 --- a/web/app/controllers/api_mixes_controller.rb +++ b/web/app/controllers/api_mixes_controller.rb @@ -39,7 +39,9 @@ class ApiMixesController < ApiController end def download - # XXX: needs to permission check + @mix = Mix.find(params[:id]) + raise PermissionError, "You can only download a mix you didn't claim" unless @mix.can_download? current_user + redirect_to @mix.sign_url end diff --git a/web/config/initializers/eventmachine.rb b/web/config/initializers/eventmachine.rb index 3a194ee35..f09eb1811 100644 --- a/web/config/initializers/eventmachine.rb +++ b/web/config/initializers/eventmachine.rb @@ -35,7 +35,7 @@ module JamWebEventMachine end end - if Rails.application.config.websocket_gateway_enable + if Rails.application.config.websocket_gateway_enable && !$rails_rake_task Thread.new { JamWebsockets::Server.new.run :port => Rails.application.config.websocket_gateway_port, :emwebsocket_debug => Rails.application.config.websocket_gateway_internal_debug, @@ -82,4 +82,4 @@ module JamWebEventMachine end end -JamWebEventMachine.start unless $rails_rake_task +JamWebEventMachine.start