diff --git a/app/controllers/super_admin/dashboard_controller.rb b/app/controllers/super_admin/dashboard_controller.rb index 56d19d563..8bc22cc59 100644 --- a/app/controllers/super_admin/dashboard_controller.rb +++ b/app/controllers/super_admin/dashboard_controller.rb @@ -2,10 +2,33 @@ class SuperAdmin::DashboardController < SuperAdmin::ApplicationController include ActionView::Helpers::NumberHelper def index - @data = Conversation.unscoped.group_by_day(:created_at, range: 30.days.ago..2.seconds.ago).count.to_a - @accounts_count = number_with_delimiter(Account.count) - @users_count = number_with_delimiter(User.count) - @inboxes_count = number_with_delimiter(Inbox.count) - @conversations_count = number_with_delimiter(Conversation.count) + respond_to do |format| + format.html + format.json { render json: dashboard_stats } + end + end + + private + + def dashboard_stats + Rails.cache.fetch('super_admin:dashboard_stats', expires_in: 30.minutes) do + { + chartData: Conversation.unscoped.group_by_day(:created_at, range: 30.days.ago..2.seconds.ago).count.to_a, + accountsCount: number_with_delimiter(Account.count), + usersCount: number_with_delimiter(User.count), + inboxesCount: number_with_delimiter(Inbox.count), + conversationsCount: number_with_delimiter(conversations_count_estimate) + } + end + end + + # Exact COUNT(*) scans the whole table; the planner estimate is instant + # and close enough for dashboard display. + def conversations_count_estimate + estimate = ActiveRecord::Base.connection.select_value( + "SELECT reltuples::bigint FROM pg_class WHERE relname = 'conversations'" + ).to_i + # reltuples is -1 until the table is first vacuumed/analyzed + estimate.negative? ? Conversation.count : estimate end end diff --git a/app/javascript/superadmin_pages/views/dashboard/Index.vue b/app/javascript/superadmin_pages/views/dashboard/Index.vue index f85ebea7f..944373673 100644 --- a/app/javascript/superadmin_pages/views/dashboard/Index.vue +++ b/app/javascript/superadmin_pages/views/dashboard/Index.vue @@ -1,13 +1,31 @@