R4.05.2 · Leaderboards — dive 2
Top-N and around-me.
Two reads serve every leaderboard view. The top-N is the first N positions of the order; the around-me window is a slice of positions either side of a player's own. Both read the same order and leave it unchanged.
Grounding: echo/apps/codemojex/lib/codemojex/board.ex · Codemojex.Board.top/2 —
the head-read ZREVRANGE … 0 (n-1) WITHSCORES against cm:<game>:board.
sora — and watch which rows it returns.ZREVRANGE 0 (N-1) WITHSCORES; an around-me read is ZREVRANK then a
rank-range read centred on the located rank.A top-N reads from the head; an around-me read locates sora's rank
(ZREVRANK = 4) and reads the band rank−k through rank+k. Neither
write the board.
Top-N — a read from the head
leaderboards.md.txt · Core OperationsThe top-N is the first N positions of the board read high-to-low. ZREVRANGE reads a rank range
from the top, and WITHSCORES returns each member's score alongside it. The arguments 0
N-1 are rank indices, inclusive — positions 0 through N−1, the leader through the Nth
player.
ZREVRANGE leaderboard 0 9 WITHSCORES # the top 10 ZREVRANGE leaderboard 0 4 WITHSCORES # the top 5
The read walks N members from the head, which is O(log N + N): the log to find the head, then N to read
across. The board is unchanged — ZREVRANGE reads the order, never writes it. Redis 6.2
folded the range commands into a unified ZRANGE … REV, which reads the identical top-N; only the
spelling differs.
The top-N is one head-read of the order. It returns the leader and the players right behind, with their scores, and touches nothing.
Pagination — the top-N, page by page
leaderboards.md.txt · PaginationA large board is read a page at a time, each page a rank range further down the order. Page p of size s is
the range (p−1)·s through p·s − 1. ZCARD returns
the member count, which divided by the page size gives the page count. Each page is the same head-read, offset
down the order.
ZREVRANGE leaderboard 0 19 WITHSCORES # page 1: ranks 1–20 ZREVRANGE leaderboard 20 39 WITHSCORES # page 2: ranks 21–40
Around-me — locate, then read the band
leaderboards.md.txt · Players Around a RankThe around-me view shows a player their standing against nearby competitors. It is two reads. First locate
the player's rank with ZREVRANK; then read the rank band centred on it. With a window half-width
k, the band is rank − k through rank + k. Near the top the band clamps at 0
— a player at rank 2 with k = 5 reads 0 7, since there is nothing above rank 0.
ZREVRANK leaderboard "sora" # say it returns 50 ZREVRANGE leaderboard 45 55 WITHSCORES # ranks 45–55: sora with five either side
The band is a slice of the existing order; neither read changes the set. Locate, then read the band around the located rank — the around-me view is the top-N read with bounds offset to the player's own rank.
Around-me is two reads of one order: locate the rank, then read the band centred on it. No stored rank is needed to answer it.
In codemojex — the top-N is Board.top/2
echo/apps/codemojex · board.ex · view.excodemojex runs the top-N read directly. Its leaderboard is one sorted set per game, keyed
cm:<game>:board, scored by each player's best linear total. The read side is
Codemojex.Board.top/2.
@doc "Top `n`, highest first: {player_id, score}."
def top(game, n \\ 10) do
case Cmd.zrevrange(k(game, "board"), 0, n - 1) |> Cmd.withscores() |> Wire.run(Bus.conn()) do ← ZREVRANGE cm:<game>:board 0 (n-1) WITHSCORES
{:ok, flat} -> {:ok, parse(flat)}
other -> other
end
end
Notes on ValkeyZREVRANGE key 0 N-1 WITHSCORES reads the
first N members high-to-low with their scores in O(log N + N); the read never writes the set —
valkey.io/commands/zrevrange.
Cmd.zrevrange/3 and Cmd.withscores/1 are the real EchoWire.Cmd
builders; 0, n - 1 is the rank range. Codemojex.View.leaderboard/2 calls it and
returns {player, max_score} rows, withholding everyone's guesses: the leaderboard is the one
place a player sees others, and only their scores. The around-me window — ZREVRANK to find
a rank, then a rank-range read — is the same order read with different bounds; the board does not need a
stored rank to answer it.
Reading a band of the queue
How the EchoMQ queue presents its ordered work, and reads a band of a group's jobs, is the Queue pillar. Open the Queue pillar for the queue reads built on the same score order a top-N and around-me read walk.
The top-N is a head-read of the score order (ZREVRANGE 0 N-1 WITHSCORES) and around-me is a
band centred on a rank (ZREVRANK, then a rank-range read).
Codemojex.Board.top/2 runs Cmd.zrevrange("cm:<game>:board", 0, n - 1) |>
Cmd.withscores() for the top-N, highest first; the same order serves an around-me band by adjusting
the bounds.
Two reads cover every view: the head for the top-N, a band for around-me. Both read the order
— codemojex's Board.top/2 is the head-read — and leave it untouched.
References
sources · relatedSources
- Redis — ZREVRANGE — read a rank range from the top, the top-N and the pagination read.
- Redis — ZREVRANK — locate a member's rank, the first read of an around-me window.
- Redis — Sorted sets — the ordered structure both reads walk.
Related in this course
- R4.05 · Leaderboardsthe module hub
- R4.05.1 · ZADD and ZREVRANKthe score in, the rank out
- R4.05.3 · The score-update pathupdating a score, the rank recomputed
- R4 · Score as meaningthe score is the semantic axis
- /echomq · the Queue pillarthe queue reads on the same order