╭─────────────╮ │scroll to top│ ╰─────────────╯ ╭ event.zig ────────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │http│ ssh │ │ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
881 comptime DB: type, 882 comptime hash_kind: hash.HashKind, 883 moment: DB.HashMap(.read_only), 884 expected: []const *const [evt.event_id_size]u8, 885 ) !void { 886 const cursor = try moment.getCursor(hash.hashInt(hash_kind, "repo-id-set")) orelse return error.NotFound; 887 const set = try DB.SortedSet(.read_only).init(cursor); 888 try std.testing.expectEqual(expected.len, try set.count()); 889 for (expected, 0..) |id, i| { 890 const kv = (try set.getIndexKeyValuePair(@intCast(i))) orelse return error.NotFound; 891 // the key is orderKey ([timestamp][event-id]); its trailing bytes are the id 892 var order_key: [@sizeOf(u64) + evt.event_id_size]u8 = undefined; 893 _ = try kv.key_cursor.readBytes(&order_key); 894 try std.testing.expectEqualSlices(u8, id, order_key[@sizeOf(u64)..]); 895 } 896 } 897 }; 898 899 // one user, then four repos, each with its own creation timestamp (user@100, 900 // repos@101..104) 901 const events = [_]evt.EventWithId{ 902 .{ .id = std.fmt.bytesToHex(user_id, .lower), .timestamp = 100, .event = .{ .user = .{ .name = "alice", .display_name = "Alice", .email = "alice@example.test", .password_hash = pw } } }, 903 .{ .id = std.fmt.bytesToHex(repo_ids[0], .lower), .timestamp = 101, .event = .{ .repo = .{ .user_id = &user_id, .name = "repo0", .description = "d0", .enable_issue = true } } }, 904 .{ .id = std.fmt.bytesToHex(repo_ids[1], .lower), .timestamp = 102, .event = .{ .repo = .{ .user_id = &user_id, .name = "repo1", .description = "d1", .enable_issue = true } } }, 905 .{ .id = std.fmt.bytesToHex(repo_ids[2], .lower), .timestamp = 103, .event = .{ .repo = .{ .user_id = &user_id, .name = "repo2", .description = "d2", .enable_issue = true } } }, 906 .{ .id = std.fmt.bytesToHex(repo_ids[3], .lower), .timestamp = 104, .event = .{ .repo = .{ .user_id = &user_id, .name = "repo3", .description = "d3", .enable_issue = true } } }, 907 }; 908 try evt.commitAndConsume(.xit, repo_opts, io, allocator, &repo, evt.events_ref, &events); 909 910 { 911 const moment = try evt.currentMoment(repo_opts, &repo); 912 try Check.order(Repo.DB, repo_opts.hash, moment, &.{ &repo_ids[0], &repo_ids[1], &repo_ids[2], &repo_ids[3] }); 913 914 // the single user shows up in its own ordered set 915 const ucur = try moment.getCursor(hash.hashInt(repo_opts.hash, "user-id-set")) orelse return error.NotFound; 916 const uset = try Repo.DB.SortedSet(.read_only).init(ucur); 917 try std.testing.expectEqual(1, try uset.count()); 918 } 919 920 // delete repo1 -> dense order (no tombstone) 921 try evt.commitAndConsume(.xit, repo_opts, io, allocator, &repo, evt.events_ref, &[_]evt.EventWithId{ 922 .{ .id = std.fmt.bytesToHex(repo_ids[1], .lower), .timestamp = 200, .event = .{ .repo = null } }, 923 }); 924 { 925 const moment = try evt.currentMoment(repo_opts, &repo); 926 try Check.order(Repo.DB, repo_opts.hash, moment, &.{ &repo_ids[0], &repo_ids[2], &repo_ids[3] }); 927 } 928 929 // update repo0 at a later timestamp -> keeps its original slot 930 try evt.commitAndConsume(.xit, repo_opts, io, allocator, &repo, evt.events_ref, &[_]evt.EventWithId{ 931 .{ .id = std.fmt.bytesToHex(repo_ids[0], .lower), .timestamp = 300, .event = .{ .repo = .{ .user_id = &user_id, .name = "repo0", .description = "updated", .enable_issue = true } } }, 932 }); 933 { 934 const moment = try evt.currentMoment(repo_opts, &repo); 935 try Check.order(Repo.DB, repo_opts.hash, moment, &.{ &repo_ids[0], &repo_ids[2], &repo_ids[3] }); 936 937 // the value really was updated 938 const e2r_cur = try moment.getCursor(hash.hashInt(repo_opts.hash, "event-id->repo")) orelse return error.NotFound; 939 const e2r = try Repo.DB.HashMap(.read_only).init(e2r_cur); 940 const rc = try e2r.getCursor(hash.hashInt(repo_opts.hash, &repo_ids[0])) orelse return error.NotFound; 941 const rm = try Repo.DB.HashMap(.read_only).init(rc); 942 const re = try evt.read(evt.Repo, Repo.DB, repo_opts.hash, &arena, rm); 943 try std.testing.expectEqualStrings("updated", re.description); 944 } 945 } 946