A request queries or updates the database state.
A request consists of one or more events of the same type sent to the cluster in a single message. For example, a single request can create multiple transfers but it cannot create both accounts and transfers.
The cluster commits an entire request at once. Events are applied in series, such that successive events observe the effects of previous ones and event timestamps are totally ordered.
Each request receives one reply message from the cluster. The reply contains one result for each event in the request.
create_accounts
: createAccount
screate_transfers
: createTransfer
slookup_accounts
: fetchAccount
s byid
lookup_transfers
: fetchTransfer
s byid
get_account_transfers
: fetchTransfer
s bydebit_account_id
orcredit_account_id
get_account_balances
: fetch the historical account balance by theAccount
'sid
.query_accounts
: queryAccount
squery_transfers
: queryTransfer
s
More request types, including more powerful queries, are coming soon!
Each request has a corresponding event and result type:
Request Type | Event | Result |
---|---|---|
create_accounts |
Account |
CreateAccountResult |
create_transfers |
Transfer |
CreateTransferResult |
lookup_accounts |
Account.id |
Account or nothing |
lookup_transfers |
Transfer.id |
Transfer or nothing |
get_account_transfers |
AccountFilter |
Transfer or nothing |
get_account_balances |
AccountFilter |
AccountBalance or nothing |
query_accounts |
QueryFilter |
Account or nothing |
query_transfers |
QueryFilter |
Transfer or nothing |
Events that create objects are idempotent. The first event to create an object with a given id
will receive the ok
result. Subsequent events that attempt to create the same object will receive
the exists
result.
To achieve high throughput, TigerBeetle amortizes the overhead of consensus and I/O by batching many events in each request.
In the default configuration, the maximum batch sizes for each request type are:
Request Type | Request Batch Size (Events) | Reply Batch Size (Results) |
---|---|---|
lookup_accounts |
8190 | 8190 |
lookup_transfers |
8190 | 8190 |
create_accounts |
8190 | 8190 |
create_transfers |
8190 | 8190 |
get_account_transfers |
1 | 8190 |
get_account_balances |
1 | 8190 |
query_accounts |
1 | 8190 |
query_transfers |
1 | 8190 |
TigerBeetle clients automatically batch events. Therefore, it is recommended to share the client instances between multiple threads or tasks to have events batched transparently.
Events within a request succeed or fail independently unless they
are explicitly linked using the flags.linked
(Account.flags.linked
or Transfer.flags.linked
).
When the linked
flag is specified, it links the outcome of a Transfer or Account creation with the
outcome of the next one in the request. These chains of events will all succeed or fail together.
The last event in a chain is denoted by the first Transfer or Account without this flag.
The last Transfer or Account in a request may never have the flags.linked
set, as it would leave a
chain open-ended. Attempting to do so will result in the
linked_event_chain_open
error.
Multiple chains of events may coexist within a request to succeed or fail independently.
Events within a chain are executed in order, or are rolled back on error, so that the effect of each
event in the chain is visible to the next. Each chain is either visible or invisible as a unit to
subsequent transfers after the chain. The event that was the first to fail within a chain will have
a unique error result. Other events in the chain will have their error result set to
linked_event_failed
.
Consider this set of Transfers as part of a request:
Transfer | Index in Request | flags.linked |
---|---|---|
A |
0 |
false |
B |
1 |
true |
C |
2 |
true |
D |
3 |
false |
E |
4 |
false |
If any of transfers B
, C
, or D
fail (for example, due to
exceeds_credits
), then B
, C
, and D
will all fail.
They are linked.
Transfers A
and E
fail or succeed independently of B
, C
, D
, and each other.
After the chain of linked events has executed, the fact that they were linked will not be saved. To save the association between Transfers or Accounts, it must be encoded into the data model, for example by adding an ID to one of the user data fields.
- A request executes within the cluster at most once.
- Requests do not time out. Clients will continuously retry requests until they receive a reply from the cluster. This is because in the case of a network partition, a lack of response from the cluster could either indicate that the request was dropped before it was processed or that the reply was dropped after the request was processed. Note that individual pending transfers within a request may have timeouts.
- Requests retried by their original client session receive identical replies.
- Requests retried by a different client (same request body, different session) may receive different replies.
- Events within a request are executed in sequence. The effects of a given event are observable when the next event within that request is applied.
- Events within a request do not interleave with events from other requests.
- All events within a request batch are committed, or none are. Note that this does not mean that all of the events in a batch will succeed, or that all will fail. Events succeed or fail independently unless they are explicitly linked
- Once committed, an event will always be committed — the cluster's state never backtracks.
- Within a cluster, object timestamps are unique and strictly increasing. No two objects within the same cluster will have the same timestamp. Furthermore, the order of the timestamps indicates the order in which the objects were committed.