Skip to content

Commit

Permalink
Enhance Leaderboard Availability During Refresh (#1101)
Browse files Browse the repository at this point in the history
* Enhance Leaderboard Availability During Refresh

The initial approach to refreshing the leaderboard, which involved deleting all entries at once, led to data unavailability for users during updates. We've revised the process to sequentially delete and rebuild entries for each time duration. This adjustment helps to ensure that leaderboard data remains accessible to users while updates for other durations are in progress.

* Do the update to user_leaderboard and user_top_challenges at the same time

* Sql null comparison needs to be 'is null' and not '= null'
  • Loading branch information
ljdelight authored Jan 16, 2024
1 parent 0900af4 commit 2dc0791
Showing 1 changed file with 37 additions and 47 deletions.
84 changes: 37 additions & 47 deletions app/org/maproulette/jobs/SchedulerActor.scala
Original file line number Diff line number Diff line change
Expand Up @@ -425,56 +425,46 @@ class SchedulerActor @Inject() (
val start = System.currentTimeMillis
logger.info(s"Scheduled Task '$action': Starting run")

db.withConnection { implicit c =>
// Clear TABLEs
SQL("DELETE FROM user_leaderboard WHERE country_code IS NULL").executeUpdate()
SQL("DELETE FROM user_top_challenges WHERE country_code IS NULL").executeUpdate()

// Past Month
logger.info(s"Scheduled Task '$action': updating user_leaderboard for the last month")
SQL(LeaderboardHelper.rebuildChallengesLeaderboardSQL(SchedulerActor.ONE_MONTH, config))
.executeUpdate()
logger.info(s"Scheduled Task '$action': updating user_top_challenges for the last month")
SQL(LeaderboardHelper.rebuildTopChallengesSQL(SchedulerActor.ONE_MONTH, config))
.executeUpdate()

// Past 3 Months
logger.info(s"Scheduled Task '$action': updating user_leaderboard for the last 3 months")
SQL(LeaderboardHelper.rebuildChallengesLeaderboardSQL(SchedulerActor.THREE_MONTHS, config))
.executeUpdate()
logger.info(s"Scheduled Task '$action': updating user_top_challenges for the last 3 months")
SQL(LeaderboardHelper.rebuildTopChallengesSQL(SchedulerActor.THREE_MONTHS, config))
.executeUpdate()

// Past 6 Months
logger.info(s"Scheduled Task '$action': updating user_leaderboard for the last 6 months")
SQL(LeaderboardHelper.rebuildChallengesLeaderboardSQL(SchedulerActor.SIX_MONTHS, config))
.executeUpdate()
logger.info(s"Scheduled Task '$action': updating user_top_challenges for the last 6 months")
SQL(LeaderboardHelper.rebuildTopChallengesSQL(SchedulerActor.SIX_MONTHS, config))
.executeUpdate()

// Past Year
logger.info(s"Scheduled Task '$action': updating user_leaderboard for the last 12 months")
SQL(LeaderboardHelper.rebuildChallengesLeaderboardSQL(SchedulerActor.TWELVE_MONTHS, config))
.executeUpdate()
logger.info(s"Scheduled Task '$action': updating user_top_challenges for the last 12 months")
SQL(LeaderboardHelper.rebuildTopChallengesSQL(SchedulerActor.TWELVE_MONTHS, config))
.executeUpdate()

// All Time
logger.info(s"Scheduled Task '$action': updating user_leaderboard for ALL TIME")
SQL(LeaderboardHelper.rebuildChallengesLeaderboardSQL(SchedulerActor.ALL_TIME, config))
.executeUpdate()
logger.info(s"Scheduled Task '$action': updating user_top_challenges for ALL TIME")
SQL(LeaderboardHelper.rebuildTopChallengesSQL(SchedulerActor.ALL_TIME, config))
.executeUpdate()
def deleteAndUpdateLeaderboardForTimePeriod(monthDuration: Int): Unit = {
logger.info(
s"Scheduled Task '$action': updating user_leaderboard monthDuration=$monthDuration"
)
db.withConnection { implicit c =>
SQL(
s"DELETE FROM user_leaderboard WHERE country_code IS NULL AND month_duration = {monthDuration}"
).on(Symbol("monthDuration") -> monthDuration)
.executeUpdate()
SQL(
s"DELETE FROM user_top_challenges WHERE country_code IS NULL AND month_duration = {monthDuration}"
).on(Symbol("monthDuration") -> monthDuration).executeUpdate()

val totalTime = System.currentTimeMillis - start
SQL(LeaderboardHelper.rebuildChallengesLeaderboardSQL(monthDuration, config))
.executeUpdate()
SQL(
LeaderboardHelper.rebuildTopChallengesSQL(monthDuration, config)
).executeUpdate()
}
logger.info(
s"Scheduled Task '$action': Finished run. Time spent: ${String.format("%1d", totalTime)}ms"
s"Scheduled Task '$action': finished updating user_leaderboard monthDuration=$monthDuration"
)
}

SchedulerActor.MONTH_DURATIONS.foreach(monthDuration => {
try {
deleteAndUpdateLeaderboardForTimePeriod(monthDuration)
} catch {
case e: Exception =>
logger.error(
s"Scheduled Task '$action': Failed to update user_leaderboard monthDuration=$monthDuration",
e
)
}
})

val totalTime = System.currentTimeMillis - start
logger.info(
s"Scheduled Task '$action': Finished run. Time spent: ${String.format("%1d", totalTime)}ms"
)
}

/**
Expand Down Expand Up @@ -892,7 +882,7 @@ object SchedulerActor {
SchedulerActor.SIX_MONTHS,
SchedulerActor.TWELVE_MONTHS,
SchedulerActor.ALL_TIME
).sorted
)

def props = Props[SchedulerActor]()

Expand Down

0 comments on commit 2dc0791

Please sign in to comment.