diff --git a/ruby/lib/jam_ruby/lib/em_helper.rb b/ruby/lib/jam_ruby/lib/em_helper.rb
index ba6e582e8..5867424ef 100644
--- a/ruby/lib/jam_ruby/lib/em_helper.rb
+++ b/ruby/lib/jam_ruby/lib/em_helper.rb
@@ -13,11 +13,15 @@ module JamWebEventMachine
@@log = Logging.logger[JamWebEventMachine]
+
+ # THIS WAS USED BY resque jobs needing EventMachine/AMQP, but it's no longer needed. It's useful code though
+
# starts amqp & eventmachine up first.
# and then calls your block.
# After the supplied block is done,
# waits until all EM tasks scheduled in the supplied block are done, or timeout
def self.run_wait_stop(timeout = 30, &blk)
+
JamWebEventMachine.run
thread = Thread.current
diff --git a/ruby/lib/jam_ruby/lib/stats.rb b/ruby/lib/jam_ruby/lib/stats.rb
index bb73931f5..c51a14ae1 100644
--- a/ruby/lib/jam_ruby/lib/stats.rb
+++ b/ruby/lib/jam_ruby/lib/stats.rb
@@ -1,5 +1,41 @@
+
require 'influxdb'
+# monkey patch InfluxDB client to clear the queue when asked to stop
+module InfluxDB
+ class Client
+ def stop!
+ @queue.clear if @queue
+ @stopped = true
+ end
+ end
+end
+
+module InfluxDB
+ class Worker
+ def spawn_threads!
+ NUM_WORKER_THREADS.times do |thread_num|
+ log :debug, "Spawning background worker thread #{thread_num}."
+
+ Thread.new do
+ Thread.current[:influxdb] = self.object_id
+
+ at_exit do
+ log :debug, "Thread exiting, bailing out (not flushing queue)"
+ end
+
+ while !client.stopped?
+ self.check_background_queue(thread_num)
+ sleep rand(SLEEP_INTERVAL)
+ end
+ end
+ end
+
+ end
+
+ end
+end
+
module JamRuby
class Stats
@@ -10,6 +46,7 @@ module JamRuby
def self.destroy!
if @client
+ @client.queue.clear if @client.queue
@client.stop!
end
end
diff --git a/ruby/lib/jam_ruby/resque/audiomixer.rb b/ruby/lib/jam_ruby/resque/audiomixer.rb
index 7ea7e7e55..cbe62d92e 100644
--- a/ruby/lib/jam_ruby/resque/audiomixer.rb
+++ b/ruby/lib/jam_ruby/resque/audiomixer.rb
@@ -20,13 +20,11 @@ module JamRuby
def self.perform(mix_id, postback_ogg_url, postback_mp3_url)
- JamWebEventMachine.run_wait_stop do
- audiomixer = AudioMixer.new()
- audiomixer.postback_ogg_url = postback_ogg_url
- audiomixer.postback_mp3_url = postback_mp3_url
- audiomixer.mix_id = mix_id
- audiomixer.run
- end
+ audiomixer = AudioMixer.new()
+ audiomixer.postback_ogg_url = postback_ogg_url
+ audiomixer.postback_mp3_url = postback_mp3_url
+ audiomixer.mix_id = mix_id
+ audiomixer.run
end
diff --git a/ruby/lib/jam_ruby/resque/quick_mixer.rb b/ruby/lib/jam_ruby/resque/quick_mixer.rb
index daddc1802..93704173f 100644
--- a/ruby/lib/jam_ruby/resque/quick_mixer.rb
+++ b/ruby/lib/jam_ruby/resque/quick_mixer.rb
@@ -19,12 +19,10 @@ module JamRuby
def self.perform(quick_mix_id, postback_mp3_url)
- JamWebEventMachine.run_wait_stop do
- audiomixer = QuickMixer.new
- audiomixer.postback_mp3_url = postback_mp3_url
- audiomixer.quick_mix_id = quick_mix_id
- audiomixer.run
- end
+ audiomixer = QuickMixer.new
+ audiomixer.postback_mp3_url = postback_mp3_url
+ audiomixer.quick_mix_id = quick_mix_id
+ audiomixer.run
end
diff --git a/ruby/lib/jam_ruby/resque/resque_hooks.rb b/ruby/lib/jam_ruby/resque/resque_hooks.rb
index 37685f0d8..9b27e7097 100644
--- a/ruby/lib/jam_ruby/resque/resque_hooks.rb
+++ b/ruby/lib/jam_ruby/resque/resque_hooks.rb
@@ -1,26 +1,53 @@
require 'resque'
+require 'resque-lonely_job'
-# https://devcenter.heroku.com/articles/forked-pg-connections
-Resque.before_fork do
- defined?(ActiveRecord::Base) and
- ActiveRecord::Base.connection.disconnect!
+ENV['FORK_PER_JOB'] = 'false'
- JamRuby::Stats.destroy!
+def shutdown
+ puts "Cleaning up resources..."
+ Stats.destroy!
+ EventMachine.stop_event_loop
+ puts "Terminated!"
+ exit!
end
-Resque.after_fork do
- defined?(ActiveRecord::Base) and
- ActiveRecord::Base.establish_connection
+Resque.before_first_fork do
+ JamWebEventMachine.start
+ #ActiveRecord::Base.establish_connection
config = {
influxdb_database: APP_CONFIG.influxdb_database,
influxdb_username: APP_CONFIG.influxdb_username,
influxdb_password: APP_CONFIG.influxdb_password,
influxdb_hosts: APP_CONFIG.influxdb_hosts,
influxdb_port: APP_CONFIG.influxdb_port,
- influxdb_async: false # if we use async=true, the forked job will die before the stat is sent
+ influxdb_async: true # if we use async=true, the forked job will die before the stat is sent
}
+
+ # handle these events and force a shutdown. this is required I think due to influxdb-client.
+ Signal.trap("TERM") do
+ shutdown
+ end
+ Signal.trap("INT") do
+ shutdown
+ end
+
JamRuby::Stats.init(config)
+
+end
+# https://devcenter.heroku.com/articles/forked-pg-connections
+Resque.before_fork do
+
+ #defined?(ActiveRecord::Base) and
+ # ActiveRecord::Base.connection.disconnect!
+
+ #JamRuby::Stats.destroy!
+end
+
+Resque.after_fork do
+ #defined?(ActiveRecord::Base) and
+ # ActiveRecord::Base.establish_connection
+
end
# for jobs that do not extend lonely job, just extend this module and get stats
diff --git a/ruby/lib/jam_ruby/resque/scheduled/active_music_session_cleaner.rb b/ruby/lib/jam_ruby/resque/scheduled/active_music_session_cleaner.rb
index e700a0427..0b12cc0ce 100644
--- a/ruby/lib/jam_ruby/resque/scheduled/active_music_session_cleaner.rb
+++ b/ruby/lib/jam_ruby/resque/scheduled/active_music_session_cleaner.rb
@@ -22,11 +22,9 @@ module JamRuby
def self.perform
@@log.debug("ActiveMusicSessionCleaner waking up")
- JamWebEventMachine.run_wait_stop do
- cleaner = ActiveMusicSessionCleaner.new
- cleaner.interval = "INTERVAL '1 minute'"
- cleaner.run
- end
+ cleaner = ActiveMusicSessionCleaner.new
+ cleaner.interval = "INTERVAL '1 minute'"
+ cleaner.run
@@log.debug("ActiveMusicSessionCleaner done")
end
diff --git a/ruby/lib/jam_ruby/resque/scheduled/icecast_source_check.rb b/ruby/lib/jam_ruby/resque/scheduled/icecast_source_check.rb
index b81c5b992..6b18cb633 100644
--- a/ruby/lib/jam_ruby/resque/scheduled/icecast_source_check.rb
+++ b/ruby/lib/jam_ruby/resque/scheduled/icecast_source_check.rb
@@ -23,9 +23,7 @@ module JamRuby
def self.perform
@@log.debug("waking up")
- JamWebEventMachine.run_wait_stop do
IcecastSourceCheck.new.run
- end
@@log.debug("done")
end
diff --git a/ruby/lib/jam_ruby/resque/scheduled/music_session_scheduler.rb b/ruby/lib/jam_ruby/resque/scheduled/music_session_scheduler.rb
index cd706285a..6fa751ef9 100644
--- a/ruby/lib/jam_ruby/resque/scheduled/music_session_scheduler.rb
+++ b/ruby/lib/jam_ruby/resque/scheduled/music_session_scheduler.rb
@@ -19,9 +19,7 @@ module JamRuby
def self.perform
@@log.debug("MusicSessionScheduler waking up")
- JamWebEventMachine.run_wait_stop do
- MusicSessionScheduler.new.run
- end
+ MusicSessionScheduler.new.run
@@log.debug("MusicSessionScheduler done")
end
diff --git a/ruby/lib/jam_ruby/resque/scheduled/unused_music_notation_cleaner.rb b/ruby/lib/jam_ruby/resque/scheduled/unused_music_notation_cleaner.rb
index 9fb3e307f..5955b1ec3 100644
--- a/ruby/lib/jam_ruby/resque/scheduled/unused_music_notation_cleaner.rb
+++ b/ruby/lib/jam_ruby/resque/scheduled/unused_music_notation_cleaner.rb
@@ -20,9 +20,7 @@ module JamRuby
def self.perform
@@log.debug("waking up")
- JamWebEventMachine.run_wait_stop do
- UnusedMusicNotationCleaner.new.run
- end
+ UnusedMusicNotationCleaner.new.run
@@log.debug("done")
end
diff --git a/ruby/spec/spec_helper.rb b/ruby/spec/spec_helper.rb
index 73e9a3384..890a195c0 100644
--- a/ruby/spec/spec_helper.rb
+++ b/ruby/spec/spec_helper.rb
@@ -12,6 +12,10 @@ require 'uses_temp_files'
require 'resque_spec'
require 'resque_failed_job_mailer'
+# to prevent embedded resque code from forking
+ENV['FORK_PER_JOB'] = 'false'
+
+
# recreate test database and migrate it
SpecDb::recreate_database
diff --git a/web/app/assets/javascripts/jquery.listenbroadcast.js b/web/app/assets/javascripts/jquery.listenbroadcast.js
index 349305b57..66c20d850 100644
--- a/web/app/assets/javascripts/jquery.listenbroadcast.js
+++ b/web/app/assets/javascripts/jquery.listenbroadcast.js
@@ -81,7 +81,7 @@
if($audio.length == 0) {
$audio =
$('')
$parent.append($audio)
audioDomElement = $audio.get(0);
@@ -105,7 +105,7 @@
if(!response.mount) {
transition(PlayStateSessionOver);
destroy();
- }
+ }
else {
audioDomElement.play();
@@ -164,9 +164,15 @@
audioDomElement.load();
var $parent = $audio.parent();
$audio.remove();
- $parent.append('');
- $audio = $('audio', $parent);
+ $audio = $('')
$audio.append(originalSource);
+ var $sources = $audio.find('source')
+ $.each($sources, function(i, source) {
+ var $source = $(source);
+ var bustedSource = cacheBustedSrc($source.attr('data-audio-src'))
+ $source.attr('src', bustedSource)
+ })
+ $parent.append($audio);
audioDomElement = $audio.get(0);
audioBind();
logger.log("recreated audio element ")
@@ -225,6 +231,9 @@
else {
// tell audio to stop/start, in attempt to retry
//audioDomElement.pause();
+
+ recreateAudioElement();
+
audioDomElement.load();
if(needsCanPlayGuard()) {
$audio.bind('canplay', function() {
@@ -443,7 +452,12 @@
// we have cause to believe the session is done; check against the server
if(refresh) {
- checkServer();
+ checkServer()
+ .done(function(response) {
+ if(!response.mount) {
+ transition(PlayStateSessionOver);
+ destroy();
+ }})
}
}
@@ -634,6 +648,7 @@
function openBubble() {
checkServer().done(function(response) {
+
var mountId = response.mount ? response.mount.id : null
if(mountId) {
@@ -648,6 +663,10 @@
}
else {
mountInfo = null;
+
+ transition(PlayStateSessionOver);
+ destroy();
+
context.JK.app.layout.notify('This session can not currently broadcast')
}
})
@@ -679,6 +698,11 @@
})
}
}
+
+ function cacheBustedSrc(src) {
+ return src + '?cache-buster=' + new Date().getTime();
+ }
+
function initialize() {
@@ -690,6 +714,7 @@
fanAccess = $parent.attr('fan-access') === 'true' // coerce to boolean
if(lazyAudioInit) {
+ // save the original src element (without any cache bust)
audioSrc = $parent.attr('data-audio-src');
if(audioSrc === null) throw 'data-audio-src must be specified in $parentElement';
audioType = $parent.attr('data-audio-type');
@@ -709,7 +734,17 @@
}
if(!lazyAudioInit) {
+ var $sources = $audio.find('source')
+ $.each($sources, function(i, source) {
+ var $source = $(source);
+ // save original src value (before cache bust)
+ $source.attr('data-audio-src', $source.attr('src'))
+
+ var bustedSource = cacheBustedSrc($source.attr('data-audio-src'))
+ $source.attr('src', bustedSource)
+ })
audioDomElement = $audio.get(0);
+
audioBind();
}
diff --git a/web/app/assets/javascripts/sessionList.js b/web/app/assets/javascripts/sessionList.js
index 80507b011..46f32fcad 100644
--- a/web/app/assets/javascripts/sessionList.js
+++ b/web/app/assets/javascripts/sessionList.js
@@ -40,7 +40,7 @@
if(data.isEnd) {
$listenText.text('Listen').removeClass('statusing')
- stopPlay();
+ stopPlay($listenLink);
}
if(data.isSessionOver) {
@@ -60,8 +60,9 @@
function togglePlay() {
var $listenLink = $(this)
- var $listenText = $('.listen-link-text', $listenLink);
- var $listenDetails = $('.listen-link-details', $listenLink);
+ var $parent = $listenLink.closest('.action-links');
+ var $listenText = $('.listen-link-text', $parent);
+ var $listenDetails = $('.listen-link-details', $parent);
if($listenLink.data('listenbroadcast-playstate') == 'playing') {
$listenText.text('Listen')
$listenDetails.removeClass('statusing')
diff --git a/web/app/assets/javascripts/web/sessions.js b/web/app/assets/javascripts/web/sessions.js
index 397795585..b39e16686 100644
--- a/web/app/assets/javascripts/web/sessions.js
+++ b/web/app/assets/javascripts/web/sessions.js
@@ -106,7 +106,7 @@
$controls.bind('statechange.listenBroadcast', stateChange);
context.JK.prettyPrintElements($('time.duration').show());
context.JK.TickDuration(null);
- $playButton.click(togglePlay);
+ $playButton.click(startPlay);
sessionId = musicSessionId;
diff --git a/web/config/environment.rb b/web/config/environment.rb
index 3807f21a1..3463d46ae 100644
--- a/web/config/environment.rb
+++ b/web/config/environment.rb
@@ -3,10 +3,14 @@ require File.expand_path('../application', __FILE__)
Mime::Type.register "audio/ogg", :audio_ogg
+# to prevent embedded resque code from forking
+ENV['FORK_PER_JOB'] = 'false'
+
# assign globals
APP_CONFIG = Rails.application.config
Stats.client = InfluxDB::Rails.client
+
# Initialize the rails application
SampleApp::Application.initialize!
diff --git a/web/lib/tasks/start.rake b/web/lib/tasks/start.rake
index b53b25f6c..2efd63076 100644
--- a/web/lib/tasks/start.rake
+++ b/web/lib/tasks/start.rake
@@ -4,6 +4,7 @@
task :all_jobs do
Rake::Task['environment'].invoke
+ ENV['FORK_PER_JOB'] = 'false'
ENV['QUEUE'] = ENV['QUEUE'] || '*'
Rake::Task['resque:work'].invoke
end
@@ -12,6 +13,7 @@ end
task :audiomixer do
Rake::Task['environment'].invoke
+ ENV['FORK_PER_JOB'] = 'false'
ENV['QUEUE'] = 'audiomixer'
Rake::Task['resque:work'].invoke
end
@@ -20,6 +22,7 @@ end
task :icecast do
Rake::Task['environment'].invoke
+ ENV['FORK_PER_JOB'] = 'false'
ENV['QUEUE'] = 'icecast'
Rake::Task['resque:work'].invoke
end
@@ -29,6 +32,7 @@ end
task :odd_jobs do
Rake::Task['environment'].invoke
+ ENV['FORK_PER_JOB'] = 'false'
ENV['QUEUE'] = '*,!icecast,!audiomixer'
Rake::Task['resque:work'].invoke
end
diff --git a/web/spec/factories.rb b/web/spec/factories.rb
index a1d3a1ef8..26756e206 100644
--- a/web/spec/factories.rb
+++ b/web/spec/factories.rb
@@ -86,7 +86,6 @@ FactoryGirl.define do
before(:create) do |user, evaluator|
if evaluator.specific_instruments
evaluator.specific_instruments.each do |instrument|
- puts "burp: "
user.musician_instruments << FactoryGirl.build(:musician_instrument, user: user, instrument: instrument)
end
else
diff --git a/web/spec/features/create_session_spec.rb b/web/spec/features/create_session_spec.rb
index b431d8d25..8bcd553a7 100644
--- a/web/spec/features/create_session_spec.rb
+++ b/web/spec/features/create_session_spec.rb
@@ -149,7 +149,7 @@ describe "Create Session", :js => true, :type => :feature, :capybara_feature =>
btn = first('#btn-alert-ok')# accept the 'If you start this session now, the scheduled start time...'
btn.trigger(:click) if btn
-
+
expect(page).to have_selector('h2', text: 'my tracks')
find('#session-screen .session-mytracks .session-track')
end
diff --git a/web/spec/spec_helper.rb b/web/spec/spec_helper.rb
index 936471e11..09606e087 100644
--- a/web/spec/spec_helper.rb
+++ b/web/spec/spec_helper.rb
@@ -67,6 +67,9 @@ Thread.new {
end
}
+# to prevent embedded resque code from forking
+ENV['FORK_PER_JOB'] = 'false'
+
bputs "before load websocket server"
current = Thread.current