╭ changed ────────────╮ │src/ui/Home/Users.zig│ ╰─────────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │29 var users: std.ArrayList(evt.User.Safe) = .empty; │ │30 │ │31 // the users ordered by creation time (oldest first); absent until the first │ │32 - // user exists. keyed by [timestamp][event-id], value = event-id. │ │33 - const created_ts_to_user_id_cursor = try haxy_moment.getCursor(hash.hashInt(hash_kind, "created-ts->user-id")) orelse│ │32 + // user exists. keyed by orderKey ([timestamp][event-id]); the trailing bytes │ │33 + // of each key are the user event id. │ │34 + const user_id_set_cursor = try haxy_moment.getCursor(hash.hashInt(hash_kind, "user-id-set")) orelse │ │35 return .{ .users = &.{}, .after = after, .next_after = null }; │ │35 - const created_ts_to_user_id = try DB.SortedMap(.read_only).init(created_ts_to_user_id_cursor); │ │36 - const count = try created_ts_to_user_id.count(); │ │36 + const user_id_set = try DB.SortedSet(.read_only).init(user_id_set_cursor); │ │37 + const count = try user_id_set.count(); │ │38 │ │39 const event_id_to_user_cursor = try haxy_moment.getCursor(hash.hashInt(hash_kind, "event-id->user")) orelse │ │40 return .{ .users = &.{}, .after = after, .next_after = null }; │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────╮ │43 // read the window [after, after+page_size) with one seek to the start rank,│ │44 // then a sequential walk │ │45 const end = @min(after + page_size, count); │ │45 - var iter = try created_ts_to_user_id.iteratorFromIndex(after); │ │46 + var iter = try user_id_set.iteratorFromIndex(after); │ │47 var i = after; │ │48 while (i < end) : (i += 1) { │ │49 var id_cursor = (try iter.next()) orelse break; │ ╰────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │50 const id_kv = try id_cursor.readKeyValuePair(); │ │50 - var event_id: [evt.event_id_size]u8 = undefined; │ │51 - _ = try id_kv.value_cursor.readBytes(&event_id); │ │52 - const user_cursor = try event_id_to_user.getCursor(hash.hashInt(hash_kind, &event_id)) orelse continue;│ │51 + var order_key: [@sizeOf(u64) + evt.event_id_size]u8 = undefined; │ │52 + _ = try id_kv.key_cursor.readBytes(&order_key); │ │53 + const event_id = order_key[@sizeOf(u64)..]; │ │54 + const user_cursor = try event_id_to_user.getCursor(hash.hashInt(hash_kind, event_id)) orelse continue; │ │55 const user_map = try DB.HashMap(.read_only).init(user_cursor); │ │56 const user_event = try evt.read(evt.User, DB, hash_kind, arena, user_map); │ │57 try users.append(arena.allocator(), evt.User.Safe.init(user_event)); │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