Fix the cursor pagination for the admin user list
Your task
The admin user list paged with LIMIT 50 OFFSET n, and while people signed up, QA saw some users twice and some never. The team is moving to keyset pagination: each page starts right after the previous page's last row, found by its sort key, not by a row count.
An assistant wrote keyset_page(rows, cursor, page_size). It is in the editor. It has a bug. Find it and fix it.
Input and output:
rows: the users table as it is now, one string per row:"id|created_at", such as"u03|2026-01-03".cursor: the last row of the previous page, in the same"id|created_at"form, or""for the first page.page_size: the most ids to return.- Return the ids on the page, in page order.
Rules the tests check:
- A
page_sizeof 0 or less returns an empty list. - Skip a row that does not split on
|into exactly 2 parts, or whose id orcreated_atis empty. - Order the rows newest first:
created_atdescending, then id descending. Compare both as plain strings, character by character, with no date parsing. So"u9"comes before"u10". - Two rows with the same id and the same
created_atare one row. The same id with a differentcreated_atis a different row. - With an empty cursor, or one that does not split into 2 non-empty parts, return the first
page_sizerows of that order. - Otherwise return the first
page_sizerows that come strictly after the cursor in that order. - The cursor's row may no longer be in
rows, because a user was deleted between pages. The page still starts right after the place the cursor's key has in the order.
Examples
keyset_page(rows: list[str], cursor: str, page_size: int) -> list[str]Example 1
Input
keyset_page(["u03|2026-01-03", "u01|2026-01-01", "u05|2026-01-03", "u02|2026-01-02", "u04|2026-01-04"], "", 2)Output
["u04", "u05"]Example 2
Input
keyset_page(["u03|2026-01-03", "u01|2026-01-01", "u05|2026-01-03", "u02|2026-01-02", "u04|2026-01-04"], "u05|2026-01-03", 2)Output
["u03", "u02"]Example 3
Input
keyset_page(["u03|2026-01-03", "u01|2026-01-01", "u05|2026-01-03", "u02|2026-01-02", "u04|2026-01-04", "u06|2026-01-05"], "u05|2026-01-03", 2)Output
["u03", "u02"]