tigerbeetle-node 0.9.0 → 0.11.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 (112) hide show
  1. package/README.md +305 -103
  2. package/dist/index.d.ts +70 -67
  3. package/dist/index.js +70 -67
  4. package/dist/index.js.map +1 -1
  5. package/package.json +6 -6
  6. package/scripts/download_node_headers.sh +14 -7
  7. package/src/index.ts +11 -10
  8. package/src/node.zig +22 -20
  9. package/src/tigerbeetle/scripts/benchmark.bat +4 -3
  10. package/src/tigerbeetle/scripts/benchmark.sh +25 -10
  11. package/src/tigerbeetle/scripts/confirm_image.sh +44 -0
  12. package/src/tigerbeetle/scripts/fuzz_loop.sh +15 -0
  13. package/src/tigerbeetle/scripts/fuzz_unique_errors.sh +7 -0
  14. package/src/tigerbeetle/scripts/install.sh +20 -4
  15. package/src/tigerbeetle/scripts/install_zig.bat +5 -1
  16. package/src/tigerbeetle/scripts/install_zig.sh +32 -26
  17. package/src/tigerbeetle/scripts/pre-commit.sh +9 -0
  18. package/src/tigerbeetle/scripts/shellcheck.sh +5 -0
  19. package/src/tigerbeetle/scripts/tests_on_alpine.sh +10 -0
  20. package/src/tigerbeetle/scripts/tests_on_ubuntu.sh +14 -0
  21. package/src/tigerbeetle/scripts/upgrade_ubuntu_kernel.sh +12 -3
  22. package/src/tigerbeetle/src/benchmark.zig +19 -9
  23. package/src/tigerbeetle/src/benchmark_array_search.zig +317 -0
  24. package/src/tigerbeetle/src/benchmarks/perf.zig +299 -0
  25. package/src/tigerbeetle/src/c/tb_client/context.zig +103 -0
  26. package/src/tigerbeetle/src/c/tb_client/packet.zig +80 -0
  27. package/src/tigerbeetle/src/c/tb_client/signal.zig +288 -0
  28. package/src/tigerbeetle/src/c/tb_client/thread.zig +328 -0
  29. package/src/tigerbeetle/src/c/tb_client.h +221 -0
  30. package/src/tigerbeetle/src/c/tb_client.zig +104 -0
  31. package/src/tigerbeetle/src/c/test.zig +1 -0
  32. package/src/tigerbeetle/src/cli.zig +143 -84
  33. package/src/tigerbeetle/src/config.zig +161 -20
  34. package/src/tigerbeetle/src/demo.zig +14 -8
  35. package/src/tigerbeetle/src/demo_05_post_pending_transfers.zig +2 -2
  36. package/src/tigerbeetle/src/ewah.zig +318 -0
  37. package/src/tigerbeetle/src/ewah_benchmark.zig +121 -0
  38. package/src/tigerbeetle/src/eytzinger_benchmark.zig +317 -0
  39. package/src/tigerbeetle/src/fifo.zig +17 -1
  40. package/src/tigerbeetle/src/io/darwin.zig +12 -10
  41. package/src/tigerbeetle/src/io/linux.zig +25 -9
  42. package/src/tigerbeetle/src/io/windows.zig +13 -9
  43. package/src/tigerbeetle/src/iops.zig +101 -0
  44. package/src/tigerbeetle/src/lsm/README.md +214 -0
  45. package/src/tigerbeetle/src/lsm/binary_search.zig +341 -0
  46. package/src/tigerbeetle/src/lsm/bloom_filter.zig +125 -0
  47. package/src/tigerbeetle/src/lsm/compaction.zig +557 -0
  48. package/src/tigerbeetle/src/lsm/composite_key.zig +77 -0
  49. package/src/tigerbeetle/src/lsm/direction.zig +11 -0
  50. package/src/tigerbeetle/src/lsm/eytzinger.zig +587 -0
  51. package/src/tigerbeetle/src/lsm/forest.zig +204 -0
  52. package/src/tigerbeetle/src/lsm/forest_fuzz.zig +412 -0
  53. package/src/tigerbeetle/src/lsm/grid.zig +549 -0
  54. package/src/tigerbeetle/src/lsm/groove.zig +1002 -0
  55. package/src/tigerbeetle/src/lsm/k_way_merge.zig +474 -0
  56. package/src/tigerbeetle/src/lsm/level_iterator.zig +315 -0
  57. package/src/tigerbeetle/src/lsm/manifest.zig +580 -0
  58. package/src/tigerbeetle/src/lsm/manifest_level.zig +925 -0
  59. package/src/tigerbeetle/src/lsm/manifest_log.zig +953 -0
  60. package/src/tigerbeetle/src/lsm/node_pool.zig +231 -0
  61. package/src/tigerbeetle/src/lsm/posted_groove.zig +387 -0
  62. package/src/tigerbeetle/src/lsm/segmented_array.zig +1318 -0
  63. package/src/tigerbeetle/src/lsm/segmented_array_benchmark.zig +148 -0
  64. package/src/tigerbeetle/src/lsm/segmented_array_fuzz.zig +9 -0
  65. package/src/tigerbeetle/src/lsm/set_associative_cache.zig +894 -0
  66. package/src/tigerbeetle/src/lsm/table.zig +967 -0
  67. package/src/tigerbeetle/src/lsm/table_immutable.zig +203 -0
  68. package/src/tigerbeetle/src/lsm/table_iterator.zig +306 -0
  69. package/src/tigerbeetle/src/lsm/table_mutable.zig +174 -0
  70. package/src/tigerbeetle/src/lsm/test.zig +423 -0
  71. package/src/tigerbeetle/src/lsm/tree.zig +1090 -0
  72. package/src/tigerbeetle/src/lsm/tree_fuzz.zig +457 -0
  73. package/src/tigerbeetle/src/main.zig +141 -109
  74. package/src/tigerbeetle/src/message_bus.zig +49 -48
  75. package/src/tigerbeetle/src/message_pool.zig +22 -12
  76. package/src/tigerbeetle/src/ring_buffer.zig +126 -30
  77. package/src/tigerbeetle/src/simulator.zig +205 -140
  78. package/src/tigerbeetle/src/state_machine.zig +1268 -721
  79. package/src/tigerbeetle/src/static_allocator.zig +65 -0
  80. package/src/tigerbeetle/src/storage.zig +40 -14
  81. package/src/tigerbeetle/src/test/accounting/auditor.zig +577 -0
  82. package/src/tigerbeetle/src/test/accounting/workload.zig +819 -0
  83. package/src/tigerbeetle/src/test/cluster.zig +104 -88
  84. package/src/tigerbeetle/src/test/conductor.zig +365 -0
  85. package/src/tigerbeetle/src/test/fuzz.zig +121 -0
  86. package/src/tigerbeetle/src/test/id.zig +89 -0
  87. package/src/tigerbeetle/src/test/message_bus.zig +15 -24
  88. package/src/tigerbeetle/src/test/network.zig +26 -17
  89. package/src/tigerbeetle/src/test/priority_queue.zig +645 -0
  90. package/src/tigerbeetle/src/test/state_checker.zig +94 -68
  91. package/src/tigerbeetle/src/test/state_machine.zig +135 -69
  92. package/src/tigerbeetle/src/test/storage.zig +78 -28
  93. package/src/tigerbeetle/src/tigerbeetle.zig +19 -16
  94. package/src/tigerbeetle/src/unit_tests.zig +15 -0
  95. package/src/tigerbeetle/src/util.zig +51 -0
  96. package/src/tigerbeetle/src/vopr.zig +494 -0
  97. package/src/tigerbeetle/src/vopr_hub/README.md +58 -0
  98. package/src/tigerbeetle/src/vopr_hub/SETUP.md +199 -0
  99. package/src/tigerbeetle/src/vopr_hub/go.mod +3 -0
  100. package/src/tigerbeetle/src/vopr_hub/main.go +1022 -0
  101. package/src/tigerbeetle/src/vopr_hub/scheduler/go.mod +3 -0
  102. package/src/tigerbeetle/src/vopr_hub/scheduler/main.go +403 -0
  103. package/src/tigerbeetle/src/vsr/client.zig +34 -7
  104. package/src/tigerbeetle/src/vsr/journal.zig +164 -174
  105. package/src/tigerbeetle/src/vsr/replica.zig +1602 -651
  106. package/src/tigerbeetle/src/vsr/superblock.zig +1761 -0
  107. package/src/tigerbeetle/src/vsr/superblock_client_table.zig +255 -0
  108. package/src/tigerbeetle/src/vsr/superblock_free_set.zig +644 -0
  109. package/src/tigerbeetle/src/vsr/superblock_manifest.zig +561 -0
  110. package/src/tigerbeetle/src/vsr.zig +118 -170
  111. package/src/tigerbeetle/scripts/vopr.bat +0 -48
  112. package/src/tigerbeetle/scripts/vopr.sh +0 -33
