From 8aff60f04c7f33397da1219f7b52c69217ea8363 Mon Sep 17 00:00:00 2001 From: Echo Date: Tue, 1 Jul 2025 00:04:09 -0400 Subject: [PATCH] fix leaderboard generation jobs --- app/controllers/leaderboards_controller.rb | 12 ++- app/jobs/warm_mini_leaderboard_cache_job.rb | 78 +++++++++++++++++-- app/models/leaderboard.rb | 6 +- config/initializers/good_job.rb | 4 + ...add_timezone_utc_offset_to_leaderboards.rb | 5 ++ db/schema.rb | 3 +- 6 files changed, 98 insertions(+), 10 deletions(-) create mode 100644 db/migrate/20250701035652_add_timezone_utc_offset_to_leaderboards.rb diff --git a/app/controllers/leaderboards_controller.rb b/app/controllers/leaderboards_controller.rb index 67a8cbc..b3a58b1 100644 --- a/app/controllers/leaderboards_controller.rb +++ b/app/controllers/leaderboards_controller.rb @@ -78,7 +78,16 @@ class LeaderboardsController < ApplicationController def generate_regional_leaderboard return nil unless current_user&.timezone_utc_offset - LeaderboardGenerator.generate_timezone_offset_leaderboard( + leaderboard = Leaderboard.where.not(finished_generating_at: nil) + .find_by( + start_date: start_date, + period_type: @period_type, + timezone_utc_offset: current_user.timezone_utc_offset, + deleted_at: nil + ) + + # fuck + leaderboard || LeaderboardGenerator.generate_timezone_offset_leaderboard( start_date, current_user.timezone_utc_offset, @period_type ) end @@ -96,6 +105,7 @@ class LeaderboardsController < ApplicationController leaderboard = Rails.cache.fetch(cache_key, expires_in: 1.minute) do Leaderboard.where.not(finished_generating_at: nil) + .global .find_by(start_date: start_date, period_type: @period_type, deleted_at: nil) end diff --git a/app/jobs/warm_mini_leaderboard_cache_job.rb b/app/jobs/warm_mini_leaderboard_cache_job.rb index 28e5b0c..23dd8c1 100644 --- a/app/jobs/warm_mini_leaderboard_cache_job.rb +++ b/app/jobs/warm_mini_leaderboard_cache_job.rb @@ -6,15 +6,79 @@ class WarmMiniLeaderboardCacheJob < ApplicationJob offsets.each do |offset| begin - LeaderboardGenerator.generate_timezone_offset_leaderboard( - Date.current, - offset, - :daily - ) - Rails.logger.info "Warmed mini leaderboard cache for UTC#{offset >= 0 ? '+' : ''}#{offset}" + # for some fucnking reason this shit broke now im pissed + [:daily, :weekly, :last_7_days].each do |period_type| + generate_timezone_leaderboard(offset, period_type) + end + + Rails.logger.info "made leaderboard offset #{offset >= 0 ? '+' : ''}#{offset}" rescue => e - Rails.logger.error "Failed to warm cache for UTC#{offset >= 0 ? '+' : ''}#{offset}: #{e.message}" + Rails.logger.error "didnt make leaderboard offset #{offset >= 0 ? '+' : ''}#{offset}: #{e.message}" end end end + + private + + def generate_timezone_leaderboard(offset, period_type) + date = case period_type + when :weekly then Date.current.beginning_of_week + when :last_7_days then Date.current - 6.days + else Date.current + end + + leaderboard = Leaderboard.create!( + start_date: date, + period_type: period_type, + timezone_utc_offset: offset + ) + + users = User.users_in_timezone_offset(offset).not_convicted + user_ids = users.pluck(:id) + + return leaderboard if user_ids.empty? + + date_range = case period_type + when :weekly + date.beginning_of_day...(date + 7.days).beginning_of_day + when :last_7_days + (date - 6.days).beginning_of_day...date.end_of_day + else + date.all_day + end + + ActiveRecord::Base.transaction do + entries_data = Heartbeat.where(user_id: user_ids, time: date_range) + .coding_only + .with_valid_timestamps + .joins(:user) + .where.not(users: { github_uid: nil }) + .group(:user_id) + .duration_seconds + + entries_data = entries_data.filter { |_, total_seconds| total_seconds > 60 } + + streaks = Heartbeat.daily_streaks_for_users(entries_data.keys) if entries_data.any? + + entries_to_create = entries_data.map do |user_id, total_seconds| + { + leaderboard_id: leaderboard.id, + user_id: user_id, + total_seconds: total_seconds, + streak_count: streaks[user_id] || 0 + } + end + + LeaderboardEntry.insert_all!(entries_to_create) if entries_to_create.any? + end + + leaderboard.update!(finished_generating_at: Time.current) + + Leaderboard.where.not(id: leaderboard.id) + .where(start_date: date, period_type: period_type, timezone_utc_offset: offset) + .where(deleted_at: nil) + .update_all(deleted_at: Time.current) + + leaderboard + end end diff --git a/app/models/leaderboard.rb b/app/models/leaderboard.rb index eca396b..e16a34a 100644 --- a/app/models/leaderboard.rb +++ b/app/models/leaderboard.rb @@ -10,9 +10,13 @@ class Leaderboard < ApplicationRecord enum :period_type, { daily: 0, weekly: 1, - last_7_days: 2 + last_7_days: 2, + daily_timezone_normalized: 3 } + scope :for_timezone_offset, ->(offset) { where(timezone_utc_offset: offset) } + scope :global, -> { where(timezone_utc_offset: nil) } + def finished_generating? finished_generating_at.present? end diff --git a/config/initializers/good_job.rb b/config/initializers/good_job.rb index 6cb113a..045cef3 100644 --- a/config/initializers/good_job.rb +++ b/config/initializers/good_job.rb @@ -42,6 +42,10 @@ Rails.application.configure do class: "LeaderboardUpdateJob", args: [ :last_7_days ] }, + timezone_leaderboard_refresh: { + cron: "*/5 * * * *", + class: "WarmMiniLeaderboardCacheJob" + }, # sailors_log_poll: { # cron: "*/2 * * * *", # class: "SailorsLogPollForChangesJob" diff --git a/db/migrate/20250701035652_add_timezone_utc_offset_to_leaderboards.rb b/db/migrate/20250701035652_add_timezone_utc_offset_to_leaderboards.rb new file mode 100644 index 0000000..8782f4e --- /dev/null +++ b/db/migrate/20250701035652_add_timezone_utc_offset_to_leaderboards.rb @@ -0,0 +1,5 @@ +class AddTimezoneUtcOffsetToLeaderboards < ActiveRecord::Migration[8.0] + def change + add_column :leaderboards, :timezone_utc_offset, :integer + end +end diff --git a/db/schema.rb b/db/schema.rb index f9b3bcf..a606cfb 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[8.0].define(version: 2025_06_30_000002) do +ActiveRecord::Schema[8.0].define(version: 2025_07_01_035652) do create_schema "pganalyze" # These are extensions that must be enabled in order to support this database @@ -272,6 +272,7 @@ ActiveRecord::Schema[8.0].define(version: 2025_06_30_000002) do t.datetime "finished_generating_at" t.datetime "deleted_at" t.integer "period_type", default: 0, null: false + t.integer "timezone_utc_offset" t.index ["start_date"], name: "index_leaderboards_on_start_date", where: "(deleted_at IS NULL)" end