From e400bf41e89213468ca2f7167df37fbd3fa34ca9 Mon Sep 17 00:00:00 2001 From: Zachary Chai Date: Mon, 31 Oct 2016 17:39:22 -0400 Subject: [PATCH] recording async update --- .../javascripts/channels/recording_update.js | 26 +++++++++++++++++++ app/assets/javascripts/landing.js | 9 ++++--- app/assets/javascripts/shared.js | 6 +++++ app/channels/recording_updates_channel.rb | 5 ++++ app/controllers/bbb_controller.rb | 15 +++++++---- app/jobs/recording_updates_job.rb | 22 ++++++++++++++++ app/{helpers/bbb_helper.rb => lib/bbb_api.rb} | 14 +++++++--- app/views/bbb/recordings.jbuilder | 3 +++ config/environments/development.rb | 4 ++- config/environments/production.rb | 2 ++ test/jobs/recording_updates_job_test.rb | 7 +++++ 11 files changed, 100 insertions(+), 13 deletions(-) create mode 100644 app/assets/javascripts/channels/recording_update.js create mode 100644 app/channels/recording_updates_channel.rb create mode 100644 app/jobs/recording_updates_job.rb rename app/{helpers/bbb_helper.rb => lib/bbb_api.rb} (91%) create mode 100644 test/jobs/recording_updates_job_test.rb diff --git a/app/assets/javascripts/channels/recording_update.js b/app/assets/javascripts/channels/recording_update.js new file mode 100644 index 00000000..a2cb32e7 --- /dev/null +++ b/app/assets/javascripts/channels/recording_update.js @@ -0,0 +1,26 @@ +(function() { + + var initRooms = function() { + App.messages = App.cable.subscriptions.create({ + channel: 'RecordingUpdatesChannel', + username: window.location.pathname.split('/').pop() + }, + { + received: function(data) { + var btn = $("#recordings").find(".recording-update:disabled"); + btn.data('published', data.published); + btn.find('i').removeClass(getPublishClass(!data.published)); + btn.find('i').addClass(getPublishClass(data.published)); + btn.prop("disabled", false); + } + }); + }; + + $(document).on("turbolinks:load", function() { + if ($("body[data-controller=landing]").get(0)) { + if ($("body[data-action=rooms]").get(0)) { + initRooms(); + } + } + }); +}).call(this); diff --git a/app/assets/javascripts/landing.js b/app/assets/javascripts/landing.js index 9ebfb1cd..ce8ee132 100644 --- a/app/assets/javascripts/landing.js +++ b/app/assets/javascripts/landing.js @@ -112,9 +112,9 @@ if (type === 'display') { var roomName = window.location.pathname.split('/').pop(); var published = row.published; - var eye = (published) ? 'eye' : 'eye-slash' + var eye = getPublishClass(published); return ' ' + + ' ' + ''; } @@ -128,12 +128,15 @@ var room = $(this).data('room'); var id = $(this).data('id'); var published = $(this).data('published'); + $(this).prop("disabled", true); $.ajax({ method: 'PATCH', url: '/rooms/'+room+'/recordings/'+id, data: {published: (!published).toString()} }).done(function(data) { - $(this).prop("disabled", true); + + }).fail(function(data) { + $(this).prop("disabled", false); }); }); diff --git a/app/assets/javascripts/shared.js b/app/assets/javascripts/shared.js index a1cc6c17..a2488f93 100644 --- a/app/assets/javascripts/shared.js +++ b/app/assets/javascripts/shared.js @@ -4,6 +4,12 @@ $.ajaxSetup({ } }); +var PUBLISHED_CLASSES = ['fa-eye-slash', 'fa-eye'] + +var getPublishClass = function(published) { + return PUBLISHED_CLASSES[+published]; +} + var meetingInstance = null; class Meeting { constructor(url, name) { diff --git a/app/channels/recording_updates_channel.rb b/app/channels/recording_updates_channel.rb new file mode 100644 index 00000000..ff814506 --- /dev/null +++ b/app/channels/recording_updates_channel.rb @@ -0,0 +1,5 @@ +class RecordingUpdatesChannel < ApplicationCable::Channel + def subscribed + stream_from "#{params[:username]}_recording_updates_channel" + end +end diff --git a/app/controllers/bbb_controller.rb b/app/controllers/bbb_controller.rb index bb3cb7be..aa140966 100644 --- a/app/controllers/bbb_controller.rb +++ b/app/controllers/bbb_controller.rb @@ -1,4 +1,5 @@ class BbbController < ApplicationController + include BbbApi before_action :authorize_owner_recording, only: [:update_recordings, :delete_recordings] @@ -20,7 +21,7 @@ class BbbController < ApplicationController end options[:meeting_logout_url] = "#{request.base_url}/#{params[:resource]}/#{params[:id]}" - bbb_res = helpers.bbb_join_url( + bbb_res = bbb_join_url( params[:id], params[:name], options @@ -42,19 +43,22 @@ class BbbController < ApplicationController render head(:not_found) && return end - bbb_res = helpers.bbb_get_recordings user.username + bbb_res = bbb_get_recordings user.username render_bbb_response bbb_res, bbb_res[:recordings] end # PATCH /rooms/:id/recordings/:record_id def update_recordings - bbb_res = helpers.bbb_update_recordings(params[:record_id], params[:published] == 'true') + bbb_res = bbb_update_recordings(params[:record_id], params[:published] == 'true') + if bbb_res[:returncode] + RecordingUpdatesJob.perform_later(@user.username, params[:record_id], bbb_res[:published]) + end render_bbb_response bbb_res end # DELETE /rooms/:id/recordings/:record_id def delete_recordings - bbb_res = helpers.bbb_delete_recordings(params[:record_id]) + bbb_res = bbb_delete_recordings(params[:record_id]) render_bbb_response bbb_res end @@ -68,9 +72,10 @@ class BbbController < ApplicationController render head(:unauthorized) && return end - recordings = helpers.bbb_get_recordings(params[:id])[:recordings] + recordings = bbb_get_recordings(params[:id])[:recordings] recordings.each do |recording| if recording[:recordID] == params[:record_id] + @user = user return true end end diff --git a/app/jobs/recording_updates_job.rb b/app/jobs/recording_updates_job.rb new file mode 100644 index 00000000..866e729d --- /dev/null +++ b/app/jobs/recording_updates_job.rb @@ -0,0 +1,22 @@ +class RecordingUpdatesJob < ApplicationJob + include BbbApi + + queue_as :default + + def perform(room, record_id, published) + tries = 0 + sleep_time = 2 + + while tries < 4 + bbb_res = bbb_get_recordings(nil, record_id) + if bbb_res[:recordings].first[:published].to_s == published + ActionCable.server.broadcast "#{room}_recording_updates_channel", + published: bbb_res[:recordings].first[:published] + break + end + sleep sleep_time + sleep_time = sleep_time * 2 + tries += 1 + end + end +end diff --git a/app/helpers/bbb_helper.rb b/app/lib/bbb_api.rb similarity index 91% rename from app/helpers/bbb_helper.rb rename to app/lib/bbb_api.rb index 4277145d..61aaa257 100644 --- a/app/helpers/bbb_helper.rb +++ b/app/lib/bbb_api.rb @@ -1,4 +1,4 @@ -module BbbHelper +module BbbApi def bbb_endpoint Rails.application.secrets[:bbb_endpoint] end @@ -67,9 +67,15 @@ module BbbHelper end end - def bbb_get_recordings(meeting_token) - meeting_id = (Digest::SHA1.hexdigest(Rails.application.secrets[:secret_key_base]+meeting_token)).to_s - bbb_safe_execute :get_recordings, meetingID: meeting_id + def bbb_get_recordings(meeting_id, record_id=nil) + options={} + if record_id + options[:recordID] = record_id + end + if meeting_id + options[:meetingID] = (Digest::SHA1.hexdigest(Rails.application.secrets[:secret_key_base]+meeting_id)).to_s + end + bbb_safe_execute :get_recordings, options end def bbb_update_recordings(id, published) diff --git a/app/views/bbb/recordings.jbuilder b/app/views/bbb/recordings.jbuilder index 0fcd74a2..63d617ca 100644 --- a/app/views/bbb/recordings.jbuilder +++ b/app/views/bbb/recordings.jbuilder @@ -11,6 +11,9 @@ unless @response.blank? json.end_time recording[:endTime] json.published recording[:published] json.playbacks do + unless recording[:playback][:format].is_a? Array + recording[:playback][:format] = [recording[:playback][:format]] + end json.array!(recording[:playback][:format]) do |playback| json.type playback[:type] json.url playback[:url] diff --git a/config/environments/development.rb b/config/environments/development.rb index b91c71aa..9616a76b 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -31,11 +31,13 @@ Rails.application.configure do config.action_mailer.perform_caching = false + config.active_job.queue_adapter = :async + # action cable socket URI config.action_cable.url = "ws://localhost/cable" # allowed action cable origins - Rails.application.config.action_cable.allowed_request_origins = ['http://localhost'] + config.action_cable.allowed_request_origins = ['http://localhost'] # Print deprecation notices to the Rails logger. config.active_support.deprecation = :log diff --git a/config/environments/production.rb b/config/environments/production.rb index 6956dec8..6f2ca454 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -55,6 +55,8 @@ Rails.application.configure do # Use a real queuing backend for Active Job (and separate queues per environment) # config.active_job.queue_adapter = :resque # config.active_job.queue_name_prefix = "greenlight_#{Rails.env}" + config.active_job.queue_adapter = :async + config.action_mailer.perform_caching = false # Ignore bad email addresses and do not raise email delivery errors. diff --git a/test/jobs/recording_updates_job_test.rb b/test/jobs/recording_updates_job_test.rb new file mode 100644 index 00000000..62dd0969 --- /dev/null +++ b/test/jobs/recording_updates_job_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class RecordingUpdatesJobTest < ActiveJob::TestCase + # test "the truth" do + # assert true + # end +end