package/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  # tigerbeetle-node
2
- [TigerBeetle](https://github.com/coilhq/tigerbeetle) client for Node.js.
2
+ [TigerBeetle](https://github.com/tigerbeetledb/tigerbeetle) client for Node.js.
3
3
 
4
4
  ## Installation
5
5
 
@@ -9,6 +9,16 @@ Install the `tigerbeetle-node` module to your current working directory:
9
9
  npm install tigerbeetle-node
10
10
  ```
11
11
 
12
+ If you run into issues, check out the distribution-specific install
13
+ steps that are run in CI to test support:
14
+
15
+ * [Alpine](./scripts/test_install_on_alpine.sh)
16
+ * [Amazon Linux](./scripts/test_install_on_amazonlinux.sh)
17
+ * [Debian](./scripts/test_install_on_debian.sh)
18
+ * [Fedora](./scripts/test_install_on_fedora.sh)
19
+ * [Ubuntu](./scripts/test_install_on_ubuntu.sh)
20
+ * [RHEL](./scripts/test_install_on_rhelubi.sh)
21
+
12
22
  ### Prerequisites
13
23
 
14
24
  * NodeJS >= `14.0.0`. _(If the correct version is not installed, an installation error will occur)_
@@ -24,140 +34,282 @@ For the moment, only one client can be instantiated globally per process.
24
34
  Future releases will allow multiple client instantiations.
25
35
 
26
36
  ```js
27
- import { createClient } from 'tigerbeetle-node'
37
+ const {
38
+ createClient,
39
+ CreateAccountError,
40
+ CreateTransferError,
41
+ AccountFlags,
42
+ TransferFlags,
43
+ } = require('tigerbeetle-node');
28
44
 
29
45
  const client = createClient({
30
46
  cluster_id: 0,
31
47
  replica_addresses: ['3001', '3002', '3003']
32
- })
48
+ });
33
49
  ```
34
50
 
35
- One of the ways TigerBeetle achieves its performance is through batching.
36
- This is reflected in the below function interfaces where each one takes in an array of events.
51
+ One of the ways TigerBeetle achieves its performance is through
52
+ batching. This is reflected in the below function interfaces where
53
+ each one takes in an array of items.
54
+
55
+ ### Sidenote: `BigInt`
56
+
57
+ TigerBeetle uses 64-bit integers for many fields while JavaScript's
58
+ builtin `Number` maximum value is 2^53-1. The `n` suffix in JavaScript
59
+ means the value is a BigInt. This is useful for literal numbers. If
60
+ you already have a `Number` variable though, you can call the `BigInt`
61
+ constructor to get a `BigInt` from it. For example, `1n` is the same
62
+ as `BigInt(1)`.
63
+
64
+ ## Creating Accounts: `client.createAccounts`
37
65
 
38
- ### Account Creation
66
+ See details for account fields in the [Accounts
67
+ reference](https://docs.tigerbeetle.com/reference/accounts).
39
68
 
40
69
  ```js
