tigerbeetle-node 0.3.3 → 0.5.0

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 (71) hide show
  1. package/README.md +21 -7
  2. package/dist/benchmark.js +1 -1
  3. package/dist/benchmark.js.map +1 -1
  4. package/dist/index.d.ts +22 -20
  5. package/dist/index.js +40 -18
  6. package/dist/index.js.map +1 -1
  7. package/dist/test.js +13 -1
  8. package/dist/test.js.map +1 -1
  9. package/package.json +12 -12
  10. package/scripts/postinstall.sh +2 -2
  11. package/src/benchmark.ts +4 -4
  12. package/src/index.ts +35 -9
  13. package/src/node.zig +139 -28
  14. package/src/test.ts +19 -5
  15. package/src/tigerbeetle/scripts/benchmark.sh +10 -3
  16. package/src/tigerbeetle/scripts/install.sh +2 -2
  17. package/src/tigerbeetle/scripts/install_zig.bat +109 -0
  18. package/src/tigerbeetle/scripts/install_zig.sh +21 -4
  19. package/src/tigerbeetle/scripts/vopr.bat +48 -0
  20. package/src/tigerbeetle/scripts/vopr.sh +33 -0
  21. package/src/tigerbeetle/src/benchmark.zig +74 -42
  22. package/src/tigerbeetle/src/cli.zig +136 -83
  23. package/src/tigerbeetle/src/config.zig +80 -26
  24. package/src/tigerbeetle/src/demo.zig +101 -78
  25. package/src/tigerbeetle/src/demo_01_create_accounts.zig +2 -7
  26. package/src/tigerbeetle/src/demo_02_lookup_accounts.zig +2 -7
  27. package/src/tigerbeetle/src/demo_03_create_transfers.zig +2 -7
  28. package/src/tigerbeetle/src/demo_04_create_transfers_two_phase_commit.zig +2 -5
  29. package/src/tigerbeetle/src/demo_05_accept_transfers.zig +2 -7
  30. package/src/tigerbeetle/src/demo_06_reject_transfers.zig +2 -7
  31. package/src/tigerbeetle/src/demo_07_lookup_transfers.zig +8 -0
  32. package/src/tigerbeetle/src/fifo.zig +20 -11
  33. package/src/tigerbeetle/src/io.zig +35 -22
  34. package/src/tigerbeetle/src/io_darwin.zig +701 -0
  35. package/src/tigerbeetle/src/main.zig +72 -25
  36. package/src/tigerbeetle/src/message_bus.zig +379 -456
  37. package/src/tigerbeetle/src/message_pool.zig +3 -3
  38. package/src/tigerbeetle/src/ring_buffer.zig +192 -37
  39. package/src/tigerbeetle/src/simulator.zig +317 -0
  40. package/src/tigerbeetle/src/state_machine.zig +846 -38
  41. package/src/tigerbeetle/src/storage.zig +488 -90
  42. package/src/tigerbeetle/src/test/cluster.zig +221 -0
  43. package/src/tigerbeetle/src/test/message_bus.zig +92 -0
  44. package/src/tigerbeetle/src/test/network.zig +182 -0
  45. package/src/tigerbeetle/src/test/packet_simulator.zig +371 -0
  46. package/src/tigerbeetle/src/test/state_checker.zig +142 -0
  47. package/src/tigerbeetle/src/test/state_machine.zig +71 -0
  48. package/src/tigerbeetle/src/test/storage.zig +375 -0
  49. package/src/tigerbeetle/src/test/time.zig +84 -0
  50. package/src/tigerbeetle/src/tigerbeetle.zig +6 -3
  51. package/src/tigerbeetle/src/time.zig +65 -0
  52. package/src/tigerbeetle/src/unit_tests.zig +14 -0
  53. package/src/tigerbeetle/src/vsr/client.zig +519 -0
  54. package/src/tigerbeetle/src/vsr/clock.zig +829 -0
  55. package/src/tigerbeetle/src/vsr/journal.zig +1368 -0
  56. package/src/tigerbeetle/src/vsr/marzullo.zig +306 -0
  57. package/src/tigerbeetle/src/vsr/replica.zig +4248 -0
  58. package/src/tigerbeetle/src/vsr.zig +601 -0
  59. package/src/tigerbeetle/LICENSE +0 -177
  60. package/src/tigerbeetle/README.md +0 -116
  61. package/src/tigerbeetle/src/client.zig +0 -319
  62. package/src/tigerbeetle/src/concurrent_ranges.zig +0 -162
  63. package/src/tigerbeetle/src/fixed_array_list.zig +0 -53
  64. package/src/tigerbeetle/src/io_async.zig +0 -600
  65. package/src/tigerbeetle/src/journal.zig +0 -567
  66. package/src/tigerbeetle/src/test_client.zig +0 -41
  67. package/src/tigerbeetle/src/test_main.zig +0 -118
  68. package/src/tigerbeetle/src/test_message_bus.zig +0 -132
  69. package/src/tigerbeetle/src/vr/journal.zig +0 -672
  70. package/src/tigerbeetle/src/vr/replica.zig +0 -3061
  71. package/src/tigerbeetle/src/vr.zig +0 -374
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tigerbeetle-node",
3
- "version": "0.3.3",
3
+ "version": "0.5.0",
4
4
  "description": "TigerBeetle Node.js client",
