tigerbeetle-node 0.9.0 → 0.9.143

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 (79) hide show
  1. package/README.md +580 -179
  2. package/dist/benchmark.js +44 -36
  3. package/dist/benchmark.js.map +1 -1
  4. package/dist/bin/aarch64-linux-gnu/client.node +0 -0
  5. package/dist/bin/aarch64-linux-musl/client.node +0 -0
  6. package/dist/bin/aarch64-macos/client.node +0 -0
  7. package/dist/bin/x86_64-linux-gnu/client.node +0 -0
  8. package/dist/bin/x86_64-linux-musl/client.node +0 -0
  9. package/dist/bin/x86_64-macos/client.node +0 -0
  10. package/dist/bin/x86_64-windows/client.node +0 -0
  11. package/dist/bindings.d.ts +141 -0
  12. package/dist/bindings.js +112 -0
  13. package/dist/bindings.js.map +1 -0
  14. package/dist/index.d.ts +2 -125
  15. package/dist/index.js +51 -101
  16. package/dist/index.js.map +1 -1
  17. package/dist/test.js +68 -54
  18. package/dist/test.js.map +1 -1
  19. package/package-lock.json +26 -0
  20. package/package.json +13 -22
  21. package/src/benchmark.ts +58 -49
  22. package/src/bindings.ts +631 -0
  23. package/src/index.ts +71 -163
  24. package/src/node.zig +169 -148
  25. package/src/test.ts +71 -57
  26. package/src/translate.zig +19 -36
  27. package/scripts/download_node_headers.sh +0 -25
  28. package/src/tigerbeetle/scripts/benchmark.bat +0 -46
  29. package/src/tigerbeetle/scripts/benchmark.sh +0 -55
  30. package/src/tigerbeetle/scripts/install.sh +0 -6
  31. package/src/tigerbeetle/scripts/install_zig.bat +0 -109
  32. package/src/tigerbeetle/scripts/install_zig.sh +0 -84
  33. package/src/tigerbeetle/scripts/lint.zig +0 -199
  34. package/src/tigerbeetle/scripts/upgrade_ubuntu_kernel.sh +0 -39
  35. package/src/tigerbeetle/scripts/vopr.bat +0 -48
  36. package/src/tigerbeetle/scripts/vopr.sh +0 -33
  37. package/src/tigerbeetle/scripts/vr_state_enumerate +0 -46
  38. package/src/tigerbeetle/src/benchmark.zig +0 -290
  39. package/src/tigerbeetle/src/cli.zig +0 -244
  40. package/src/tigerbeetle/src/config.zig +0 -239
  41. package/src/tigerbeetle/src/demo.zig +0 -125
  42. package/src/tigerbeetle/src/demo_01_create_accounts.zig +0 -35
  43. package/src/tigerbeetle/src/demo_02_lookup_accounts.zig +0 -7
  44. package/src/tigerbeetle/src/demo_03_create_transfers.zig +0 -24
  45. package/src/tigerbeetle/src/demo_04_create_pending_transfers.zig +0 -61
  46. package/src/tigerbeetle/src/demo_05_post_pending_transfers.zig +0 -37
  47. package/src/tigerbeetle/src/demo_06_void_pending_transfers.zig +0 -24
  48. package/src/tigerbeetle/src/demo_07_lookup_transfers.zig +0 -7
  49. package/src/tigerbeetle/src/fifo.zig +0 -104
  50. package/src/tigerbeetle/src/io/benchmark.zig +0 -213
  51. package/src/tigerbeetle/src/io/darwin.zig +0 -793
  52. package/src/tigerbeetle/src/io/linux.zig +0 -1038
  53. package/src/tigerbeetle/src/io/test.zig +0 -643
  54. package/src/tigerbeetle/src/io/windows.zig +0 -1161
  55. package/src/tigerbeetle/src/io.zig +0 -34
  56. package/src/tigerbeetle/src/main.zig +0 -144
  57. package/src/tigerbeetle/src/message_bus.zig +0 -1000
  58. package/src/tigerbeetle/src/message_pool.zig +0 -142
  59. package/src/tigerbeetle/src/ring_buffer.zig +0 -289
  60. package/src/tigerbeetle/src/simulator.zig +0 -417
  61. package/src/tigerbeetle/src/state_machine.zig +0 -2470
  62. package/src/tigerbeetle/src/storage.zig +0 -308
  63. package/src/tigerbeetle/src/test/cluster.zig +0 -351
  64. package/src/tigerbeetle/src/test/message_bus.zig +0 -93
  65. package/src/tigerbeetle/src/test/network.zig +0 -179
  66. package/src/tigerbeetle/src/test/packet_simulator.zig +0 -387
  67. package/src/tigerbeetle/src/test/state_checker.zig +0 -145
  68. package/src/tigerbeetle/src/test/state_machine.zig +0 -76
  69. package/src/tigerbeetle/src/test/storage.zig +0 -438
  70. package/src/tigerbeetle/src/test/time.zig +0 -84
  71. package/src/tigerbeetle/src/tigerbeetle.zig +0 -222
  72. package/src/tigerbeetle/src/time.zig +0 -113
  73. package/src/tigerbeetle/src/unit_tests.zig +0 -14
  74. package/src/tigerbeetle/src/vsr/client.zig +0 -505
  75. package/src/tigerbeetle/src/vsr/clock.zig +0 -812
  76. package/src/tigerbeetle/src/vsr/journal.zig +0 -2293
  77. package/src/tigerbeetle/src/vsr/marzullo.zig +0 -309
  78. package/src/tigerbeetle/src/vsr/replica.zig +0 -5015
  79. package/src/tigerbeetle/src/vsr.zig +0 -1017