41
70
  const account = {
42
- id: 137n, // u128
43
- user_data: 0n, // u128, opaque third-party identifier to link this account to an external entity:
44
- reserved: Buffer.alloc(48, 0), // [48]u8
45
- ledger: 1, // u32, ledger value
46
- code: 718, // u16, a chart of accounts code describing the type of account (e.g. clearing, settlement)
47
- flags: 0, // u16
48
- debits_pending: 0n, // u64
49
- debits_posted: 0n, // u64
50
- credits_pending: 0n, // u64
51
- credits_posted: 0n, // u64
52
- timestamp: 0n, // u64, Reserved: This will be set by the server.
71
+ id: 137n, // u128
72
+ user_data: 0n, // u128, opaque third-party identifier to link this account to an external entity:
73
+ reserved: Buffer.alloc(48, 0), // [48]u8
74
+ ledger: 1, // u32, ledger value
75
+ code: 718, // u16, a chart of accounts code describing the type of account (e.g. clearing, settlement)
76
+ flags: 0, // u16
77
+ debits_pending: 0n, // u64
78
+ debits_posted: 0n, // u64
79
+ credits_pending: 0n, // u64
80
+ credits_posted: 0n, // u64
81
+ timestamp: 0n, // u64, Reserved: This will be set by the server.
82
+ };
83
+
84
+ const errors = await client.createAccounts([account]);
85
+ if (errors.length) {
86
+ // Grab a human-readable message from the response
87
+ console.log(CreateAccountError[errors[0].code]);
53
88
  }
89
+ ```
90
+
91
+ ### Account Flags
92
+
93
+ The account `flags` value is a bitfield. See details for these flags in
94
+ the [Accounts
95
+ reference](https://docs.tigerbeetle.com/reference/accounts#flags).
54
96
 
55
- const errors = await client.createAccounts([account])
97
+ To toggle behavior for an account, combine enum values stored in the
98
+ `AccountFlags` object (in TypeScript it is an actual enum) with
99
+ bitwise-or:
100
+
101
+ * `AccountFlags.linked`
102
+ * `AccountFlags.debits_must_not_exceed_credits`
103
+ * `AccountFlags.credits_must_not_exceed_credits`
104
+
105
+ For example, to link `account0` and `account1`, where `account0`
106
+ additionally has the `debits_must_not_exceed_credits` constraint:
107
+
108
+ ```js
109
+ const account0 = { ... account values ... };
110
+ const account1 = { ... account values ... };
111
+ account0.flags = AccountFlags.linked | AccountFlags.debits_must_not_exceed_credits;
112
+ // Create the account
113
+ const errors = client.createAccounts([account0, account1]);
56
114
  ```
57
- Successfully executed events return an empty array whilst unsuccessful ones return an array with errors for **only the ones that failed**. An error will point to the index in the submitted array of the failed event.
115
+
116
+ ### Response and Errors
117
+
118
+ The response is an empty array if all accounts were created
119
+ successfully. If the response is non-empty, each object in the
120
+ response array contains error information for an account that
121
+ failed. The error object contains an error code and the index of the
122
+ account in the request batch.
123
+
58
124
  ```js
