pagination.ry
module pagination
purpose: Fetch every page of a cursor-paginated API and count customers per country.
import std.console
import std.http exposing Url, HttpError
import std.json exposing JsonError
public type Customer
purpose: One customer record as the API returns it.
has id: Integer
has name: Text
has country: Text
can FromJson
end
type Page
has items: List of Customer
has next_cursor: maybe Text as "nextCursor"
can FromJson
end
public function fetch_all(base_url: Url)
returns List of Customer
or fails with HttpError or JsonError
needs network.http
purpose: Follow next_cursor from page to page until the API returns no cursor.
tags: http, pagination
let mutable customers: List of Customer be []
let mutable cursor: maybe Text be nothing
let mutable has_more be true
repeat until not has_more
let url be
match cursor
when some(token) then Url("{base_url}?cursor={token}")
when nothing then base_url
end
let response be http.get(url) otherwise fail
let page: Page be json.parse(response.body) otherwise fail
change customers to customers.append_all(page.items)
change cursor to page.next_cursor
change has_more to page.next_cursor is not nothing
end
return customers
end
public function main() or fails with HttpError or JsonError needs console, network.http
purpose: Print how many customers each country has, largest first.
let customers be fetch_all(Url("https://api.example.com/customers")) otherwise fail
let by_country be for each customer in customers group by customer.country
for each country, members in by_country sorted by members.length() descending
console.print("{country}: {members.length()}")
end
end
test "every page is fetched" needs network.http replays "fixtures/pagination.json"
let customers be fetch_all(Url("https://api.example.com/customers")) otherwise fail
check customers.length() is 3
end