╭ changed ────────────╮ │src/event/Comment.zig│ ╰─────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │118 const replies_cursor = try parent_id_to_comment_id_set.putCursor(hash.hashInt(hash_kind, &record_to_write.event.parent_id));│ │119 const replies = try DB.SortedSet(.read_write).init(replies_cursor); │ │120 try replies.put(&thread_order_key); │ │121 +} │ │122 + │ │123 +// read a comment by event id, or null if the id isn't a known comment. field │ │124 +// byte slices are allocated in `arena`. │ │125 +pub fn readById( │ │126 + comptime DB: type, │ │127 + comptime hash_kind: hash.HashKind, │ │128 + haxy_moment: DB.HashMap(.read_only), │ │129 + arena: *std.heap.ArenaAllocator, │ │130 + comment_id: []const u8, │ │131 +) !?Record { │ │132 + const records_cursor = try haxy_moment.getCursor(hash.hashInt(hash_kind, record_map_key)) orelse return null; │ │133 + const records = try DB.HashMap(.read_only).init(records_cursor); │ │134 + const record_cursor = try records.getCursor(hash.hashInt(hash_kind, comment_id)) orelse return null; │ │135 + const record_map = try DB.HashMap(.read_only).init(record_cursor); │ │136 + return try evt.read(Record, DB, hash_kind, arena, record_map); │ │137 } │ │138 │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ──────────────╮ │src/ui/Repo/Comment.zig│ ╰───────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │125 id: []const u8, │ │126 ) !?CommentWithId { │ │127 const DB = evt.EventDB(hash_kind); │ │128 - const records_cursor = try haxy_moment.getCursor(hash.hashInt(hash_kind, evt.Comment.record_map_key)) orelse return null;│ │129 - const records = try DB.HashMap(.read_only).init(records_cursor); │ │130 - const record_cursor = try records.getCursor(hash.hashInt(hash_kind, id_bytes)) orelse return null; │ │131 - const record_map = try DB.HashMap(.read_only).init(record_cursor); │ │132 - const comment = try evt.read(evt.Comment.Record, DB, hash_kind, arena, record_map); │ │128 + const comment = (try evt.Comment.readById(DB, hash_kind, haxy_moment, arena, id_bytes)) orelse return null; │ │129 const parent_author: ?ui.Author = if (!std.mem.eql(u8, &comment.event.parent_id, &comment.event.thread_id)) blk: { │ │130 const parent_bytes = (try idBytes(&comment.event.parent_id)) orelse break :blk null; │ │135 - const parent_cursor = try records.getCursor(hash.hashInt(hash_kind, &parent_bytes)) orelse break :blk null; │ │136 - const parent_map = try DB.HashMap(.read_only).init(parent_cursor); │ │137 - const parent = try evt.read(evt.Comment.Record, DB, hash_kind, arena, parent_map); │ │131 + const parent = (try evt.Comment.readById(DB, hash_kind, haxy_moment, arena, &parent_bytes)) orelse break :blk null; │ │132 break :blk try ui.Author.initFromEmail(admin_moment, arena, parent.author_email); │ │133 } else null; │ │134 return .{ │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