59
- const errors = await client.createAccounts([account1, account2, account3])
125
+ const errors = await client.createAccounts([account1, account2, account3]);
60
126
 
61
- // errors = [{ index: 1, code: 1 }]
62
- const error = errors[0]
127
+ // errors = [{ index: 1, code: 1 }];
128
+ for (const error of errors) {
63
129
  switch (error.code) {
64
- case CreateAccountError.exists: {
65
- console.error(`Batch event at ${error.index} already exists.`)
66
- }
130
+ case CreateAccountError.exists:
131
+ console.error(`Batch account at ${error.index} already exists.`);
132
+ break;
133
+ default:
134
+ console.error(`Batch account at ${error.index} failed to create: ${CreateAccountError[error.code]}.`);
67
135
  }
136
+ }
68
137
  ```
69
- The example above shows that the event in index 1 failed with error 1. This means that `account1` and `account3` were created successfully but not `account2`.
70
138
 
71
- The `flags` on an account provide a way for you to enforce policies by toggling the bits below.
72
- | bit 0 | bit 1 | bit 2 |
73
- |----------|----------------------------------|-----------------------------------------|
74
- | `linked` | `debits_must_not_exceed_credits` | `credits_must_not_exceed_debits` |
139
+ The example above shows that the account in index 1 failed with
140
+ error 1. This error here means that `account1` and `account3` were
141
+ created successfully. But `account2` was not created.
75
142
 
76
- The creation of an account can be linked to the successful creation of another by setting the `linked` flag (see [linked events](#linked-events)). By setting `debits_must_not_exceed_credits`, then any transfer such that `debits_posted + debits_pending + amount > credits_posted` will fail. Similarly for `credits_must_not_exceed_debits`.
77
- ```js
78
- enum CreateAccountFlags {
79
- linked = (1 << 0),
80
- debits_must_not_exceed_credits = (1 << 1),
81
- credits_must_not_exceed_debits = (1 << 2)
82
- }
143
+ To handle errors you can either 1) exactly match error codes returned
144
+ from `client.createAccounts` with enum values in the
145
+ `CreateAccountError` object, or you can 2) look up the error code in
146
+ the `CreateAccountError` object for a human-readable string.
83
147
 
84
- let flags = 0
85
- flags |= CreateAccountFlags.debits_must_not_exceed_credits
86
- ```
148
+ ## Account Lookup: `client.lookupAccounts`
149
+
150
+ Account lookup is batched, like account creation. Pass in all `id`s to
151
+ fetch, and matched accounts are returned.
87
152
 
88
- ### Account Lookup
153
+ If no account matches an `id`, no object is returned for that
154
+ account. So the order of accounts in the response is not necessarily
155
+ the same as the order of `id`s in the request. You can refer to the
156
+ `id` field in the response to distinguish accounts.
89
157
 
90
- The `id` of the account is used for lookups. Only matched accounts are returned.
91
158
  ```js
92
- // account 137n exists, 138n does not
93
- const accounts = await client.lookupAccounts([137n, 138n])
94
-
95
- /**
96
- * const accounts = [{
97
- * id: 137n,
98
- * user_data: 0n,
99
- * reserved: Buffer,
100
- * ledger: 1,
101
- * code: 718,
102
- * flags: 0,
103
- * debits_pending: 0n,
104
- * debits_posted: 0n,
105
- * credits_pending: 0n,
106
- * credits_posted: 0n,
107
- * timestamp: 1623062009212508993n,
108
- * }]
109
- */
110
- ```
111
-
112
- ### Creating a Transfer
159
+ // account 137n exists, 138n does not
160
+ const accounts = await client.lookupAccounts([137n, 138n]);
161
+ /* console.log(accounts);
162
+ * [{
163
+ * id: 137n,
164
+ * user_data: 0n,
165
+ * reserved: Buffer,
166
+ * ledger: 1,
167
+ * code: 718,
168
+ * flags: 0,
169
+ * debits_pending: 0n,
170
+ * debits_posted: 0n,
171
+ * credits_pending: 0n,
172
+ * credits_posted: 0n,
173
+ * timestamp: 1623062009212508993n,
174
+ * }]
175
+ */
176
+ ```
177
+
178
+ ## Creating Transfers: `client.createTransfers`
113
179
 
