diff --git a/app/channels/meeting_info_channel.rb b/app/channels/meeting_info_channel.rb index 63c57c51..43d7b951 100644 --- a/app/channels/meeting_info_channel.rb +++ b/app/channels/meeting_info_channel.rb @@ -20,7 +20,6 @@ class MeetingInfoChannel < ApplicationCable::Channel def subscribed @chosen_room = Room.find(params[:room_id]) stream_for(@chosen_room) - NotifyMeetingWatcherJob.set(wait: 1.second).perform_later(@chosen_room, {}) end def unsubscribed diff --git a/app/controllers/rooms_controller.rb b/app/controllers/rooms_controller.rb index 675783c0..39351e83 100644 --- a/app/controllers/rooms_controller.rb +++ b/app/controllers/rooms_controller.rb @@ -151,7 +151,7 @@ def meeting_join @meeting = join_meeting_url - broadcast_meeting(action: 'join', delay: true) + broadcast_meeting(action: 'join') redirect_to(@meeting) rescue BigBlueButton::BigBlueButtonException => e logger.error(e.to_s) @@ -169,18 +169,14 @@ def meeting_end redirect_to(room_path(@room.id, launch_nonce: params['launch_nonce'])) # fallback if actioncable doesn't work end - def broadcast_meeting(action: 'none', delay: false) - if delay - NotifyMeetingWatcherJob.set(wait: 5.seconds).perform_later(@chosen_room, action: action) - else - NotifyMeetingWatcherJob.perform_now(@chosen_room, action: action) - end + def broadcast_meeting(action: 'none') + RoomMeetingWatcherJob.set(wait: 5.seconds).perform_later(@chosen_room, action: action) unless @chosen_room.watcher_job_active end # GET /rooms/:id/meeting/close def meeting_close respond_to do |format| - broadcast_meeting(action: 'someone left', delay: true) + broadcast_meeting(action: 'someone left') format.html { render(:autoclose) } end end diff --git a/app/javascript/packs/meetingInfo.js b/app/javascript/packs/meetingInfo.js index d247862c..82fd10f5 100644 --- a/app/javascript/packs/meetingInfo.js +++ b/app/javascript/packs/meetingInfo.js @@ -20,35 +20,31 @@ import '../channels/consumer' $(document).on('turbolinks:load', function () { - var controller = $("body").data('controller'); - var action = $("body").data('action'); var chosenRoomId = $("#body").data("chosenroomid"); - if (!(controller == "rooms" && action == "meeting_join")) { - App.meetingInfo = App.cable.subscriptions.create({ - channel: "MeetingInfoChannel", - room_id: chosenRoomId - }, { - connected: function () { - console.log("Connected to meeting info channel for [" + chosenRoomId + "]"); - }, - disconnected: function () { - console.log("Disconnected from meeting info channel"); - }, - received: function (data) { - console.log("Received data from meeting info channel. data: " + JSON.stringify(data)); - if (data.meeting_in_progress == true) { - startTime = data.elapsed_time - start_elapsed_time(); - display_participant_count(data.participant_count); - show_elems(); - } - if (data.action == "end") { - hide_elements(); - } + App.meetingInfo = App.cable.subscriptions.create({ + channel: "MeetingInfoChannel", + room_id: chosenRoomId + }, { + connected: function () { + console.log("Connected to meeting info channel for [" + chosenRoomId + "]"); + }, + disconnected: function () { + console.log("Disconnected from meeting info channel"); + }, + received: function (data) { + console.log("Received data from meeting info channel. data: " + JSON.stringify(data)); + if (data.meeting_in_progress == true) { + startTime = data.elapsed_time + start_elapsed_time(); + display_participant_count(data.participant_count); + show_elems(); } - }); - } + if (data.action == "end") { + hide_elements(); + } + } + }); }); var startTime = 0; @@ -56,13 +52,11 @@ var startTime = 0; var show_elems = function () { $('#end-meeting-btn').show(); $('#meeting-info-msg').show(); - $('#wait-for-mod-msg').hide(); } var hide_elements = function () { $('#end-meeting-btn').hide(); $('#meeting-info-msg').hide(); - $('#wait-for-mod-msg').hide(); } var display_participant_count = function (participantCount) { diff --git a/app/jobs/notify_meeting_watcher_job.rb b/app/jobs/notify_meeting_watcher_job.rb deleted file mode 100644 index 368ecb86..00000000 --- a/app/jobs/notify_meeting_watcher_job.rb +++ /dev/null @@ -1,48 +0,0 @@ -# frozen_string_literal: true - -# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/. -# -# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below). -# -# This program is free software; you can redistribute it and/or modify it under the -# terms of the GNU Lesser General Public License as published by the Free Software -# Foundation; either version 3.0 of the License, or (at your option) any later -# version. -# -# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY -# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with BigBlueButton; if not, see . - -require 'bbb_app_rooms/user' - -class NotifyMeetingWatcherJob < ApplicationJob - # Include libraries. - include BbbAppRooms - # Include concerns. - include BbbHelper - include OmniauthHelper - - queue_as :default - - def perform(room, data) - @chosen_room = room - MeetingInfoChannel.broadcast_to(room, job_data(data)) - end - - private - - def job_data(data) - info = meeting_info - data[:meeting_in_progress] = (info[:returncode] == 'SUCCESS' || info[:running] == true) - # Data for meeting not in progress. - (data[:action] = 'end') && (return data) unless data[:meeting_in_progress] - - # Data for meeting in progress. - data[:elapsed_time] = info[:startTime] - data[:participant_count] = info[:participantCount] - data - end -end diff --git a/app/jobs/room_meeting_watcher_job.rb b/app/jobs/room_meeting_watcher_job.rb new file mode 100644 index 00000000..05139af4 --- /dev/null +++ b/app/jobs/room_meeting_watcher_job.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +class RoomMeetingWatcherJob < ApplicationJob + queue_as :default + include BbbHelper + + def perform(room, data) + return unless room + + @chosen_room = room + + info = fetch_meeting_info(data) + if info[:meeting_in_progress] + @chosen_room.update(watcher_job_active: true) unless @chosen_room.watcher_job_active # no need to update if it's already true + + logger.info("Meeting in progress. Sending broadcast to room '#{room.name}'") + # Broadcast updates to this room’s channel + MeetingInfoChannel.broadcast_to(room, info) + + # Re-enqueue to run again in 5 seconds + self.class.set(wait: 10.seconds).perform_later(room, info) + else + logger.info("Meeting is not in progress. Sending broadcast to room '#{room.name}'") + + # Broadcast that the meeting ended + MeetingInfoChannel.broadcast_to(room, { meeting_in_progress: false, action: 'end' }) + @chosen_room.update(watcher_job_active: false) if @chosen_room.watcher_job_active # no need to update if it's already false + # Do not re-enqueue, job ends here + end + end + + private + + def fetch_meeting_info(data) + info = meeting_info + data[:meeting_in_progress] = (info[:returncode] == 'SUCCESS' || info[:running] == true) + # Data for meeting not in progress. + (data[:action] = 'end') && (return data) unless data[:meeting_in_progress] + + # Data for meeting in progress. + data[:elapsed_time] = info[:startTime] + data[:participant_count] = info[:participantCount] + data + end +end diff --git a/db/migrate/20241205194937_add_watcher_job_active_to_rooms.rb b/db/migrate/20241205194937_add_watcher_job_active_to_rooms.rb new file mode 100644 index 00000000..14f61b42 --- /dev/null +++ b/db/migrate/20241205194937_add_watcher_job_active_to_rooms.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class AddWatcherJobActiveToRooms < ActiveRecord::Migration[6.1] + def up + add_column(:rooms, :watcher_job_active, :boolean, default: false, null: false) + end + + def down + remove_column(:rooms, :watcher_job_active) + end +end diff --git a/db/schema.rb b/db/schema.rb index fcbd4105..5ea7cffe 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2024_11_20_203200) do +ActiveRecord::Schema.define(version: 2024_12_05_194937) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -35,6 +35,7 @@ t.string "code" t.string "shared_code" t.boolean "use_shared_code" + t.boolean "watcher_job_active", default: false, null: false t.index ["code"], name: "index_rooms_on_code" t.index ["tenant", "code"], name: "index_rooms_on_tenant_and_code", unique: true t.index ["tenant", "handler"], name: "index_rooms_on_tenant_and_handler", unique: true diff --git a/spec/controllers/rooms_spec.rb b/spec/controllers/rooms_spec.rb index bb091813..0efe0cef 100644 --- a/spec/controllers/rooms_spec.rb +++ b/spec/controllers/rooms_spec.rb @@ -20,7 +20,7 @@ }, }, }) - allow_any_instance_of(NotifyMeetingWatcherJob).to(receive(:bbb).and_return(bbb_api)) # stub actioncable processes + allow_any_instance_of(RoomMeetingWatcherJob).to(receive(:bbb).and_return(bbb_api)) # stub actioncable processes allow_any_instance_of(BrokerHelper).to(receive(:broker_tenant_info).and_return({ 'handler_params' => 'context_id', 'hide_build_tag' => 'false',