package/src/node.zig CHANGED
@@ -3,7 +3,7 @@ const assert = std.debug.assert;
3
3
 
4
4
  const c = @import("c.zig");
5
5
  const translate = @import("translate.zig");
6
- const tb = @import("tigerbeetle/src/tigerbeetle.zig");
6
+ const tb = @import("../../../tigerbeetle.zig");
7
7
 
8
8
  const Account = tb.Account;
9
9
  const AccountFlags = tb.AccountFlags;
@@ -12,17 +12,22 @@ const TransferFlags = tb.TransferFlags;
12
12
  const CreateAccountsResult = tb.CreateAccountsResult;
13
13
  const CreateTransfersResult = tb.CreateTransfersResult;
14
14
 
15
- const StateMachine = @import("tigerbeetle/src/state_machine.zig").StateMachine;
15
+ const Storage = @import("../../../storage.zig").Storage;
16
+ const StateMachine = @import("../../../state_machine.zig").StateMachineType(Storage, constants.state_machine_config);
16
17
  const Operation = StateMachine.Operation;
17
- const MessageBus = @import("tigerbeetle/src/message_bus.zig").MessageBusClient;
18
- const IO = @import("tigerbeetle/src/io.zig").IO;
19
- const config = @import("tigerbeetle/src/config.zig");
18
+ const MessageBus = @import("../../../message_bus.zig").MessageBusClient;
19
+ const MessagePool = @import("../../../message_pool.zig").MessagePool;
20
+ const IO = @import("../../../io.zig").IO;
21
+ const constants = @import("../../../constants.zig");
20
22
 
21
- const vsr = @import("tigerbeetle/src/vsr.zig");
23
+ const vsr = @import("../../../vsr.zig");
22
24
  const Header = vsr.Header;
23
25
  const Client = vsr.Client(StateMachine, MessageBus);
24
26
 
25
- pub const log_level: std.log.Level = .info;
27
+ pub const std_options = struct {
28
+ // Since this is running in application space, log only critical messages to reduce noise.
29
+ pub const log_level: std.log.Level = .err;
30
+ };
26
31
 
27
32
  /// N-API will call this constructor automatically to register the module.