5
5
  "main": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
@@ -10,38 +10,38 @@
10
10
  },
11
11
  "preferUnplugged": true,
12
12
  "files": [
13
- "LICENSE",
14
- "README.md",
15
- "package.json",
16
- "tsconfig.json",
17
- "yarn.lock",
18
13
  ".yarn/releases",
19
14
  ".yarnrc.yml",
15
+ "LICENSE",
16
+ "README.md",
20
17
  "dist",
21
18
  "!dist/client.node",
19
+ "package.json",
20
+ "scripts/download_node_headers.sh",
21
+ "scripts/postinstall.sh",
22
22
  "src/c.zig",
23
- "src/index.ts",
24
- "src/test.ts",
25
23
  "src/benchmark.ts",
24
+ "src/index.ts",
26
25
  "src/node.zig",
26
+ "src/test.ts",
27
27
  "src/tigerbeetle/src",
28
28
  "src/tigerbeetle/scripts",
29
29
  "src/translate.zig",
30
- "scripts/download_node_headers.sh",
31
- "scripts/postinstall.sh"
30
+ "tsconfig.json",
31
+ "yarn.lock"
32
32
  ],
33
33
  "engines": {
34
34
  "node": ">=14.0.0"
35
35
  },
36
36
  "scripts": {
37
- "prepack": "git submodule deinit --all && git submodule update --init && yarn build",
38
37
  "benchmark": "./scripts/benchmark.sh",
39
38
  "build": "yarn build:tsc && yarn build:zig",
40
39
  "build:tsc": "tsc",
41
- "build:zig": "mkdir -p dist && zig/zig build-lib -mcpu=baseline -OReleaseSafe -dynamic -lc -isystem build/node-$(node --version)/include/node src/node.zig -femit-bin=dist/client.node",
40
+ "build:zig": "mkdir -p dist && ZIG_SYSTEM_LINKER_HACK=1 zig/zig build-lib -mcpu=baseline -OReleaseSafe -dynamic -lc -isystem build/node-$(node --version)/include/node src/node.zig -fallow-shlib-undefined -femit-bin=dist/client.node",
42
41
  "clean": "rm -rf build dist node_modules src/zig-cache zig",
43
42
  "install:zig": "./src/tigerbeetle/scripts/install_zig.sh",
44
43
  "postinstall": "./scripts/postinstall.sh",
44
+ "prepack": "git submodule deinit --all && git submodule update --init && yarn build:tsc",
45
45
  "test": "yarn build && node dist/test"
46
46
  },
47
47
  "author": "Coil Technologies, Inc",
@@ -1,6 +1,6 @@
1
1
  #!/bin/bash
2
2
  set -e
3
3
 
4
- ./src/tigerbeetle/scripts/install_zig.sh 0.8.0
4
+ ./src/tigerbeetle/scripts/install_zig.sh 0.8.1
5
5
  ./scripts/download_node_headers.sh
