tigerbeetle-node 0.10.0 → 0.11.1

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.
Files changed (109) hide show
  1. package/README.md +302 -101
  2. package/dist/index.d.ts +70 -72
  3. package/dist/index.js +70 -72
  4. package/dist/index.js.map +1 -1
  5. package/package.json +9 -8
  6. package/scripts/download_node_headers.sh +14 -7
  7. package/src/index.ts +6 -10
  8. package/src/node.zig +6 -3
  9. package/src/tigerbeetle/scripts/benchmark.sh +4 -4
  10. package/src/tigerbeetle/scripts/confirm_image.sh +44 -0
  11. package/src/tigerbeetle/scripts/fuzz_loop.sh +15 -0
  12. package/src/tigerbeetle/scripts/fuzz_unique_errors.sh +7 -0
  13. package/src/tigerbeetle/scripts/install.sh +19 -4
  14. package/src/tigerbeetle/scripts/install_zig.bat +5 -1
  15. package/src/tigerbeetle/scripts/install_zig.sh +24 -14
  16. package/src/tigerbeetle/scripts/pre-commit.sh +9 -0
  17. package/src/tigerbeetle/scripts/shellcheck.sh +5 -0
  18. package/src/tigerbeetle/scripts/tests_on_alpine.sh +10 -0
  19. package/src/tigerbeetle/scripts/tests_on_ubuntu.sh +14 -0
  20. package/src/tigerbeetle/scripts/validate_docs.sh +17 -0
  21. package/src/tigerbeetle/src/benchmark.zig +29 -13
  22. package/src/tigerbeetle/src/c/tb_client/context.zig +248 -47
  23. package/src/tigerbeetle/src/c/tb_client/echo_client.zig +108 -0
  24. package/src/tigerbeetle/src/c/tb_client/packet.zig +2 -2
  25. package/src/tigerbeetle/src/c/tb_client/signal.zig +2 -4
  26. package/src/tigerbeetle/src/c/tb_client/thread.zig +17 -257
  27. package/src/tigerbeetle/src/c/tb_client.h +118 -84
  28. package/src/tigerbeetle/src/c/tb_client.zig +88 -23
  29. package/src/tigerbeetle/src/c/tb_client_header_test.zig +135 -0
  30. package/src/tigerbeetle/src/c/test.zig +371 -1
  31. package/src/tigerbeetle/src/cli.zig +37 -7
  32. package/src/tigerbeetle/src/config.zig +58 -17
  33. package/src/tigerbeetle/src/demo.zig +5 -2
  34. package/src/tigerbeetle/src/demo_01_create_accounts.zig +1 -1
  35. package/src/tigerbeetle/src/demo_03_create_transfers.zig +13 -0
  36. package/src/tigerbeetle/src/ewah.zig +11 -33
  37. package/src/tigerbeetle/src/ewah_benchmark.zig +8 -9
  38. package/src/tigerbeetle/src/io/linux.zig +1 -1
  39. package/src/tigerbeetle/src/lsm/README.md +308 -0
  40. package/src/tigerbeetle/src/lsm/binary_search.zig +137 -10
  41. package/src/tigerbeetle/src/lsm/bloom_filter.zig +43 -0
  42. package/src/tigerbeetle/src/lsm/compaction.zig +376 -397
  43. package/src/tigerbeetle/src/lsm/composite_key.zig +2 -0
  44. package/src/tigerbeetle/src/lsm/eytzinger.zig +1 -1
  45. package/src/tigerbeetle/src/{eytzinger_benchmark.zig → lsm/eytzinger_benchmark.zig} +34 -21
  46. package/src/tigerbeetle/src/lsm/forest.zig +21 -447
  47. package/src/tigerbeetle/src/lsm/forest_fuzz.zig +414 -0
  48. package/src/tigerbeetle/src/lsm/grid.zig +170 -76
  49. package/src/tigerbeetle/src/lsm/groove.zig +197 -133
  50. package/src/tigerbeetle/src/lsm/k_way_merge.zig +40 -18
  51. package/src/tigerbeetle/src/lsm/level_iterator.zig +28 -9
  52. package/src/tigerbeetle/src/lsm/manifest.zig +93 -180
  53. package/src/tigerbeetle/src/lsm/manifest_level.zig +161 -454
  54. package/src/tigerbeetle/src/lsm/manifest_log.zig +243 -356
  55. package/src/tigerbeetle/src/lsm/manifest_log_fuzz.zig +665 -0
  56. package/src/tigerbeetle/src/lsm/node_pool.zig +4 -0
  57. package/src/tigerbeetle/src/lsm/posted_groove.zig +65 -76
  58. package/src/tigerbeetle/src/lsm/segmented_array.zig +580 -251
  59. package/src/tigerbeetle/src/lsm/segmented_array_benchmark.zig +148 -0
  60. package/src/tigerbeetle/src/lsm/segmented_array_fuzz.zig +9 -0
  61. package/src/tigerbeetle/src/lsm/set_associative_cache.zig +62 -12
  62. package/src/tigerbeetle/src/lsm/table.zig +115 -68
  63. package/src/tigerbeetle/src/lsm/table_immutable.zig +30 -23
  64. package/src/tigerbeetle/src/lsm/table_iterator.zig +27 -17
  65. package/src/tigerbeetle/src/lsm/table_mutable.zig +63 -12
  66. package/src/tigerbeetle/src/lsm/test.zig +61 -56
  67. package/src/tigerbeetle/src/lsm/tree.zig +450 -407
  68. package/src/tigerbeetle/src/lsm/tree_fuzz.zig +461 -0
  69. package/src/tigerbeetle/src/main.zig +83 -8
  70. package/src/tigerbeetle/src/message_bus.zig +20 -9
  71. package/src/tigerbeetle/src/message_pool.zig +22 -19
  72. package/src/tigerbeetle/src/ring_buffer.zig +7 -3
  73. package/src/tigerbeetle/src/simulator.zig +179 -119
  74. package/src/tigerbeetle/src/state_machine.zig +381 -246
  75. package/src/tigerbeetle/src/static_allocator.zig +65 -0
  76. package/src/tigerbeetle/src/storage.zig +3 -7
  77. package/src/tigerbeetle/src/test/accounting/auditor.zig +577 -0
  78. package/src/tigerbeetle/src/test/accounting/workload.zig +823 -0
  79. package/src/tigerbeetle/src/test/cluster.zig +33 -81
  80. package/src/tigerbeetle/src/test/conductor.zig +366 -0
  81. package/src/tigerbeetle/src/test/fuzz.zig +121 -0
  82. package/src/tigerbeetle/src/test/id.zig +89 -0
  83. package/src/tigerbeetle/src/test/network.zig +45 -19
  84. package/src/tigerbeetle/src/test/packet_simulator.zig +40 -29
  85. package/src/tigerbeetle/src/test/priority_queue.zig +645 -0
  86. package/src/tigerbeetle/src/test/state_checker.zig +91 -69
  87. package/src/tigerbeetle/src/test/state_machine.zig +11 -35
  88. package/src/tigerbeetle/src/test/storage.zig +470 -106
  89. package/src/tigerbeetle/src/test/storage_checker.zig +204 -0
  90. package/src/tigerbeetle/src/tigerbeetle.zig +15 -16
  91. package/src/tigerbeetle/src/unit_tests.zig +13 -1
  92. package/src/tigerbeetle/src/util.zig +97 -11
  93. package/src/tigerbeetle/src/vopr.zig +495 -0
  94. package/src/tigerbeetle/src/vsr/client.zig +21 -3
  95. package/src/tigerbeetle/src/vsr/journal.zig +293 -212
  96. package/src/tigerbeetle/src/vsr/replica.zig +1086 -515
  97. package/src/tigerbeetle/src/vsr/superblock.zig +382 -637
  98. package/src/tigerbeetle/src/vsr/superblock_client_table.zig +14 -16
  99. package/src/tigerbeetle/src/vsr/superblock_free_set.zig +416 -153
  100. package/src/tigerbeetle/src/vsr/superblock_free_set_fuzz.zig +332 -0
  101. package/src/tigerbeetle/src/vsr/superblock_fuzz.zig +349 -0
  102. package/src/tigerbeetle/src/vsr/superblock_manifest.zig +62 -12
  103. package/src/tigerbeetle/src/vsr/superblock_quorums.zig +394 -0
  104. package/src/tigerbeetle/src/vsr/superblock_quorums_fuzz.zig +312 -0
  105. package/src/tigerbeetle/src/vsr.zig +94 -60
  106. package/src/tigerbeetle/scripts/vopr.bat +0 -48
  107. package/src/tigerbeetle/scripts/vopr.sh +0 -33
  108. package/src/tigerbeetle/src/benchmark_array_search.zig +0 -317
  109. package/src/tigerbeetle/src/benchmarks/perf.zig +0 -299
