╭ changed ─────────╮ │src/event/User.zig│ ╰──────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭───────────────────────────────────────────────────────────╮ │34 event_id: *const [evt.event_id_size]u8, │ │35 event_maybe: ?@This(), │ │36 arena: *std.heap.ArenaAllocator, │ │37 + created_ts: u64, │ │38 ) !void { │ │39 const user_key = hash.hashInt(hash_kind, event_id);│ │40 │ ╰───────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │64 │ │65 try name_to_user_id.put(hash.hashInt(hash_kind, event.name), .{ .bytes = event_id }); │ │66 │ │66 - // first time we've seen this user: append its id to the ordered list │ │67 - // the users view paginates through (a delete leaves a tombstone here). │ │67 + // first time we've seen this user: record its creation timestamp and add it │ │68 + // to the ordered map the users view paginates through │ │69 if (existing_cursor_maybe == null) { │ │69 - const user_list_cursor = try haxy_moment.putCursor(hash.hashInt(hash_kind, "user-list")); │ │70 - const user_list = try DB.ArrayList(.read_write).init(user_list_cursor); │ │71 - try user_list.append(.{ .bytes = event_id }); │ │70 + try user.put(hash.hashInt(hash_kind, "created-ts"), .{ .uint = created_ts }); │ │71 + │ │72 + const timestamp_to_user_id_cursor = try haxy_moment.putCursor(hash.hashInt(hash_kind, "timestamp->user-id"));│ │73 + const timestamp_to_user_id = try DB.SortedMap(.read_write).init(timestamp_to_user_id_cursor); │ │74 + const order_key = evt.orderKey(created_ts, event_id); │ │75 + try timestamp_to_user_id.put(&order_key, .{ .bytes = event_id }); │ │76 } │ │77 } else { │ │78 // read the user's name so we can drop its name->id index entry │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │80 const existing_user = try DB.HashMap(.read_only).init(existing_cursor); │ │81 const existing_event = try evt.read(@This(), DB, hash_kind, arena, existing_user); │ │82 _ = try name_to_user_id.remove(hash.hashInt(hash_kind, existing_event.name)); │ │83 + │ │84 + // drop it from the ordered map using its recorded creation timestamp │ │85 + if (try existing_user.getCursor(hash.hashInt(hash_kind, "created-ts"))) |created_ts_cursor| { │ │86 + const stored_ts = try created_ts_cursor.readUint(); │ │87 + const timestamp_to_user_id_cursor = try haxy_moment.putCursor(hash.hashInt(hash_kind, "timestamp->user-id"));│ │88 + const timestamp_to_user_id = try DB.SortedMap(.read_write).init(timestamp_to_user_id_cursor); │ │89 + const order_key = evt.orderKey(stored_ts, event_id); │ │90 + _ = try timestamp_to_user_id.remove(&order_key); │ │91 + } │ │92 } │ │93 │ │94 if (!try event_id_to_user.remove(user_key)) return error.EventNotFound; │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │213 updated.enable_ansi = !user.enable_ansi; │ │214 try evt.commitAndConsume(repo_opts, io, allocator, repo, evt.events_ref, &[_]evt.EventWithId{.{│ │215 .id = std.fmt.bytesToHex(user_id[0..evt.event_id_size].*, .lower), │ │216 + .timestamp = @intCast(std.Io.Timestamp.now(io, .real).toSeconds()), │ │217 .event = .{ .user = updated }, │ │218 }}); │ │219 } │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────╯