╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ───────────────╮ │src/event/Attachment.zig│ ╰────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │118 const parent_attachments_cursor = try parent_id_to_attachment_id_set.putCursor(hash.hashInt(hash_kind, &record_to_write.event.parent_id));│ │119 const parent_attachments = try DB.SortedSet(.read_write).init(parent_attachments_cursor); │ │120 - try parent_attachments.put(&evt.orderKey(record_to_write.created_ts, event_id)); │ │120 + try parent_attachments.put(&evt.orderKey(record_to_write.created_order, event_id)); │ │121 } │ │122 │ │123 // attach `blob` to a parent event and return the event id. `repo` must be │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ────────────╮ │src/event/Comment.zig│ ╰─────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────╮ │13 event: Self, │ │14 removed: bool = false, │ │15 author_email: ?[]const u8 = null, │ │16 - created_ts: u64 = 0, // the commit timestamp of the event that first created this comment│ │16 + created_order: u64 = 0, │ │17 }; │ │18 │ │19 const Self = @This(); │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │67 }; │ │68 │ │69 // references use the same lower-case hex form as event ids in json │ │70 - var id_bytes: [evt.event_id_size]u8 = undefined; │ │71 - _ = try std.fmt.hexToBytes(&id_bytes, &record_to_write.event.thread_id); │ │72 - if (!std.mem.eql(u8, &record_to_write.event.thread_id, &std.fmt.bytesToHex(id_bytes, .lower))) return error.InvalidEventId; │ │73 - _ = try std.fmt.hexToBytes(&id_bytes, &record_to_write.event.parent_id); │ │74 - if (!std.mem.eql(u8, &record_to_write.event.parent_id, &std.fmt.bytesToHex(id_bytes, .lower))) return error.InvalidEventId; │ │70 + var thread_id: [evt.event_id_size]u8 = undefined; │ │71 + _ = try std.fmt.hexToBytes(&thread_id, &record_to_write.event.thread_id); │ │72 + if (!std.mem.eql(u8, &record_to_write.event.thread_id, &std.fmt.bytesToHex(thread_id, .lower))) return error.InvalidEventId;│ │73 + var parent_id: [evt.event_id_size]u8 = undefined; │ │74 + _ = try std.fmt.hexToBytes(&parent_id, &record_to_write.event.parent_id); │ │75 + if (!std.mem.eql(u8, &record_to_write.event.parent_id, &std.fmt.bytesToHex(parent_id, .lower))) return error.InvalidEventId;│ │76 │ │77 if (existing_record_maybe) |existing_record| { │ │77 - // updates preserve the original creation timestamp and author │ │78 - record_to_write.created_ts = existing_record.created_ts; │ │78 + // updates preserve the original creation order and author │ │79 + record_to_write.created_order = existing_record.created_order; │ │80 record_to_write.author_email = existing_record.author_email; │ │81 │ │82 // a comment cannot move between threads or positions in the thread │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │87 const comment_cursor = try event_id_to_comment.putCursor(comment_key); │ │88 const comment = try DB.HashMap(.read_write).init(comment_cursor); │ │89 try evt.upsert(Record, DB, hash_kind, comment, record_to_write); │ │89 - try evt.indexEvent(DB, hash_kind, haxy_moment, event_id, .comment, record_to_write.created_ts, record_to_write.removed); │ │90 + try evt.indexEvent(DB, hash_kind, haxy_moment, event_id, .comment, record_to_write.created_order, record_to_write.removed);│ │91 │ │92 if (existing_cursor_maybe == null) { │ │93 const comment_id_set_cursor = try haxy_moment.putCursor(hash.hashInt(hash_kind, id_set_key)); │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │94 const comment_id_set = try DB.SortedSet(.read_write).init(comment_id_set_cursor); │ │94 - try comment_id_set.put(&evt.orderKeyDesc(record_to_write.created_ts, event_id)); │ │95 + try comment_id_set.put(&evt.orderKeyDesc(record_to_write.created_order, event_id)); │ │96 + try evt.touchThread(DB, hash_kind, haxy_moment, &thread_id, record_to_write.created_order, arena);│ │97 } │ │98 │ │99 // removed comments stay in the thread so their replies remain connected │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ 98 - const thread_order_key = evt.orderKey(record_to_write.created_ts, event_id); │ │100 + const thread_order_key = evt.orderKey(record_to_write.created_order, event_id); │ │101 const thread_comments_cursor = try thread_id_to_comment_id_set.putCursor(hash.hashInt(hash_kind, &record_to_write.event.thread_id));│ │102 const thread_comments = try DB.SortedSet(.read_write).init(thread_comments_cursor); │ │103 try thread_comments.put(&thread_order_key); │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ───────────────╮ │src/event/Discussion.zig│ ╰────────────────────────╯ ╭─────────────────────────────────────────╮ │12 event: Self, │ │13 removed: bool = false, │ │14 author_email: ?[]const u8 = null,│ │15 - created_ts: u64 = 0, │ │15 + created_order: u64 = 0, │ │16 }; │ │17 │ │18 const Self = @This(); │ ╰─────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────╮ │24 pub const id_set_key = "discussion-id-set"; │ │25 pub const active_id_set_key = "active-discussion-id-set"; │ │26 pub const tag_to_id_set_key = "tag->discussion-id-set"; │ │27 +const activity_order_key = "discussion-id->activity-order"; │ │28 │ │29 pub fn tagIterator(tags: []const u8) std.mem.SplitIterator(u8, .scalar) {│ │30 return std.mem.splitScalar(u8, tags, ' '); │ ╰─────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │52 const records = try DB.HashMap(.read_write).init(try haxy_moment.putCursor(hash.hashInt(hash_kind, record_map_key))); │ │53 const active = try DB.SortedSet(.read_write).init(try haxy_moment.putCursor(hash.hashInt(hash_kind, active_id_set_key)));│ │54 const tags = try DB.SortedMap(.read_write).init(try haxy_moment.putCursor(hash.hashInt(hash_kind, tag_to_id_set_key))); │ │54 - │ │55 var existing_record_maybe: ?Record = null; │ │56 const existing_cursor_maybe = try records.getCursor(discussion_key); │ │57 if (existing_cursor_maybe) |existing_cursor| { │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────╮ │67 }; │ │68 │ │69 if (existing_record_maybe) |existing| { │ │70 - record_to_write.created_ts = existing.created_ts; │ │70 + record_to_write.created_order = existing.created_order; │ │71 record_to_write.author_email = existing.author_email; │ │72 + } │ │73 + │ │74 + const activity_order = if (existing_record_maybe != null) │ │75 + try activityOrder(DB, hash_kind, haxy_moment.readOnly(), event_id) │ │76 + else │ │77 + record_to_write.created_order; │ │78 + if (existing_record_maybe) |existing| { │ │79 if (!existing.removed) { │ │73 - const order_key = evt.orderKeyDesc(existing.created_ts, event_id);│ │74 - _ = try active.remove(&order_key); │ │75 - try removeFromTagSets(DB, tags, existing.event.tags, &order_key); │ │80 + const old_key = evt.orderKeyDesc(activity_order, event_id); │ │81 + _ = try active.remove(&old_key); │ │82 + try removeFromTagSets(DB, tags, existing.event.tags, &old_key); │ │83 } │ │84 } │ │85 │ ╰──────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