@@ -0,0 +1,108 @@
1
+ const std = @import("std");
2
+ const assert = std.debug.assert;
3
+ const mem = std.mem;
4
+
5
+ const config = @import("../../config.zig");
6
+ const vsr = @import("../../vsr.zig");
7
+ const Header = vsr.Header;
8
+
9
+ const RingBuffer = @import("../../ring_buffer.zig").RingBuffer;
10
+ const MessagePool = @import("../../message_pool.zig").MessagePool;
11
+ const Message = @import("../../message_pool.zig").MessagePool.Message;
12
+
13
+ pub fn EchoClient(comptime StateMachine_: type, comptime MessageBus: type) type {
14
+ return struct {
15
+ const Self = @This();
16
+
17
+ // Exposing the same types the real client does:
18
+ pub usingnamespace blk: {
19
+ const Client = @import("../../vsr/client.zig").Client(StateMachine_, MessageBus);
20
+ break :blk struct {
21
+ pub const StateMachine = Client.StateMachine;
22
+ pub const Error = Client.Error;
23
+ pub const Request = Client.Request;
24
+ };
25
+ };
26
+
27
+ request_queue: RingBuffer(Self.Request, config.client_request_queue_max, .array) = .{},
28
+ message_pool: *MessagePool,
29
+
30
+ pub fn init(
31
+ allocator: mem.Allocator,
32
+ id: u128,
33
+ cluster: u32,
34
+ replica_count: u8,
35
+ message_pool: *MessagePool,
36
+ message_bus_options: MessageBus.Options,
37
+ ) !Self {
38
+ _ = allocator;
39
+ _ = id;
40
+ _ = cluster;
41
+ _ = replica_count;
42
+ _ = message_bus_options;
43
+
44
+ return Self{
45
+ .message_pool = message_pool,
46
+ };
47
+ }
48
+
49
+ pub fn deinit(self: *Self, allocator: std.mem.Allocator) void {
50
+ _ = allocator;
51
+ // Drains all pending requests before deiniting.
52
+ self.reply();
53
+ }
54
+
55
+ pub fn tick(self: *Self) void {
56
+ self.reply();
57
+ }
58
+
59
+ pub fn request(
60
+ self: *Self,
61
+ user_data: u128,
62
+ callback: Self.Request.Callback,
63
+ operation: Self.StateMachine.Operation,
64
+ message: *Message,
65
+ message_body_size: usize,
66
+ ) void {
67
+ message.header.* = .{
68
+ .client = 0,
69
+ .request = 0,
70
+ .cluster = 0,
71
+ .command = .request,
72
+ .operation = vsr.Operation.from(Self.StateMachine, operation),
73
+ .size = @intCast(u32, @sizeOf(Header) + message_body_size),
74
+ };
75
+
76
+ if (self.request_queue.full()) {
77
+ callback(user_data, operation, error.TooManyOutstandingRequests);
78
+ return;
79
+ }
80
+
81
+ self.request_queue.push_assume_capacity(.{
82
+ .user_data = user_data,
83
+ .callback = callback,
84
+ .message = message.ref(),
85
+ });
86
+ }
87
+
88
+ pub fn get_message(self: *Self) *Message {
89
+ return self.message_pool.get_message();
90
+ }
91
+
92
+ pub fn unref(self: *Self, message: *Message) void {
93
+ self.message_pool.unref(message);
94
+ }
95
+
96
+ fn reply(self: *Self) void {
97
+ while (self.request_queue.pop()) |inflight| {
98
+ defer self.unref(inflight.message);
99
+
100
+ inflight.callback(
101
+ inflight.user_data,
102
+ inflight.message.header.operation.cast(Self.StateMachine),
103
+ inflight.message.body(),
104
+ );
105
+ }
106
+ }
107
+ };
108
+ }
@@ -4,11 +4,11 @@ const Atomic = std.atomic.Atomic;
4
4
 
