tigerbeetle-node 0.4.2 → 0.5.2
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/README.md +19 -5
- package/dist/benchmark.js.map +1 -1
- package/dist/index.d.ts +18 -16
- package/dist/index.js +35 -13
- package/dist/index.js.map +1 -1
- package/dist/test.js +12 -0
- package/dist/test.js.map +1 -1
- package/package.json +2 -2
- package/scripts/postinstall.sh +2 -2
- package/src/benchmark.ts +2 -2
- package/src/index.ts +29 -4
- package/src/node.zig +120 -17
- package/src/test.ts +14 -0
- package/src/tigerbeetle/scripts/install.sh +1 -1
- package/src/tigerbeetle/scripts/install_zig.bat +109 -0
- package/src/tigerbeetle/scripts/install_zig.sh +4 -2
- package/src/tigerbeetle/scripts/lint.zig +8 -2
- package/src/tigerbeetle/scripts/vopr.bat +48 -0
- package/src/tigerbeetle/src/benchmark.zig +10 -8
- package/src/tigerbeetle/src/cli.zig +6 -4
- package/src/tigerbeetle/src/config.zig +2 -2
- package/src/tigerbeetle/src/demo.zig +119 -89
- package/src/tigerbeetle/src/demo_01_create_accounts.zig +5 -3
- package/src/tigerbeetle/src/demo_02_lookup_accounts.zig +2 -3
- package/src/tigerbeetle/src/demo_03_create_transfers.zig +5 -3
- package/src/tigerbeetle/src/demo_04_create_transfers_two_phase_commit.zig +5 -3
- package/src/tigerbeetle/src/demo_05_accept_transfers.zig +5 -3
- package/src/tigerbeetle/src/demo_06_reject_transfers.zig +5 -3
- package/src/tigerbeetle/src/demo_07_lookup_transfers.zig +7 -0
- package/src/tigerbeetle/src/io/benchmark.zig +238 -0
- package/src/tigerbeetle/src/{io_darwin.zig → io/darwin.zig} +89 -124
- package/src/tigerbeetle/src/io/linux.zig +933 -0
- package/src/tigerbeetle/src/io/test.zig +621 -0
- package/src/tigerbeetle/src/io.zig +7 -1328
- package/src/tigerbeetle/src/main.zig +18 -10
- package/src/tigerbeetle/src/message_bus.zig +43 -60
- package/src/tigerbeetle/src/message_pool.zig +3 -2
- package/src/tigerbeetle/src/ring_buffer.zig +135 -68
- package/src/tigerbeetle/src/simulator.zig +41 -37
- package/src/tigerbeetle/src/state_machine.zig +851 -26
- package/src/tigerbeetle/src/storage.zig +49 -46
- package/src/tigerbeetle/src/test/cluster.zig +2 -2
- package/src/tigerbeetle/src/test/message_bus.zig +6 -6
- package/src/tigerbeetle/src/test/network.zig +3 -3
- package/src/tigerbeetle/src/test/packet_simulator.zig +32 -29
- package/src/tigerbeetle/src/test/state_checker.zig +2 -2
- package/src/tigerbeetle/src/test/state_machine.zig +4 -0
- package/src/tigerbeetle/src/test/storage.zig +39 -19
- package/src/tigerbeetle/src/test/time.zig +2 -2
- package/src/tigerbeetle/src/tigerbeetle.zig +6 -129
- package/src/tigerbeetle/src/time.zig +6 -5
- package/src/tigerbeetle/src/vsr/client.zig +11 -11
- package/src/tigerbeetle/src/vsr/clock.zig +26 -43
- package/src/tigerbeetle/src/vsr/journal.zig +7 -6
- package/src/tigerbeetle/src/vsr/marzullo.zig +6 -3
- package/src/tigerbeetle/src/vsr/replica.zig +51 -48
- package/src/tigerbeetle/src/vsr.zig +24 -20
- package/src/translate.zig +55 -55
package/src/index.ts
CHANGED
|
@@ -130,7 +130,6 @@ export enum CommitTransferError {
|
|
|
130
130
|
transfer_not_found,
|
|
131
131
|
transfer_not_two_phase_commit,
|
|
132
132
|
transfer_expired,
|
|
133
|
-
already_auto_committed,
|
|
134
133
|
already_committed,
|
|
135
134
|
already_committed_but_accepted,
|
|
136
135
|
already_committed_but_rejected,
|
|
@@ -151,16 +150,18 @@ export type CommitTransfersError = {
|
|
|
151
150
|
}
|
|
152
151
|
|
|
153
152
|
export type AccountID = bigint // u128
|
|
153
|
+
export type TransferID = bigint // u128
|
|
154
154
|
|
|
155
|
-
export type Event = Account | Transfer | Commit | AccountID
|
|
156
|
-
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
|
|
157
157
|
export type ResultCallback = (error: undefined | Error, results: Result[]) => void
|
|
158
158
|
|
|
159
159
|
export enum Operation {
|
|
160
160
|
CREATE_ACCOUNT = 3,
|
|
161
161
|
CREATE_TRANSFER,
|
|
162
162
|
COMMIT_TRANSFER,
|
|
163
|
-
ACCOUNT_LOOKUP
|
|
163
|
+
ACCOUNT_LOOKUP,
|
|
164
|
+
TRANSFER_LOOKUP
|
|
164
165
|
}
|
|
165
166
|
|
|
166
167
|
export interface Client {
|
|
@@ -168,6 +169,7 @@ export interface Client {
|
|
|
168
169
|
createTransfers: (batch: Transfer[]) => Promise<CreateTransfersError[]>
|
|
169
170
|
commitTransfers: (batch: Commit[]) => Promise<CommitTransfersError[]>
|
|
170
171
|
lookupAccounts: (batch: AccountID[]) => Promise<Account[]>
|
|
172
|
+
lookupTransfers: (batch: TransferID[]) => Promise<Transfer[]>
|
|
171
173
|
request: (operation: Operation, batch: Event[], callback: ResultCallback) => void
|
|
172
174
|
rawRequest: (operation: Operation, rawBatch: Buffer, callback: ResultCallback) => void
|
|
173
175
|
destroy: () => void
|
|
@@ -237,6 +239,7 @@ export function createClient (args: InitArgs): Client {
|
|
|
237
239
|
const callback = (error: undefined | Error, results: CreateAccountsError[]) => {
|
|
238
240
|
if (error) {
|
|
239
241
|
reject(error)
|
|
242
|
+
return
|
|
240
243
|
}
|
|
241
244
|
resolve(results)
|
|
242
245
|
}
|
|
@@ -263,6 +266,7 @@ export function createClient (args: InitArgs): Client {
|
|
|
263
266
|
const callback = (error: undefined | Error, results: CreateTransfersError[]) => {
|
|
264
267
|
if (error) {
|
|
265
268
|
reject(error)
|
|
269
|
+
return
|
|
266
270
|
}
|
|
267
271
|
resolve(results)
|
|
268
272
|
}
|
|
@@ -289,6 +293,7 @@ export function createClient (args: InitArgs): Client {
|
|
|
289
293
|
const callback = (error: undefined | Error, results: CommitTransfersError[]) => {
|
|
290
294
|
if (error) {
|
|
291
295
|
reject(error)
|
|
296
|
+
return
|
|
292
297
|
}
|
|
293
298
|
resolve(results)
|
|
294
299
|
}
|
|
@@ -306,6 +311,7 @@ export function createClient (args: InitArgs): Client {
|
|
|
306
311
|
const callback = (error: undefined | Error, results: Account[]) => {
|
|
307
312
|
if (error) {
|
|
308
313
|
reject(error)
|
|
314
|
+
return
|
|
309
315
|
}
|
|
310
316
|
resolve(results)
|
|
311
317
|
}
|
|
@@ -318,6 +324,24 @@ export function createClient (args: InitArgs): Client {
|
|
|
318
324
|
})
|
|
319
325
|
}
|
|
320
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
|
+
|
|
321
345
|
const destroy = (): void => {
|
|
322
346
|
binding.deinit(context)
|
|
323
347
|
if (_interval){
|
|
@@ -331,6 +355,7 @@ export function createClient (args: InitArgs): Client {
|
|
|
331
355
|
createTransfers,
|
|
332
356
|
commitTransfers,
|
|
333
357
|
lookupAccounts,
|
|
358
|
+
lookupTransfers,
|
|
334
359
|
request,
|
|
335
360
|
rawRequest,
|
|
336
361
|
destroy
|
package/src/node.zig
CHANGED
|
@@ -45,7 +45,7 @@ export fn napi_register_module_v1(env: c.napi_env, exports: c.napi_value) c.napi
|
|
|
45
45
|
|
|
46
46
|
const allocator = std.heap.c_allocator;
|
|
47
47
|
var global = Globals.init(allocator, env) catch {
|
|
48
|
-
std.log.
|
|
48
|
+
std.log.err("Failed to initialise environment.\n", .{});
|
|
49
49
|
return null;
|
|
50
50
|
};
|
|
51
51
|
errdefer global.deinit();
|
|
@@ -57,7 +57,7 @@ export fn napi_register_module_v1(env: c.napi_env, exports: c.napi_value) c.napi
|
|
|
57
57
|
// state.
|
|
58
58
|
translate.set_instance_data(
|
|
59
59
|
env,
|
|
60
|
-
@ptrCast(*
|
|
60
|
+
@ptrCast(*anyopaque, @alignCast(@alignOf(u8), global)),
|
|
61
61
|
Globals.destroy,
|
|
62
62
|
) catch {
|
|
63
63
|
global.deinit();
|
|
@@ -68,11 +68,11 @@ export fn napi_register_module_v1(env: c.napi_env, exports: c.napi_value) c.napi
|
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
const Globals = struct {
|
|
71
|
-
allocator:
|
|
71
|
+
allocator: std.mem.Allocator,
|
|
72
72
|
io: IO,
|
|
73
73
|
napi_undefined: c.napi_value,
|
|
74
74
|
|
|
75
|
-
pub fn init(allocator:
|
|
75
|
+
pub fn init(allocator: std.mem.Allocator, env: c.napi_env) !*Globals {
|
|
76
76
|
const self = try allocator.create(Globals);
|
|
77
77
|
errdefer allocator.destroy(self);
|
|
78
78
|
|
|
@@ -93,7 +93,7 @@ const Globals = struct {
|
|
|
93
93
|
};
|
|
94
94
|
errdefer self.io.deinit();
|
|
95
95
|
|
|
96
|
-
if (c.napi_get_undefined(env, &self.napi_undefined) != .napi_ok) {
|
|
96
|
+
if (c.napi_get_undefined(env, &self.napi_undefined) != c.napi_ok) {
|
|
97
97
|
return translate.throw(env, "Failed to capture the value of \"undefined\".");
|
|
98
98
|
}
|
|
99
99
|
|
|
@@ -105,13 +105,16 @@ const Globals = struct {
|
|
|
105
105
|
self.allocator.destroy(self);
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
-
pub fn destroy(env: c.napi_env, data: ?*
|
|
108
|
+
pub fn destroy(env: c.napi_env, data: ?*anyopaque, hint: ?*anyopaque) callconv(.C) void {
|
|
109
|
+
_ = env;
|
|
110
|
+
_ = hint;
|
|
111
|
+
|
|
109
112
|
const self = globalsCast(data.?);
|
|
110
113
|
self.deinit();
|
|
111
114
|
}
|
|
112
115
|
};
|
|
113
116
|
|
|
114
|
-
fn globalsCast(globals_raw: *
|
|
117
|
+
fn globalsCast(globals_raw: *anyopaque) *Globals {
|
|
115
118
|
return @ptrCast(*Globals, @alignCast(@alignOf(Globals), globals_raw));
|
|
116
119
|
}
|
|
117
120
|
|
|
@@ -123,7 +126,7 @@ const Context = struct {
|
|
|
123
126
|
|
|
124
127
|
fn create(
|
|
125
128
|
env: c.napi_env,
|
|
126
|
-
allocator:
|
|
129
|
+
allocator: std.mem.Allocator,
|
|
127
130
|
io: *IO,
|
|
128
131
|
cluster: u32,
|
|
129
132
|
addresses_raw: []const u8,
|
|
@@ -163,7 +166,7 @@ const Context = struct {
|
|
|
163
166
|
}
|
|
164
167
|
};
|
|
165
168
|
|
|
166
|
-
fn contextCast(context_raw: *
|
|
169
|
+
fn contextCast(context_raw: *anyopaque) !*Context {
|
|
167
170
|
return @ptrCast(*Context, @alignCast(@alignOf(Context), context_raw));
|
|
168
171
|
}
|
|
169
172
|
|
|
@@ -213,7 +216,7 @@ fn decode_from_object(comptime T: type, env: c.napi_env, object: c.napi_value) !
|
|
|
213
216
|
.credits_accepted = try translate.u64_from_object(env, object, "credits_accepted"),
|
|
214
217
|
.timestamp = try validate_timestamp(env, object),
|
|
215
218
|
},
|
|
216
|
-
u128 => try translate.u128_from_value(env, object, "
|
|
219
|
+
u128 => try translate.u128_from_value(env, object, "lookup"),
|
|
217
220
|
else => unreachable,
|
|
218
221
|
};
|
|
219
222
|
}
|
|
@@ -229,6 +232,7 @@ pub fn decode_events(
|
|
|
229
232
|
.create_transfers => try decode_events_from_array(env, array, Transfer, output),
|
|
230
233
|
.commit_transfers => try decode_events_from_array(env, array, Commit, output),
|
|
231
234
|
.lookup_accounts => try decode_events_from_array(env, array, u128, output),
|
|
235
|
+
.lookup_transfers => try decode_events_from_array(env, array, u128, output),
|
|
232
236
|
else => unreachable,
|
|
233
237
|
};
|
|
234
238
|
}
|
|
@@ -307,7 +311,7 @@ fn encode_napi_results_array(
|
|
|
307
311
|
);
|
|
308
312
|
}
|
|
309
313
|
},
|
|
310
|
-
|
|
314
|
+
Account => {
|
|
311
315
|
var i: u32 = 0;
|
|
312
316
|
while (i < results.len) : (i += 1) {
|
|
313
317
|
const result = results[i];
|
|
@@ -413,6 +417,105 @@ fn encode_napi_results_array(
|
|
|
413
417
|
);
|
|
414
418
|
}
|
|
415
419
|
},
|
|
420
|
+
Transfer => {
|
|
421
|
+
var i: u32 = 0;
|
|
422
|
+
while (i < results.len) : (i += 1) {
|
|
423
|
+
const result = results[i];
|
|
424
|
+
const napi_object = try translate.create_object(
|
|
425
|
+
env,
|
|
426
|
+
"Failed to create transfer lookup result object.",
|
|
427
|
+
);
|
|
428
|
+
|
|
429
|
+
try translate.u128_into_object(
|
|
430
|
+
env,
|
|
431
|
+
napi_object,
|
|
432
|
+
"id",
|
|
433
|
+
result.id,
|
|
434
|
+
"Failed to set property \"id\" of transfer lookup result.",
|
|
435
|
+
);
|
|
436
|
+
|
|
437
|
+
try translate.u128_into_object(
|
|
438
|
+
env,
|
|
439
|
+
napi_object,
|
|
440
|
+
"debit_account_id",
|
|
441
|
+
result.debit_account_id,
|
|
442
|
+
"Failed to set property \"debit_account_id\" of transfer lookup result.",
|
|
443
|
+
);
|
|
444
|
+
|
|
445
|
+
try translate.u128_into_object(
|
|
446
|
+
env,
|
|
447
|
+
napi_object,
|
|
448
|
+
"credit_account_id",
|
|
449
|
+
result.credit_account_id,
|
|
450
|
+
"Failed to set property \"credit_account_id\" of transfer lookup result.",
|
|
451
|
+
);
|
|
452
|
+
|
|
453
|
+
try translate.u128_into_object(
|
|
454
|
+
env,
|
|
455
|
+
napi_object,
|
|
456
|
+
"user_data",
|
|
457
|
+
result.user_data,
|
|
458
|
+
"Failed to set property \"user_data\" of transfer lookup result.",
|
|
459
|
+
);
|
|
460
|
+
|
|
461
|
+
try translate.byte_slice_into_object(
|
|
462
|
+
env,
|
|
463
|
+
napi_object,
|
|
464
|
+
"reserved",
|
|
465
|
+
&result.reserved,
|
|
466
|
+
"Failed to set property \"reserved\" of transfer lookup result.",
|
|
467
|
+
);
|
|
468
|
+
|
|
469
|
+
try translate.u64_into_object(
|
|
470
|
+
env,
|
|
471
|
+
napi_object,
|
|
472
|
+
"timeout",
|
|
473
|
+
result.timeout,
|
|
474
|
+
"Failed to set property \"timeout\" of transfer lookup result.",
|
|
475
|
+
);
|
|
476
|
+
|
|
477
|
+
try translate.u32_into_object(
|
|
478
|
+
env,
|
|
479
|
+
napi_object,
|
|
480
|
+
"code",
|
|
481
|
+
@intCast(u32, result.code),
|
|
482
|
+
"Failed to set property \"code\" of transfer lookup result.",
|
|
483
|
+
);
|
|
484
|
+
|
|
485
|
+
try translate.u32_into_object(
|
|
486
|
+
env,
|
|
487
|
+
napi_object,
|
|
488
|
+
"flags",
|
|
489
|
+
@bitCast(u32, result.flags),
|
|
490
|
+
"Failed to set property \"flags\" of transfer lookup result.",
|
|
491
|
+
);
|
|
492
|
+
|
|
493
|
+
try translate.u64_into_object(
|
|
494
|
+
env,
|
|
495
|
+
napi_object,
|
|
496
|
+
"amount",
|
|
497
|
+
result.amount,
|
|
498
|
+
"Failed to set property \"amount\" of transfer lookup result.",
|
|
499
|
+
);
|
|
500
|
+
|
|
501
|
+
try translate.u64_into_object(
|
|
502
|
+
env,
|
|
503
|
+
napi_object,
|
|
504
|
+
"timestamp",
|
|
505
|
+
result.timestamp,
|
|
506
|
+
"Failed to set property \"timestamp\" of transfer lookup result.",
|
|
507
|
+
);
|
|
508
|
+
|
|
509
|
+
try translate.set_array_element(
|
|
510
|
+
env,
|
|
511
|
+
napi_array,
|
|
512
|
+
i,
|
|
513
|
+
napi_object,
|
|
514
|
+
"Failed to set element in results array.",
|
|
515
|
+
);
|
|
516
|
+
}
|
|
517
|
+
},
|
|
518
|
+
else => unreachable,
|
|
416
519
|
}
|
|
417
520
|
|
|
418
521
|
return napi_array;
|
|
@@ -422,7 +525,7 @@ fn encode_napi_results_array(
|
|
|
422
525
|
fn init(env: c.napi_env, info: c.napi_callback_info) callconv(.C) c.napi_value {
|
|
423
526
|
var argc: usize = 1;
|
|
424
527
|
var argv: [1]c.napi_value = undefined;
|
|
425
|
-
if (c.napi_get_cb_info(env, info, &argc, &argv, null, null) != .napi_ok) {
|
|
528
|
+
if (c.napi_get_cb_info(env, info, &argc, &argv, null, null) != c.napi_ok) {
|
|
426
529
|
translate.throw(env, "Failed to get args.") catch return null;
|
|
427
530
|
}
|
|
428
531
|
if (argc != 1) translate.throw(
|
|
@@ -455,7 +558,7 @@ fn init(env: c.napi_env, info: c.napi_callback_info) callconv(.C) c.napi_value {
|
|
|
455
558
|
fn request(env: c.napi_env, info: c.napi_callback_info) callconv(.C) c.napi_value {
|
|
456
559
|
var argc: usize = 4;
|
|
457
560
|
var argv: [4]c.napi_value = undefined;
|
|
458
|
-
if (c.napi_get_cb_info(env, info, &argc, &argv, null, null) != .napi_ok) {
|
|
561
|
+
if (c.napi_get_cb_info(env, info, &argc, &argv, null, null) != c.napi_ok) {
|
|
459
562
|
translate.throw(env, "Failed to get args.") catch return null;
|
|
460
563
|
}
|
|
461
564
|
|
|
@@ -509,7 +612,7 @@ fn request(env: c.napi_env, info: c.napi_callback_info) callconv(.C) c.napi_valu
|
|
|
509
612
|
fn raw_request(env: c.napi_env, info: c.napi_callback_info) callconv(.C) c.napi_value {
|
|
510
613
|
var argc: usize = 4;
|
|
511
614
|
var argv: [4]c.napi_value = undefined;
|
|
512
|
-
if (c.napi_get_cb_info(env, info, &argc, &argv, null, null) != .napi_ok) {
|
|
615
|
+
if (c.napi_get_cb_info(env, info, &argc, &argv, null, null) != c.napi_ok) {
|
|
513
616
|
translate.throw(env, "Failed to get args.") catch return null;
|
|
514
617
|
}
|
|
515
618
|
|
|
@@ -610,6 +713,7 @@ fn on_result(user_data: u128, operation: Operation, results: Client.Error![]cons
|
|
|
610
713
|
value,
|
|
611
714
|
) catch return,
|
|
612
715
|
.lookup_accounts => encode_napi_results_array(Account, env, value) catch return,
|
|
716
|
+
.lookup_transfers => encode_napi_results_array(Transfer, env, value) catch return,
|
|
613
717
|
};
|
|
614
718
|
|
|
615
719
|
argv[0] = globals.napi_undefined;
|
|
@@ -629,11 +733,10 @@ fn on_result(user_data: u128, operation: Operation, results: Client.Error![]cons
|
|
|
629
733
|
fn tick(env: c.napi_env, info: c.napi_callback_info) callconv(.C) c.napi_value {
|
|
630
734
|
var argc: usize = 1;
|
|
631
735
|
var argv: [1]c.napi_value = undefined;
|
|
632
|
-
if (c.napi_get_cb_info(env, info, &argc, &argv, null, null) != .napi_ok) {
|
|
736
|
+
if (c.napi_get_cb_info(env, info, &argc, &argv, null, null) != c.napi_ok) {
|
|
633
737
|
translate.throw(env, "Failed to get args.") catch return null;
|
|
634
738
|
}
|
|
635
739
|
|
|
636
|
-
const allocator = std.heap.c_allocator;
|
|
637
740
|
if (argc != 1) translate.throw(
|
|
638
741
|
env,
|
|
639
742
|
"Function tick() requires 1 argument exactly.",
|
|
@@ -659,7 +762,7 @@ fn tick(env: c.napi_env, info: c.napi_callback_info) callconv(.C) c.napi_value {
|
|
|
659
762
|
fn deinit(env: c.napi_env, info: c.napi_callback_info) callconv(.C) c.napi_value {
|
|
660
763
|
var argc: usize = 1;
|
|
661
764
|
var argv: [1]c.napi_value = undefined;
|
|
662
|
-
if (c.napi_get_cb_info(env, info, &argc, &argv, null, null) != .napi_ok) {
|
|
765
|
+
if (c.napi_get_cb_info(env, info, &argc, &argv, null, null) != c.napi_ok) {
|
|
663
766
|
translate.throw(env, "Failed to get args.") catch return null;
|
|
664
767
|
}
|
|
665
768
|
|
package/src/test.ts
CHANGED
|
@@ -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> => {
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
@echo off
|
|
2
|
+
|
|
3
|
+
set ZIG_RELEASE_DEFAULT=0.9.0
|
|
4
|
+
|
|
5
|
+
:: Determine the Zig build:
|
|
6
|
+
if "%~1"=="" (
|
|
7
|
+
set ZIG_RELEASE=%ZIG_RELEASE_DEFAULT%
|
|
8
|
+
) else if "%~1"=="latest" (
|
|
9
|
+
set ZIG_RELEASE=builds
|
|
10
|
+
) else (
|
|
11
|
+
set ZIG_RELEASE=%~1
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
:: Checks format of release version.
|
|
15
|
+
echo.%ZIG_RELEASE% | findstr /b /r /c:"builds" /c:"^[0-9][0-9]*.[0-9][0-9]*.[0-9][0-9]*">nul || (echo.Unexpected release format. && exit 1)
|
|
16
|
+
|
|
17
|
+
set ZIG_OS=windows
|
|
18
|
+
set ZIG_ARCH=x86_64
|
|
19
|
+
|
|
20
|
+
set ZIG_TARGET=zig-%ZIG_OS%-%ZIG_ARCH%
|
|
21
|
+
|
|
22
|
+
:: Determine the build, split the JSON line on whitespace and extract the 2nd field:
|
|
23
|
+
for /f "tokens=2" %%a in ('curl --silent https://ziglang.org/download/index.json ^| findstr %ZIG_TARGET% ^| findstr %ZIG_RELEASE%' ) do (
|
|
24
|
+
set ZIG_URL=%%a
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
:: Then remove quotes and commas:
|
|
28
|
+
for /f %%b in ("%ZIG_URL:,=%") do (
|
|
29
|
+
set ZIG_URL=%%~b
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
:: Checks the ZIG_URL variable follows the expected format.
|
|
33
|
+
echo.%ZIG_URL% | findstr /b /r /c:"https://ziglang.org/builds/" /c:"https://ziglang.org/download/%ZIG_RELEASE%">nul || (echo.Unexpected release URL format. && exit 1)
|
|
34
|
+
|
|
35
|
+
if "%ZIG_RELEASE%"=="builds" (
|
|
36
|
+
echo Installing Zig latest build...
|
|
37
|
+
) else (
|
|
38
|
+
echo Installing Zig %ZIG_RELEASE% release build...
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
:: Using variable modifiers to determine the directory and filename from the URL:
|
|
42
|
+
:: %~ni Expands %i to a file name only and %~xi Expands %i to a file name extension only.
|
|
43
|
+
for /f %%i in ("%ZIG_URL%") do (
|
|
44
|
+
set ZIG_DIRECTORY=%%~ni
|
|
45
|
+
set ZIG_TARBALL=%%~nxi
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
:: Checks the ZIG_DIRECTORY variable follows the expected format.
|
|
49
|
+
echo.%ZIG_DIRECTORY% | findstr /b /r /c:"zig-win64-" /c:"zig-windows-x86_64-">nul || (echo.Unexpected zip directory name format. && exit 1)
|
|
50
|
+
|
|
51
|
+
:: Making sure we download to the same output document, without wget adding "-1" etc. if the file was previously partially downloaded:
|
|
52
|
+
if exist %ZIG_TARBALL% (
|
|
53
|
+
del /q %ZIG_TARBALL%
|
|
54
|
+
if exist %ZIG_TARBALL% (
|
|
55
|
+
echo Failed to delete %ZIG_TARBALL%.
|
|
56
|
+
exit 1
|
|
57
|
+
)
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
echo Downloading %ZIG_URL%...
|
|
61
|
+
curl --silent --progress-bar --output %ZIG_TARBALL% %ZIG_URL%
|
|
62
|
+
if not exist %ZIG_TARBALL% (
|
|
63
|
+
echo Failed to download Zig zip file.
|
|
64
|
+
exit 1
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
:: Replace any existing Zig installation so that we can install or upgrade:
|
|
68
|
+
echo Removing any existing 'zig' and %ZIG_DIRECTORY% folders before extracting.
|
|
69
|
+
if exist zig\ (
|
|
70
|
+
rd /s /q zig\
|
|
71
|
+
:: Ensure the directory has been deleted.
|
|
72
|
+
if exist zig\ (
|
|
73
|
+
echo The ‘zig’ directory could not be deleted.
|
|
74
|
+
exit 1
|
|
75
|
+
)
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
if exist %ZIG_DIRECTORY%\ (
|
|
79
|
+
rd /s /q %ZIG_DIRECTORY%
|
|
80
|
+
:: Ensure the directory has been deleted.
|
|
81
|
+
if exist %ZIG_DIRECTORY% (
|
|
82
|
+
echo The %ZIG_DIRECTORY% directory could not be deleted.
|
|
83
|
+
exit 1
|
|
84
|
+
)
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
:: Extract and then remove the downloaded tarball:
|
|
88
|
+
echo Extracting %ZIG_TARBALL%...
|
|
89
|
+
powershell -Command "Expand-Archive %ZIG_TARBALL% -DestinationPath ."
|
|
90
|
+
if not exist %ZIG_TARBALL% (
|
|
91
|
+
echo Failed to extract zip file.
|
|
92
|
+
exit 1
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
echo Installing %ZIG_DIRECTORY% to 'zig' in current working directory...
|
|
96
|
+
ren %ZIG_DIRECTORY% zig
|
|
97
|
+
if exist %ZIG_DIRECTORY% (
|
|
98
|
+
echo Failed to rename %ZIG_DIRECTORY% to zig.
|
|
99
|
+
exit 1
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
:: Removes the zip file
|
|
103
|
+
del /q %ZIG_TARBALL%
|
|
104
|
+
if exist %ZIG_TARBALL% (
|
|
105
|
+
echo Failed to delete %ZIG_TARBALL% file.
|
|
106
|
+
exit 1
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
echo "Congratulations, you have successfully installed Zig version %ZIG_RELEASE%. Enjoy!"
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
set -e
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
ZIG_RELEASE_DEFAULT="0.9.0"
|
|
5
|
+
|
|
6
|
+
# Default to the release build, or allow the latest dev build, or an explicit release version:
|
|
5
7
|
if [ -z "$1" ]; then
|
|
6
|
-
ZIG_RELEASE
|
|
8
|
+
ZIG_RELEASE=$ZIG_RELEASE_DEFAULT
|
|
7
9
|
elif [ "$1" == "latest" ]; then
|
|
8
10
|
ZIG_RELEASE="builds"
|
|
9
11
|
else
|
|
@@ -23,7 +23,7 @@ var file_stats = std.ArrayListUnmanaged(Stats){};
|
|
|
23
23
|
var seen = std.AutoArrayHashMapUnmanaged(fs.File.INode, void){};
|
|
24
24
|
|
|
25
25
|
var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{}){};
|
|
26
|
-
const gpa =
|
|
26
|
+
const gpa = general_purpose_allocator.allocator();
|
|
27
27
|
|
|
28
28
|
pub fn main() !void {
|
|
29
29
|
const argv = std.os.argv;
|
|
@@ -119,7 +119,13 @@ fn lint_file(file_path: []const u8, dir: fs.Dir, sub_path: []const u8) LintError
|
|
|
119
119
|
// Add to set after no longer possible to get error.IsDir.
|
|
120
120
|
if (try seen.fetchPut(gpa, stat.inode, {})) |_| return;
|
|
121
121
|
|
|
122
|
-
const source = try source_file.
|
|
122
|
+
const source = try source_file.readToEndAllocOptions(
|
|
123
|
+
gpa,
|
|
124
|
+
math.maxInt(usize),
|
|
125
|
+
null,
|
|
126
|
+
@alignOf(u8),
|
|
127
|
+
0,
|
|
128
|
+
);
|
|
123
129
|
try check_line_length(source, file_path);
|
|
124
130
|
|
|
125
131
|
var tree = try std.zig.parse(gpa, source);
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
:: Installs Zig if needed and runs the VOPR
|
|
2
|
+
@echo off
|
|
3
|
+
|
|
4
|
+
:: Install Zig if a zig folder does not already exist:
|
|
5
|
+
if not exist zig\ (
|
|
6
|
+
:: Installs the latest version of Zig
|
|
7
|
+
call scripts\install_zig.bat
|
|
8
|
+
:: Checks that the Zig folder now exists
|
|
9
|
+
if not exist zig\ (
|
|
10
|
+
echo The Zig installation failed.
|
|
11
|
+
exit 1
|
|
12
|
+
)
|
|
13
|
+
echo Running the TigerBeetle VOPR for the first time...
|
|
14
|
+
echo Visit https://www.tigerbeetle.com
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
:: If a seed is provided as an argument then replay the seed, otherwise test 1,000 seeds:
|
|
18
|
+
if not "%~1"=="" (
|
|
19
|
+
:: Build in fast ReleaseSafe mode if required, useful where you don't need debug logging:
|
|
20
|
+
if "%~2"=="-OReleaseSafe" (
|
|
21
|
+
echo Replaying seed %~1 in ReleaseSafe mode...
|
|
22
|
+
call zig\zig run src\simulator.zig -OReleaseSafe -- %~1
|
|
23
|
+
if not %ERRORLEVEL%==0 (
|
|
24
|
+
echo Cannot replay the %~1 seed using the VOPR.
|
|
25
|
+
exit 1
|
|
26
|
+
)
|
|
27
|
+
) else (
|
|
28
|
+
echo Replaying seed %~1 in Debug mode with full debug logging enabled...
|
|
29
|
+
call zig\zig run src\simulator.zig -ODebug -- %~1
|
|
30
|
+
if not %ERRORLEVEL%==0 (
|
|
31
|
+
echo Cannot run the VOPR.
|
|
32
|
+
exit 1
|
|
33
|
+
)
|
|
34
|
+
)
|
|
35
|
+
) else (
|
|
36
|
+
call zig\zig build-exe src\simulator.zig -OReleaseSafe
|
|
37
|
+
if not %ERRORLEVEL%==0 (
|
|
38
|
+
echo Cannot run the VOPR.
|
|
39
|
+
exit 1
|
|
40
|
+
)
|
|
41
|
+
for %%i in (1,1,1000) do (
|
|
42
|
+
call simulator
|
|
43
|
+
if not %ERRORLEVEL%==0 (
|
|
44
|
+
echo Cannot run a seed using the VOPR.
|
|
45
|
+
exit 1
|
|
46
|
+
)
|
|
47
|
+
)
|
|
48
|
+
)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const std = @import("std");
|
|
2
|
+
const builtin = @import("builtin");
|
|
2
3
|
const assert = std.debug.assert;
|
|
3
4
|
const config = @import("config.zig");
|
|
4
5
|
|
|
@@ -30,7 +31,7 @@ const BATCHES: f32 = MAX_TRANSFERS / BATCH_SIZE;
|
|
|
30
31
|
const TOTAL_BATCHES = @ceil(BATCHES);
|
|
31
32
|
|
|
32
33
|
const log = std.log;
|
|
33
|
-
pub const log_level: std.log.Level = .
|
|
34
|
+
pub const log_level: std.log.Level = .info;
|
|
34
35
|
|
|
35
36
|
var accounts = [_]Account{
|
|
36
37
|
Account{
|
|
@@ -65,13 +66,14 @@ pub fn main() !void {
|
|
|
65
66
|
const stdout = std.io.getStdOut().writer();
|
|
66
67
|
const stderr = std.io.getStdErr().writer();
|
|
67
68
|
|
|
68
|
-
if (
|
|
69
|
+
if (builtin.mode != .ReleaseSafe and builtin.mode != .ReleaseFast) {
|
|
69
70
|
try stderr.print("Benchmark must be built as ReleaseSafe for minimum performance.\n", .{});
|
|
70
71
|
}
|
|
71
72
|
|
|
72
73
|
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
|
73
74
|
defer arena.deinit();
|
|
74
|
-
|
|
75
|
+
|
|
76
|
+
const allocator = arena.allocator();
|
|
75
77
|
|
|
76
78
|
const client_id = std.crypto.random.int(u128);
|
|
77
79
|
const cluster_id: u32 = 0;
|
|
@@ -90,7 +92,7 @@ pub fn main() !void {
|
|
|
90
92
|
message_bus.set_on_message(*Client, &client, Client.on_message);
|
|
91
93
|
|
|
92
94
|
// Pre-allocate a million transfers:
|
|
93
|
-
|
|
95
|
+
const transfers = try arena.allocator().alloc(Transfer, MAX_TRANSFERS);
|
|
94
96
|
for (transfers) |*transfer, index| {
|
|
95
97
|
transfer.* = .{
|
|
96
98
|
.id = index,
|
|
@@ -106,7 +108,7 @@ pub fn main() !void {
|
|
|
106
108
|
}
|
|
107
109
|
|
|
108
110
|
// Pre-allocate a million commits:
|
|
109
|
-
|
|
111
|
+
const commits: ?[]Commit = if (IS_TWO_PHASE_COMMIT) try arena.allocator().alloc(Commit, MAX_TRANSFERS) else null;
|
|
110
112
|
if (commits) |all_commits| {
|
|
111
113
|
for (all_commits) |*commit, index| {
|
|
112
114
|
commit.* = .{
|
|
@@ -223,7 +225,7 @@ const TimedQueue = struct {
|
|
|
223
225
|
|
|
224
226
|
const now = std.time.milliTimestamp();
|
|
225
227
|
self.start = now;
|
|
226
|
-
if (self.batches.
|
|
228
|
+
if (self.batches.head_ptr()) |starting_batch| {
|
|
227
229
|
log.debug("sending first batch...", .{});
|
|
228
230
|
self.batch_start = now;
|
|
229
231
|
var message = self.client.get_message() orelse {
|
|
@@ -254,7 +256,7 @@ const TimedQueue = struct {
|
|
|
254
256
|
pub fn lap(user_data: u128, operation: Operation, results: Client.Error![]const u8) void {
|
|
255
257
|
const now = std.time.milliTimestamp();
|
|
256
258
|
const value = results catch |err| {
|
|
257
|
-
log.
|
|
259
|
+
log.err("Client returned error={o}", .{@errorName(err)});
|
|
258
260
|
@panic("Client returned error during benchmarking.");
|
|
259
261
|
};
|
|
260
262
|
|
|
@@ -285,7 +287,7 @@ const TimedQueue = struct {
|
|
|
285
287
|
else => unreachable,
|
|
286
288
|
}
|
|
287
289
|
|
|
288
|
-
if (self.batches.
|
|
290
|
+
if (self.batches.head_ptr()) |next_batch| {
|
|
289
291
|
var message = self.client.get_message() orelse {
|
|
290
292
|
@panic("Client message pool has been exhausted.");
|
|
291
293
|
};
|