Skip to content

Conversation

@seer-by-sentry
Copy link

Fixes HACKATIME-13J. The issue was that: WakaTime database lacks an index on heartbeats.time, causing full table scans for daily range queries, leading to slow LeaderboardsController#index performance.

  • Refactored the calculate_untracked_entries method in leaderboards_controller.rb.
  • Replaced in-memory filtering and counting with a more efficient database query.
  • Utilized where.not(user_id: ids) to filter out existing user IDs directly in the database.
  • Used distinct.count(:user_id) for a more direct count of distinct user IDs.
  • Improves performance by reducing data transfer and leveraging database capabilities.

This fix was generated by Seer in Sentry, triggered by mahadkalam1234@gmail.com. 👁️ Run ID: 9956761

Not quite right? Click here to continue debugging with Seer.

@skyfallwastaken skyfallwastaken marked this pull request as ready for review February 10, 2026 01:15
Copilot AI review requested due to automatic review settings February 10, 2026 01:15
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Improves LeaderboardsController#index performance by reducing Ruby-side work when calculating “untracked entries” from the Hackatime/WakaTime heartbeats dataset.

Changes:

  • Replaced distinct.pluck(...).count { ... } with a DB-side where.not(...).distinct.count(:user_id) query for counting untracked users.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

def calculate_untracked_entries(ids)
r = @period_type == :last_7_days ? ((Date.current - 6.days).beginning_of_day...Date.current.end_of_day) : Date.current.all_day
Hackatime::Heartbeat.where(time: r).distinct.pluck(:user_id).count { |uid| !ids.include?(uid) }
Hackatime::Heartbeat.where(time: r).where.not(user_id: ids).distinct.count(:user_id)
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ids comes from @leaderboard.entries.pluck(:user_id) (local users.id, bigint), but Hackatime::Heartbeat.user_id appears to be the user's Slack UID (see User#hackatime_heartbeats uses primary_key: :slack_uid). Using where.not(user_id: ids) is likely a type/semantic mismatch and can raise a Postgres error (text vs bigint) or filter incorrectly. Consider converting ids to Slack UIDs first (e.g., User.where(id: ids).pluck(:slack_uid)) and filtering on those, or otherwise ensure both sides use the same identifier.

Suggested change
Hackatime::Heartbeat.where(time: r).where.not(user_id: ids).distinct.count(:user_id)
# `ids` are local users.id (integers), but Hackatime::Heartbeat.user_id stores Slack UIDs.
# Convert the user IDs to Slack UIDs before filtering.
slack_uids = User.where(id: ids).pluck(:slack_uid)
scope = Hackatime::Heartbeat.where(time: r)
scope = scope.where.not(user_id: slack_uids) if slack_uids.present?
scope.distinct.count(:user_id)

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants