tigerbeetle-node 0.11.9 → 0.11.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.client.node.sha256 +1 -1
- package/dist/index.d.ts +70 -67
- package/dist/index.js +70 -67
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/scripts/build_lib.sh +22 -10
- package/src/index.ts +3 -0
- package/src/tigerbeetle/src/config.zig +2 -0
- package/src/tigerbeetle/src/constants.zig +18 -0
- package/src/tigerbeetle/src/lsm/forest_fuzz.zig +0 -2
- package/src/tigerbeetle/src/lsm/manifest_log_fuzz.zig +6 -5
- package/src/tigerbeetle/src/lsm/test.zig +5 -4
- package/src/tigerbeetle/src/lsm/tree.zig +3 -30
- package/src/tigerbeetle/src/lsm/tree_fuzz.zig +0 -2
- package/src/tigerbeetle/src/simulator.zig +34 -53
- package/src/tigerbeetle/src/testing/cluster/state_checker.zig +1 -1
- package/src/tigerbeetle/src/testing/cluster/storage_checker.zig +6 -6
- package/src/tigerbeetle/src/testing/cluster.zig +5 -99
- package/src/tigerbeetle/src/testing/storage.zig +26 -23
- package/src/tigerbeetle/src/vsr/journal.zig +86 -90
- package/src/tigerbeetle/src/vsr/replica.zig +631 -687
- package/src/tigerbeetle/src/vsr/replica_format.zig +12 -12
- package/src/tigerbeetle/src/vsr/superblock.zig +192 -110
- package/src/tigerbeetle/src/vsr/superblock_fuzz.zig +35 -8
- package/src/tigerbeetle/src/vsr/superblock_quorums.zig +48 -48
- package/src/tigerbeetle/src/vsr/superblock_quorums_fuzz.zig +50 -50
- package/src/tigerbeetle/src/vsr.zig +93 -29
|
@@ -38,7 +38,7 @@ pub const Clock = @import("vsr/clock.zig").Clock;
|
|
|
38
38
|
pub const JournalType = @import("vsr/journal.zig").JournalType;
|
|
39
39
|
pub const SlotRange = @import("vsr/journal.zig").SlotRange;
|
|
40
40
|
pub const SuperBlockType = superblock.SuperBlockType;
|
|
41
|
-
pub const VSRState = superblock.
|
|
41
|
+
pub const VSRState = superblock.SuperBlockHeader.VSRState;
|
|
42
42
|
|
|
43
43
|
/// The version of our Viewstamped Replication protocol in use, including customizations.
|
|
44
44
|
/// For backwards compatibility through breaking changes (e.g. upgrading checksums/ciphers).
|
|
@@ -106,9 +106,6 @@ pub const Command = enum(u8) {
|
|
|
106
106
|
do_view_change,
|
|
107
107
|
start_view,
|
|
108
108
|
|
|
109
|
-
recovery,
|
|
110
|
-
recovery_response,
|
|
111
|
-
|
|
112
109
|
request_start_view,
|
|
113
110
|
request_headers,
|
|
114
111
|
request_prepare,
|
|
@@ -323,8 +320,6 @@ pub const Header = extern struct {
|
|
|
323
320
|
.start_view_change => self.invalid_start_view_change(),
|
|
324
321
|
.do_view_change => self.invalid_do_view_change(),
|
|
325
322
|
.start_view => self.invalid_start_view(),
|
|
326
|
-
.recovery => self.invalid_recovery(),
|
|
327
|
-
.recovery_response => self.invalid_recovery_response(),
|
|
328
323
|
.request_start_view => self.invalid_request_start_view(),
|
|
329
324
|
.request_headers => self.invalid_request_headers(),
|
|
330
325
|
.request_prepare => self.invalid_request_prepare(),
|
|
@@ -527,29 +522,6 @@ pub const Header = extern struct {
|
|
|
527
522
|
return null;
|
|
528
523
|
}
|
|
529
524
|
|
|
530
|
-
fn invalid_recovery(self: *const Header) ?[]const u8 {
|
|
531
|
-
assert(self.command == .recovery);
|
|
532
|
-
if (self.parent != 0) return "parent != 0";
|
|
533
|
-
if (self.client != 0) return "client != 0";
|
|
534
|
-
if (self.request != 0) return "request != 0";
|
|
535
|
-
if (self.view != 0) return "view != 0";
|
|
536
|
-
if (self.op != 0) return "op != 0";
|
|
537
|
-
if (self.commit != 0) return "commit != 0";
|
|
538
|
-
if (self.timestamp != 0) return "timestamp != 0";
|
|
539
|
-
if (self.operation != .reserved) return "operation != .reserved";
|
|
540
|
-
return null;
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
fn invalid_recovery_response(self: *const Header) ?[]const u8 {
|
|
544
|
-
assert(self.command == .recovery_response);
|
|
545
|
-
if (self.parent != 0) return "parent != 0";
|
|
546
|
-
if (self.client != 0) return "client != 0";
|
|
547
|
-
if (self.request != 0) return "request != 0";
|
|
548
|
-
if (self.timestamp != 0) return "timestamp != 0";
|
|
549
|
-
if (self.operation != .reserved) return "operation != .reserved";
|
|
550
|
-
return null;
|
|
551
|
-
}
|
|
552
|
-
|
|
553
525
|
fn invalid_request_start_view(self: *const Header) ?[]const u8 {
|
|
554
526
|
assert(self.command == .request_start_view);
|
|
555
527
|
if (self.parent != 0) return "parent != 0";
|
|
@@ -1026,3 +998,95 @@ pub fn quorums(replica_count: u8) struct {
|
|
|
1026
998
|
.view_change = quorum_view_change,
|
|
1027
999
|
};
|
|
1028
1000
|
}
|
|
1001
|
+
|
|
1002
|
+
/// The SuperBlock's persisted VSR headers.
|
|
1003
|
+
/// One of the following:
|
|
1004
|
+
///
|
|
1005
|
+
/// - SV headers (consecutive chain)
|
|
1006
|
+
/// - DVC headers (disjoint chain)
|
|
1007
|
+
pub const ViewChangeHeaders = struct {
|
|
1008
|
+
/// Headers are ordered from high-to-low op.
|
|
1009
|
+
slice: []const Header,
|
|
1010
|
+
|
|
1011
|
+
pub const BoundedArray = std.BoundedArray(Header, constants.pipeline_prepare_queue_max);
|
|
1012
|
+
|
|
1013
|
+
pub fn init(slice: []const Header) ViewChangeHeaders {
|
|
1014
|
+
ViewChangeHeaders.verify(slice);
|
|
1015
|
+
|
|
1016
|
+
return .{ .slice = slice };
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
pub fn verify(slice: []const Header) void {
|
|
1020
|
+
assert(slice.len > 0);
|
|
1021
|
+
assert(slice.len <= constants.pipeline_prepare_queue_max);
|
|
1022
|
+
|
|
1023
|
+
var child: ?*const Header = null;
|
|
1024
|
+
for (slice) |*header| {
|
|
1025
|
+
assert(header.valid_checksum());
|
|
1026
|
+
assert(header.command == .prepare);
|
|
1027
|
+
|
|
1028
|
+
if (child) |child_header| {
|
|
1029
|
+
assert(header.op < child_header.op);
|
|
1030
|
+
assert(header.view <= child_header.view);
|
|
1031
|
+
assert((header.op + 1 == child_header.op) ==
|
|
1032
|
+
(header.checksum == child_header.parent));
|
|
1033
|
+
assert(header.timestamp < child_header.timestamp);
|
|
1034
|
+
}
|
|
1035
|
+
child = header;
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
const ViewRange = struct {
|
|
1040
|
+
min: u32, // inclusive
|
|
1041
|
+
max: u32, // inclusive
|
|
1042
|
+
|
|
1043
|
+
pub fn contains(range: ViewRange, view: u32) bool {
|
|
1044
|
+
return range.min <= view and view <= range.max;
|
|
1045
|
+
}
|
|
1046
|
+
};
|
|
1047
|
+
|
|
1048
|
+
/// Returns the range of possible views (of prepare, not commit) for a message that is part of
|
|
1049
|
+
/// the same log_view as these headers.
|
|
1050
|
+
///
|
|
1051
|
+
/// - When these are DVC headers for a log_view=V, we must be in view_change status working to
|
|
1052
|
+
/// transition to a view beyond V. So we will never prepare anything else as part of view V.
|
|
1053
|
+
/// - When these are SV headers for a log_view=V, we can continue to add to them (by preparing
|
|
1054
|
+
/// more ops), but those ops will laways be part of the log_view. If they were prepared during
|
|
1055
|
+
/// a view prior to the log_view, they would already be part of the headers.
|
|
1056
|
+
pub fn view_for_op(headers: ViewChangeHeaders, op: u64, log_view: u32) ViewRange {
|
|
1057
|
+
const header_newest = &headers.slice[0];
|
|
1058
|
+
const header_oldest = &headers.slice[headers.slice.len - 1];
|
|
1059
|
+
|
|
1060
|
+
if (op < header_oldest.op) return .{ .min = 0, .max = header_oldest.view };
|
|
1061
|
+
if (op > header_newest.op) return .{ .min = log_view, .max = log_view };
|
|
1062
|
+
|
|
1063
|
+
for (headers.slice) |*header| {
|
|
1064
|
+
if (header.op == op) return .{ .min = header.view, .max = header.view };
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
for (headers.slice[0 .. headers.slice.len - 1]) |*header_next, header_next_index| {
|
|
1068
|
+
const header_prev = headers.slice[header_next_index + 1];
|
|
1069
|
+
if (header_prev.op < op and op < header_next.op) {
|
|
1070
|
+
return .{ .min = header_prev.view, .max = header_next.view };
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
unreachable;
|
|
1074
|
+
}
|
|
1075
|
+
};
|
|
1076
|
+
|
|
1077
|
+
test "ViewChangeHeaders.view_for_op" {
|
|
1078
|
+
var headers_array = [_]Header{
|
|
1079
|
+
std.mem.zeroInit(Header, .{ .op = 9, .view = 10 }),
|
|
1080
|
+
std.mem.zeroInit(Header, .{ .op = 6, .view = 7 }),
|
|
1081
|
+
};
|
|
1082
|
+
|
|
1083
|
+
const headers = ViewChangeHeaders{ .slice = &headers_array };
|
|
1084
|
+
try std.testing.expect(std.meta.eql(headers.view_for_op(11, 12), .{ .min = 12, .max = 12 }));
|
|
1085
|
+
try std.testing.expect(std.meta.eql(headers.view_for_op(10, 12), .{ .min = 12, .max = 12 }));
|
|
1086
|
+
try std.testing.expect(std.meta.eql(headers.view_for_op(9, 12), .{ .min = 10, .max = 10 }));
|
|
1087
|
+
try std.testing.expect(std.meta.eql(headers.view_for_op(8, 12), .{ .min = 7, .max = 10 }));
|
|
1088
|
+
try std.testing.expect(std.meta.eql(headers.view_for_op(7, 12), .{ .min = 7, .max = 10 }));
|
|
1089
|
+
try std.testing.expect(std.meta.eql(headers.view_for_op(6, 12), .{ .min = 7, .max = 7 }));
|
|
1090
|
+
try std.testing.expect(std.meta.eql(headers.view_for_op(5, 12), .{ .min = 0, .max = 7 }));
|
|
1091
|
+
try std.testing.expect(std.meta.eql(headers.view_for_op(0, 12), .{ .min = 0, .max = 7 }));
|
|
1092
|
+
}
|