* fixes for multiple issues: VRFS-2587 - no forking in resque, VRFS-2586 - fix influxdb client's shutdown behavior, VRFS-2585 - firefox cache busting

This commit is contained in:
Seth Call 2014-12-31 20:39:22 -06:00
parent d901c3a498
commit 71399dcaa7
18 changed files with 152 additions and 46 deletions

View File

@ -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

View File

@ -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

View File

@ -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
end

View File

@ -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
end

View File

@ -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

View File

@ -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
@@log.debug("ActiveMusicSessionCleaner done")
end

View File

@ -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

View File

@ -19,9 +19,7 @@ module JamRuby
def self.perform
@@log.debug("MusicSessionScheduler waking up")
JamWebEventMachine.run_wait_stop do
MusicSessionScheduler.new.run
end
@@log.debug("MusicSessionScheduler done")
end

View File

@ -20,9 +20,7 @@ module JamRuby
def self.perform
@@log.debug("waking up")
JamWebEventMachine.run_wait_stop do
UnusedMusicNotationCleaner.new.run
end
@@log.debug("done")
end

View File

@ -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

View File

@ -81,7 +81,7 @@
if($audio.length == 0) {
$audio =
$('<audio preload="none">' +
'<source src="' + audioSrc + '" type="' + audioType + '" />' +
'<source src="' + cacheBustedSrc(audioSrc) + '" type="' + audioType + '" data-audio-src="' + audioSrc + '" />' +
'</audio>')
$parent.append($audio)
audioDomElement = $audio.get(0);
@ -164,9 +164,15 @@
audioDomElement.load();
var $parent = $audio.parent();
$audio.remove();
$parent.append('<audio preload="none"></audio>');
$audio = $('audio', $parent);
$audio = $('<audio preload="none"></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();
}

View File

@ -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')

View File

@ -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;

View File

@ -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!

View File

@ -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

View File

@ -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

View File

@ -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