╭ changed ────────────╮ │src/ui/Home/Repos.zig│ ╰─────────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │32 │ │33 const empty: Self = .{ .repos = &.{}, .owner_names = &.{}, .after = after, .next_after = null }; │ │34 │ │35 - // the ordered repo-list (oldest first); absent until the first repo exists. │ │36 - const repo_list_cursor = try haxy_moment.getCursor(hash.hashInt(hash_kind, "repo-list")) orelse return empty; │ │37 - const repo_list = try DB.ArrayList(.read_only).init(repo_list_cursor); │ │38 - const count = try repo_list.count(); │ │35 + // the repos ordered by creation time (oldest first); absent until the first │ │36 + // repo exists. keyed by [timestamp][event-id], value = event-id. │ │37 + const timestamp_to_repo_id_cursor = try haxy_moment.getCursor(hash.hashInt(hash_kind, "timestamp->repo-id")) orelse return empty;│ │38 + const timestamp_to_repo_id = try DB.SortedMap(.read_only).init(timestamp_to_repo_id_cursor); │ │39 + const count = try timestamp_to_repo_id.count(); │ │40 │ │41 const event_id_to_repo_cursor = try haxy_moment.getCursor(hash.hashInt(hash_kind, "event-id->repo")) orelse return empty; │ │42 const event_id_to_repo = try DB.HashMap(.read_only).init(event_id_to_repo_cursor); │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────╮ │43 │ │43 - // read the window [after, after+page_size) by index — a direct O(log n) │ │44 - // seek per entry, never scanning the whole table. ids whose repo has been │ │45 - // deleted (tombstones) are skipped. │ │44 + // read the window [after, after+page_size) by index — a direct O(log n) seek│ │45 + // per entry, never scanning the whole table. deletes remove their entry (no │ │46 + // tombstones), so the window is dense. │ │47 const end = @min(after + page_size, count); │ │48 var i = after; │ │49 while (i < end) : (i += 1) { │ ╰─────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │49 - const id_cursor = try repo_list.getCursor(@intCast(i)) orelse continue; │ │50 + const id_kv = try timestamp_to_repo_id.getIndexKeyValuePair(@intCast(i)) orelse continue; │ │51 var event_id: [evt.event_id_size]u8 = undefined; │ │51 - _ = try id_cursor.readBytes(&event_id); │ │52 + _ = try id_kv.value_cursor.readBytes(&event_id); │ │53 const repo_cursor = try event_id_to_repo.getCursor(hash.hashInt(hash_kind, &event_id)) orelse continue;│ │54 const repo_map = try DB.HashMap(.read_only).init(repo_cursor); │ │55 const repo_event = try evt.read(evt.Repo, DB, hash_kind, arena, repo_map); │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