╭─────────────╮ │scroll to top│ ╰─────────────╯ ╭ event.zig ────────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │http│ ssh │ │ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
818 819 var prng = std.Random.DefaultPrng.init(std.testing.random_seed); 820 const user_event_id = evt.EventWithId.randomId(prng.random()); 821 const repo_event_id = evt.EventWithId.randomId(prng.random()); 822 823 var first_password_hash_buf: [evt.User.password_hash_max_len]u8 = undefined; 824 const first_password_hash = try evt.User.hashPassword("correct horse battery staple", &first_password_hash_buf, io); 825 826 var second_password_hash_buf: [evt.User.password_hash_max_len]u8 = undefined; 827 const second_password_hash = try evt.User.hashPassword("Tr0ub4dor&3", &second_password_hash_buf, io); 828 829 const events_to_consume = [_]evt.EventWithId{ 830 .{ 831 .id = std.fmt.bytesToHex(user_event_id, .lower), 832 .event = .{ 833 .user = .{ 834 .name = "Alice Example", 835 .email = "alice@example.test", 836 .password_hash = first_password_hash, 837 }, 838 }, 839 }, 840 // this event edits the previous one because it has the same id 841 .{ 842 .id = std.fmt.bytesToHex(user_event_id, .lower), 843 .event = .{ 844 .user = .{ 845 .name = "Alice Example", 846 .email = "alice@example.test", 847 .password_hash = second_password_hash, 848 }, 849 }, 850 }, 851 .{ 852 .id = std.fmt.bytesToHex(repo_event_id, .lower), 853 .event = .{ 854 .repo = .{ 855 .user_id = &user_event_id, 856 .name = "ziglings", 857 .enable_issue = true, 858 }, 859 }, 860 }, 861 }; 862 863 // 864 // insert users and repos as commits in the repo 865 // 866 867 { 868 var json: std.Io.Writer.Allocating = .init(std.testing.allocator); 869 defer json.deinit(); 870 871 for (events_to_consume) |event| { 872 json.clearRetainingCapacity(); 873 874 try std.json.Stringify.value(event, .{}, &json.writer); 875 876 // commit the event into a special branch 877 _ = try repo.commitAtRef(io, allocator, .{ .message = json.written() }, null, .{ .kind = .head, .name = "haxy/meta" }); 878 } 879 } 880 881 // 882 // consume events into the database 883 // 884 885 { 886 try evt.consume(repo_opts, io, allocator, &repo, .{ .kind = .head, .name = "haxy/meta" }); 887 888 const history = try Repo.DB.ArrayList(.read_only).init(repo.core.db.rootCursor().readOnly()); 889 890 // read the moment we just created 891 const moment_cursor = try history.getCursor(-1) orelse return error.NotFound; 892 const moment = try Repo.DB.HashMap(.read_only).init(moment_cursor); 893 894 // get the last object id 895 const last_object_id_cursor = try moment.getCursor(hash.hashInt(repo_opts.hash, "haxy-last-object-id")) orelse return error.NotFound; 896 var last_object_id: [hash.byteLen(repo_opts.hash)]u8 = undefined; 897 _ = try last_object_id_cursor.readBytes(&last_object_id); 898 899 const haxy_cursor = try moment.getCursor(hash.hashInt(repo_opts.hash, "haxy")) orelse return error.NotFound; 900 const haxy = try Repo.DB.ArrayList(.read_only).init(haxy_cursor); 901 902 try std.testing.expectEqual(1, try haxy.count()); 903 904 const haxy_moments_cursor = try haxy.getCursor(-1) orelse return error.NotFound; 905 const haxy_moments = try Repo.DB.HashMap(.read_only).init(haxy_moments_cursor); 906 907 const haxy_moment_cursor = try haxy_moments.getCursor(hash.bytesToInt(repo_opts.hash, &last_object_id)) orelse return error.NotFound; 908 const haxy_moment = try Repo.DB.HashMap(.read_only).init(haxy_moment_cursor); 909 910 // get the map of users 911 const event_id_to_user_cursor = try haxy_moment.getCursor(hash.hashInt(repo_opts.hash, "event-id->user")) orelse return error.NotFound; 912 const event_id_to_user = try Repo.DB.HashMap(.read_only).init(event_id_to_user_cursor); 913 914 // get the user out of the map that was edited 915 const user_cursor = try event_id_to_user.getCursor(hash.hashInt(repo_opts.hash, &user_event_id)) orelse return error.NotFound; 916 const user_map = try Repo.DB.HashMap(.read_only).init(user_cursor); 917 const user_event = try evt.read(evt.User, Repo.DB, repo_opts.hash, &arena, user_map); 918 919 // the password was correctly edited 920 try std.testing.expectEqualStrings(events_to_consume[1].event.user.?.password_hash, user_event.password_hash); 921 922 // get the map of repos 923 const event_id_to_repo_cursor = try haxy_moment.getCursor(hash.hashInt(repo_opts.hash, "event-id->repo")) orelse return error.NotFound; 924 const event_id_to_repo = try Repo.DB.HashMap(.read_only).init(event_id_to_repo_cursor); 925 926 // get the repo out of the map 927 const repo_cursor = try event_id_to_repo.getCursor(hash.hashInt(repo_opts.hash, &repo_event_id)) orelse return error.NotFound; 928 const repo_map = try Repo.DB.HashMap(.read_only).init(repo_cursor); 929 const repo_event = try evt.read(evt.Repo, Repo.DB, repo_opts.hash, &arena, repo_map); 930 931 try std.testing.expectEqualSlices(u8, &user_event_id, repo_event.user_id); 932 try std.testing.expectEqualStrings("ziglings", repo_event.name); 933 934 // get the repos created by the user 935 const user_id_to_repos_cursor = try haxy_moment.getCursor(hash.hashInt(repo_opts.hash, "user-id->repos")) orelse return error.NotFound; 936 const user_id_to_repos = try Repo.DB.HashMap(.read_only).init(user_id_to_repos_cursor); 937 938 const user_repos_cursor = try user_id_to_repos.getCursor(hash.hashInt(repo_opts.hash, &user_event_id)) orelse return error.NotFound; 939 const user_repos = try Repo.DB.CountedHashSet(.read_only).init(user_repos_cursor); 940 941 try std.testing.expectEqual(1, try user_repos.count()); 942 943 try std.testing.expect(null != try user_repos.getCursor(hash.hashInt(repo_opts.hash, &repo_event_id))); 944 } 945 946 // 947 // remove the repo 948 // 949 950 const events_to_consume2 = [_]evt.EventWithId{ 951 .{ 952 .id = std.fmt.bytesToHex(repo_event_id, .lower), 953 .event = .{ .repo = null }, 954 }, 955 }; 956 957 { 958 var json: std.Io.Writer.Allocating = .init(std.testing.allocator); 959 defer json.deinit(); 960 961 for (events_to_consume2) |event| { 962 json.clearRetainingCapacity(); 963 964 try std.json.Stringify.value(event, .{}, &json.writer); 965 966 // commit the event into a special branch 967 _ = try repo.commitAtRef(io, allocator, .{ .message = json.written() }, null, .{ .kind = .head, .name = "haxy/meta" }); 968 } 969 } 970 971 // 972 // consume the removal into the database 973 // 974 975 { 976 try evt.consume(repo_opts, io, allocator, &repo, .{ .kind = .head, .name = "haxy/meta" }); 977 978 const history = try Repo.DB.ArrayList(.read_only).init(repo.core.db.rootCursor().readOnly()); 979 980 // read the moment we just created 981 const moment_cursor = try history.getCursor(-1) orelse return error.NotFound; 982 const moment = try Repo.DB.HashMap(.read_only).init(moment_cursor); 983 984 // get the last object id 985 const last_object_id_cursor = try moment.getCursor(hash.hashInt(repo_opts.hash, "haxy-last-object-id")) orelse return error.NotFound; 986 var last_object_id: [hash.byteLen(repo_opts.hash)]u8 = undefined; 987 _ = try last_object_id_cursor.readBytes(&last_object_id); 988 989 const haxy_cursor = try moment.getCursor(hash.hashInt(repo_opts.hash, "haxy")) orelse return error.NotFound; 990 const haxy = try Repo.DB.ArrayList(.read_only).init(haxy_cursor); 991 992 try std.testing.expectEqual(2, try haxy.count()); 993 994 const haxy_moments_cursor = try haxy.getCursor(-1) orelse return error.NotFound; 995 const haxy_moments = try Repo.DB.HashMap(.read_only).init(haxy_moments_cursor); 996 997 const haxy_moment_cursor = try haxy_moments.getCursor(hash.bytesToInt(repo_opts.hash, &last_object_id)) orelse return error.NotFound; 998 const haxy_moment = try Repo.DB.HashMap(.read_only).init(haxy_moment_cursor); 999 1000 // get the map of repos 1001 const event_id_to_repo_cursor = try haxy_moment.getCursor(hash.hashInt(repo_opts.hash, "event-id->repo")) orelse return error.NotFound; 1002 const event_id_to_repo = try Repo.DB.HashMap(.read_only).init(event_id_to_repo_cursor); 1003 1004 try std.testing.expect(null == try event_id_to_repo.getCursor(hash.hashInt(repo_opts.hash, &repo_event_id))); 1005 1006 // get the repos created by the user 1007 const user_id_to_repos_cursor = try haxy_moment.getCursor(hash.hashInt(repo_opts.hash, "user-id->repos")) orelse return error.NotFound; 1008 const user_id_to_repos = try Repo.DB.HashMap(.read_only).init(user_id_to_repos_cursor); 1009 1010 const user_repos_cursor = try user_id_to_repos.getCursor(hash.hashInt(repo_opts.hash, &user_event_id)) orelse return error.NotFound; 1011 const user_repos = try Repo.DB.CountedHashSet(.read_only).init(user_repos_cursor); 1012 1013 try std.testing.expectEqual(0, try user_repos.count()); 1014 try std.testing.expect(null == try user_repos.getCursor(hash.hashInt(repo_opts.hash, &repo_event_id))); 1015 } 1016 1017 // 1018 // remove the user 1019 // 1020 1021 const events_to_consume3 = [_]evt.EventWithId{ 1022 .{ 1023 .id = std.fmt.bytesToHex(user_event_id, .lower), 1024 .event = .{ .user = null }, 1025 }, 1026 }; 1027 1028 { 1029 var json: std.Io.Writer.Allocating = .init(std.testing.allocator); 1030 defer json.deinit(); 1031 1032 for (events_to_consume3) |event| { 1033 json.clearRetainingCapacity(); 1034 1035 try std.json.Stringify.value(event, .{}, &json.writer); 1036 1037 // commit the event into a special branch 1038 _ = try repo.commitAtRef(io, allocator, .{ .message = json.written() }, null, .{ .kind = .head, .name = "haxy/meta" }); 1039 } 1040 } 1041 1042 // 1043 // consume the user removal into the database 1044 // 1045 1046 { 1047 try evt.consume(repo_opts, io, allocator, &repo, .{ .kind = .head, .name = "haxy/meta" }); 1048 1049 const history = try Repo.DB.ArrayList(.read_only).init(repo.core.db.rootCursor().readOnly()); 1050 1051 // read the moment we just created 1052 const moment_cursor = try history.getCursor(-1) orelse return error.NotFound; 1053 const moment = try Repo.DB.HashMap(.read_only).init(moment_cursor); 1054 1055 // get the last object id 1056 const last_object_id_cursor = try moment.getCursor(hash.hashInt(repo_opts.hash, "haxy-last-object-id")) orelse return error.NotFound; 1057 var last_object_id: [hash.byteLen(repo_opts.hash)]u8 = undefined; 1058 _ = try last_object_id_cursor.readBytes(&last_object_id); 1059 1060 const haxy_cursor = try moment.getCursor(hash.hashInt(repo_opts.hash, "haxy")) orelse return error.NotFound; 1061 const haxy = try Repo.DB.ArrayList(.read_only).init(haxy_cursor); 1062 1063 try std.testing.expectEqual(3, try haxy.count()); 1064 1065 const haxy_moments_cursor = try haxy.getCursor(-1) orelse return error.NotFound; 1066 const haxy_moments = try Repo.DB.HashMap(.read_only).init(haxy_moments_cursor); 1067 1068 const haxy_moment_cursor = try haxy_moments.getCursor(hash.bytesToInt(repo_opts.hash, &last_object_id)) orelse return error.NotFound; 1069 const haxy_moment = try Repo.DB.HashMap(.read_only).init(haxy_moment_cursor); 1070 1071 // get the map of users 1072 const event_id_to_user_cursor = try haxy_moment.getCursor(hash.hashInt(repo_opts.hash, "event-id->user")) orelse return error.NotFound; 1073 const event_id_to_user = try Repo.DB.HashMap(.read_only).init(event_id_to_user_cursor); 1074 1075 try std.testing.expect(null == try event_id_to_user.getCursor(hash.hashInt(repo_opts.hash, &user_event_id))); 1076 } 1077 } 1078