Remove Cron job to generate stats

Since now generating stats (assuming the results aren't in the cache)
only takes a few seconds even when there are a hundred thousand
participants, as opposed to the several minutes it took to generate them
when we introduced the Cron job, we can simply generate the stats during
the first request to the stats page.

Note that, in order to avoid creating a temporary table when the stats
are cached, we're making sure we only create this table when we need to.
Otherwise, we could spend up to 1 second on every request to the stats
page creating a table that isn't going to be used.

Also note we're using an instance variable to check whether we're
creating a table; I tried to use `table_exists?`, but it didn't work. I
wonder whether `table_exists?` doesn't detect temporary tables.
This commit is contained in:
Javi Martín
2024-04-18 21:11:54 +02:00
parent 653848fc4e
commit a5646fcdb3
5 changed files with 9 additions and 30 deletions

View File

@@ -8,7 +8,7 @@ module Budgets
def show
authorize! :read_stats, @budget
@stats = Budget::Stats.new(@budget)
@stats = Budget::Stats.new(@budget).tap(&:generate)
@headings = @budget.headings.sort_by_name
end

View File

@@ -23,7 +23,7 @@ class PollsController < ApplicationController
end
def stats
@stats = Poll::Stats.new(@poll)
@stats = Poll::Stats.new(@poll).tap(&:generate)
end
def results

View File

@@ -48,10 +48,9 @@ module Statisticable
def generate
User.transaction do
create_participants_table
begin
define_singleton_method :participants do
create_participants_table unless participants_table_created?
participants_class.all
end
@@ -176,10 +175,12 @@ module Statisticable
)
User.connection.add_index participants_table_name, :date_of_birth
User.connection.add_index participants_table_name, :geozone_id
@participants_table_created = true
end
def drop_participants_table
User.connection.drop_table(participants_table_name, if_exists: true, temporary: true)
@participants_table_created = false
end
def participants_table_name
@@ -190,6 +191,10 @@ module Statisticable
@participants_class ||= Class.new(User).tap { |klass| klass.table_name = participants_table_name }
end
def participants_table_created?
@participants_table_created.present?
end
def total_participants_with_gender
@total_participants_with_gender ||= participants.where.not(gender: nil).distinct.count
end

View File

@@ -27,10 +27,6 @@ every 1.day, at: "5:00 am" do
rake "-s sitemap:refresh:no_ping"
end
every 2.hours do
rake "-s stats:generate"
end
every 1.day, at: "1:00 am", roles: [:cron] do
rake "files:remove_old_cached_attachments"
end

View File

@@ -1,23 +1,4 @@
namespace :stats do
desc "Generates stats which are not cached yet"
task generate: :environment do
ApplicationLogger.new.info "Updating budget and poll stats"
Tenant.run_on_each do
admin_ability = Ability.new(Administrator.first.user)
Budget.accessible_by(admin_ability, :read_stats).find_each do |budget|
Budget::Stats.new(budget).generate
print "."
end
Poll.accessible_by(admin_ability, :stats).find_each do |poll|
Poll::Stats.new(poll).generate
print "."
end
end
end
desc "Expires stats cache"
task expire_cache: :environment do
Tenant.run_on_each do
@@ -26,7 +7,4 @@ namespace :stats do
end
end
end
desc "Deletes stats cache and generates it again"
task regenerate: [:expire_cache, :generate]
end