5
5
  pub const Packet = extern struct {
6
6
  next: ?*Packet,
7
- user_data: usize,
7
+ user_data: ?*anyopaque,
8
8
  operation: u8,
9
9
  status: Status,
10
10
  data_size: u32,
11
- data: [*]const u8,
11
+ data: ?*anyopaque,
12
12
 
13
13
  pub const Status = enum(u8) {
14
14
  ok,
@@ -8,12 +8,10 @@ const Atomic = std.atomic.Atomic;
8
8
 
9
9
  const log = std.log.scoped(.tb_client_signal);
10
10
 
11
- /// A Signal is a way to trigger a registered callback on a tigerbeetle IO instace
11
+ /// A Signal is a way to trigger a registered callback on a tigerbeetle IO instance
12
12
  /// when notification occurs from another thread.
13
13
  /// It does this by using OS sockets (which are thread safe)
14
14
  /// to resolve IO.Completions on the tigerbeetle thread.
15
- ///
16
- /// TODO: implement a simpler version of this eventually..
17
15
  pub const Signal = struct {
18
16
  io: *IO,
19
17
  server_socket: os.socket_t,
@@ -50,7 +48,7 @@ pub const Signal = struct {
50
48
 
51
49
  // Windows requires that the socket is bound before listening
52
50
  if (builtin.target.os.tag == .windows) {
53
- var addr = std.net.Address.initIp4(.{ 127, 0, 0, 1 }, 0); // zero port lets the OS choose
51
+ const addr = std.net.Address.initIp4(.{ 127, 0, 0, 1 }, 0); // zero port lets the OS choose
54
52
  os.bind(self.server_socket, &addr.any, addr.getOsSockLen()) catch |err| {
55
53
  log.err("failed to bind the server socket to a local random port: {}", .{err});
56
54
  return switch (err) {
@@ -1,180 +1,44 @@
1
1
  const std = @import("std");
2
- const os = std.os;
3
2
  const assert = std.debug.assert;
4
3
 
5
4
  const config = @import("../../config.zig");
6
- const log = std.log.scoped(.tb_client);
7
-
8
- const vsr = @import("../../vsr.zig");
9
- const Header = vsr.Header;
10
-
11
- const IO = @import("../../io.zig").IO;
12
- const message_pool = @import("../../message_pool.zig");
13
-
14
- const MessagePool = message_pool.MessagePool;
15
- const Message = MessagePool.Message;
5
+ const log = std.log.scoped(.tb_client_thread);
16
6
 
17
7
  const Packet = @import("packet.zig").Packet;
18
8
  const Signal = @import("signal.zig").Signal;
19
9
 
20
10
  pub fn ThreadType(
21
- comptime StateMachine: type,
22
- comptime MessageBus: type,
11
+ comptime Context: type,
23
12
  ) type {
24
13
  return struct {
25
- pub const Client = vsr.Client(StateMachine, MessageBus);
26
- pub const Operation = StateMachine.Operation;
27
-
28
- fn operation_size_of(op: u8) ?usize {
29
- const allowed_operations = [_]Operation{
30
- .create_accounts,
31
- .create_transfers,
32
- .lookup_accounts,
33
- .lookup_transfers,
34
- };
35
-
36
- inline for (allowed_operations) |operation| {
37
- if (op == @enumToInt(operation)) {
38
- return @sizeOf(StateMachine.Event(operation));
39
- }
40
- }
41
-
42
- return null;
43
- }
44
-
45
- /////////////////////////////////////////////////////////////////////////
46
-
47
14
  const Self = @This();
48
15
 
49
- allocator: std.mem.Allocator,
50
- client_id: u128,
51
- packets: []Packet,
52
-
53
- addresses: []std.net.Address,
54
- io: IO,
55
- message_pool: MessagePool,
56
- message_bus: MessageBus,
57
- client: Client,
16
+ context: *Context,
58
17
 
59
18
  retry: Packet.List,
60
19
  submitted: Packet.Stack,
61
- available_messages: usize,
62
- on_completion_fn: CompletionFn,
63
20
 
64
21
  signal: Signal,
65
22
  thread: std.Thread,
66
23
 
67
- pub const CompletionFn = fn (
68
- client_thread: *Self,
69
- packet: *Packet,
70
- result: ?[]const u8,
71
- ) void;
72
-
73
- pub const Error = error{
74
- Unexpected,
75
- OutOfMemory,
76
- InvalidAddress,
77
- SystemResources,
78
- NetworkSubsystemFailed,
79
- };
80
-
81
24
  pub fn init(
82
25
  self: *Self,
83
- allocator: std.mem.Allocator,
84
- cluster_id: u32,
85
- addresses: []const u8,
86
- num_packets: u32,
87
- on_completion_fn: CompletionFn,
88
- ) Error!void {
89
- self.allocator = allocator;
90
- self.client_id = std.crypto.random.int(u128);
91
- log.debug("init: initializing client_id={}.", .{self.client_id});
92
-
93
- log.debug("init: allocating tb_packets.", .{});
94
- self.packets = self.allocator.alloc(Packet, num_packets) catch |err| {
95
- log.err("failed to allocate tb_packets: {}", .{err});
96
- return Error.OutOfMemory;
97
- };
98
- errdefer self.allocator.free(self.packets);
99
-
100
- log.debug("init: parsing vsr addresses.", .{});
101
- self.addresses = vsr.parse_addresses(self.allocator, addresses) catch |err| {
102
- log.err("failed to parse addresses: {}.", .{err});
103
- return Error.InvalidAddress;
104
- };
105
- errdefer self.allocator.free(self.addresses);
106
-
107
- log.debug("init: initializing IO.", .{});
108
- self.io = IO.init(32, 0) catch |err| {
109
- log.err("failed to initialize IO: {}.", .{err});
110
- return switch (err) {
111
- error.ProcessFdQuotaExceeded => error.SystemResources,
112
- error.Unexpected => error.Unexpected,
113
- else => unreachable,
114
- };
115
- };
116
- errdefer self.io.deinit();
117
-
118
- log.debug("init: initializing MessagePool", .{});
119
- self.message_pool = MessagePool.init(allocator, .client) catch |err| {
120
- log.err("failed to initialize MessagePool: {}", .{err});
121
- return err;
122
- };
123
- errdefer self.message_pool.deinit(self.allocator);
124
-
125
- log.debug("init: initializing MessageBus.", .{});
126
- self.message_bus = MessageBus.init(
127
- self.allocator,
128
- cluster_id,
129
- .{ .client = self.client_id },
130
- &self.message_pool,
131
- Client.on_message,
132
- .{
133
- .configuration = self.addresses,
134
- .io = &self.io,
135
- },
136
- ) catch |err| {
137
- log.err("failed to initialize message bus: {}.", .{err});
138
- return err;
139
- };
140
- errdefer self.message_bus.deinit(self.allocator);
141
-
142
- log.debug("init: Initializing client(cluster_id={d}, client_id={d}, addresses={o})", .{
143
- cluster_id,
144
- self.client_id,
145
- self.addresses,
146
- });
147
- self.client = Client.init(
148
- allocator,
149
- self.client_id,
150
- cluster_id,
151
- @intCast(u8, self.addresses.len),
152
- &self.message_pool,
153
- .{
154
- .configuration = self.addresses,
155
- .io = &self.io,
156
- },
157
- ) catch |err| {
158
- log.err("failed to initalize client: {}", .{err});
159
- return err;
160
- };
161
- errdefer self.client.deinit(self.allocator);
162
-
26
+ context: *Context,
27
+ ) !void {
28
+ self.context = context;
163
29
  self.retry = .{};
164
30
  self.submitted = .{};
165
- self.available_messages = message_pool.messages_max_client;
166
- self.on_completion_fn = on_completion_fn;
167
31
 
168
- log.debug("init: initializing Signal.", .{});
169
- self.signal.init(&self.io, Self.on_signal) catch |err| {
170
- log.err("failed to initialize Signal: {}.", .{err});
171
- return err;
172
- };
32
+ log.debug("{}: init: initializing signal", .{context.client_id});
33
+ try self.signal.init(&context.io, Self.on_signal);
173
34
  errdefer self.signal.deinit();
174
35
 
175
- log.debug("init: spawning Context thread.", .{});
176
- self.thread = std.Thread.spawn(.{}, Self.run, .{self}) catch |err| {
177
- log.err("failed to spawn context thread: {}.", .{err});
36
+ log.debug("{}: init: spawning thread", .{context.client_id});
37
+ self.thread = std.Thread.spawn(.{}, Context.run, .{context}) catch |err| {
38
+ log.err("{}: failed to spawn thread: {s}", .{
39
+ context.client_id,
40
+ @errorName(err),
41
+ });
178
42
  return switch (err) {
179
43
  error.Unexpected => error.Unexpected,
180
44
  error.OutOfMemory => error.OutOfMemory,
@@ -188,13 +52,6 @@ pub fn ThreadType(
188
52
  self.thread.join();
189
53
  self.signal.deinit();
190
54
 
191
- self.client.deinit(self.allocator);
192
- self.message_bus.deinit(self.allocator);
193
- self.message_pool.deinit(self.allocator);
194
- self.io.deinit();
195
-
196
- self.allocator.free(self.addresses);
197
- self.allocator.free(self.packets);
198
55
  self.* = undefined;
199
56
  }
200
57
 
@@ -204,19 +61,9 @@ pub fn ThreadType(
204
61
  self.signal.notify();
205
62
  }
206
63
 
207
- fn run(self: *Self) void {
208
- while (!self.signal.is_shutdown()) {
209
- self.client.tick();
210
- self.io.run_for_ns(config.tick_ms * std.time.ns_per_ms) catch |err| {
211
- log.err("IO.run() failed with {}", .{err});
212
- return;
213
- };
214
- }
215
- }
216
-
217
64
  fn on_signal(signal: *Signal) void {
218
65
  const self = @fieldParentPtr(Self, "signal", signal);
219
- self.client.tick();
66
+ self.context.tick();
220
67
 
221
68
  // Consume all of retry here to avoid infinite loop
222
69
  // if the code below pushes to self.retry while we're dequeueing.
@@ -233,97 +80,10 @@ pub fn ThreadType(
233
80
  }
234
81
 
235
82
  // Process packets from either pending or submitted as long as we have messages.
236
- while (self.available_messages > 0) {
83
+ while (self.context.messages_available > 0) {
237
84
  const packet = pending.pop() orelse self.submitted.pop() orelse break;
238
- const message = self.client.get_message();
239
- self.available_messages -= 1;
240
- self.request(packet, message);
85
+ self.context.request(packet);
241
86
  }
242
87
  }
243
-
244
- fn request(self: *Self, packet: *Packet, message: *Message) void {
245
- // Get the size of each request structure in the packet.data
246
- const request_size: usize = operation_size_of(packet.operation) orelse {
247
- return self.on_complete(packet, message, error.InvalidOperation);
248
- };
249
-
250
- // Make sure the packet.data size is correct.
251
- const readable = packet.data[0..packet.data_size];
252
- if (readable.len == 0 or readable.len % request_size != 0) {
253
- return self.on_complete(packet, message, error.InvalidDataSize);
254
- }
255
-
256
- // Make sure the packet.data wouldn't overflow a message.
257
- const writable = message.buffer[@sizeOf(Header)..];
258
- if (readable.len > writable.len) {
259
- return self.on_complete(packet, message, error.TooMuchData);
260
- }
261
-
262
- // Write the packet data to the message
263
- std.mem.copy(u8, writable, readable);
264
- const wrote = readable.len;
265
-
266
- // .. and submit the message for processing
267
- self.client.request(
268
- @bitCast(u128, UserData{
269
- .self = self,
270
- .packet = packet,
271
- }),
272
- Self.on_result,
273
- @intToEnum(Operation, packet.operation),
274
- message,
275
- wrote,
276
- );
277
- }
278
-
279
- const UserData = packed struct {
280
- self: *Self,
281
- packet: *Packet,
282
- };
283
-
284
- fn on_result(raw_user_data: u128, op: Operation, results: Client.Error![]const u8) void {
285
- const user_data = @bitCast(UserData, raw_user_data);
286
- const self = user_data.self;
287
- const packet = user_data.packet;
288
-
289
- // Complete the packet without a message as it's already unref()'s by the Client.
290
- assert(packet.operation == @enumToInt(op));
291
- self.on_complete(packet, null, results);
292
- }
293
-
294
- const PacketError = Client.Error || error{
295
- TooMuchData,
296
- InvalidOperation,
297
- InvalidDataSize,
298
- };
299
-
300
- fn on_complete(
301
- self: *Self,
302
- packet: *Packet,
303
- message: ?*Message,
304
- result: PacketError![]const u8,
305
- ) void {
306
- // Mark the message as completed
307
- if (message) |m| self.client.unref(m);
308
- assert(self.available_messages < message_pool.messages_max_client);
309
- self.available_messages += 1;
310
-
311
- const bytes = result catch |err| {
312
- packet.status = switch (err) {
313
- // If there's too many requests, (re)try submitting the packet later
314
- error.TooManyOutstandingRequests => {
315
- return self.retry.push(Packet.List.from(packet));
316
- },
317
- error.TooMuchData => .too_much_data,
318
- error.InvalidOperation => .invalid_operation,
319
- error.InvalidDataSize => .invalid_data_size,
320
- };
321
- return self.on_completion_fn(self, packet, null);
322
- };
323
-
324
- // The packet completed normally
325
- packet.status = .ok;
326
- self.on_completion_fn(self, packet, bytes);
327
- }
328
88
  };
329
89
  }