28
33
  export fn napi_register_module_v1(env: c.napi_env, exports: c.napi_value) c.napi_value {
@@ -36,7 +41,7 @@ export fn napi_register_module_v1(env: c.napi_env, exports: c.napi_value) c.napi
36
41
  env,
37
42
  exports,
38
43
  "tick_ms",
39
- config.tick_ms,
44
+ constants.tick_ms,
40
45
  "failed to add tick_ms to exports",
41
46
  ) catch return null;
42
47
 
@@ -54,7 +59,7 @@ export fn napi_register_module_v1(env: c.napi_env, exports: c.napi_value) c.napi
54
59
  // state.
55
60
  translate.set_instance_data(
56
61
  env,
57
- @ptrCast(*anyopaque, @alignCast(@alignOf(u8), global)),
62
+ @ptrCast(@alignCast(global)),
58
63
  Globals.destroy,
59
64
  ) catch {
60
65
  global.deinit();
@@ -112,14 +117,14 @@ const Globals = struct {
112
117
  };
113
118
 
114
119
  fn globalsCast(globals_raw: *anyopaque) *Globals {
115
- return @ptrCast(*Globals, @alignCast(@alignOf(Globals), globals_raw));
120
+ return @ptrCast(@alignCast(globals_raw));
116
121
  }
117
122
 
118
123
  const Context = struct {
119
124
  io: *IO,
120
125
  addresses: []std.net.Address,
121
- message_bus: MessageBus,
122
126
  client: Client,
127
+ message_pool: MessagePool,
123
128
 
124
129
  fn create(
125
130
  env: c.napi_env,
@@ -132,39 +137,33 @@ const Context = struct {
132
137
  errdefer allocator.destroy(context);
133
138
 
134
139
  context.io = io;
140
+ context.message_pool = try MessagePool.init(allocator, .client);
141
+ errdefer context.message_pool.deinit(allocator);
135
142
 
136
- context.addresses = try vsr.parse_addresses(allocator, addresses_raw);
143
+ context.addresses = try vsr.parse_addresses(allocator, addresses_raw, constants.replicas_max);
137
144
  errdefer allocator.free(context.addresses);
138
145
  assert(context.addresses.len > 0);
139
146
 
140
147
  const client_id = std.crypto.random.int(u128);
141
-
142
- context.message_bus = try MessageBus.init(
143
- allocator,
144
- cluster,
145
- context.addresses,
146
- client_id,
147
- context.io,
148
- );
149
- errdefer context.message_bus.deinit();
150
-
151
148
  context.client = try Client.init(
152
149
  allocator,
153
150
  client_id,
154
151
  cluster,
155
- @intCast(u8, context.addresses.len),
156
- &context.message_bus,
152
+ @as(u8, @intCast(context.addresses.len)),
153
+ &context.message_pool,
154
+ .{
155
+ .configuration = context.addresses,
156
+ .io = context.io,
157
+ },
157
158
  );
158
- errdefer context.client.deinit();
159
-
160
- context.message_bus.set_on_message(*Client, &context.client, Client.on_message);
159
+ errdefer context.client.deinit(allocator);
161
160
 
162
161
  return try translate.create_external(env, context);
163
162
  }
164
163
  };
165
164
 
166
165
  fn contextCast(context_raw: *anyopaque) !*Context {
167
- return @ptrCast(*Context, @alignCast(@alignOf(Context), context_raw));
166
+ return @ptrCast(@alignCast(context_raw));
168
167
  }
169
168
 
170
169
  fn validate_timestamp(env: c.napi_env, object: c.napi_value) !u64 {
@@ -185,27 +184,30 @@ fn decode_from_object(comptime T: type, env: c.napi_env, object: c.napi_value) !
185
184
  .id = try translate.u128_from_object(env, object, "id"),
186
185
  .debit_account_id = try translate.u128_from_object(env, object, "debit_account_id"),
187
186
  .credit_account_id = try translate.u128_from_object(env, object, "credit_account_id"),
188
- .user_data = try translate.u128_from_object(env, object, "user_data"),
189
- .reserved = try translate.u128_from_object(env, object, "reserved"),
187
+ .amount = try translate.u128_from_object(env, object, "amount"),
190
188
  .pending_id = try translate.u128_from_object(env, object, "pending_id"),
191
- .timeout = try translate.u64_from_object(env, object, "timeout"),
189
+ .user_data_128 = try translate.u128_from_object(env, object, "user_data_128"),
190
+ .user_data_64 = try translate.u64_from_object(env, object, "user_data_64"),
191
+ .user_data_32 = try translate.u32_from_object(env, object, "user_data_32"),
192
+ .timeout = try translate.u32_from_object(env, object, "timeout"),
192
193
  .ledger = try translate.u32_from_object(env, object, "ledger"),
193
194
  .code = try translate.u16_from_object(env, object, "code"),
194
- .flags = @bitCast(TransferFlags, try translate.u16_from_object(env, object, "flags")),
195
- .amount = try translate.u64_from_object(env, object, "amount"),
195
+ .flags = @as(TransferFlags, @bitCast(try translate.u16_from_object(env, object, "flags"))),
196
196
  .timestamp = try validate_timestamp(env, object),
197
197
  },
198
198
  Account => Account{
199
199
  .id = try translate.u128_from_object(env, object, "id"),
200
- .user_data = try translate.u128_from_object(env, object, "user_data"),
201
- .reserved = try translate.bytes_from_object(env, object, 48, "reserved"),
200
+ .debits_pending = try translate.u128_from_object(env, object, "debits_pending"),
201
+ .debits_posted = try translate.u128_from_object(env, object, "debits_posted"),
202
+ .credits_pending = try translate.u128_from_object(env, object, "credits_pending"),
203
+ .credits_posted = try translate.u128_from_object(env, object, "credits_posted"),
204
+ .user_data_128 = try translate.u128_from_object(env, object, "user_data_128"),
205
+ .user_data_64 = try translate.u64_from_object(env, object, "user_data_64"),
206
+ .user_data_32 = try translate.u32_from_object(env, object, "user_data_32"),
207
+ .reserved = try translate.u32_from_object(env, object, "reserved"),
202
208
  .ledger = try translate.u32_from_object(env, object, "ledger"),
203
209
  .code = try translate.u16_from_object(env, object, "code"),
204
- .flags = @bitCast(AccountFlags, try translate.u16_from_object(env, object, "flags")),
205
- .debits_pending = try translate.u64_from_object(env, object, "debits_pending"),
206
- .debits_posted = try translate.u64_from_object(env, object, "debits_posted"),
207
- .credits_pending = try translate.u64_from_object(env, object, "credits_pending"),
208
- .credits_posted = try translate.u64_from_object(env, object, "credits_posted"),
210
+ .flags = @bitCast(try translate.u16_from_object(env, object, "flags")),
209
211
  .timestamp = try validate_timestamp(env, object),
210
212
  },
211
213
  u128 => try translate.u128_from_value(env, object, "lookup"),
@@ -224,7 +226,6 @@ pub fn decode_events(
224
226
  .create_transfers => try decode_events_from_array(env, array, Transfer, output),
225
227
  .lookup_accounts => try decode_events_from_array(env, array, u128, output),
226
228
  .lookup_transfers => try decode_events_from_array(env, array, u128, output),
227
- else => unreachable,
228
229
  };
229
230
  }
230
231
 
@@ -238,7 +239,7 @@ fn decode_events_from_array(
238
239
  if (array_length < 1) return translate.throw(env, "Batch must contain at least one event.");
239
240
 
240
241
  const body_length = @sizeOf(T) * array_length;
241
- if (@sizeOf(Header) + body_length > config.message_size_max) {
242
+ if (@sizeOf(Header) + body_length > constants.message_size_max) {
242
243
  return translate.throw(env, "Batch is larger than the maximum message size.");
243
244
  }
244
245
 
@@ -263,7 +264,7 @@ fn encode_napi_results_array(
263
264
  const results = std.mem.bytesAsSlice(Result, data);
264
265
  const napi_array = try translate.create_array(
265
266
  env,
266
- @intCast(u32, results.len),
267
+ @as(u32, @intCast(results.len)),
267
268
  "Failed to allocate array for results.",
268
269
  );
269
270
 
@@ -288,9 +289,9 @@ fn encode_napi_results_array(
288
289
  try translate.u32_into_object(
289
290
  env,
290
291
  napi_object,
291
- "code",
292
- @enumToInt(result.result),
293
- "Failed to set property \"code\" of result.",
292
+ "result",
293
+ @intFromEnum(result.result),
294
+ "Failed to set property \"result\" of result.",
294
295
  );
295
296
 
296
297
  try translate.set_array_element(
@@ -322,73 +323,89 @@ fn encode_napi_results_array(
322
323
  try translate.u128_into_object(
323
324
  env,
324
325
  napi_object,
325
- "user_data",
326
- result.user_data,
327
- "Failed to set property \"user_data\" of account lookup result.",
326
+ "debits_pending",
327
+ result.debits_pending,
328
+ "Failed to set property \"debits_pending\" of account lookup result.",
328
329
  );
329
330
 
330
- try translate.byte_slice_into_object(
331
+ try translate.u128_into_object(
331
332
  env,
332
333
  napi_object,
333
- "reserved",
334
- &result.reserved,
335
- "Failed to set property \"reserved\" of account lookup result.",
334
+ "debits_posted",
335
+ result.debits_posted,
336
+ "Failed to set property \"debits_posted\" of account lookup result.",
336
337
  );
337
338
 
338
- try translate.u32_into_object(
339
+ try translate.u128_into_object(
339
340
  env,
340
341
  napi_object,
341
- "ledger",
342
- @intCast(u32, result.ledger),
343
- "Failed to set property \"ledger\" of account lookup result.",
342
+ "credits_pending",
343
+ result.credits_pending,
344
+ "Failed to set property \"credits_pending\" of account lookup result.",
344
345
  );
345
346
 
346
- try translate.u16_into_object(
347
+ try translate.u128_into_object(
347
348
  env,
348
349
  napi_object,
349
- "code",
350
- @intCast(u16, result.code),
351
- "Failed to set property \"code\" of account lookup result.",
350
+ "credits_posted",
351
+ result.credits_posted,
352
+ "Failed to set property \"credits_posted\" of account lookup result.",
352
353
  );
353
354
 
354
- try translate.u16_into_object(
355
+ try translate.u128_into_object(
355
356
  env,
356
357
  napi_object,
357
- "flags",
358
- @bitCast(u16, result.flags),
359
- "Failed to set property \"flags\" of account lookup result.",
358
+ "user_data_128",
359
+ result.user_data_128,
360
+ "Failed to set property \"user_data_128\" of account lookup result.",
360
361
  );
361
362
 
362
363
  try translate.u64_into_object(
363
364
  env,
364
365
  napi_object,
365
- "debits_pending",
366
- result.debits_pending,
367
- "Failed to set property \"debits_pending\" of account lookup result.",
366
+ "user_data_64",
367
+ result.user_data_64,
368
+ "Failed to set property \"user_data_64\" of account lookup result.",
368
369
  );
369
370
 
370
- try translate.u64_into_object(
371
+ try translate.u32_into_object(
371
372
  env,
372
373
  napi_object,
373
- "debits_posted",
374
- result.debits_posted,
375
- "Failed to set property \"debits_posted\" of account lookup result.",
374
+ "user_data_32",
375
+ result.user_data_32,
376
+ "Failed to set property \"user_data_32\" of account lookup result.",
376
377
  );
377
378
 
378
- try translate.u64_into_object(
379
+ try translate.u32_into_object(
379
380
  env,
380
381
  napi_object,
381
- "credits_pending",
382
- result.credits_pending,
383
- "Failed to set property \"credits_pending\" of account lookup result.",
382
+ "reserved",
383
+ result.reserved,
384
+ "Failed to set property \"reserved\" of account lookup result.",
384
385
  );
385
386
 
386
- try translate.u64_into_object(
387
+ try translate.u32_into_object(
387
388
  env,
388
389
  napi_object,
389
- "credits_posted",
390
- result.credits_posted,
391
- "Failed to set property \"credits_posted\" of account lookup result.",
390
+ "ledger",
391
+ @as(u32, @intCast(result.ledger)),
392
+ "Failed to set property \"ledger\" of account lookup result.",
393
+ );
394
+
395
+ try translate.u16_into_object(
396
+ env,
397
+ napi_object,
398
+ "code",
399
+ @as(u16, @intCast(result.code)),
400
+ "Failed to set property \"code\" of account lookup result.",
401
+ );
402
+
403
+ try translate.u16_into_object(
404
+ env,
405
+ napi_object,
406
+ "flags",
407
+ @as(u16, @bitCast(result.flags)),
408
+ "Failed to set property \"flags\" of account lookup result.",
392
409
  );
393
410
 
394
411
  try translate.u64_into_object(
@@ -444,28 +461,44 @@ fn encode_napi_results_array(
444
461
  try translate.u128_into_object(
445
462
  env,
446
463
  napi_object,
447
- "user_data",
448
- result.user_data,
449
- "Failed to set property \"user_data\" of transfer lookup result.",
464
+ "amount",
465
+ result.amount,
466
+ "Failed to set property \"amount\" of transfer lookup result.",
450
467
  );
451
468
 
452
469
  try translate.u128_into_object(
453
470
  env,
454
471
  napi_object,
455
- "reserved",
456
- result.reserved,
457
- "Failed to set property \"reserved\" of transfer lookup result.",
472
+ "pending_id",
473
+ result.pending_id,
474
+ "Failed to set property \"pending_id\" of transfer lookup result.",
458
475
  );
459
476
 
460
477
  try translate.u128_into_object(
461
478
  env,
462
479
  napi_object,
463
- "pending_id",
464
- result.pending_id,
465
- "Failed to set property \"pending_id\" of transfer lookup result.",
480
+ "user_data_128",
481
+ result.user_data_128,
482
+ "Failed to set property \"user_data_128\" of transfer lookup result.",
466
483
  );
467
484
 
468
485
  try translate.u64_into_object(
486
+ env,
487
+ napi_object,
488
+ "user_data_64",
489
+ result.user_data_64,
490
+ "Failed to set property \"user_data_64\" of transfer lookup result.",
491
+ );
492
+
493
+ try translate.u32_into_object(
494
+ env,
495
+ napi_object,
496
+ "user_data_32",
497
+ result.user_data_32,
498
+ "Failed to set property \"user_data_32\" of transfer lookup result.",
499
+ );
500
+
501
+ try translate.u32_into_object(
469
502
  env,
470
503
  napi_object,
471
504
  "timeout",
@@ -477,7 +510,7 @@ fn encode_napi_results_array(
477
510
  env,
478
511
  napi_object,
479
512
  "ledger",
480
- @intCast(u32, result.ledger),
513
+ @as(u32, @intCast(result.ledger)),
481
514
  "Failed to set property \"ledger\" of transfer lookup result.",
482
515
  );
483
516
 
@@ -485,7 +518,7 @@ fn encode_napi_results_array(
485
518
  env,
486
519
  napi_object,
487
520
  "code",
488
- @intCast(u16, result.code),
521
+ @as(u16, @intCast(result.code)),
489
522
  "Failed to set property \"code\" of transfer lookup result.",
490
523
  );
491
524
 
@@ -493,18 +526,10 @@ fn encode_napi_results_array(
493
526
  env,
494
527
  napi_object,
495
528
  "flags",
496
- @bitCast(u16, result.flags),
529
+ @as(u16, @bitCast(result.flags)),
497
530
  "Failed to set property \"flags\" of transfer lookup result.",
498
531
  );
499
532
 
500
- try translate.u64_into_object(
501
- env,
502
- napi_object,
503
- "amount",
504
- result.amount,
505
- "Failed to set property \"amount\" of transfer lookup result.",
506
- );
507
-
508
533
  try translate.u64_into_object(
509
534
  env,
510
535
  napi_object,
@@ -582,14 +607,20 @@ fn request(env: c.napi_env, info: c.napi_callback_info) callconv(.C) c.napi_valu
582
607
  const context = contextCast(context_raw.?) catch return null;
583
608
  const operation_int = translate.u32_from_value(env, argv[1], "operation") catch return null;
584
609
 
585
- if (operation_int >= @typeInfo(Operation).Enum.fields.len) {
610
+ if (!@as(vsr.Operation, @enumFromInt(operation_int)).valid(StateMachine)) {
586
611
  translate.throw(env, "Unknown operation.") catch return null;
587
612
  }
588
613
 
614
+ if (context.client.messages_available == 0) {
615
+ translate.throw(
616
+ env,
617
+ "Too many outstanding requests - message pool exhausted.",
618
+ ) catch return null;
619
+ }
589
620
  const message = context.client.get_message();
590
- defer context.client.unref(message);
621
+ errdefer context.client.release(message);
591
622
 
592
- const operation = @intToEnum(Operation, @intCast(u8, operation_int));
623
+ const operation = @as(Operation, @enumFromInt(@as(u8, @intCast(operation_int))));
593
624
  const body_length = decode_events(
594
625
  env,
595
626
  argv[2],
@@ -603,7 +634,7 @@ fn request(env: c.napi_env, info: c.napi_callback_info) callconv(.C) c.napi_valu
603
634
  // free in order to avoid a leak. We therefore do this last to ensure we cannot fail after
604
635
  // taking this reference.
605
636
  const user_data = translate.user_data_from_value(env, argv[3]) catch return null;
606
- context.client.request(@bitCast(u128, user_data), on_result, operation, message, body_length);
637
+ context.client.request(@as(u128, @bitCast(user_data)), on_result, operation, message, body_length);
607
638
 
608
639
  return null;
609
640
  }
@@ -631,13 +662,19 @@ fn raw_request(env: c.napi_env, info: c.napi_callback_info) callconv(.C) c.napi_
631
662
  const context = contextCast(context_raw.?) catch return null;
632
663
  const operation_int = translate.u32_from_value(env, argv[1], "operation") catch return null;
633
664
 
634
- if (operation_int >= @typeInfo(Operation).Enum.fields.len) {
665
+ if (!@as(vsr.Operation, @enumFromInt(operation_int)).valid(StateMachine)) {
635
666
  translate.throw(env, "Unknown operation.") catch return null;
636
667
  }
637
- const operation = @intToEnum(Operation, @intCast(u8, operation_int));
668
+ const operation = @as(Operation, @enumFromInt(@as(u8, @intCast(operation_int))));
638
669
 
670
+ if (context.client.messages_available == 0) {
671
+ translate.throw(
672
+ env,
673
+ "Too many outstanding requests - message pool exhausted.",
674
+ ) catch return null;
675
+ }
639
676
  const message = context.client.get_message();
640
- defer context.client.unref(message);
677
+ errdefer context.client.release(message);
641
678
 
642
679
  const body_length = translate.bytes_from_buffer(
643
680
  env,
@@ -652,25 +689,16 @@ fn raw_request(env: c.napi_env, info: c.napi_callback_info) callconv(.C) c.napi_
652
689
  // free in order to avoid a leak. We therefore do this last to ensure we cannot fail after
653
690
  // taking this reference.
654
691
  const user_data = translate.user_data_from_value(env, argv[3]) catch return null;
655
- context.client.request(@bitCast(u128, user_data), on_result, operation, message, body_length);
692
+ context.client.request(@as(u128, @bitCast(user_data)), on_result, operation, message, body_length);
656
693
 
657
694
  return null;
658
695
  }
659
696
 
660
- fn create_client_error(env: c.napi_env, client_error: Client.Error) !c.napi_value {
661
- return switch (client_error) {
662
- error.TooManyOutstandingRequests => try translate.create_error(
663
- env,
664
- "Too many outstanding requests - message pool exhausted.",
665
- ),
666
- };
667
- }
668
-
669
- fn on_result(user_data: u128, operation: Operation, results: Client.Error![]const u8) void {
697
+ fn on_result(user_data: u128, operation: Operation, results: []const u8) void {
670
698
  // A reference to the user's JS callback was made in `request` or `raw_request`. This MUST be
671
699
  // cleaned up regardless of the result of this function.
672
- const env = @bitCast(translate.UserData, user_data).env;
673
- const callback_reference = @bitCast(translate.UserData, user_data).callback_reference;
700
+ const env = @as(translate.UserData, @bitCast(user_data)).env;
701
+ const callback_reference = @as(translate.UserData, @bitCast(user_data)).callback_reference;
674
702
  defer translate.delete_reference(env, callback_reference) catch {
675
703
  std.log.warn("on_result: Failed to delete reference to user's JS callback.", .{});
676
704
  };
@@ -689,33 +717,23 @@ fn on_result(user_data: u128, operation: Operation, results: Client.Error![]cons
689
717
  const argc: usize = 2;
690
718
  var argv: [argc]c.napi_value = undefined;
691
719
 
692
- if (results) |value| {
693
- const napi_results = switch (operation) {
694
- .reserved, .root, .register => {
695
- translate.throw(env, "Reserved operation.") catch return;
696
- },
697
- .create_accounts => encode_napi_results_array(
698
- CreateAccountsResult,
699
- env,
700
- value,
701
- ) catch return,
702
- .create_transfers => encode_napi_results_array(
703
- CreateTransfersResult,
704
- env,
705
- value,
706
- ) catch return,
707
- .lookup_accounts => encode_napi_results_array(Account, env, value) catch return,
708
- .lookup_transfers => encode_napi_results_array(Transfer, env, value) catch return,
709
- };
720
+ const napi_results = switch (operation) {
721
+ .create_accounts => encode_napi_results_array(
722
+ CreateAccountsResult,
723
+ env,
724
+ results,
725
+ ) catch return,
726
+ .create_transfers => encode_napi_results_array(
727
+ CreateTransfersResult,
728
+ env,
729
+ results,
730
+ ) catch return,
731
+ .lookup_accounts => encode_napi_results_array(Account, env, results) catch return,
732
+ .lookup_transfers => encode_napi_results_array(Transfer, env, results) catch return,
733
+ };
710
734
 
711
- argv[0] = globals.napi_undefined;
712
- argv[1] = napi_results;
713
- } else |err| {
714
- argv[0] = create_client_error(env, err) catch {
715
- translate.throw(env, "Failed to create Node Error.") catch return;
716
- };
717
- argv[1] = globals.napi_undefined;
718
- }
735
+ argv[0] = globals.napi_undefined;
736
+ argv[1] = napi_results;
719
737
 
720
738
  translate.call_function(env, scope, napi_callback, argc, argv[0..]) catch {
721
739
  translate.throw(env, "Failed to call JS results callback.") catch return;
@@ -769,8 +787,11 @@ fn deinit(env: c.napi_env, info: c.napi_callback_info) callconv(.C) c.napi_value
769
787
  "Failed to get Client Context pointer.",
770
788
  ) catch return null;
771
789
  const context = contextCast(context_raw.?) catch return null;
772
- context.client.deinit();
773
- context.message_bus.deinit();
790
+
791
+ const allocator = std.heap.c_allocator;
792
+ context.client.deinit(allocator);
793
+ context.message_pool.deinit(allocator);
794
+ allocator.free(context.addresses);
774
795
 
775
796
  return null;
776
797
  }