diff --git a/ruby/lib/jam_ruby/models/genre.rb b/ruby/lib/jam_ruby/models/genre.rb index 18fef77b8..f2582fe94 100644 --- a/ruby/lib/jam_ruby/models/genre.rb +++ b/ruby/lib/jam_ruby/models/genre.rb @@ -12,5 +12,9 @@ module JamRuby # music sessions has_and_belongs_to_many :music_sessions, :class_name => "JamRuby::MusicSession", :join_table => "genres_music_sessions" + + def to_s + description + end end end \ No newline at end of file diff --git a/ruby/lib/jam_ruby/models/icecast_mount.rb b/ruby/lib/jam_ruby/models/icecast_mount.rb index cfa3424a2..97ca69431 100644 --- a/ruby/lib/jam_ruby/models/icecast_mount.rb +++ b/ruby/lib/jam_ruby/models/icecast_mount.rb @@ -76,13 +76,11 @@ module JamRuby end # creates a templated - def self.build_session_mount(music_session) + def self.build_session_mount(music_session, icecast_server) # only public sessions get mounts currently return nil unless music_session.fan_access - icecast_server = IcecastServer.find_best_server_for_user(music_session.creator) - mount = nil if icecast_server && icecast_server.mount_template_id # we have a server with an associated mount_template; we can create a mount automatically diff --git a/ruby/lib/jam_ruby/models/music_session.rb b/ruby/lib/jam_ruby/models/music_session.rb index a296fb5e5..e58ec75ff 100644 --- a/ruby/lib/jam_ruby/models/music_session.rb +++ b/ruby/lib/jam_ruby/models/music_session.rb @@ -24,7 +24,8 @@ module JamRuby has_many :recordings, :class_name => "JamRuby::Recording", :inverse_of => :music_session belongs_to :band, :inverse_of => :music_sessions, :class_name => "JamRuby::Band", :foreign_key => "band_id" - after_save :require_at_least_one_genre, :limit_max_genres, :sync_music_session_history + validate :require_at_least_one_genre, :limit_max_genres + after_save :sync_music_session_history after_destroy do |obj| JamRuby::MusicSessionHistory.removed_music_session(obj.id) @@ -269,7 +270,7 @@ module JamRuby def require_at_least_one_genre unless skip_genre_validation - if self.genres.count < Limits::MIN_GENRES_PER_SESSION + if self.genres.length < Limits::MIN_GENRES_PER_SESSION errors.add(:genres, ValidationMessages::SESSION_GENRE_MINIMUM_NOT_MET) end end @@ -277,7 +278,7 @@ module JamRuby def limit_max_genres unless skip_genre_validation - if self.genres.count > Limits::MAX_GENRES_PER_SESSION + if self.genres.length > Limits::MAX_GENRES_PER_SESSION errors.add(:genres, ValidationMessages::SESSION_GENRE_LIMIT_EXCEEDED) end end diff --git a/ruby/lib/jam_ruby/models/music_session_history.rb b/ruby/lib/jam_ruby/models/music_session_history.rb index 1bdc4676e..5677c2cf2 100644 --- a/ruby/lib/jam_ruby/models/music_session_history.rb +++ b/ruby/lib/jam_ruby/models/music_session_history.rb @@ -144,7 +144,7 @@ module JamRuby session_history.description = music_session.description unless music_session.description.nil? session_history.user_id = music_session.creator.id session_history.band_id = music_session.band.id unless music_session.band.nil? - session_history.genres = music_session.genres.map { |g| g.id }.join SEPARATOR + session_history.genres = music_session.genres.map { |g| g.id }.join SEPARATOR if music_session.genres.count > 0 session_history.fan_access = music_session.fan_access session_history.save! end diff --git a/ruby/lib/jam_ruby/resque/icecast_config_writer.rb b/ruby/lib/jam_ruby/resque/icecast_config_writer.rb index 31fc218a9..05ce40a26 100644 --- a/ruby/lib/jam_ruby/resque/icecast_config_writer.rb +++ b/ruby/lib/jam_ruby/resque/icecast_config_writer.rb @@ -89,27 +89,33 @@ module JamRuby if File.exist?(config_file) && !icecast_server.config_changed @@log.info("config not changed. skipping run for server: #{icecast_server.server_id}") else + # don't try to write to the file if for some reason the model isn't valid + # this could happen if an admin mucks around in the db directly + raise "icecast_server.id=#{icecast_server.server_id} not valid. errors=#{icecast_server.errors.inspect}" unless icecast_server.valid? + + # write the new config to a temporary location + tmp_config = Dir::Tmpname.make_tmpname(["#{Dir.tmpdir}/icecast", '.xml'], nil) + + buffer = nil + # allow no write to the server while dumping XML + icecast_server.with_lock do - - # don't try to write to the file if for some reason the model isn't valid - # this could happen if an admin mucks around in the db directly - raise "icecast_server.id=#{icecast_server.server_id} not valid. errors=#{icecast_server.errors.inspect}" unless icecast_server.valid? - - # write the new config to a temporary location - tmp_config = Dir::Tmpname.make_tmpname(["#{Dir.tmpdir}/icecast", '.xml'], nil) - - File.open(tmp_config, 'w') do |f| - icecast_server.dumpXml(f) - end - - # if written successfully, overwrite the current file - FileUtils.mv tmp_config, config_file - - # reload server - reload - - icecast_server.config_updated + buffer = StringIO.new + icecast_server.dumpXml(buffer) end + + buffer.rewind + File.open(tmp_config, 'w') do |f| + f.write buffer.read + end + + # if written successfully, overwrite the current file + FileUtils.mv tmp_config, config_file + + # reload server + reload + + icecast_server.config_updated end @@log.info("successful update of config for server: #{icecast_server.server_id}") diff --git a/ruby/spec/jam_ruby/models/icecast_mount_spec.rb b/ruby/spec/jam_ruby/models/icecast_mount_spec.rb index bcd0955a7..990db1902 100644 --- a/ruby/spec/jam_ruby/models/icecast_mount_spec.rb +++ b/ruby/spec/jam_ruby/models/icecast_mount_spec.rb @@ -176,29 +176,29 @@ describe IcecastMount do end it "no fan access means no mount" do - mount = IcecastMount.build_session_mount(hidden_music_session) + mount = IcecastMount.build_session_mount(hidden_music_session, IcecastServer.find_best_server_for_user(hidden_music_session.creator)) mount.should be_nil end it "with no servers" do IcecastServer.count.should == 0 - mount = IcecastMount.build_session_mount(public_music_session) + mount = IcecastMount.build_session_mount(public_music_session, IcecastServer.find_best_server_for_user(public_music_session.creator)) mount.should be_nil end it "with a server that has a mount template" do server1.mount_template.should_not be_nil - mount = IcecastMount.build_session_mount(public_music_session) + mount = IcecastMount.build_session_mount(public_music_session, IcecastServer.find_best_server_for_user(public_music_session.creator)) mount.should_not be_nil mount.save! end it "with a server that already has an associated mount" do server1.mount_template.should_not be_nil - mount = IcecastMount.build_session_mount(public_music_session) + mount = IcecastMount.build_session_mount(public_music_session, IcecastServer.find_best_server_for_user(public_music_session.creator)) mount.save! - mount = IcecastMount.build_session_mount(public_music_session2) + mount = IcecastMount.build_session_mount(public_music_session2, IcecastServer.find_best_server_for_user(public_music_session2.creator)) mount.save! server1.reload server1.mounts.length.should == 2 @@ -207,13 +207,13 @@ describe IcecastMount do it "picks a second server once the 1st has been chosen" do server1.touch - mount = IcecastMount.build_session_mount(public_music_session) + mount = IcecastMount.build_session_mount(public_music_session, IcecastServer.find_best_server_for_user(public_music_session.creator)) mount.listeners = 1 # affect the weight mount.save! server2.touch - mount = IcecastMount.build_session_mount(public_music_session2) + mount = IcecastMount.build_session_mount(public_music_session2, IcecastServer.find_best_server_for_user(public_music_session2.creator)) mount.save! server1.reload server1.mounts.length.should == 1 @@ -224,17 +224,17 @@ describe IcecastMount do it "picks the 1st server again once the 2nd has higher weight" do server1.touch - mount = IcecastMount.build_session_mount(public_music_session) + mount = IcecastMount.build_session_mount(public_music_session, IcecastServer.find_best_server_for_user(public_music_session.creator)) mount.listeners = 1 # affect the weight mount.save! server2.touch - mount = IcecastMount.build_session_mount(public_music_session2) + mount = IcecastMount.build_session_mount(public_music_session2, IcecastServer.find_best_server_for_user(public_music_session2.creator)) mount.sourced = 1 mount.save! - mount = IcecastMount.build_session_mount(public_music_session3) + mount = IcecastMount.build_session_mount(public_music_session3, IcecastServer.find_best_server_for_user(public_music_session3.creator)) mount.listeners = 1 mount.save! diff --git a/ruby/spec/jam_ruby/models/icecast_mount_template_spec.rb b/ruby/spec/jam_ruby/models/icecast_mount_template_spec.rb index 2478af012..7470219d7 100644 --- a/ruby/spec/jam_ruby/models/icecast_mount_template_spec.rb +++ b/ruby/spec/jam_ruby/models/icecast_mount_template_spec.rb @@ -14,7 +14,7 @@ describe IcecastMountTemplate do before(:each) do server.touch - mount = IcecastMount.build_session_mount(music_session) + mount = IcecastMount.build_session_mount(music_session, IcecastServer.find_best_server_for_user(music_session.creator)) mount.save! server.save! server.config_updated diff --git a/ruby/spec/jam_ruby/models/music_session_spec.rb b/ruby/spec/jam_ruby/models/music_session_spec.rb index 515dc33de..a22b94e53 100644 --- a/ruby/spec/jam_ruby/models/music_session_spec.rb +++ b/ruby/spec/jam_ruby/models/music_session_spec.rb @@ -7,6 +7,15 @@ describe MusicSession do IcecastServer.delete_all IcecastMount.delete_all end + + describe "validations" do + it "genre must be set" do + music_session = FactoryGirl.build(:music_session) + music_session.genres = [] + music_session.save.should be_false + music_session.errors[:genres].should == [ValidationMessages::SESSION_GENRE_MINIMUM_NOT_MET] + end + end it 'can grant access to valid user' do user1 = FactoryGirl.create(:user) # in the jam session @@ -461,5 +470,14 @@ describe MusicSession do @music_session.get_connection_ids(exclude_client_id: @connection2.client_id, as_musician: true).should == [@connection1.client_id] end end + + + describe "autosave of music session history" do + it "is created on initial music session create" do + music_session = FactoryGirl.create(:music_session) + history = MusicSessionHistory.find(music_session.id) + history.genres.should == music_session.genres.first.id + end + end end diff --git a/web/app/assets/images/web/carousel_bands.jpg b/web/app/assets/images/web/carousel_bands.jpg index 309366d68..c308849bb 100644 Binary files a/web/app/assets/images/web/carousel_bands.jpg and b/web/app/assets/images/web/carousel_bands.jpg differ diff --git a/web/app/assets/images/web/carousel_fans.jpg b/web/app/assets/images/web/carousel_fans.jpg index 929864c5b..38c187b33 100644 Binary files a/web/app/assets/images/web/carousel_fans.jpg and b/web/app/assets/images/web/carousel_fans.jpg differ diff --git a/web/app/assets/images/web/carousel_musicians.jpg b/web/app/assets/images/web/carousel_musicians.jpg index 74d0fe73a..78434f243 100644 Binary files a/web/app/assets/images/web/carousel_musicians.jpg and b/web/app/assets/images/web/carousel_musicians.jpg differ diff --git a/web/app/assets/javascripts/feed_item_recording.js b/web/app/assets/javascripts/feed_item_recording.js index 05dfd3706..eee0a8dcb 100644 --- a/web/app/assets/javascripts/feed_item_recording.js +++ b/web/app/assets/javascripts/feed_item_recording.js @@ -6,6 +6,7 @@ context.JK.FeedItemRecording = function($parentElement, options){ var $feedItem = $parentElement; + var $name = $('.name', $feedItem); var $description = $('.description', $feedItem); var $musicians = $('.musician-detail', $feedItem); var $controls = $('.recording-controls', $feedItem); @@ -67,11 +68,15 @@ $musicians.hide(); $description.css('height', $description.data('original-height')); $description.dotdotdot(); + $name.css('height', $name.data('original-height')); + $name.dotdotdot(); }); } else { $description.trigger('destroy.dot'); $description.data('original-height', $description.css('height')).css('height', 'auto'); + $name.trigger('destroy.dot'); + $name.data('original-height', $name.css('height')).css('height', 'auto'); $musicians.show(); $feedItem.animate({'max-height': '1000px'}); } diff --git a/web/app/assets/javascripts/jam_rest.js b/web/app/assets/javascripts/jam_rest.js index 36be62054..73cceae13 100644 --- a/web/app/assets/javascripts/jam_rest.js +++ b/web/app/assets/javascripts/jam_rest.js @@ -34,12 +34,11 @@ }); } - function updateSession(id, newSession, onSuccess) { + function updateSession(id, newSession) { return $.ajax('/api/sessions/' + id, { type: "PUT", data : newSession, - dataType : 'json', - success: onSuccess + dataType : 'json' }); } diff --git a/web/app/assets/javascripts/session.js b/web/app/assets/javascripts/session.js index 10dcc7921..025136df1 100644 --- a/web/app/assets/javascripts/session.js +++ b/web/app/assets/javascripts/session.js @@ -1528,8 +1528,8 @@ return sessionModel.getCurrentSession(); }; - this.refreshCurrentSession = function() { - sessionModel.refreshCurrentSession(); + this.refreshCurrentSession = function(force) { + sessionModel.refreshCurrentSession(force); }; this.setPromptLeave = function(_promptLeave) { diff --git a/web/app/assets/javascripts/sessionModel.js b/web/app/assets/javascripts/sessionModel.js index 59b06530c..4a546a26a 100644 --- a/web/app/assets/javascripts/sessionModel.js +++ b/web/app/assets/javascripts/sessionModel.js @@ -166,6 +166,12 @@ function refreshCurrentSession(force) { // XXX use backend instead: https://jamkazam.atlassian.net/browse/VRFS-854 //logger.debug("SessionModel.refreshCurrentSession(" + currentSessionId +")"); + if(force) { + logger.debug("refreshCurrentSession(force=true)") + } + else { + + } refreshCurrentSessionRest(sessionChanged, force); } diff --git a/web/app/assets/javascripts/sessionSettingsDialog.js b/web/app/assets/javascripts/sessionSettingsDialog.js index 6118bde32..5b414bd6d 100644 --- a/web/app/assets/javascripts/sessionSettingsDialog.js +++ b/web/app/assets/javascripts/sessionSettingsDialog.js @@ -96,12 +96,12 @@ if (typeof newSessionInfo.genres === "string") { newSessionInfo.genres = [newSessionInfo.genres]; } - rest.updateSession(id, newSessionInfo, settingsSaved); + rest.updateSession(id, newSessionInfo).done(settingsSaved); } function settingsSaved(response) { // No response returned from this call. 204. - sessionScreen.refreshCurrentSession(); + sessionScreen.refreshCurrentSession(true); app.layout.closeDialog('session-settings'); } diff --git a/web/app/assets/javascripts/web/welcome.js b/web/app/assets/javascripts/web/welcome.js index 5c74bfa45..8ea3141a3 100644 --- a/web/app/assets/javascripts/web/welcome.js +++ b/web/app/assets/javascripts/web/welcome.js @@ -1,69 +1,87 @@ -(function(context,$) { +(function (context, $) { - "use strict"; + "use strict"; - context.JK = context.JK || {}; + context.JK = context.JK || {}; - var welcomeRoot; + var welcomeRoot; + var rest = context.JK.Rest(); - function initialize() { + function initialize() { - welcomeRoot = $('.landing-content .wrapper .welcome') + welcomeRoot = $('.landing-content .wrapper .welcome') - $('#signup').click(function(e) { - context.JK.app.layout.showDialog('signup-dialog'); + $('#signup').click(function (e) { + context.JK.app.layout.showDialog('signup-dialog'); + e.preventDefault(); + return false; + }); + + $('#signin').click(function (e) { + if (context.JK.currentUserId) { + rest.getUserDetail() + .done(function () { e.preventDefault(); + window.location = '/client'; return false; - }); - - $('#signin').click(function(e) { + }) + .fail(function () { context.JK.app.layout.showDialog('signin-dialog'); e.preventDefault(); return false; - }); - - $('.carousel').carousel({ - hAlign:'center', - vAlign:'bottom', - vMargin:.5, - reflection:true, - reflectionColor:'0,0,0', - directionNav:false, - frontWidth:424, - frontHeight:263, - carouselWidth:750, - carouselHeight:440, - slidesPerScroll:3, - backOpacity:2 - }); - - - $.each($('.feed-entry'), function(index, feedEntry) { - var $feedEntry = $(this); - if($feedEntry.is('.recording-entry')) { - new context.JK.FeedItemRecording($feedEntry); - } - else { - new context.JK.FeedItemSession($feedEntry); - } - }) - - context.JK.TickDuration('.feed-entry.music-session-history-entry .inprogress .tick-duration'); - - if($.QueryString['showVideo']) { - // pop a video automatically - var slides = $('.slideItem'); - $.each(slides, function(i, slide) { - slide = $(slide) - if(slide.attr('data-video-url') == $.QueryString['showVideo']) { - slide.click(); - } - }); + }) } + else { + // don't bother checking if no context.JK.currentUserId + context.JK.app.layout.showDialog('signin-dialog'); + e.preventDefault(); + return false; + } + + }); + + $('.carousel').carousel({ + hAlign: 'center', + vAlign: 'bottom', + vMargin: .5, + reflection: true, + reflectionColor: '0,0,0', + directionNav: false, + frontWidth: 424, + frontHeight: 263, + carouselWidth: 750, + carouselHeight: 440, + slidesPerScroll: 3, + backOpacity: 2 + }); + $('.carousel').show() + + + $.each($('.feed-entry'), function (index, feedEntry) { + var $feedEntry = $(this); + if ($feedEntry.is('.recording-entry')) { + new context.JK.FeedItemRecording($feedEntry); + } + else { + new context.JK.FeedItemSession($feedEntry); + } + }) + + context.JK.TickDuration('.feed-entry.music-session-history-entry .inprogress .tick-duration'); + + if ($.QueryString['showVideo']) { + // pop a video automatically + var slides = $('.slideItem'); + $.each(slides, function (i, slide) { + slide = $(slide) + if (slide.attr('data-video-url') == $.QueryString['showVideo']) { + slide.click(); + } + }); } + } - context.JK.WelcomePage = initialize; - + context.JK.WelcomePage = initialize; })(window, jQuery); \ No newline at end of file diff --git a/web/app/assets/stylesheets/web/audioWidgets.css.scss b/web/app/assets/stylesheets/web/audioWidgets.css.scss index 167cacd5e..3c4ea267c 100644 --- a/web/app/assets/stylesheets/web/audioWidgets.css.scss +++ b/web/app/assets/stylesheets/web/audioWidgets.css.scss @@ -209,9 +209,13 @@ .name { font-weight:bold; + min-height:16px; font-size:14px; + line-height:14px; + height:16px; overflow:hidden; - whitespace:nowrap; + text-overflow:ellipsis; + white-space:normal; } .description { diff --git a/web/app/assets/stylesheets/web/welcome.css.scss b/web/app/assets/stylesheets/web/welcome.css.scss index 854fe5c09..9f18a0e5c 100644 --- a/web/app/assets/stylesheets/web/welcome.css.scss +++ b/web/app/assets/stylesheets/web/welcome.css.scss @@ -79,6 +79,7 @@ Version: 1.1 .carousel { + display:none; position :relative ; margin :30px auto 0; width :auto; diff --git a/web/app/controllers/users_controller.rb b/web/app/controllers/users_controller.rb index 0c3afbac2..7d786ebd4 100644 --- a/web/app/controllers/users_controller.rb +++ b/web/app/controllers/users_controller.rb @@ -5,9 +5,9 @@ require 'builder' class Slide attr_accessor :img_url, :header, :vid_url - def initialize(type, img_url, vid_url) + def initialize(header, img_url, vid_url) @img_url = img_url # preview image - @header = "jamkazam for #{type}" # + @header = header @vid_url = vid_url + '?autoplay=1' end end @@ -198,12 +198,12 @@ class UsersController < ApplicationController def welcome @slides = [ - Slide.new("musicians", "web/carousel_musicians.jpg", "http://www.youtube.com/embed/eaYNM7p6Z5s"), - Slide.new("fans", "web/carousel_fans.jpg", "http://www.youtube.com/embed/eaYNM7p6Z5s"), - Slide.new("bands", "web/carousel_bands.jpg", "http://www.youtube.com/embed/eaYNM7p6Z5s"), - Slide.new("musicians", "web/carousel_musicians.jpg", "http://www.youtube.com/embed/eaYNM7p6Z5s"), - Slide.new("fans", "web/carousel_fans.jpg", "http://www.youtube.com/embed/eaYNM7p6Z5s"), - Slide.new("bands", "web/carousel_bands.jpg", "http://www.youtube.com/embed/eaYNM7p6Z5s") + Slide.new("JamKazam Overview", "web/carousel_musicians.jpg", "http://www.youtube.com/embed/eaYNM7p6Z5s"), + Slide.new("Getting Started", "web/carousel_fans.jpg", "http://www.youtube.com/embed/eaYNM7p6Z5s"), + Slide.new("Playing in a Session", "web/carousel_bands.jpg", "http://www.youtube.com/embed/eaYNM7p6Z5s"), + Slide.new("JamKazam Overview", "web/carousel_musicians.jpg", "http://www.youtube.com/embed/eaYNM7p6Z5s"), + Slide.new("Getting Started", "web/carousel_fans.jpg", "http://www.youtube.com/embed/eaYNM7p6Z5s"), + Slide.new("Playing in a Session", "web/carousel_bands.jpg", "http://www.youtube.com/embed/eaYNM7p6Z5s") ] @promo_buzz = PromoBuzz.active diff --git a/web/lib/music_session_manager.rb b/web/lib/music_session_manager.rb index 7de689c0a..3f6ea7cd8 100644 --- a/web/lib/music_session_manager.rb +++ b/web/lib/music_session_manager.rb @@ -12,64 +12,76 @@ MusicSessionManager < BaseManager def create(user, client_id, description, musician_access, approval_required, fan_chat, fan_access, band, genres, tracks, legal_terms) return_value = nil - ActiveRecord::Base.transaction do - # check if we are connected to rabbitmq - music_session = MusicSession.new - music_session.id = SecureRandom.uuid - music_session.creator = user - music_session.description = description - music_session.musician_access = musician_access - music_session.approval_required = approval_required - music_session.fan_chat = fan_chat - music_session.fan_access = fan_access - music_session.band = band - music_session.legal_terms = legal_terms + time = Benchmark.realtime do + ActiveRecord::Base.transaction do - unless genres.nil? - genres.each do |genre_id| - loaded_genre = Genre.find(genre_id) - music_session.genres << loaded_genre - end - end + # we need to lock the icecast server in this transaction for writing, to make sure thath IcecastConfigWriter + # doesn't dumpXML as we are changing the server's configuraion + icecast_server = IcecastServer.find_best_server_for_user(user) if fan_access + icecast_server.lock! if icecast_server - if fan_access - # create an icecast mount since regular users can listen in to the broadcast - music_session.mount = IcecastMount.build_session_mount(music_session) - end + # check if we are connected to rabbitmq + music_session = MusicSession.new + music_session.id = SecureRandom.uuid + music_session.creator = user + music_session.description = description + music_session.musician_access = musician_access + music_session.approval_required = approval_required + music_session.fan_chat = fan_chat + music_session.fan_access = fan_access + music_session.band = band + music_session.legal_terms = legal_terms - music_session.save - - unless music_session.errors.any? - # save session parameters for next session - User.save_session_settings(user, music_session) - - # auto-join this user into the newly created session - as_musician = true - connection = ConnectionManager.new.join_music_session(user, client_id, music_session, as_musician, tracks) - - unless connection.errors.any? - user.update_progression_field(:first_music_session_at) - MusicSessionUserHistory.save(music_session.id, user.id, client_id, tracks) - - - unless band.nil? - Notification.send_band_session_join(music_session, band) + unless genres.nil? + genres.each do |genre_id| + loaded_genre = Genre.find(genre_id) + music_session.genres << loaded_genre + end + end + + if fan_access + # create an icecast mount since regular users can listen in to the broadcast + music_session.mount = IcecastMount.build_session_mount(music_session, icecast_server) + end + + music_session.save + + unless music_session.errors.any? + # save session parameters for next session + User.save_session_settings(user, music_session) + + # auto-join this user into the newly created session + as_musician = true + connection = ConnectionManager.new.join_music_session(user, client_id, music_session, as_musician, tracks) + + unless connection.errors.any? + user.update_progression_field(:first_music_session_at) + MusicSessionUserHistory.save(music_session.id, user.id, client_id, tracks) + + + unless band.nil? + Notification.send_band_session_join(music_session, band) + end + + return_value = music_session + else + return_value = connection + # rollback the transaction to make sure nothing is disturbed in the database + raise ActiveRecord::Rollback end - - return_value = music_session else - return_value = connection + return_value = music_session # rollback the transaction to make sure nothing is disturbed in the database raise ActiveRecord::Rollback end - else - return_value = music_session - # rollback the transaction to make sure nothing is disturbed in the database - raise ActiveRecord::Rollback end end - return return_value + if time > 2 + @log.warn "creating a music session took #{time*1000} milliseconds" + end + + return_value end # Update the session. If a field is left out (meaning, it's set to nil), it's not updated.