|
|
# The leaderboard payload as published by Api::V1::LeaderboardController.
|
|
|
#
|
|
|
# The API serves this out of a short cache, so what a consumer of the endpoint
|
|
|
# sees is whatever landed in `CACHE_KEY` on the last refresh -- not a live read
|
|
|
# of the players table. The admin screen reads that same cached entry, which is
|
|
|
# why the key, the TTL and the shape all live here rather than in the
|
|
|
# controller: one place publishes, both places agree on what "published" means.
|
|
|
class LeaderboardPayload
|
|
|
CACHE_KEY = "api/v1/leaderboard".freeze
|
|
|
TTL = 1.minute
|
|
|
|
|
|
# What the API returns. Recomputes and republishes when the cache is cold.
|
|
|
def self.fetch
|
|
|
Rails.cache.fetch(CACHE_KEY, expires_in: TTL) do
|
|
|
DemoActivity.simulate! # TEMP: fake gameplay so the banner has moving numbers
|
|
|
build
|
|
|
end
|
|
|
end
|
|
|
|
|
|
|
|
|
# The currently published payload, or nil when the cache has expired and no
|
|
|
# one has called the endpoint since. Never computes, never publishes -- the
|
|
|
# admin screen uses this to show what consumers are actually being served.
|
|
|
def self.published
|
|
|
Rails.cache.read(CACHE_KEY)
|
|
|
end
|
|
|
|
|
|
|
|
|
# A fresh payload that is NOT written to the cache and does not invent demo
|
|
|
# players. This is what the next API call would publish.
|
|
|
def self.build
|
|
|
leaderboard = LeaderboardScore.call
|
|
|
|
|
|
{
|
|
|
leaderboard: leaderboard,
|
|
|
badges: LeaderboardBadges.call(leaderboard),
|
|
|
updated_at: Time.current
|
|
|
}
|
|
|
end
|
|
|
|
|
|
|
|
|
def self.expire!
|
|
|
Rails.cache.delete(CACHE_KEY)
|
|
|
end
|
|
|
end
|