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.
- package/README.md +21 -7
- package/dist/benchmark.js +1 -1
- package/dist/benchmark.js.map +1 -1
- package/dist/index.d.ts +22 -20
- package/dist/index.js +40 -18
- package/dist/index.js.map +1 -1
- package/dist/test.js +13 -1
- package/dist/test.js.map +1 -1
- package/package.json +12 -12
- package/scripts/postinstall.sh +2 -2
- package/src/benchmark.ts +4 -4
- package/src/index.ts +35 -9
- package/src/node.zig +139 -28
- package/src/test.ts +19 -5
- package/src/tigerbeetle/scripts/benchmark.sh +10 -3
- package/src/tigerbeetle/scripts/install.sh +2 -2
- package/src/tigerbeetle/scripts/install_zig.bat +109 -0
- package/src/tigerbeetle/scripts/install_zig.sh +21 -4
- package/src/tigerbeetle/scripts/vopr.bat +48 -0
- package/src/tigerbeetle/scripts/vopr.sh +33 -0
- package/src/tigerbeetle/src/benchmark.zig +74 -42
- package/src/tigerbeetle/src/cli.zig +136 -83
- package/src/tigerbeetle/src/config.zig +80 -26
- package/src/tigerbeetle/src/demo.zig +101 -78
- package/src/tigerbeetle/src/demo_01_create_accounts.zig +2 -7
- package/src/tigerbeetle/src/demo_02_lookup_accounts.zig +2 -7
- package/src/tigerbeetle/src/demo_03_create_transfers.zig +2 -7
- package/src/tigerbeetle/src/demo_04_create_transfers_two_phase_commit.zig +2 -5
- package/src/tigerbeetle/src/demo_05_accept_transfers.zig +2 -7
- package/src/tigerbeetle/src/demo_06_reject_transfers.zig +2 -7
- package/src/tigerbeetle/src/demo_07_lookup_transfers.zig +8 -0
- package/src/tigerbeetle/src/fifo.zig +20 -11
- package/src/tigerbeetle/src/io.zig +35 -22
- package/src/tigerbeetle/src/io_darwin.zig +701 -0
- package/src/tigerbeetle/src/main.zig +72 -25
- package/src/tigerbeetle/src/message_bus.zig +379 -456
- package/src/tigerbeetle/src/message_pool.zig +3 -3
- package/src/tigerbeetle/src/ring_buffer.zig +192 -37
- package/src/tigerbeetle/src/simulator.zig +317 -0
- package/src/tigerbeetle/src/state_machine.zig +846 -38
- package/src/tigerbeetle/src/storage.zig +488 -90
- package/src/tigerbeetle/src/test/cluster.zig +221 -0
- package/src/tigerbeetle/src/test/message_bus.zig +92 -0
- package/src/tigerbeetle/src/test/network.zig +182 -0
- package/src/tigerbeetle/src/test/packet_simulator.zig +371 -0
- package/src/tigerbeetle/src/test/state_checker.zig +142 -0
- package/src/tigerbeetle/src/test/state_machine.zig +71 -0
- package/src/tigerbeetle/src/test/storage.zig +375 -0
- package/src/tigerbeetle/src/test/time.zig +84 -0
- package/src/tigerbeetle/src/tigerbeetle.zig +6 -3
- package/src/tigerbeetle/src/time.zig +65 -0
- package/src/tigerbeetle/src/unit_tests.zig +14 -0
- package/src/tigerbeetle/src/vsr/client.zig +519 -0
- package/src/tigerbeetle/src/vsr/clock.zig +829 -0
- package/src/tigerbeetle/src/vsr/journal.zig +1368 -0
- package/src/tigerbeetle/src/vsr/marzullo.zig +306 -0
- package/src/tigerbeetle/src/vsr/replica.zig +4248 -0
- package/src/tigerbeetle/src/vsr.zig +601 -0
- package/src/tigerbeetle/LICENSE +0 -177
- package/src/tigerbeetle/README.md +0 -116
- package/src/tigerbeetle/src/client.zig +0 -319
- package/src/tigerbeetle/src/concurrent_ranges.zig +0 -162
- package/src/tigerbeetle/src/fixed_array_list.zig +0 -53
- package/src/tigerbeetle/src/io_async.zig +0 -600
- package/src/tigerbeetle/src/journal.zig +0 -567
- package/src/tigerbeetle/src/test_client.zig +0 -41
- package/src/tigerbeetle/src/test_main.zig +0 -118
- package/src/tigerbeetle/src/test_message_bus.zig +0 -132
- package/src/tigerbeetle/src/vr/journal.zig +0 -672
- package/src/tigerbeetle/src/vr/replica.zig +0 -3061
- 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
|
+
"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
|
-
"
|
|
31
|
-
"
|
|
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 &&
|
|
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",
|
package/scripts/postinstall.sh
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
set -e
|
|
3
3
|
|
|
4
|
-
./src/tigerbeetle/scripts/install_zig.sh 0.8.
|
|
4
|
+
./src/tigerbeetle/scripts/install_zig.sh 0.8.1
|
|
5
5
|
./scripts/download_node_headers.sh
|
|
6
|
-
mkdir -p dist &&
|
|
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:
|
|
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:
|
|
12
|
+
cluster_id: number, // u32
|
|
12
13
|
replica_addresses: Buffer,
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
export interface InitArgs {
|
|
16
|
-
cluster_id:
|
|
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 =
|
|
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
|
-
},
|
|
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
|
|
19
|
-
const 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
|
|
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
|
-
|
|
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:
|
|
121
|
-
|
|
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
|
-
|
|
129
|
-
errdefer allocator.free(
|
|
130
|
-
assert(
|
|
131
|
-
|
|
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.
|
|
137
|
-
|
|
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(
|
|
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
|
-
|
|
160
|
+
context.message_bus.set_on_message(*Client, &context.client, Client.on_message);
|
|
152
161
|
|
|
153
|
-
return
|
|
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, "
|
|
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
|
-
|
|
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.
|
|
425
|
-
const
|
|
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
|
-
|
|
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:
|
|
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:
|
|
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
|
-
|
|
9
|
-
|
|
8
|
+
CreateAccountError,
|
|
9
|
+
CreateTransferError
|
|
10
10
|
} from '.'
|
|
11
11
|
|
|
12
12
|
const client = createClient({
|
|
13
|
-
cluster_id:
|
|
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
|
-
|
|
29
|
-
|
|
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
|
|
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:
|