6
- mkdir -p dist && zig/zig build-lib -dynamic -lc -isystem build/node-$(node --version)/include/node src/node.zig -femit-bin=dist/client.node
6
+ mkdir -p dist && ZIG_SYSTEM_LINKER_HACK=1 zig/zig build-lib -mcpu=baseline -OReleaseSafe -dynamic -lc -isystem build/node-$(node --version)/include/node src/node.zig -fallow-shlib-undefined -femit-bin=dist/client.node
package/src/benchmark.ts CHANGED
@@ -20,7 +20,7 @@ const PREVIOUS_BENCHMARK = IS_RAW_REQUEST ? PREVIOUS_RAW_REQUEST_RESULT : PREVIO
20
20
  const TOLERANCE = 10 // percent that the benchmark is allowed to deviate from the previous benchmark
21
21
 
22
22
  const client = createClient({
23
- cluster_id: 0x0a5ca1ab1ebee11en,
23
+ cluster_id: 1,
24
24
  replica_addresses: ['3001']
25
25
  })
26
26
 
@@ -185,7 +185,7 @@ const runBenchmarkRawReqeust = async () => {
185
185
  let maxCommitTransfersLatency = 0
186
186
  const start = Date.now()
187
187
 
188
- for(let i = 0; i < transfers.length; i++) {
188
+ for (let i = 0; i < transfers.length; i++) {
189
189
  const ms1 = Date.now()
190
190
 
191
191
  const transferResults = await rawCreateTransfers(transfers[i])
@@ -265,7 +265,7 @@ const runBenchmark = async () => {
265
265
  let maxCommitTransfersLatency = 0
266
266
  const start = Date.now()
267
267
 
268
- for(let i = 0; i < transfers.length; i++) {
268
+ for (let i = 0; i < transfers.length; i++) {
269
269
  const ms1 = Date.now()
270
270
 
271
271
  const transferResults = await client.createTransfers(transfers[i])
@@ -327,4 +327,4 @@ main().catch(error => {
327
327
  console.log(error)
328
328
  }).finally(async () => {
329
329
  await client.destroy()
330
- })
330
+ })
package/src/index.ts CHANGED
@@ -4,16 +4,17 @@ interface Binding {
4
4
  request: (context: Context, operation: Operation, batch: Event[], result: ResultCallback) => void
5
5
  raw_request: (context: Context, operation: Operation, raw_batch: Buffer, result: ResultCallback) => void
6
6
  tick: (context: Context) => void,
7
- deinit: (context: Context) => void
7
+ deinit: (context: Context) => void,
8
+ tick_ms: number
8
9
  }
9
10
 
10
11
  interface BindingInitArgs {
11
- cluster_id: bigint, // u128
12
+ cluster_id: number, // u32
12
13
  replica_addresses: Buffer,
13
14
  }
14
15
 
15
16
  export interface InitArgs {
16
- cluster_id: bigint, // u128
17
+ cluster_id: number, // u32
17
18
  replica_addresses: Array<string | number>,
18
19
  }
19
20
 
@@ -129,7 +130,6 @@ export enum CommitTransferError {
129
130
  transfer_not_found,
130
131
  transfer_not_two_phase_commit,
131
132
  transfer_expired,
132
- already_auto_committed,
133
133
  already_committed,
134
134
  already_committed_but_accepted,
135
135
  already_committed_but_rejected,
@@ -150,16 +150,18 @@ export type CommitTransfersError = {
150
150
  }
151
151
 
152
152
  export type AccountID = bigint // u128
153
+ export type TransferID = bigint // u128
153
154
 
154
- export type Event = Account | Transfer | Commit | AccountID
155
- export type Result = CreateAccountsError | CreateTransfersError | CommitTransfersError | Account
155
+ export type Event = Account | Transfer | Commit | AccountID | TransferID
156
+ export type Result = CreateAccountsError | CreateTransfersError | CommitTransfersError | Account | Transfer
156
157
  export type ResultCallback = (error: undefined | Error, results: Result[]) => void
157
158
 
158
159
  export enum Operation {
159
- CREATE_ACCOUNT = 2,
160
+ CREATE_ACCOUNT = 3,
160
161
  CREATE_TRANSFER,
161
162
  COMMIT_TRANSFER,
162
- ACCOUNT_LOOKUP
163
+ ACCOUNT_LOOKUP,
164
+ TRANSFER_LOOKUP
163
165
  }
164
166
 
165
167
  export interface Client {
@@ -167,6 +169,7 @@ export interface Client {
167
169
  createTransfers: (batch: Transfer[]) => Promise<CreateTransfersError[]>
168
170
  commitTransfers: (batch: Commit[]) => Promise<CommitTransfersError[]>
169
171
  lookupAccounts: (batch: AccountID[]) => Promise<Account[]>
172
+ lookupTransfers: (batch: TransferID[]) => Promise<Transfer[]>
170
173
  request: (operation: Operation, batch: Event[], callback: ResultCallback) => void
171
174
  rawRequest: (operation: Operation, rawBatch: Buffer, callback: ResultCallback) => void
172
175
  destroy: () => void
@@ -236,6 +239,7 @@ export function createClient (args: InitArgs): Client {
236
239
  const callback = (error: undefined | Error, results: CreateAccountsError[]) => {
237
240
  if (error) {
238
241
  reject(error)
242
+ return
239
243
  }
240
244
  resolve(results)
241
245
  }
@@ -262,6 +266,7 @@ export function createClient (args: InitArgs): Client {
262
266
  const callback = (error: undefined | Error, results: CreateTransfersError[]) => {
263
267
  if (error) {
264
268
  reject(error)
269
+ return
265
270
  }
266
271
  resolve(results)
267
272
  }
@@ -288,6 +293,7 @@ export function createClient (args: InitArgs): Client {
288
293
  const callback = (error: undefined | Error, results: CommitTransfersError[]) => {
289
294
  if (error) {
290
295
  reject(error)
296
+ return
291
297
  }
292
298
  resolve(results)
293
299
  }
@@ -305,6 +311,7 @@ export function createClient (args: InitArgs): Client {
305
311
  const callback = (error: undefined | Error, results: Account[]) => {
306
312
  if (error) {
307
313
  reject(error)
314
+ return
308
315
  }
309
316
  resolve(results)
310
317
  }
@@ -317,6 +324,24 @@ export function createClient (args: InitArgs): Client {
317
324
  })
318
325
  }
319
326
 
327
+ const lookupTransfers = async (batch: TransferID[]): Promise<Transfer[]> => {
328
+ return new Promise((resolve, reject) => {
329
+ const callback = (error: undefined | Error, results: Transfer[]) => {
330
+ if (error) {
331
+ reject(error)
332
+ return
333
+ }
334
+ resolve(results)
335
+ }
336
+
337
+ try {
338
+ binding.request(context, Operation.TRANSFER_LOOKUP, batch, callback)
339
+ } catch (error) {
340
+ reject(error)
341
+ }
342
+ })
343
+ }
344
+
320
345
  const destroy = (): void => {
321
346
  binding.deinit(context)
322
347
  if (_interval){
@@ -330,6 +355,7 @@ export function createClient (args: InitArgs): Client {
330
355
  createTransfers,
331
356
  commitTransfers,
332
357
  lookupAccounts,
358
+ lookupTransfers,
333
359
  request,
334
360
  rawRequest,
335
361
  destroy
@@ -337,7 +363,7 @@ export function createClient (args: InitArgs): Client {
337
363
 
338
364
  _interval = setInterval(() => {
339
365
  binding.tick(context)
340
- }, 5)
366
+ }, binding.tick_ms)
341
367
 
342
368
  return _client
343
369
  }
package/src/node.zig CHANGED
@@ -15,15 +15,15 @@ const CreateAccountsResult = tb.CreateAccountsResult;
15
15
  const CreateTransfersResult = tb.CreateTransfersResult;
16
16
  const CommitTransfersResult = tb.CommitTransfersResult;
17
17
 
18
- const Header = @import("tigerbeetle/src/vr.zig").Header;
19
- const Operation = @import("tigerbeetle/src/state_machine.zig").Operation;
18
+ const StateMachine = @import("tigerbeetle/src/state_machine.zig").StateMachine;
19
+ const Operation = StateMachine.Operation;
20
20
  const MessageBus = @import("tigerbeetle/src/message_bus.zig").MessageBusClient;
21
- const Client = @import("tigerbeetle/src/client.zig").Client;
22
- const ClientError = @import("tigerbeetle/src/client.zig").ClientError;
23
21
  const IO = @import("tigerbeetle/src/io.zig").IO;
24
22
  const config = @import("tigerbeetle/src/config.zig");
25
23
 
26
- const vr = @import("tigerbeetle/src/vr.zig");
24
+ const vsr = @import("tigerbeetle/src/vsr.zig");
25
+ const Header = vsr.Header;
26
+ const Client = vsr.Client(StateMachine, MessageBus);
27
27
 
28
28
  pub const log_level: std.log.Level = .info;
29
29
 
@@ -35,6 +35,14 @@ export fn napi_register_module_v1(env: c.napi_env, exports: c.napi_value) c.napi
35
35
  translate.register_function(env, exports, "raw_request", raw_request) catch return null;
36
36
  translate.register_function(env, exports, "tick", tick) catch return null;
37
37
 
38
+ translate.u32_into_object(
39
+ env,
40
+ exports,
41
+ "tick_ms",
42
+ config.tick_ms,
43
+ "failed to add tick_ms to exports",
44
+ ) catch return null;
45
+
38
46
  const allocator = std.heap.c_allocator;
39
47
  var global = Globals.init(allocator, env) catch {
40
48
  std.log.emerg("Failed to initialise environment.\n", .{});
@@ -109,7 +117,7 @@ fn globalsCast(globals_raw: *c_void) *Globals {
109
117
 
110
118
  const Context = struct {
111
119
  io: *IO,
112
- configuration: [32]std.net.Address,
120
+ addresses: []std.net.Address,
113
121
  message_bus: MessageBus,
114
122
  client: Client,
115
123
 
@@ -117,40 +125,41 @@ const Context = struct {
117
125
  env: c.napi_env,
118
126
  allocator: *std.mem.Allocator,
119
127
  io: *IO,
120
- cluster: u128,
121
- configuration_raw: []const u8,
128
+ cluster: u32,
129
+ addresses_raw: []const u8,
122
130
  ) !c.napi_value {
123
131
  const context = try allocator.create(Context);
124
132
  errdefer allocator.destroy(context);
125
133
 
126
134
  context.io = io;
127
135
 
128
- const configuration = try vr.parse_configuration(allocator, configuration_raw);
129
- errdefer allocator.free(configuration);
130
- assert(configuration.len > 0);
131
- for (configuration) |address, index| context.configuration[index] = address;
136
+ context.addresses = try vsr.parse_addresses(allocator, addresses_raw);
137
+ errdefer allocator.free(context.addresses);
138
+ assert(context.addresses.len > 0);
139
+
140
+ const client_id = std.crypto.random.int(u128);
132
141
 
133
142
  context.message_bus = try MessageBus.init(
134
143
  allocator,
135
144
  cluster,
136
- context.configuration[0..configuration.len],
137
- std.crypto.random.int(u128),
145
+ context.addresses,
146
+ client_id,
138
147
  context.io,
139
148
  );
140
149
  errdefer context.message_bus.deinit();
141
150
 
142
151
  context.client = try Client.init(
143
152
  allocator,
153
+ client_id,
144
154
  cluster,
145
- @intCast(u16, configuration.len),
155
+ @intCast(u8, context.addresses.len),
146
156
  &context.message_bus,
147
157
  );
148
158
  errdefer context.client.deinit();
149
- context.message_bus.process = .{ .client = &context.client };
150
159
 
151
- const ret = try translate.create_external(env, context);
160
+ context.message_bus.set_on_message(*Client, &context.client, Client.on_message);
152
161
 
153
- return ret;
162
+ return try translate.create_external(env, context);
154
163
  }
155
164
  };
156
165
 
@@ -204,7 +213,7 @@ fn decode_from_object(comptime T: type, env: c.napi_env, object: c.napi_value) !
204
213
  .credits_accepted = try translate.u64_from_object(env, object, "credits_accepted"),
205
214
  .timestamp = try validate_timestamp(env, object),
206
215
  },
207
- u128 => try translate.u128_from_value(env, object, "Account lookup"),
216
+ u128 => try translate.u128_from_value(env, object, "lookup"),
208
217
  else => unreachable,
209
218
  };
210
219
  }
@@ -220,6 +229,7 @@ pub fn decode_events(
220
229
  .create_transfers => try decode_events_from_array(env, array, Transfer, output),
221
230
  .commit_transfers => try decode_events_from_array(env, array, Commit, output),
222
231
  .lookup_accounts => try decode_events_from_array(env, array, u128, output),
232
+ .lookup_transfers => try decode_events_from_array(env, array, u128, output),
223
233
  else => unreachable,
224
234
  };
225
235
  }
@@ -298,7 +308,7 @@ fn encode_napi_results_array(
298
308
  );
299
309
  }
300
310
  },
301
- else => {
311
+ Account => {
302
312
  var i: u32 = 0;
303
313
  while (i < results.len) : (i += 1) {
304
314
  const result = results[i];
@@ -404,6 +414,105 @@ fn encode_napi_results_array(
404
414
  );
405
415
  }
406
416
  },
417
+ Transfer => {
418
+ var i: u32 = 0;
419
+ while (i < results.len) : (i += 1) {
420
+ const result = results[i];
421
+ const napi_object = try translate.create_object(
422
+ env,
423
+ "Failed to create transfer lookup result object.",
424
+ );
425
+
426
+ try translate.u128_into_object(
427
+ env,
428
+ napi_object,
429
+ "id",
430
+ result.id,
431
+ "Failed to set property \"id\" of transfer lookup result.",
432
+ );
433
+
434
+ try translate.u128_into_object(
435
+ env,
436
+ napi_object,
437
+ "debit_account_id",
438
+ result.debit_account_id,
439
+ "Failed to set property \"debit_account_id\" of transfer lookup result.",
440
+ );
441
+
442
+ try translate.u128_into_object(
443
+ env,
444
+ napi_object,
445
+ "credit_account_id",
446
+ result.credit_account_id,
447
+ "Failed to set property \"credit_account_id\" of transfer lookup result.",
448
+ );
449
+
450
+ try translate.u128_into_object(
451
+ env,
452
+ napi_object,
453
+ "user_data",
454
+ result.user_data,
455
+ "Failed to set property \"user_data\" of transfer lookup result.",
456
+ );
457
+
458
+ try translate.byte_slice_into_object(
459
+ env,
460
+ napi_object,
461
+ "reserved",
462
+ &result.reserved,
463
+ "Failed to set property \"reserved\" of transfer lookup result.",
464
+ );
465
+
466
+ try translate.u64_into_object(
467
+ env,
468
+ napi_object,
469
+ "timeout",
470
+ result.timeout,
471
+ "Failed to set property \"timeout\" of transfer lookup result.",
472
+ );
473
+
474
+ try translate.u32_into_object(
475
+ env,
476
+ napi_object,
477
+ "code",
478
+ @intCast(u32, result.code),
479
+ "Failed to set property \"code\" of transfer lookup result.",
480
+ );
481
+
482
+ try translate.u32_into_object(
483
+ env,
484
+ napi_object,
485
+ "flags",
486
+ @bitCast(u32, result.flags),
487
+ "Failed to set property \"flags\" of transfer lookup result.",
488
+ );
489
+
490
+ try translate.u64_into_object(
491
+ env,
492
+ napi_object,
493
+ "amount",
494
+ result.amount,
495
+ "Failed to set property \"amount\" of transfer lookup result.",
496
+ );
497
+
498
+ try translate.u64_into_object(
499
+ env,
500
+ napi_object,
501
+ "timestamp",
502
+ result.timestamp,
503
+ "Failed to set property \"timestamp\" of transfer lookup result.",
504
+ );
505
+
506
+ try translate.set_array_element(
507
+ env,
508
+ napi_array,
509
+ i,
510
+ napi_object,
511
+ "Failed to set element in results array.",
512
+ );
513
+ }
514
+ },
515
+ else => unreachable,
407
516
  }
408
517
 
409
518
  return napi_array;
@@ -421,8 +530,8 @@ fn init(env: c.napi_env, info: c.napi_callback_info) callconv(.C) c.napi_value {
421
530
  "Function init() must receive 1 argument exactly.",
422
531
  ) catch return null;
423
532
 
424
- const cluster = translate.u128_from_object(env, argv[0], "cluster_id") catch return null;
425
- const configuration = translate.slice_from_object(
533
+ const cluster = translate.u32_from_object(env, argv[0], "cluster_id") catch return null;
534
+ const addresses = translate.slice_from_object(
426
535
  env,
427
536
  argv[0],
428
537
  "replica_addresses",
@@ -432,7 +541,8 @@ fn init(env: c.napi_env, info: c.napi_callback_info) callconv(.C) c.napi_value {
432
541
 
433
542
  const globals_raw = translate.globals(env) catch return null;
434
543
  const globals = globalsCast(globals_raw.?);
435
- const context = Context.create(env, allocator, &globals.io, cluster, configuration) catch {
544
+
545
+ const context = Context.create(env, allocator, &globals.io, cluster, addresses) catch {
436
546
  // TODO: switch on err and provide more detailed messages
437
547
  translate.throw(env, "Failed to initialize Client.") catch return null;
438
548
  };
@@ -440,7 +550,7 @@ fn init(env: c.napi_env, info: c.napi_callback_info) callconv(.C) c.napi_value {
440
550
  return context;
441
551
  }
442
552
 
443
- /// This function decodes and validates an array of Node objects, one-by-one, directly into an
553
+ /// This function decodes and validates an array of Node objects, one-by-one, directly into an
444
554
  /// available message before requesting the client to send it.
445
555
  fn request(env: c.napi_env, info: c.napi_callback_info) callconv(.C) c.napi_value {
446
556
  var argc: usize = 4;
@@ -493,7 +603,7 @@ fn request(env: c.napi_env, info: c.napi_callback_info) callconv(.C) c.napi_valu
493
603
  return null;
494
604
  }
495
605
 
496
- /// The batch has already been encoded into a byte slice. This means that we only have to do one
606
+ /// The batch has already been encoded into a byte slice. This means that we only have to do one
497
607
  /// copy directly into an available message. No validation of the encoded data is performed except
498
608
  /// that it will fit into the message buffer.
499
609
  fn raw_request(env: c.napi_env, info: c.napi_callback_info) callconv(.C) c.napi_value {
@@ -547,7 +657,7 @@ fn raw_request(env: c.napi_env, info: c.napi_callback_info) callconv(.C) c.napi_
547
657
  return null;
548
658
  }
549
659
 
550
- fn create_client_error(env: c.napi_env, client_error: ClientError) !c.napi_value {
660
+ fn create_client_error(env: c.napi_env, client_error: Client.Error) !c.napi_value {
551
661
  return switch (client_error) {
552
662
  error.TooManyOutstandingRequests => try translate.create_error(
553
663
  env,
@@ -556,7 +666,7 @@ fn create_client_error(env: c.napi_env, client_error: ClientError) !c.napi_value
556
666
  };
557
667
  }
558
668
 
559
- fn on_result(user_data: u128, operation: Operation, results: ClientError![]const u8) void {
669
+ fn on_result(user_data: u128, operation: Operation, results: Client.Error![]const u8) void {
560
670
  // A reference to the user's JS callback was made in `request` or `raw_request`. This MUST be
561
671
  // cleaned up regardless of the result of this function.
562
672
  const env = @bitCast(translate.UserData, user_data).env;
@@ -581,7 +691,7 @@ fn on_result(user_data: u128, operation: Operation, results: ClientError![]const
581
691
 
582
692
  if (results) |value| {
583
693
  const napi_results = switch (operation) {
584
- .reserved, .init => {
694
+ .reserved, .init, .register => {
585
695
  translate.throw(env, "Reserved operation.") catch return;
586
696
  },
587
697
  .create_accounts => encode_napi_results_array(
@@ -600,6 +710,7 @@ fn on_result(user_data: u128, operation: Operation, results: ClientError![]const
600
710
  value,
601
711
  ) catch return,
602
712
  .lookup_accounts => encode_napi_results_array(Account, env, value) catch return,
713
+ .lookup_transfers => encode_napi_results_array(Transfer, env, value) catch return,
603
714
  };
604
715
 
605
716
  argv[0] = globals.napi_undefined;
package/src/test.ts CHANGED
@@ -1,16 +1,16 @@
1
1
  import assert, { AssertionError } from 'assert'
2
2
  import { CommitFlags,
3
+ createClient,
3
4
  Commit,
4
5
  Account,
5
- createClient,
6
6
  Transfer,
7
7
  TransferFlags,
8
- CreateTransferError,
9
- CreateAccountError
8
+ CreateAccountError,
9
+ CreateTransferError
10
10
  } from '.'
11
11
 
12
12
  const client = createClient({
13
- cluster_id: 0x0a5ca1ab1ebee11en,
13
+ cluster_id: 0,
14
14
  replica_addresses: ['3001']
15
15
  })
16
16
 
@@ -176,6 +176,20 @@ test('can create a two-phase transfer', async (): Promise<void> => {
176
176
  assert.strictEqual(accounts[1].credits_reserved, 0n)
177
177
  assert.strictEqual(accounts[1].debits_accepted, 100n)
178
178
  assert.strictEqual(accounts[1].debits_reserved, 50n)
179
+
180
+ // Lookup the transfer
181
+ const transfers = await client.lookupTransfers([transfer.id])
182
+ assert.strictEqual(transfers.length, 1)
183
+ assert.strictEqual(transfers[0].id, 1n)
184
+ assert.strictEqual(transfers[0].debit_account_id, accountB.id)
185
+ assert.strictEqual(transfers[0].credit_account_id, accountA.id)
186
+ assert.strictEqual(transfers[0].user_data, 0n)
187
+ assert.notStrictEqual(transfers[0].reserved, Zeroed32Bytes)
188
+ assert.strictEqual(transfers[0].timeout > 0, true)
189
+ assert.strictEqual(transfers[0].code, 1)
190
+ assert.strictEqual(transfers[0].flags, 2)
191
+ assert.strictEqual(transfers[0].amount, 50n)
192
+ assert.strictEqual(transfers[0].timestamp > 0, true)
179
193
  })
180
194
 
181
195
  test('can commit a two-phase transfer', async (): Promise<void> => {
@@ -312,4 +326,4 @@ async function main () {
312
326
  main().catch((error: AssertionError) => {
313
327
  console.log('operator:', error.operator)
314
328
  console.log('stack:', error.stack)
315
- })
329
+ })
@@ -25,13 +25,20 @@ function onerror {
25
25
  }
26
26
  trap onerror EXIT
27
27
 
28
- CLUSTER_ID="--cluster-id=0a5ca1ab1ebee11e"
29
- REPLICA_ADDRESSES="--replica-addresses=3001"
28
+ for I in 0
29
+ do
30
+ echo "Initializing replica $I..."
31
+ FILE="./cluster_0000000000_replica_00${I}.tigerbeetle"
32
+ if [ -f $FILE ]; then
33
+ rm $FILE
34
+ fi
35
+ ./tigerbeetle init --directory=. --cluster=0 --replica=$I > benchmark.log 2>&1
36
+ done
30
37
 
31
38
  for I in 0
32
39
  do
33
40
  echo "Starting replica $I..."
34
- ./tigerbeetle $CLUSTER_ID $REPLICA_ADDRESSES --replica-index=$I > benchmark.log 2>&1 &
41
+ ./tigerbeetle start --directory=. --cluster=0 --addresses=3001 --replica=$I > benchmark.log 2>&1 &
35
42
  done
36
43
 
37
44
  # Wait for replicas to start, listen and connect:
@@ -1,6 +1,6 @@
1
1
  #!/bin/bash
2
2
  set -e
3
- scripts/install_zig.sh
3
+ scripts/install_zig.sh 0.8.1
4
4
  echo "Building TigerBeetle..."
5
- zig/zig build -Drelease-safe
5
+ zig/zig build -Dcpu=baseline -Drelease-safe
6
6
  mv zig-out/bin/tigerbeetle .