GRN2-277: Optimize server recordings to make it useable for large deployments (#2411)

* First changes to server recordings

* Update server recordings

* Rubocop

* Make sure to return nothing for empty searches

* Made sure exactly the right amount of recordings are returned

* Added test cases
This commit is contained in:
Ahmad Farhat 2021-01-12 17:36:51 -05:00 committed by GitHub
parent 9cd08dab54
commit 2b0a80c7eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 102 additions and 15 deletions

View File

@ -56,12 +56,19 @@ class AdminsController < ApplicationController
# GET /admins/server_recordings
def server_recordings
server_rooms = rooms_list_for_recordings
@search = params[:search] || ""
@search, @order_column, @order_direction, recs =
all_recordings(server_rooms, params.permit(:search, :column, :direction), true, true)
if @search.present?
if @search.include? "@"
user_email = @search
else
room_uid = @search
end
else
@latest = true
end
@pagy, @recordings = pagy_array(recs)
@pagy, @recordings = pagy_array(recordings_to_show(user_email, room_uid))
end
# GET /admins/rooms

View File

@ -56,12 +56,22 @@ module Populator
end
end
# Returns list of rooms needed to get the recordings on the server
def rooms_list_for_recordings
if Rails.configuration.loadbalanced_configuration
Room.includes(:owner).where(users: { provider: @user_domain }).pluck(:bbb_id)
# Returns the correct recordings based on the users inputs
def recordings_to_show(user = nil, room = nil)
if user.present?
# Find user and get his recordings
rooms = User.find_by(email: user)&.rooms&.pluck(:bbb_id)
return all_recordings(rooms) if user.present?
[] # return no recs if room not found
elsif room.present?
# Find room and get its recordings
room = Room.find_by(uid: room)&.bbb_id
return all_recordings([room]) if room.present?
[]
else
Room.pluck(:bbb_id)
latest_recordings
end
end
@ -75,4 +85,36 @@ module Populator
list.admins_search(@search).order(updated_at: :desc)
end
private
# Returns exactly 1 page of the latest recordings
def latest_recordings
return_length = Rails.configuration.pagination_number
recordings = []
counter = 0
# Manually paginate through the rooms
while recordings.length < return_length
rooms = if Rails.configuration.loadbalanced_configuration
Room.includes(:owner)
.where(users: { provider: @user_domain })
.order(last_session: :desc)
.limit(return_length)
.offset(counter * return_length)
.pluck(:bbb_id)
else
Room.order(last_session: :desc)
.limit(return_length)
.offset(counter * return_length)
.pluck(:bbb_id)
end
break if rooms.blank?
counter += 1
recordings.push(*all_recordings(rooms))
end
recordings[0..return_length]
end
end

View File

@ -37,7 +37,7 @@ module Recorder
def all_recordings(room_bbb_ids, search_params = {}, ret_search_params = false, search_name = false)
res = { recordings: [] }
until room_bbb_ids.empty?
until room_bbb_ids.empty? || res[:recordings].length > Rails.configuration.pagination_number
# bbb.get_recordings returns an object
# take only the array portion of the object that is returned
full_res = get_multiple_recordings(room_bbb_ids.pop(Rails.configuration.pagination_number))

View File

@ -51,7 +51,7 @@ class Room < ApplicationRecord
# Rely on manual ordering if trying to sort by status
return order_by_status(table, running_ids) if column == "status"
return table.order("COALESCE(rooms.last_session,rooms.created_at) DESC") if column == "created_at"
return table.order(Arel.sql("COALESCE(rooms.last_session,rooms.created_at) DESC")) if column == "created_at"
return table.order(Arel.sql("rooms.#{column} #{direction}")) if table.column_names.include?(column)

View File

@ -90,6 +90,11 @@
<button class= "merge-user dropdown-item" data-path="<%= merge_user_path(user_uid: user.uid) %>" data-info="<%= user.slice(:name, :email, :uid).to_json %>" data-toggle="modal" data-target="#mergeUserModal">
<i class="dropdown-icon fas fa-user-friends"></i> <%= t("administrator.users.settings.merge") %>
</button>
<% unless user.rooms.length.zero? %>
<%= link_to admin_recordings_path(search: user.email), class: "dropdown-item" do %>
<i class="dropdown-icon fas fa-video"></i> <%= t("administrator.rooms.table.recordings") %>
<% end %>
<% end %>
<%= button_to admin_ban_path(user_uid: user.uid), class: "dropdown-item", "data-disable": "" do %>
<i class="dropdown-icon fas fa-lock"></i> <%= t("administrator.users.settings.ban") %>
<% end %>

View File

@ -93,7 +93,7 @@
<% end %>
</tbody>
</table>
<% if !@recordings.empty?%>
<% if !@recordings.empty? && !@latest%>
<div class="float-md-right mt-4">
<%== pagy_bootstrap_nav(@pagy) %>
</div>

View File

@ -65,6 +65,9 @@
<a href="" data-toggle="modal" data-target="#createRoomModal" class="update-room dropdown-item" data-settings-path="<%= room_settings_path(room) %>">
<i class="dropdown-icon fas fa-cog"></i> <%= t("room.settings") %>
</a>
<%= link_to admin_recordings_path(search: room.uid), class: "dropdown-item" do %>
<i class="dropdown-icon fas fa-video"></i> <%= t("administrator.rooms.table.recordings") %>
<% end %>
<% if preupload_allowed? %>
<a href="" data-toggle="modal" data-target="#preuploadPresentationModal" class="preupload-room dropdown-item" data-path="<%= preupload_presentation_path(room) %>" data-settings-path="<%= current_presentation_path(room) %>" data-remove="<%= remove_presentation_path(room) %>">
<i class="dropdown-icon fas fa-file-upload"></i> <%= t("room.add_presentation") %>

View File

@ -17,7 +17,7 @@
<div class="card-body p-6">
<div class="card-title text-primary">
<div class="form-group">
<%= render "shared/components/subtitle", subtitle: setting_title, search: search %>
<%= render "shared/components/subtitle", subtitle: setting_title, search: search, search_info: defined?(search_info) ? search_info : "" %>
</div>
</div>

View File

@ -21,7 +21,7 @@
<%= render "admins/components/menu_buttons" %>
</div>
<div id="server_recordings" class="col-lg-9">
<%= render "admins/components/setting_view", setting_id: "recordings", setting_title: t("administrator.recordings.title"), search: true %>
<%= render "admins/components/setting_view", setting_id: "recordings", setting_title: t("administrator.recordings.latest"), search: true, search_info: t("administrator.recordings.search_info") %>
</div>
</div>
</div>

View File

@ -35,6 +35,14 @@
</span>
</div>
</div>
<% if defined?(search_info) && search_info.present? %>
<div class="float-right mt-5">
<small>
<i class="fas fa-info-circle"></i>
<%= search_info %>
</small>
</div>
<% end %>
</div>
<% else %>
<div class="col-12">

View File

@ -138,8 +138,10 @@ en:
settings: Site Settings successfully changed
unauthorized: You are not authorized to perform actions on this user
recordings:
latest: Latest Recordings
title: Server Recordings
no_recordings: This server has no recordings.
search_info: Enter a user's full email or a room's uid
roles:
appear_in_share_list: Include users with this role in the dropdown for sharing rooms
can_create_rooms: Can create rooms

View File

@ -28,6 +28,26 @@ describe AdminsController, type: :controller do
@admin.set_role :admin
end
describe "Server Recordings" do
it "renders the server_recordings page" do
@request.session[:user_id] = @admin.id
get :server_recordings
expect(response).to render_template(:server_recordings)
end
end
describe "Server Rooms" do
it "renders the server_rooms page" do
@request.session[:user_id] = @admin.id
get :server_rooms
expect(response).to render_template(:server_rooms)
end
end
describe "User Roles" do
before do
allow(Rails.configuration).to receive(:enable_email_verification).and_return(true)