tigerbeetle 0.0.1.pre.dev → 0.0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a54d9b5cd63da1c737566b85d0e719bad994ed4e43e5ac3d04e2c0efdac4ef4a
4
- data.tar.gz: 229b14cfa7ee986831a4f83b029d42e37c1b744388e83644c3b9e571fb092927
3
+ metadata.gz: a43ba782e05b5f19597449072629a92c1d3116d17b7290fa3ac944287cb4aa43
4
+ data.tar.gz: 4be7ab09feaca3f520fcb0d1ba2f98e1836cc81011fb54a5c240086b1dda4a0a
5
5
  SHA512:
6
- metadata.gz: 97b9a2b121ffa25ae9d65a2e8d0ae57c533dd208562d72b8984cd1228483407929c64ef44458dd67bc471eaf569264c6459c9d2cb68e33ce5fa27b6d36465b9c
7
- data.tar.gz: aa7cd0fe0219867c6a737faeb60dcad7b4974d114b3130b7fcc7e6642ea18fa1a06e406f0674878661c94d5f2aa18f9ec6da7ccd837eeb23833be28217c2e093
6
+ metadata.gz: 86cbf91c466a9c3b6811239bf6d56835dfa50e381524a3e2f36f5d01409a2d2679ec6a88f938d9df545b7eba88e1c4e51b64333b547aad27089b3bbbe0aa1749
7
+ data.tar.gz: f2ed940ae715bf9c5c8dad92e2886069bcd67c2d3ecfb6b77567284adbaf5875f814c8d999509f2671cc300973178689a0758dcdf69afa8f5c206cf092f09d5e
data/CHANGELOG.md ADDED
@@ -0,0 +1,13 @@
1
+ # Changelog
2
+
3
+ ## 0.0.2
4
+
5
+ - Non-optional fields no longer have default values
6
+ - Client errors are now `TigerBeetle::ClientError`
7
+ - Dependency versions corrected
8
+ - Fixed issue with in-flight requests
9
+
10
+ ## 0.0.1
11
+
12
+ - First release
13
+ - Based on TigerBeetle 0.16.37
data/README.md ADDED
@@ -0,0 +1,94 @@
1
+ # Ruby Client for TigerBeetle
2
+
3
+ [![Gem](https://badge.fury.io/rb/tigerbeetle.svg)](https://rubygems.org/gems/tigerbeetle)
4
+ [![CI](https://github.com/antstorm/tigerbeetle-ruby/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/antstorm/tigerbeetle-ruby/actions/workflows/ci.yml)
5
+ [![License](https://img.shields.io/github/license/antstorm/tigerbeetle-ruby.svg)](https://opensource.org/licenses/apache-2-0)
6
+
7
+ Are you looking to integrate [Tigebeetle](https://tigerbeetle.com/) into your Ruby (or Rails) stack?
8
+ You've come to the right place!
9
+
10
+ TigerBeetle is a high performance financial transaction database (i.e. Ledger) designed to power
11
+ the next 30 years of Online Transaction Processing. And this is a feature complete Ruby client for
12
+ it that leverages [the native Zig client](https://tigerbeetle.com/blog/2023-02-21-writing-high-performance-clients-for-tigerbeetle/).
13
+
14
+
15
+ ## Usage
16
+
17
+ Start by adding the TigerBeetle gem to your Gemfile:
18
+
19
+ ```ruby
20
+ gem 'tigerbeeetle'
21
+ ```
22
+
23
+ Ensure TigerBeetle is running ([more on this](https://docs.tigerbeetle.com/start/)):
24
+
25
+ ```bash
26
+ $ curl -Lo tigerbeetle.zip https://linux.tigerbeetle.com && unzip tigerbeetle.zip && ./tigerbeetle version
27
+ $ ./tigerbeetle format --cluster=0 --replica=0 --replica-count=1 --development 0_0.tigerbeetle
28
+ $ ./tigerbeetle start --addresses=3000 --development 0_0.tigerbeetle
29
+ ```
30
+
31
+ Connect your Ruby client and start using it:
32
+
33
+ ```ruby
34
+ client = TigerBeetle.connect # using default cluster_id (0) and address (127.0.0.1:3000)
35
+
36
+ # create accounts
37
+ client.create_accounts(
38
+ TigerBeetle::Account.new(id: 100, ledger: 1, code: 1),
39
+ TigerBeetle::Account.new(id: 101, ledger: 1, code: 1)
40
+ )
41
+
42
+ # move funds between accounts
43
+ client.create_transfers(
44
+ TigerBeetle::Transfer.new(
45
+ id: 100,
46
+ debit_account_id: 100,
47
+ credit_account_id: 101,
48
+ amount: 999,
49
+ ledger: 1,
50
+ code: 10
51
+ )
52
+ )
53
+
54
+ # check balances
55
+ account_1, account_2 = client.lookup_accounts(100, 101)
56
+ account_1.debits_posted # 999
57
+ account_2.credits_posted # 999
58
+ ```
59
+
60
+ *More information on the `ledger` and `code` attributes can be found
61
+ [here](https://docs.tigerbeetle.com/coding/data-modeling/).*
62
+
63
+ ## IDs
64
+
65
+ You can choose whatever IDs you want when creating accounts and transfers (as long as they are
66
+ unique per cluster). However to leverage the maximum performance TigerBeetle recommends using
67
+ strictly increasing decentralized 128-bit IDs. To generate such an ID you can use the provided
68
+ `TigerBeetle.id` method.
69
+
70
+ ```ruby
71
+ client.create_accounts(
72
+ TigerBeetle::Account.new(id: TigerBeetle.id, ledger: 1, code: 1)
73
+ )
74
+ ```
75
+
76
+ *More on how to approach this — https://docs.tigerbeetle.com/coding/data-modeling/#id.*
77
+
78
+
79
+ ## Contributing
80
+
81
+ We'd love your help building the TigerBeetle Ruby gem.
82
+
83
+ - Join the [official Slack](https://slack.tigerbeetle.com/join) for general questions on TigerBeetle
84
+ - For any discovered problems or questions about the Ruby client — [open a new issue](https://github.com/antstorm/tigerbeetle-ruby/issues/new)
85
+ - For codebase improvements:
86
+ - Fork this repo
87
+ - Implement your changes
88
+ - Ensure the tests pass by running `bundle exec rspec`
89
+ - Open a new pull request
90
+
91
+
92
+ ## License
93
+
94
+ This project is licensed under [Apache 2.0 license](https://github.com/temporalio/temporal/blob/main/LICENSE).
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env ruby
2
+ require 'mkmf'
3
+
4
+ makefile_path = File.join('Makefile')
5
+ client_version = '0.16.37'
6
+ tar_package = 'pkg.tar.gz'
7
+
8
+ makefile = ''
9
+
10
+ if find_executable('zig') && File.exist?('./tigerbeetle/build.zig')
11
+ makefile = <<~MFILE
12
+ all:
13
+ \techo "Compiling native TB client from the source"
14
+ \tzig version
15
+ \tunset -v DESTDIR && cd ./tigerbeetle && zig build clients:c -Dconfig-release=#{client_version} -Dconfig-release-client-min=#{client_version}
16
+ \n\n
17
+ install:
18
+ \tcp -rf ./tigerbeetle/src/clients/c/lib ./pkg
19
+ \n\n
20
+ clean:
21
+ \trm -rf ./tigerbeetle/src/clients/c/lib
22
+ MFILE
23
+ elsif File.exist?("./#{tar_package}")
24
+ makefile = <<~MFILE
25
+ all:
26
+ \tmkdir -p pkg
27
+ \ttar -xzf #{tar_package} -C ./pkg
28
+ \n\n
29
+ install:
30
+ \techo "Installing precompiled native TB client"
31
+ \n\n
32
+ clean:
33
+ \techo "Nothing to clean"
34
+ MFILE
35
+ end
36
+
37
+ File.open(makefile_path, 'w') do |f|
38
+ f.puts makefile
39
+ end
Binary file
@@ -0,0 +1,59 @@
1
+ module TBClient
2
+ module SharedLib
3
+ class << self
4
+ PKG_DIR = '../../ext/tb_client/pkg'.freeze
5
+
6
+ def path
7
+ prefix = ''
8
+ linux_libc = ''
9
+ suffix = ''
10
+
11
+ arch, os = RUBY_PLATFORM.split('-')
12
+
13
+ arch =
14
+ case arch
15
+ when 'x86_64', 'amd64' then 'x86_64'
16
+ when 'aarch64', 'arm64' then 'aarch64'
17
+ else
18
+ raise "Unsupported architecture: #{arch}"
19
+ end
20
+
21
+ case os
22
+ when /darwin/
23
+ prefix = 'lib'
24
+ system = 'macos'
25
+ suffix = '.dylib'
26
+ when 'linux'
27
+ prefix = 'lib'
28
+ system = 'linux'
29
+ linux_libc = detect_libc
30
+ suffix = '.so'
31
+ when 'windows'
32
+ system = 'windows'
33
+ suffix = '.dll'
34
+ else
35
+ raise "Unsupported system: #{os}"
36
+ end
37
+
38
+ File.expand_path(
39
+ "#{PKG_DIR}/#{arch}-#{system}#{linux_libc}/#{prefix}tb_client#{suffix}",
40
+ __dir__
41
+ )
42
+ end
43
+
44
+ private
45
+
46
+ def detect_libc
47
+ ldd_output = `ldd --version 2>&1 | head -n 1`.downcase
48
+
49
+ if ldd_output.include?('musl')
50
+ '-musl'
51
+ elsif ldd_output.include?('gnu') || ldd_output.include?('glibc')
52
+ '-gnu.2.27'
53
+ else
54
+ raise "Unsupported libc: #{ldd_output}"
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
data/lib/tb_client.rb ADDED
@@ -0,0 +1,282 @@
1
+ require 'ffi'
2
+ require 'tb_client/shared_lib'
3
+
4
+ module TBClient
5
+ extend FFI::Library
6
+
7
+ ffi_lib SharedLib.path
8
+
9
+ InitStatus = enum(FFI::Type::UINT8, [
10
+ :SUCCESS, 0,
11
+ :UNEXPECTED,
12
+ :OUT_OF_MEMORY,
13
+ :ADDRESS_INVALID,
14
+ :ADDRESS_LIMIT_EXCEEDED,
15
+ :SYSTEM_RESOURCES,
16
+ :NETWORK_SUBSYSTEM])
17
+
18
+ ClientStatus = enum(FFI::Type::UINT8, [
19
+ :OK, 0,
20
+ :INVALID])
21
+
22
+ PacketStatus = enum(FFI::Type::UINT8, [
23
+ :OK, 0,
24
+ :TOO_MUCH_DATA,
25
+ :CLIENT_EVICTED,
26
+ :CLIENT_RELEASE_TOO_LOW,
27
+ :CLIENT_RELEASE_TOO_HIGH,
28
+ :CLIENT_SHUTDOWN,
29
+ :INVALID_OPERATION,
30
+ :INVALID_DATA_SIZE])
31
+
32
+ RegisterLogCallbackStatus = enum(FFI::Type::UINT8, [
33
+ :SUCCESS, 0,
34
+ :ALREADY_REGISTERED,
35
+ :NOT_REGISTERED])
36
+
37
+ Operation = enum(FFI::Type::UINT8, [
38
+ :PULSE, 128,
39
+ :GET_EVENTS, 137,
40
+ :CREATE_ACCOUNTS, 138,
41
+ :CREATE_TRANSFERS, 139,
42
+ :LOOKUP_ACCOUNTS, 140,
43
+ :LOOKUP_TRANSFERS, 141,
44
+ :GET_ACCOUNT_TRANSFERS, 142,
45
+ :GET_ACCOUNT_BALANCES, 143,
46
+ :QUERY_ACCOUNTS, 144,
47
+ :QUERY_TRANSFERS, 145])
48
+
49
+ CreateAccountResult = enum(FFI::Type::UINT32, [
50
+ :OK, 0,
51
+ :LINKED_EVENT_FAILED, 1,
52
+ :LINKED_EVENT_CHAIN_OPEN, 2,
53
+ :IMPORTED_EVENT_EXPECTED, 22,
54
+ :IMPORTED_EVENT_NOT_EXPECTED, 23,
55
+ :TIMESTAMP_MUST_BE_ZERO, 3,
56
+ :IMPORTED_EVENT_TIMESTAMP_OUT_OF_RANGE, 24,
57
+ :IMPORTED_EVENT_TIMESTAMP_MUST_NOT_ADVANCE, 25,
58
+ :RESERVED_FIELD, 4,
59
+ :RESERVED_FLAG, 5,
60
+ :ID_MUST_NOT_BE_ZERO, 6,
61
+ :ID_MUST_NOT_BE_INT_MAX, 7,
62
+ :EXISTS_WITH_DIFFERENT_FLAGS, 15,
63
+ :EXISTS_WITH_DIFFERENT_USER_DATA_128, 16,
64
+ :EXISTS_WITH_DIFFERENT_USER_DATA_64, 17,
65
+ :EXISTS_WITH_DIFFERENT_USER_DATA_32, 18,
66
+ :EXISTS_WITH_DIFFERENT_LEDGER, 19,
67
+ :EXISTS_WITH_DIFFERENT_CODE, 20,
68
+ :EXISTS, 21,
69
+ :FLAGS_ARE_MUTUALLY_EXCLUSIVE, 8,
70
+ :DEBITS_PENDING_MUST_BE_ZERO, 9,
71
+ :DEBITS_POSTED_MUST_BE_ZERO, 10,
72
+ :CREDITS_PENDING_MUST_BE_ZERO, 11,
73
+ :CREDITS_POSTED_MUST_BE_ZERO, 12,
74
+ :LEDGER_MUST_NOT_BE_ZERO, 13,
75
+ :CODE_MUST_NOT_BE_ZERO, 14,
76
+ :IMPORTED_EVENT_TIMESTAMP_MUST_NOT_REGRESS, 26])
77
+
78
+ CreateTransferResult = enum(FFI::Type::UINT32, [
79
+ :OK, 0,
80
+ :LINKED_EVENT_FAILED, 1,
81
+ :LINKED_EVENT_CHAIN_OPEN, 2,
82
+ :IMPORTED_EVENT_EXPECTED, 56,
83
+ :IMPORTED_EVENT_NOT_EXPECTED, 57,
84
+ :TIMESTAMP_MUST_BE_ZERO, 3,
85
+ :IMPORTED_EVENT_TIMESTAMP_OUT_OF_RANGE, 58,
86
+ :IMPORTED_EVENT_TIMESTAMP_MUST_NOT_ADVANCE, 59,
87
+ :RESERVED_FLAG, 4,
88
+ :ID_MUST_NOT_BE_ZERO, 5,
89
+ :ID_MUST_NOT_BE_INT_MAX, 6,
90
+ :EXISTS_WITH_DIFFERENT_FLAGS, 36,
91
+ :EXISTS_WITH_DIFFERENT_PENDING_ID, 40,
92
+ :EXISTS_WITH_DIFFERENT_TIMEOUT, 44,
93
+ :EXISTS_WITH_DIFFERENT_DEBIT_ACCOUNT_ID, 37,
94
+ :EXISTS_WITH_DIFFERENT_CREDIT_ACCOUNT_ID, 38,
95
+ :EXISTS_WITH_DIFFERENT_AMOUNT, 39,
96
+ :EXISTS_WITH_DIFFERENT_USER_DATA_128, 41,
97
+ :EXISTS_WITH_DIFFERENT_USER_DATA_64, 42,
98
+ :EXISTS_WITH_DIFFERENT_USER_DATA_32, 43,
99
+ :EXISTS_WITH_DIFFERENT_LEDGER, 67,
100
+ :EXISTS_WITH_DIFFERENT_CODE, 45,
101
+ :EXISTS, 46,
102
+ :ID_ALREADY_FAILED, 68,
103
+ :FLAGS_ARE_MUTUALLY_EXCLUSIVE, 7,
104
+ :DEBIT_ACCOUNT_ID_MUST_NOT_BE_ZERO, 8,
105
+ :DEBIT_ACCOUNT_ID_MUST_NOT_BE_INT_MAX, 9,
106
+ :CREDIT_ACCOUNT_ID_MUST_NOT_BE_ZERO, 10,
107
+ :CREDIT_ACCOUNT_ID_MUST_NOT_BE_INT_MAX, 11,
108
+ :ACCOUNTS_MUST_BE_DIFFERENT, 12,
109
+ :PENDING_ID_MUST_BE_ZERO, 13,
110
+ :PENDING_ID_MUST_NOT_BE_ZERO, 14,
111
+ :PENDING_ID_MUST_NOT_BE_INT_MAX, 15,
112
+ :PENDING_ID_MUST_BE_DIFFERENT, 16,
113
+ :TIMEOUT_RESERVED_FOR_PENDING_TRANSFER, 17,
114
+ :CLOSING_TRANSFER_MUST_BE_PENDING, 64,
115
+ :LEDGER_MUST_NOT_BE_ZERO, 19,
116
+ :CODE_MUST_NOT_BE_ZERO, 20,
117
+ :DEBIT_ACCOUNT_NOT_FOUND, 21,
118
+ :CREDIT_ACCOUNT_NOT_FOUND, 22,
119
+ :ACCOUNTS_MUST_HAVE_THE_SAME_LEDGER, 23,
120
+ :TRANSFER_MUST_HAVE_THE_SAME_LEDGER_AS_ACCOUNTS, 24,
121
+ :PENDING_TRANSFER_NOT_FOUND, 25,
122
+ :PENDING_TRANSFER_NOT_PENDING, 26,
123
+ :PENDING_TRANSFER_HAS_DIFFERENT_DEBIT_ACCOUNT_ID, 27,
124
+ :PENDING_TRANSFER_HAS_DIFFERENT_CREDIT_ACCOUNT_ID, 28,
125
+ :PENDING_TRANSFER_HAS_DIFFERENT_LEDGER, 29,
126
+ :PENDING_TRANSFER_HAS_DIFFERENT_CODE, 30,
127
+ :EXCEEDS_PENDING_TRANSFER_AMOUNT, 31,
128
+ :PENDING_TRANSFER_HAS_DIFFERENT_AMOUNT, 32,
129
+ :PENDING_TRANSFER_ALREADY_POSTED, 33,
130
+ :PENDING_TRANSFER_ALREADY_VOIDED, 34,
131
+ :PENDING_TRANSFER_EXPIRED, 35,
132
+ :IMPORTED_EVENT_TIMESTAMP_MUST_NOT_REGRESS, 60,
133
+ :IMPORTED_EVENT_TIMESTAMP_MUST_POSTDATE_DEBIT_ACCOUNT, 61,
134
+ :IMPORTED_EVENT_TIMESTAMP_MUST_POSTDATE_CREDIT_ACCOUNT, 62,
135
+ :IMPORTED_EVENT_TIMEOUT_MUST_BE_ZERO, 63,
136
+ :DEBIT_ACCOUNT_ALREADY_CLOSED, 65,
137
+ :CREDIT_ACCOUNT_ALREADY_CLOSED, 66,
138
+ :OVERFLOWS_DEBITS_PENDING, 47,
139
+ :OVERFLOWS_CREDITS_PENDING, 48,
140
+ :OVERFLOWS_DEBITS_POSTED, 49,
141
+ :OVERFLOWS_CREDITS_POSTED, 50,
142
+ :OVERFLOWS_DEBITS, 51,
143
+ :OVERFLOWS_CREDITS, 52,
144
+ :OVERFLOWS_TIMEOUT, 53,
145
+ :EXCEEDS_CREDITS, 54,
146
+ :EXCEEDS_DEBITS, 55])
147
+
148
+ LogLevel = enum(FFI::Type::UINT8, [
149
+ :ERR, 0,
150
+ :WARN,
151
+ :INFO,
152
+ :DEBUG])
153
+
154
+ AccountFlags = bitmask(FFI::Type::UINT16, [
155
+ :LINKED,
156
+ :DEBITS_MUST_NOT_EXCEED_CREDITS,
157
+ :CREDITS_MUST_NOT_EXCEED_DEBITS,
158
+ :HISTORY,
159
+ :IMPORTED,
160
+ :CLOSED]
161
+ )
162
+
163
+ TransferFlags = bitmask(FFI::Type::UINT16, [
164
+ :LINKED,
165
+ :PENDING,
166
+ :POST_PENDING_TRANSFER,
167
+ :VOID_PENDING_TRANSFER,
168
+ :BALANCING_DEBIT,
169
+ :BALANCING_CREDIT,
170
+ :CLOSING_DEBIT,
171
+ :CLOSING_CREDIT,
172
+ :IMPORTED]
173
+ )
174
+
175
+ AccountFilterFlags = bitmask(FFI::Type::UINT32, [:DEBITS, :CREDITS, :REVERSED])
176
+
177
+ QueryFilterFlags = bitmask(FFI::Type::UINT32, [:REVERSED])
178
+
179
+ class Client < FFI::Struct
180
+ layout opaque: [:uint64, 4]
181
+ end
182
+
183
+ class UInt128 < FFI::Struct
184
+ layout low: :uint64,
185
+ high: :uint64
186
+ end
187
+
188
+ class Packet < FFI::Struct
189
+ layout user_data: :pointer,
190
+ data: :pointer,
191
+ data_size: :uint32,
192
+ user_tag: :uint16,
193
+ operation: Operation,
194
+ status: PacketStatus,
195
+ opaque: [:uint8, 32]
196
+ end
197
+
198
+ class Account < FFI::Struct
199
+ layout id: UInt128,
200
+ debits_pending: UInt128,
201
+ debits_posted: UInt128,
202
+ credits_pending: UInt128,
203
+ credits_posted: UInt128,
204
+ user_data_128: UInt128,
205
+ user_data_64: :uint64,
206
+ user_data_32: :uint32,
207
+ reserved: :uint32,
208
+ ledger: :uint32,
209
+ code: :uint16,
210
+ flags: AccountFlags,
211
+ timestamp: :uint64
212
+ end
213
+
214
+ class Transfer < FFI::Struct
215
+ layout id: UInt128,
216
+ debit_account_id: UInt128,
217
+ credit_account_id: UInt128,
218
+ amount: UInt128,
219
+ pending_id: UInt128,
220
+ user_data_128: UInt128,
221
+ user_data_64: :uint64,
222
+ user_data_32: :uint32,
223
+ timeout: :uint32,
224
+ ledger: :uint32,
225
+ code: :uint16,
226
+ flags: TransferFlags,
227
+ timestamp: :uint64
228
+ end
229
+
230
+ class CreateAccountsResult < FFI::Struct
231
+ layout index: :uint32,
232
+ result: CreateAccountResult
233
+ end
234
+
235
+ class CreateTransfersResult < FFI::Struct
236
+ layout index: :uint32,
237
+ result: CreateTransferResult
238
+ end
239
+
240
+ class AccountFilter < FFI::Struct
241
+ layout account_id: UInt128,
242
+ user_data_128: UInt128,
243
+ user_data_64: :uint64,
244
+ user_data_32: :uint32,
245
+ code: :uint16,
246
+ reserved: [:uint8, 58],
247
+ timestamp_min: :uint64,
248
+ timestamp_max: :uint64,
249
+ limit: :uint32,
250
+ flags: AccountFilterFlags
251
+ end
252
+
253
+ class QueryFilter < FFI::Struct
254
+ layout user_data_128: UInt128,
255
+ user_data_64: :uint64,
256
+ user_data_32: :uint32,
257
+ ledger: :uint32,
258
+ code: :uint16,
259
+ reserved: [:uint8, 6],
260
+ timestamp_min: :uint64,
261
+ timestamp_max: :uint64,
262
+ limit: :uint32,
263
+ flags: QueryFilterFlags
264
+ end
265
+
266
+ class AccountBalance < FFI::Struct
267
+ layout debits_pending: UInt128,
268
+ debits_posted: UInt128,
269
+ credits_pending: UInt128,
270
+ credits_posted: UInt128,
271
+ timestamp: :uint64,
272
+ reserved: [:uint8, 56]
273
+ end
274
+
275
+ callback :on_completion, [:uint, Packet.by_ref, :uint64, :pointer, :uint32], :void
276
+ callback :log_handler, [LogLevel, :pointer, :uint32], :void
277
+
278
+ attach_function :tb_client_init, [Client.by_ref, :pointer, :string, :uint32, :uint, :on_completion], InitStatus
279
+ attach_function :tb_client_submit, [Client.by_ref, Packet.by_ref], ClientStatus
280
+ attach_function :tb_client_deinit, [Client.by_ref], ClientStatus
281
+ attach_function :tb_client_register_log_callback, [:log_handler, :bool], RegisterLogCallbackStatus
282
+ end
@@ -0,0 +1,38 @@
1
+ module TigerBeetle
2
+ ACCOUNT_PARAMS = %i[
3
+ id debits_pending debits_posted credits_pending credits_posted user_data_128
4
+ user_data_64 user_data_32 ledger code flags timestamp
5
+ ]
6
+
7
+ Account = Struct.new(*ACCOUNT_PARAMS) do
8
+ def initialize(
9
+ id:,
10
+ debits_pending: 0,
11
+ debits_posted: 0,
12
+ credits_pending: 0,
13
+ credits_posted: 0,
14
+ user_data_128: 0,
15
+ user_data_64: 0,
16
+ user_data_32: 0,
17
+ ledger:,
18
+ code:,
19
+ flags: [],
20
+ timestamp: nil
21
+ )
22
+ super(
23
+ id,
24
+ debits_pending,
25
+ debits_posted,
26
+ credits_pending,
27
+ credits_posted,
28
+ user_data_128,
29
+ user_data_64,
30
+ user_data_32,
31
+ ledger,
32
+ code,
33
+ flags,
34
+ timestamp
35
+ )
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,23 @@
1
+ module TigerBeetle
2
+ ACCOUNT_BALANCE_PARAMS = %i[
3
+ debits_pending debits_posted credits_pending credits_posted timestamp
4
+ ]
5
+
6
+ AccountBalance = Struct.new(*ACCOUNT_BALANCE_PARAMS) do
7
+ def initialize(
8
+ debits_pending: 0,
9
+ debits_posted: 0,
10
+ credits_pending: 0,
11
+ credits_posted: 0,
12
+ timestamp: 0
13
+ )
14
+ super(
15
+ debits_pending,
16
+ debits_posted,
17
+ credits_pending,
18
+ credits_posted,
19
+ timestamp
20
+ )
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,31 @@
1
+ module TigerBeetle
2
+ ACCOUNT_FILTER_PARAMS = %i[
3
+ account_id user_data_128 user_data_64 user_data_32 code timestamp_min timestamp_max limit flags
4
+ ]
5
+
6
+ AccountFilter = Struct.new(*ACCOUNT_FILTER_PARAMS) do
7
+ def initialize(
8
+ account_id:,
9
+ user_data_128: 0,
10
+ user_data_64: 0,
11
+ user_data_32: 0,
12
+ code: 0,
13
+ timestamp_min: 0,
14
+ timestamp_max: 0,
15
+ limit:,
16
+ flags: []
17
+ )
18
+ super(
19
+ account_id,
20
+ user_data_128,
21
+ user_data_64,
22
+ user_data_32,
23
+ code,
24
+ timestamp_min,
25
+ timestamp_max,
26
+ limit,
27
+ flags
28
+ )
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,14 @@
1
+ module TigerBeetle
2
+ class AtomicCounter
3
+ attr_reader :value
4
+
5
+ def initialize(value = 0)
6
+ @value = value
7
+ @mutex = Mutex.new
8
+ end
9
+
10
+ def increment
11
+ @mutex.synchronize { @value += 1 }
12
+ end
13
+ end
14
+ end