From faa6c81081c5a496385da3ff98c7e2d845f328a4 Mon Sep 17 00:00:00 2001
From: Samuel Couillard <43917914+scouillard@users.noreply.github.com>
Date: Mon, 31 Jul 2023 10:37:27 -0400
Subject: [PATCH] Improve ServerRooms & RunningMeetingChecker (#5349)

* Improve ServerRooms process

* Improve Server Rooms query

* Rework RunningMeetingChecker
---
 .../api/v1/admin/server_rooms_controller.rb   | 22 ++----
 app/controllers/api/v1/rooms_controller.rb    |  2 +-
 app/services/running_meeting_checker.rb       | 18 ++---
 .../admin/server_rooms_controller_spec.rb     | 30 --------
 spec/services/running_meeting_checker_spec.rb | 69 +++++++++++++------
 5 files changed, 64 insertions(+), 77 deletions(-)

diff --git a/app/controllers/api/v1/admin/server_rooms_controller.rb b/app/controllers/api/v1/admin/server_rooms_controller.rb
index cb021412..c45fdc15 100644
--- a/app/controllers/api/v1/admin/server_rooms_controller.rb
+++ b/app/controllers/api/v1/admin/server_rooms_controller.rb
@@ -31,14 +31,14 @@ module Api
         def index
           sort_config = config_sorting(allowed_columns: %w[name users.name])
 
-          rooms = Room.includes(:user).joins(:user).where(users: { provider: current_provider }).order(sort_config, online: :desc)
+          rooms = Room.includes(:user).where(users: { provider: current_provider }).order(sort_config, online: :desc)
                       .order('last_session DESC NULLS LAST')&.admin_search(params[:search])
 
-          online_server_rooms(rooms)
+          pagy, paged_rooms = pagy(rooms)
 
-          pagy, rooms = pagy_array(rooms)
+          RunningMeetingChecker.new(rooms: paged_rooms.select(&:online)).call if paged_rooms.select(&:online).any?
 
-          render_data data: rooms, meta: pagy_metadata(pagy), serializer: ServerRoomSerializer, status: :ok
+          render_data data: paged_rooms, meta: pagy_metadata(pagy), serializer: ServerRoomSerializer, status: :ok
         end
 
         # GET /api/v1/admin/server_rooms/:friendly_id/resync.json
@@ -54,20 +54,6 @@ module Api
         def find_room
           @room = Room.find_by!(friendly_id: params[:friendly_id])
         end
-
-        def online_server_rooms(rooms)
-          online_rooms = BigBlueButtonApi.new(provider: current_provider).active_meetings
-          online_rooms_hash = {}
-
-          online_rooms.each do |online_room|
-            online_rooms_hash[online_room[:meetingID]] = online_room[:participantCount]
-          end
-
-          rooms.each do |room|
-            room.online = online_rooms_hash.key?(room.meeting_id)
-            room.participants = online_rooms_hash[room.meeting_id]
-          end
-        end
       end
     end
   end
diff --git a/app/controllers/api/v1/rooms_controller.rb b/app/controllers/api/v1/rooms_controller.rb
index 408c0b8f..0cfd7962 100644
--- a/app/controllers/api/v1/rooms_controller.rb
+++ b/app/controllers/api/v1/rooms_controller.rb
@@ -51,7 +51,7 @@ module Api
           room.shared = true if room.user_id != current_user.id
         end
 
-        RunningMeetingChecker.new(rooms:).call
+        RunningMeetingChecker.new(rooms: rooms.select(&:online)).call if rooms.select(&:online).any?
 
         render_data data: rooms, status: :ok
       end
diff --git a/app/services/running_meeting_checker.rb b/app/services/running_meeting_checker.rb
index 0e820092..57c18b8d 100644
--- a/app/services/running_meeting_checker.rb
+++ b/app/services/running_meeting_checker.rb
@@ -16,21 +16,23 @@
 
 # frozen_string_literal: true
 
-# Pass the room(s) to the service and it will confirm if the meeting is online or not and will return the # of participants
+# Pass the online rooms to the service and it will confirm if the meeting is running or not and return the # of participants
 class RunningMeetingChecker
   def initialize(rooms:)
     @rooms = rooms
   end
 
   def call
-    online_rooms = Array(@rooms).select { |room| room.online == true }
+    Array(@rooms).each do |room|
+      next unless room.online
 
-    online_rooms.each do |online_room|
-      bbb_meeting = BigBlueButtonApi.new(provider: online_room.user.provider).get_meeting_info(meeting_id: online_room.meeting_id)
-      online_room.participants = bbb_meeting[:participantCount]
-    rescue BigBlueButton::BigBlueButtonException
-      online_room.update(online: false)
-      next
+      begin
+        bbb_meeting = BigBlueButtonApi.new(provider: room.user.provider).get_meeting_info(meeting_id: room.meeting_id)
+        room.participants = bbb_meeting[:participantCount]
+      rescue BigBlueButton::BigBlueButtonException
+        room.update(online: false)
+        next
+      end
     end
   end
 end
diff --git a/spec/controllers/admin/server_rooms_controller_spec.rb b/spec/controllers/admin/server_rooms_controller_spec.rb
index d8591c48..ec691cfc 100644
--- a/spec/controllers/admin/server_rooms_controller_spec.rb
+++ b/spec/controllers/admin/server_rooms_controller_spec.rb
@@ -36,7 +36,6 @@ RSpec.describe Api::V1::Admin::ServerRoomsController, type: :controller do
       create_list(:room, 2, user_id: user_one.id)
       create_list(:room, 2, user_id: user_two.id)
 
-      allow_any_instance_of(BigBlueButtonApi).to receive(:active_meetings).and_return([])
       get :index
       expect(JSON.parse(response.body)['data'].pluck('friendly_id'))
         .to match_array(Room.all.pluck(:friendly_id))
@@ -56,39 +55,12 @@ RSpec.describe Api::V1::Admin::ServerRoomsController, type: :controller do
         create_list(:room, 2, user_id: user_one.id)
         create_list(:room, 2, user_id: user_two.id)
 
-        allow_any_instance_of(BigBlueButtonApi).to receive(:active_meetings).and_return([])
         get :index
         expect(JSON.parse(response.body)['data'].pluck('friendly_id'))
           .to match_array(Room.all.pluck(:friendly_id))
       end
     end
 
-    it 'returns the server room status as online if the meeting has started' do
-      active_server_room = create(:room)
-      active_server_room.update(meeting_id: 'hulsdzwvitlk1dbekzxdprshsxmvycvar0jeaszc')
-
-      allow_any_instance_of(BigBlueButtonApi).to receive(:active_meetings).and_return(bbb_meetings)
-      get :index
-      expect(JSON.parse(response.body)['data'][0]['online']).to be(true)
-    end
-
-    it 'returns the number of participants in an online server room' do
-      active_server_room = create(:room)
-      active_server_room.update(meeting_id: 'hulsdzwvitlk1dbekzxdprshsxmvycvar0jeaszc')
-
-      allow_any_instance_of(BigBlueButtonApi).to receive(:active_meetings).and_return(bbb_meetings)
-      get :index
-      expect(JSON.parse(response.body)['data'][0]['participants']).to be(1)
-    end
-
-    it 'returns the server status as not running if BBB server does not return any online meetings' do
-      create(:room)
-
-      allow_any_instance_of(BigBlueButtonApi).to receive(:active_meetings).and_return([])
-      get :index
-      expect(JSON.parse(response.body)['data'][0]['online']).to be(false)
-    end
-
     it 'excludes rooms whose owners have a different provider' do
       user1 = create(:user, provider: 'greenlight')
       role_with_provider_test = create(:role, provider: 'test')
@@ -96,8 +68,6 @@ RSpec.describe Api::V1::Admin::ServerRoomsController, type: :controller do
       rooms = create_list(:room, 2, user: user1)
       create_list(:room, 2, user: user2)
 
-      allow_any_instance_of(BigBlueButtonApi).to receive(:active_meetings).and_return([])
-
       get :index
       expect(JSON.parse(response.body)['data'].pluck('id')).to match_array(rooms.pluck(:id))
     end
diff --git a/spec/services/running_meeting_checker_spec.rb b/spec/services/running_meeting_checker_spec.rb
index 8a3af2e9..fa0ed5f1 100644
--- a/spec/services/running_meeting_checker_spec.rb
+++ b/spec/services/running_meeting_checker_spec.rb
@@ -19,36 +19,65 @@
 require 'rails_helper'
 
 RSpec.describe RunningMeetingChecker, type: :service do
-  let!(:online_room) { create(:room, online: true, user: create(:user, provider: 'greenlight')) }
-  let(:bbb_api) { instance_double(BigBlueButtonApi) }
+  let!(:room) { create(:room, user: create(:user, provider: 'greenlight'), online: true) }
+  let!(:rooms) { create_list(:room, 3, user: create(:user, provider: 'greenlight'), online: true) }
 
-  before do
-    allow(BigBlueButtonApi).to receive(:new).and_return(bbb_api)
-  end
+  describe '#call' do
+    it 'retrieves the room participants for an online room' do
+      allow_any_instance_of(BigBlueButtonApi).to receive(:get_meeting_info).with(meeting_id: room.meeting_id).and_return(meeting_info)
+
+      described_class.new(rooms: room).call
 
-  context 'when the meeting is running' do
-    let(:bbb_response) do
-      {
-        running: true
-      }
+      expect(room.participants).to eq(5)
     end
 
-    it 'updates the online status to true' do
-      allow(bbb_api).to receive(:get_meeting_info).and_return(bbb_response)
+    it 'retrieves the room participants for multiple online room' do
+      allow_any_instance_of(BigBlueButtonApi).to receive(:get_meeting_info).and_return(meeting_info)
 
-      described_class.new(rooms: Room.all).call
+      described_class.new(rooms:).call
 
-      expect(online_room.reload.online).to eq(bbb_response[:running])
+      rooms.each do |room|
+        expect(room.participants).to eq(5)
+      end
     end
-  end
 
-  context 'when the meeting is not running' do
-    it 'updates the online status to false' do
-      allow(bbb_api).to receive(:get_meeting_info).and_raise(BigBlueButton::BigBlueButtonException)
+    it 'handles BigBlueButtonException and sets room online status to false' do
+      allow_any_instance_of(BigBlueButtonApi).to receive(:get_meeting_info).and_raise(BigBlueButton::BigBlueButtonException)
 
-      described_class.new(rooms: Room.all).call
+      described_class.new(rooms: room).call
 
-      expect(online_room.reload.online).to be_falsey
+      expect(room.online).to be(false)
     end
   end
+
+  def meeting_info
+    {
+      returncode: 'SUCCESS',
+      meetingName: 'random-671854',
+      meetingID: 'random-671854',
+      internalMeetingID: 'ed055e2011ec6a76e39347808259a42a56f270d6-1690571458817',
+      createTime: '1690571458817',
+      createDate: 'Fri Jul 28 19:10:58 UTC 2023',
+      voiceBridge: '79474',
+      dialNumber: '343-633-0064',
+      attendeePW: 'PvioX208',
+      moderatorPW: 'b9WMdCtJ',
+      running: 'false',
+      duration: '0',
+      hasUserJoined: 'false',
+      recording: 'false',
+      hasBeenForciblyEnded: 'false',
+      startTime: '1690571458841',
+      endTime: '0',
+      participantCount: 5, # Also as integer
+      listenerCount: '0',
+      voiceParticipantCount: '0',
+      videoCount: '0',
+      maxUsers: '0',
+      moderatorCount: '0',
+      attendees: '',
+      metadata: '',
+      isBreakout: 'false'
+    }
+  end
 end
-- 
GitLab