114
180
  This creates a journal entry between two accounts.
181
+
182
+ See details for transfer fields in the [Transfers
183
+ reference](https://docs.tigerbeetle.com/reference/transfers).
184
+
115
185
  ```js
116
186
  const transfer = {
117
- id: 1n, // u128
118
- // Double-entry accounting:
119
- debit_account_id: 1n, // u128
120
- credit_account_id: 2n, // u128
121
- // Opaque third-party identifier to link this transfer to an external entity:
122
- user_data: 0n, // u128
123
- reserved: 0n, // u128
124
- // Timeout applicable for a pending/2-phase transfer:
125
- timeout: 0n, // u64, in nano-seconds.
126
- // Collection of accounts usually grouped by the currency:
127
- // You can't transfer money between accounts with different ledgers:
128
- ledger: 720, // u32, ledger for transfer (e.g. currency).
129
- // Chart of accounts code describing the reason for the transfer:
130
- code: 1, // u16, (e.g. deposit, settlement)
131
- flags: 0, // u16
132
- amount: 10n, // u64
133
- timestamp: 0n, //u64, Reserved: This will be set by the server.
187
+ id: 1n, // u128
188
+ pending_id: 0n, // u128
189
+ // Double-entry accounting:
190
+ debit_account_id: 1n, // u128
191
+ credit_account_id: 2n, // u128
192
+ // Opaque third-party identifier to link this transfer to an external entity:
193
+ user_data: 0n, // u128
194
+ reserved: 0n, // u128
195
+ // Timeout applicable for a pending/2-phase transfer:
196
+ timeout: 0n, // u64, in nano-seconds.
197
+ // Collection of accounts usually grouped by the currency:
198
+ // You can't transfer money between accounts with different ledgers:
199
+ ledger: 1, // u32, ledger for transfer (e.g. currency).
200
+ // Chart of accounts code describing the reason for the transfer:
201
+ code: 720, // u16, (e.g. deposit, settlement)
202
+ flags: 0, // u16
203
+ amount: 10n, // u64
204
+ timestamp: 0n, //u64, Reserved: This will be set by the server.
205
+ };
206
+ const errors = await client.createTransfers([transfer]);
207
+ for (const error of errors) {
208
+ switch (error.code) {
209
+ default:
210
+ console.error(`Batch transfer at ${error.index} failed to create: ${CreateAccountError[error.code]}.`);
211
+ }
134
212
  }
135
- const errors = await client.createTransfers([transfer])
136
213
  ```
137
- Two-phase transfers are supported natively by toggling the appropriate flag. TigerBeetle will then adjust the `credits_pending` and `debits_pending` fields of the appropriate accounts. A corresponding commit transfer then needs to be sent to accept or reject the transfer.
138
214
 
139
- Transfers within a batch may also be linked (see [linked events](#linked-events)).
215
+ ### Response and Errors
216
+
217
+ The response is an empty array if all transfers were created
218
+ successfully. If the response is non-empty, each object in the
219
+ response array contains error information for an transfer that
220
+ failed. The error object contains an error code and the index of the
221
+ transfer in the request batch.
222
+
140
223
  ```js
141
- enum TransferFlags {
142
- linked = (1 << 0),
143
- pending = (1 << 1),
144
- post_pending_transfer = (1 << 2),
145
- void_pending_transfer = (1 << 3)
224
+ const errors = await client.createTransfers([transfer1, transfer2, transfer3]);
225
+
226
+ // errors = [{ index: 1, code: 1 }];
227
+ for (const error of errors) {
228
+ switch (error.code) {
229
+ case CreateTransferError.exists:
230
+ console.error(`Batch transfer at ${error.index} already exists.`);
231
+ break;
232
+ default:
233
+ console.error(`Batch transfer at ${error.index} failed to create: ${CreateTransferError[error.code]}.`);
146
234
  }
147
-
148
- // Two-phase transfer (pending):
149
- let flags = 0n
150
- flags |= TransferFlags.pending
235
+ }
236
+ ```
237
+
238
+ The example above shows that the transfer in index 1 failed with
239
+ error 1. This error here means that `transfer1` and `transfer3` were
240
+ created successfully. But `transfer2` was not created.
241
+
242
+ To handle errors you can either 1) exactly match error codes returned
243
+ from `client.createTransfers` with enum values in the
244
+ `CreateTransferError` object, or you can 2) look up the error code in
245
+ the `CreateTransferError` object for a human-readable string.
246
+
247
+ ### Batching
248
+
249
+ TigerBeetle performance is maximized when you batch inserts. The
250
+ client does not do this automatically for you. So, for example, you
251
+ can insert 1 million transfers one at a time like so:
252
+
253
+ ```js
254
+ for (let i = 0; i < 1_000_000; i++) {
255
+ const errors = client.createTransfers(transfers[i]);
256
+ // error handling omitted
257
+ }
258
+ ```
259
+
260
+ But the insert rate will be a fraction of potential. Instead, always
261
+ batch what you can. The maximum batch size is set in the TigerBeetle
262
+ server. The default is 8191.
263
+
264
+ ```js
265
+ const BATCH_SIZE = 8191;
266
+ for (let i = 0; i < 1_000_000; i += BATCH_SIZE) {
267
+ const errors = client.createTransfers(transfers.slice(i, Math.min(transfers.length, BATCH_SIZE)));
268
+ // error handling omitted
269
+ }
270
+ ```
271
+
272
+ ### Transfer Flags
273
+
274
+ The transfer `flags` value is a bitfield. See details for these flags in
275
+ the [Transfers
276
+ reference](https://docs.tigerbeetle.com/reference/transfers#flags).
151
277
 
152
- // Linked two-phase transfer (pending):
153
- let flags = 0n
154
- flags |= TransferFlags.linked
155
- flags |= TransferFlags.pending
278
+ To toggle behavior for a transfer, combine enum values stored in the
279
+ `TransferFlags` object (in TypeScript it is an actual enum) with
280
+ bitwise-or:
281
+
282
+ * `TransferFlags.linked`
283
+ * `TransferFlags.pending`
284
+ * `TransferFlags.post_pending_transfer`
285
+ * `TransferFlags.void_pending_transfer`
286
+
287
+ For example, to link `transfer0` and `transfer1`:
288
+
289
+ ```js
290
+ const transfer0 = { ... transfer values ... };
291
+ const transfer1 = { ... transfer values ... };
292
+ transfer0.flags = TransferFlags.linked;
293
+ // Create the transfer
294
+ const errors = client.createTransfers([transfer0, transfer1]);
156
295
  ```
157
296
 
158
- ### Post a Pending Transfer (2-Phase)
297
+ #### Two-Phase Transfers
298
+
299
+ Two-phase transfers are supported natively by toggling the appropriate
300
+ flag. TigerBeetle will then adjust the `credits_pending` and
301
+ `debits_pending` fields of the appropriate accounts. A corresponding
302
+ post pending transfer then needs to be sent to post or void the
303
+ transfer.
304
+
305
+ ##### Post a Pending Transfer
306
+
307
+ With `transfer.flags == TransferFlags.post_pending_transfer`,
308
+ TigerBeetle will post the transfer. TigerBeetle will atomically roll
309
+ back the changes to `debits_pending` and `credits_pending` of the
310
+ appropriate accounts and apply them to the `debits_posted` and
311
+ `credits_posted` balances.
159
312
 
160
- With `flags = post_pending_transfer`, TigerBeetle will accept the transfer. TigerBeetle will atomically rollback the changes to `debits_pending` and `credits_pending` of the appropriate accounts and apply them to the `debits_posted` and `credits_posted` balances.
161
313
  ```js
162
314
  const post = {
163
315
  id: 2n, // u128, must correspond to the transfer id
@@ -168,9 +320,58 @@ const post = {
168
320
  const errors = await client.createTransfers([post])
169
321
  ```
170
322
 
171
- ### Linked Events
323
+ ## Transfer Lookup: `client.lookupTransfers`
324
+
325
+ NOTE: While transfer lookup exists, it is not a flexible query API. We
326
+ are developing query APIs and there will be new methods for querying
327
+ transfers in the future.
328
+
329
+ Transfer lookup is batched, like transfer creation. Pass in all `id`s to
330
+ fetch, and matched transfers are returned.
331
+
332
+ If no transfer matches an `id`, no object is returned for that
333
+ transfer. So the order of transfers in the response is not necessarily
334
+ the same as the order of `id`s in the request. You can refer to the
335
+ `id` field in the response to distinguish transfers.
336
+
337
+ ```js
338
+ // transfer 1n exists, 2n does not
339
+ const transfers = await client.lookupTransfers([1n, 2n]);
340
+ /* console.log(transfers);
341
+ * [{
342
+ * id: 1n,
343
+ * pending_id: 0n,
344
+ * debit_account_id: 1n,
345
+ * credit_account_id: 2n,
346
+ * user_data: 0n,
347
+ * reserved: 0n,
348
+ * timeout: 0n,
349
+ * ledger: 1,
350
+ * code: 720,
351
+ * flags: 0,
352
+ * amount: 10n,
353
+ * timestamp: 1623062009212508993n,
354
+ * }]
355
+ */
356
+ ```
357
+
358
+ ## Linked Events
359
+
360
+ When the `linked` flag is specified for the `createAccount` or
361
+ `createTransfer` event, it links an event with the next event in the
362
+ batch, to create a chain of events, of arbitrary length, which all
363
+ succeed or fail together. The tail of a chain is denoted by the first
364
+ event without this flag. The last event in a batch may therefore never
365
+ have the `linked` flag set as this would leave a chain
366
+ open-ended. Multiple chains or individual events may coexist within a
367
+ batch to succeed or fail independently.
172
368
 
173
- When the `linked` flag is specified for the `createAccount`, `createTransfer`, `commitTransfer` event, it links an event with the next event in the batch, to create a chain of events, of arbitrary length, which all succeed or fail together. The tail of a chain is denoted by the first event without this flag. The last event in a batch may therefore never have the `linked` flag set as this would leave a chain open-ended. Multiple chains or individual events may coexist within a batch to succeed or fail independently. Events within a chain are executed within order, or are rolled back on error, so that the effect of each event in the chain is visible to the next, and so that the chain is either visible or invisible as a unit to subsequent events after the chain. The event that was the first to break the chain will have a unique error result. Other events in the chain will have their error result set to `linked_event_failed`.
369
+ Events within a chain are executed within order, or are rolled back on
370
+ error, so that the effect of each event in the chain is visible to the
371
+ next, and so that the chain is either visible or invisible as a unit
372
+ to subsequent events after the chain. The event that was the first to
373
+ break the chain will have a unique error result. Other events in the
374
+ chain will have their error result set to `linked_event_failed`.
174
375
 
175
376
  ```js
176
377
  let batch = []
@@ -218,7 +419,7 @@ const errors = await client.createTransfers(batch)
218
419
  To get up and running when cloning the repo:
219
420
 
220
421
  ```shell
221
- git clone --recurse-submodules https://github.com/coilhq/tigerbeetle-node.git
422
+ git clone --recurse-submodules https://github.com/tigerbeetledb/tigerbeetle-node.git
222
423
  cd tigerbeetle-node/
223
424
  npm install --include dev # This will automatically install and build everything you need.
224
425
  ```
@@ -243,7 +444,8 @@ npm run benchmark
243
444
  #### Test
244
445
 
245
446
  ```shell
246
- ./tigerbeetle init --cluster=1 --replica=0 --directory=.
247
- ./tigerbeetle start --cluster=1 --replica=0 --directory=. --addresses=3001
447
+ ./tigerbeetle format --cluster=0 --replica=0 ./cluster_0_replica_0_test.tigerbeetle
448
+ ./tigerbeetle start --addresses=3001 ./cluster_0_replica_0_test.tigerbeetle > tigerbeetle_test.log 2>&1
248
449
  npm run test
249
450
  ```
451
+ For more information, type; `./tigerbeetle -h`
package/dist/index.d.ts CHANGED
@@ -24,25 +24,23 @@ export declare enum AccountFlags {
24
24
  }
25
25
  export declare enum CreateAccountError {
26
26
  linked_event_failed = 1,
27
- reserved_flag = 2,
28
- reserved_field = 3,
29
- id_must_not_be_zero = 4,
30
- ledger_must_not_be_zero = 5,
31
- code_must_not_be_zero = 6,
32
- mutually_exclusive_flags = 7,
33
- overflows_debits = 8,
34
- overflows_credits = 9,
35
- exceeds_credits = 10,
36
- exceeds_debits = 11,
37
- exists_with_different_flags = 12,
38
- exists_with_different_user_data = 13,
39
- exists_with_different_ledger = 14,
40
- exists_with_different_code = 15,
41
- exists_with_different_debits_pending = 16,
42
- exists_with_different_debits_posted = 17,
43
- exists_with_different_credits_pending = 18,
44
- exists_with_different_credits_posted = 19,
45
- exists = 20
27
+ linked_event_chain_open = 2,
28
+ reserved_flag = 3,
29
+ reserved_field = 4,
30
+ id_must_not_be_zero = 5,
31
+ id_must_not_be_int_max = 6,
32
+ ledger_must_not_be_zero = 7,
33
+ code_must_not_be_zero = 8,
34
+ debits_pending_must_be_zero = 9,
35
+ debits_posted_must_be_zero = 10,
36
+ credits_pending_must_be_zero = 11,
37
+ credits_posted_must_be_zero = 12,
38
+ mutually_exclusive_flags = 13,
39
+ exists_with_different_flags = 14,
40
+ exists_with_different_user_data = 15,
41
+ exists_with_different_ledger = 16,
42
+ exists_with_different_code = 17,
43
+ exists = 18
46
44
  }
47
45
  export declare type CreateAccountsError = {
48
46
  index: number;
@@ -70,54 +68,59 @@ export declare enum TransferFlags {
70
68
  }
71
69
  export declare enum CreateTransferError {
72
70
  linked_event_failed = 1,
73
- reserved_flag = 2,
74
- reserved_field = 3,
75
- id_must_not_be_zero = 4,
76
- debit_account_id_must_not_be_zero = 5,
77
- credit_account_id_must_not_be_zero = 6,
78
- accounts_must_be_different = 7,
79
- pending_id_must_be_zero = 8,
80
- pending_transfer_must_timeout = 9,
81
- ledger_must_not_be_zero = 10,
82
- code_must_not_be_zero = 11,
83
- amount_must_not_be_zero = 12,
84
- debit_account_not_found = 13,
85
- credit_account_not_found = 14,
86
- accounts_must_have_the_same_ledger = 15,
87
- transfer_must_have_the_same_ledger_as_accounts = 16,
88
- exists_with_different_flags = 17,
89
- exists_with_different_debit_account_id = 18,
90
- exists_with_different_credit_account_id = 19,
91
- exists_with_different_user_data = 20,
92
- exists_with_different_pending_id = 21,
93
- exists_with_different_timeout = 22,
94
- exists_with_different_code = 23,
95
- exists_with_different_amount = 24,
96
- exists = 25,
97
- overflows_debits_pending = 26,
98
- overflows_credits_pending = 27,
99
- overflows_debits_posted = 28,
100
- overflows_credits_posted = 29,
101
- overflows_debits = 30,
102
- overflows_credits = 31,
103
- exceeds_credits = 32,
104
- exceeds_debits = 33,
105
- cannot_post_and_void_pending_transfer = 34,
106
- pending_transfer_cannot_post_or_void_another = 35,
107
- timeout_reserved_for_pending_transfer = 36,
108
- pending_id_must_not_be_zero = 37,
109
- pending_id_must_be_different = 38,
110
- pending_transfer_not_found = 39,
111
- pending_transfer_not_pending = 40,
112
- pending_transfer_has_different_debit_account_id = 41,
113
- pending_transfer_has_different_credit_account_id = 42,
114
- pending_transfer_has_different_ledger = 43,
115
- pending_transfer_has_different_code = 44,
116
- exceeds_pending_transfer_amount = 45,
117
- pending_transfer_has_different_amount = 46,
118
- pending_transfer_already_posted = 47,
119
- pending_transfer_already_voided = 48,
120
- pending_transfer_expired = 49
71
+ linked_event_chain_open = 2,
72
+ reserved_flag = 3,
73
+ reserved_field = 4,
74
+ id_must_not_be_zero = 5,
75
+ id_must_not_be_int_max = 6,
76
+ debit_account_id_must_not_be_zero = 7,
77
+ debit_account_id_must_not_be_int_max = 8,
78
+ credit_account_id_must_not_be_zero = 9,
79
+ credit_account_id_must_not_be_int_max = 10,
80
+ accounts_must_be_different = 11,
81
+ pending_id_must_be_zero = 12,
82
+ pending_transfer_must_timeout = 13,
83
+ ledger_must_not_be_zero = 14,
84
+ code_must_not_be_zero = 15,
85
+ amount_must_not_be_zero = 16,
86
+ debit_account_not_found = 17,
87
+ credit_account_not_found = 18,
88
+ accounts_must_have_the_same_ledger = 19,
89
+ transfer_must_have_the_same_ledger_as_accounts = 20,
90
+ exists_with_different_flags = 21,
91
+ exists_with_different_debit_account_id = 22,
92
+ exists_with_different_credit_account_id = 23,
93
+ exists_with_different_user_data = 24,
94
+ exists_with_different_pending_id = 25,
95
+ exists_with_different_timeout = 26,
96
+ exists_with_different_code = 27,
97
+ exists_with_different_amount = 28,
98
+ exists = 29,
99
+ overflows_debits_pending = 30,
100
+ overflows_credits_pending = 31,
101
+ overflows_debits_posted = 32,
102
+ overflows_credits_posted = 33,
103
+ overflows_debits = 34,
104
+ overflows_credits = 35,
105
+ exceeds_credits = 36,
106
+ exceeds_debits = 37,
107
+ cannot_post_and_void_pending_transfer = 38,
108
+ pending_transfer_cannot_post_or_void_another = 39,
109
+ timeout_reserved_for_pending_transfer = 40,
110
+ pending_id_must_not_be_zero = 41,
111
+ pending_id_must_not_be_int_max = 42,
112
+ pending_id_must_be_different = 43,
113
+ pending_transfer_not_found = 44,
114
+ pending_transfer_not_pending = 45,
115
+ pending_transfer_has_different_debit_account_id = 46,
116
+ pending_transfer_has_different_credit_account_id = 47,
117
+ pending_transfer_has_different_ledger = 48,
118
+ pending_transfer_has_different_code = 49,
119
+ exceeds_pending_transfer_amount = 50,
120
+ pending_transfer_has_different_amount = 51,
121
+ pending_transfer_already_posted = 52,
122
+ pending_transfer_already_voided = 53,
123
+ pending_transfer_expired = 54
121
124
  }
122
125
  export declare type CreateTransfersError = {
123
126
  index: number;