╭ changed ─────────╮ │src/test/event.zig│ ╰──────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1000 │ │1001 const haxy_moment = try evt.currentMoment(repo_opts, &repo); │ │1002 │ │1003 - // the one we left alone is gone, and its tags left the index with it │ │1003 + // the one we left alone is tombstoned, and its tags left the index │ │1004 var dropped_id: [evt.event_id_size]u8 = undefined; │ │1005 _ = try std.fmt.hexToBytes(&dropped_id, &events_to_consume2[0].id); │ │1006 - try std.testing.expectError(error.NotFound, readIssue(Repo.DB, repo_opts.hash, haxy_moment, &arena, &dropped_id)); │ │1006 + const dropped = try readIssue(Repo.DB, repo_opts.hash, haxy_moment, &arena, &dropped_id); │ │1007 + try std.testing.expect(dropped.deleted); │ │1008 │ │1009 const tag_to_issues_cursor = try haxy_moment.getCursor(hash.hashInt(repo_opts.hash, "tag+status->issue-id-set")) orelse return error.NotFound;│ │1010 const tag_to_issues = try Repo.DB.SortedMap(.read_only).init(tag_to_issues_cursor); │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────╮ │1014 var kept_id: [evt.event_id_size]u8 = undefined; │ │1015 _ = try std.fmt.hexToBytes(&kept_id, &events_to_consume2[1].id); │ │1016 const kept = try readIssue(Repo.DB, repo_opts.hash, haxy_moment, &arena, &kept_id);│ │1017 + try std.testing.expect(!kept.deleted); │ │1018 try std.testing.expectEqualStrings("Kept by the edit", kept.event.title); │ │1019 } │ │1020 } │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1201 const event_id_to_repo_cursor = try haxy_moment.getCursor(hash.hashInt(repo_opts.hash, "event-id->repo")) orelse return error.NotFound; │ │1202 const event_id_to_repo = try Repo.DB.HashMap(.read_only).init(event_id_to_repo_cursor); │ │1203 │ │1202 - try std.testing.expect(null == try event_id_to_repo.getCursor(hash.hashInt(repo_opts.hash, &repo_event_id))); │ │1204 + const repo_cursor = try event_id_to_repo.getCursor(hash.hashInt(repo_opts.hash, &repo_event_id)) orelse return error.NotFound; │ │1205 + const repo_map = try Repo.DB.HashMap(.read_only).init(repo_cursor); │ │1206 + const repo_event = try evt.read(evt.Repo.Record, Repo.DB, repo_opts.hash, &arena, repo_map); │ │1207 + try std.testing.expect(repo_event.deleted); │ │1208 │ │1209 // get the repos created by the user │ │1210 const user_id_to_repo_id_set_cursor = try haxy_moment.getCursor(hash.hashInt(repo_opts.hash, "user-id->repo-id-set")) orelse return error.NotFound;│ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1217 try std.testing.expectEqual(0, try user_repos.count()); │ │1218 } │ │1219 │ │1220 + // a non-null payload restores the repo and its indexes │ │1221 + try evt.consume(.xit, repo_opts, io, allocator, &repo, evt.events_ref, &[_]evt.EventWithId{.{ │ │1222 + .id = std.fmt.bytesToHex(repo_event_id, .lower), │ │1223 + .author_email = author_email, │ │1224 + .event = events_to_consume[2].event, │ │1225 + }}); │ │1226 + │ │1227 + { │ │1228 + const haxy_moment = try evt.currentMoment(repo_opts, &repo); │ │1229 + const event_id_to_repo_cursor = try haxy_moment.getCursor(hash.hashInt(repo_opts.hash, "event-id->repo")) orelse return error.NotFound; │ │1230 + const event_id_to_repo = try Repo.DB.HashMap(.read_only).init(event_id_to_repo_cursor); │ │1231 + const repo_cursor = try event_id_to_repo.getCursor(hash.hashInt(repo_opts.hash, &repo_event_id)) orelse return error.NotFound; │ │1232 + const repo_map = try Repo.DB.HashMap(.read_only).init(repo_cursor); │ │1233 + const repo_event = try evt.read(evt.Repo.Record, Repo.DB, repo_opts.hash, &arena, repo_map); │ │1234 + try std.testing.expect(!repo_event.deleted); │ │1235 + │ │1236 + const user_id_to_repo_id_set_cursor = try haxy_moment.getCursor(hash.hashInt(repo_opts.hash, "user-id->repo-id-set")) orelse return error.NotFound;│ │1237 + const user_id_to_repo_id_set = try Repo.DB.HashMap(.read_only).init(user_id_to_repo_id_set_cursor); │ │1238 + const user_repos_cursor = try user_id_to_repo_id_set.getCursor(hash.hashInt(repo_opts.hash, &user_event_id)) orelse return error.NotFound; │ │1239 + const user_repos = try Repo.DB.SortedSet(.read_only).init(user_repos_cursor); │ │1240 + try std.testing.expectEqual(1, try user_repos.count()); │ │1241 + } │ │1242 + │ │1243 // │ │1244 // remove the user │ │1245 // │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1262 const event_id_to_user_cursor = try haxy_moment.getCursor(hash.hashInt(repo_opts.hash, "event-id->user")) orelse return error.NotFound;│ │1263 const event_id_to_user = try Repo.DB.HashMap(.read_only).init(event_id_to_user_cursor); │ │1264 │ │1237 - try std.testing.expect(null == try event_id_to_user.getCursor(hash.hashInt(repo_opts.hash, &user_event_id))); │ │1265 + const user_cursor = try event_id_to_user.getCursor(hash.hashInt(repo_opts.hash, &user_event_id)) orelse return error.NotFound; │ │1266 + const user_map = try Repo.DB.HashMap(.read_only).init(user_cursor); │ │1267 + const user_event = try evt.read(evt.User.Record, Repo.DB, repo_opts.hash, &arena, user_map); │ │1268 + try std.testing.expect(user_event.deleted); │ │1269 + │ │1270 + // deleting the user tombstones their active repos too │ │1271 + const event_id_to_repo_cursor = try haxy_moment.getCursor(hash.hashInt(repo_opts.hash, "event-id->repo")) orelse return error.NotFound;│ │1272 + const event_id_to_repo = try Repo.DB.HashMap(.read_only).init(event_id_to_repo_cursor); │ │1273 + const repo_cursor = try event_id_to_repo.getCursor(hash.hashInt(repo_opts.hash, &repo_event_id)) orelse return error.NotFound; │ │1274 + const repo_map = try Repo.DB.HashMap(.read_only).init(repo_cursor); │ │1275 + const repo_event = try evt.read(evt.Repo.Record, Repo.DB, repo_opts.hash, &arena, repo_map); │ │1276 + try std.testing.expect(repo_event.deleted); │ │1277 } │ │1278 } │ │1279 │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1355 try std.testing.expectEqual(1, try uset.count()); │ │1356 } │ │1357 │ │1319 - // delete repo1 -> dense order (no tombstone) │ │1358 + // deleting repo1 retains its place in the canonical order │ │1359 try evt.consume(.xit, repo_opts, io, allocator, &repo, evt.events_ref, &[_]evt.EventWithId{ │ │1360 .{ .id = std.fmt.bytesToHex(repo_ids[1], .lower), .author_email = author_email, .timestamp = 200, .event = .{ .repo = null } },│ │1361 }); │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1362 { │ │1363 const moment = try evt.currentMoment(repo_opts, &repo); │ │1325 - try Check.order(Repo.DB, repo_opts.hash, moment, &.{ &repo_ids[3], &repo_ids[2], &repo_ids[0] }); │ │1364 + try Check.order(Repo.DB, repo_opts.hash, moment, &.{ &repo_ids[3], &repo_ids[2], &repo_ids[1], &repo_ids[0] });│ │1365 } │ │1366 │ │1367 // update repo0 at a later timestamp -> keeps its original place │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1370 }); │ │1371 { │ │1372 const moment = try evt.currentMoment(repo_opts, &repo); │ │1334 - try Check.order(Repo.DB, repo_opts.hash, moment, &.{ &repo_ids[3], &repo_ids[2], &repo_ids[0] }); │ │1373 + try Check.order(Repo.DB, repo_opts.hash, moment, &.{ &repo_ids[3], &repo_ids[2], &repo_ids[1], &repo_ids[0] }); │ │1374 │ │1375 // the value really was updated │ │1376 const e2r_cur = try moment.getCursor(hash.hashInt(repo_opts.hash, "event-id->repo")) orelse return error.NotFound;│ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