API changes
0.17.0
Applications using the TigerBeetle Client 0.16.x
will require changes when upgrading to
0.17.x.
Future releases of the TigerBeetle cluster tagged as
0.17.x will continue to support old clients for an extended
period, giving application developers time to plan a smooth upgrade to
the new client library while independently upgrading the cluster to
newer releases.
New return type for create_accounts and
create_transfers.
The TigerBeetle release 0.17.0 introduced a new API for
handling results when creating Accounts and Transfers.
The previous API for create_accounts
and create_transfers
reported outcomes only for failed events, returning a sparse
array of results. Each result included the index of
the failed element within the event batch and the corresponding error
code. Successfully created events were not returned by the TigerBeetle
cluster, and the application could safely assume them as
ok.
While this approach prioritized saving network bandwidth by omitting results for the common happy path, it didn’t provide enough information about the outcome.
The new protocol departs from the sparse array style,
returning the status of each event, including the successfully created
ones, along with the timestamp when they were processed by
the TigerBeetle cluster.
Applications can now benefit from knowing the timestamp
assigned to a successfully created Account or Transfer,
while also handling alternative paths more efficiently by knowing
when validation occurred for those that couldn’t be
created.
The enums CreateAccountResult and
CreateTransferResult were renamed to
CreateAccountStatus and
CreateTransferStatus, and the status code
ok was renamed to created.
This makes it explicit whether an event became part of the database
state (created and exists) or not. By removing
the duality of ok and errors, applications can handle
results more clearly according to their policies, since some outcomes
might not be considered a failure by application logic — for example, a
Transfer not being created due to balance checks or pending
timeouts isn’t necessarily an error.
Likewise, the exists status now reports the same
timestamp returned by created, allowing the
application to treat both cases consistently.
The result types CreateAccountsResult and
CreateTransfersResult were renamed to the singular
form, CreateAccountResult and
CreateTransferResult.
// Before:
pub const CreateAccountsResult = extern struct {
index: u32,
result: CreateAccountResult,
};
// After:
pub const CreateAccountResult = extern struct {
timestamp: u64,
status: CreateAccountStatus,
reserved: u32 = 0,
};// Before:
pub const CreateTransfersResult = extern struct {
index: u32,
result: CreateTransferResult,
};
// After:
pub const CreateTransferResult = extern struct {
timestamp: u64,
status: CreateTransferStatus,
reserved: u32 = 0,
};Query limits.
The previous API did not validate the maximum range of the fields AccountFilter.limit
and QueryFilter.limit.
Values up to 2^32 - 1 were accepted, and the TigerBeetle
cluster was responsible for capping the number of results to fit the
message size.
Now the TigerBeetle client enforces a valid limit and
rejects requests with limits greater than the maximum batch size,
returning the too_much_data error code.
This is the same behavior as when, for example, create_accounts
or create_transfers
are called with more than 8189 events.
The operations query_accounts,
query_transfers,
get_account_transfers,
and get_account_balances
are affected.
Client breaking changes
Along with the new result types, some client libraries have changed the API to be more idiomatic, for naming consistency, or even due to bug fixes in the previous API.
See below is a list of API changes specific to each client library:
.NET
.NET Client breaking changes
The TigerBeetle .NET Client 0.17.0 introduced the
following breaking changes:
The enum types
CreateAccountResultandCreateTransferResult, with the status codes for thecreate_accountsandcreate_transfersoperations respectively, were renamed toCreateAccountStatusandCreateTransferStatus.The enum value
Ok, present in both enum types, was replaced by the new status codeCreated, which indicates that the event was successfully created.Type Before After Enum CreateAccountResultCreateAccountStatusEnum Value CreateAccountResult.OkCreateAccountStatus.CreatedEnum CreateTransferResultCreateTransferStatusEnum Value CreateTransferResult.OkCreateTransferStatus.CreatedThe result types
CreateAccountsResultandCreateTransfersResultwere renamed to the singular form,CreateAccountResultandCreateTransferResult.The property
Indexwas removed, since each result value corresponds to an event in the batch at the same index.Additional changes include the new
Timestampproperty and renaming theResultproperty toStatus, reflecting the change to the associated enums.Type Before After Struct CreateAccountsResultCreateAccountResultProperty CreateAccountsResult.Indexremoved Property NA CreateAccountResult.TimestampProperty CreateAccountsResult.ResultCreateAccountResult.StatusStruct CreateTransfersResultCreateTransferResultProperty CreateTransfersResult.Indexremoved Property NA CreateTransferResult.TimestampProperty CreateTransfersResult.ResultCreateTransferResult.StatusNon-batched methods of the
Clientclass that received a single event such asCreateAccount,CreateTransfer,LookupAccount, andLookupTransferwere removed.The batched versions that take an array of events such as
CreateAccounts,CreateTransfers,LookupAccounts, andLookupTransfersremain unchanged.New exceptions were introduced for conditions that can be handled by the application. The
PacketStatusenum is now internal and theRequestExceptionwas madeabstract.The client can be explicitly closed by calling
Client.Close(), whereas previously the only way to close a client was throughClient.Dispose(). Interacting with a closed client now throws aClientClosedExceptioninstead of anObjectDisposedException.Type Before After Enum PacketStatusremoved Exception RequestExceptionremoved Method added Client.Close()Exception ClientClosedExceptionException ClientEvictedExceptionException ClientReleaseExceptionException TooMuchDataException
Example:
Before:
CreateTransfersResult[] transferErrors = client.CreateTransfers(transfers);
if (transferErrors.Length > 0) {
// Error handling ...
}After:
CreateTransferResult[] transferResults = client.CreateTransfers(transfers);
Assert.AreEqual(transferResults.Length, transfers.Length);
foreach(CreateTransferResult result in transferResults)
{
switch(result.Status)
{
case CreateTransferStatus.Created:
case CreateTransferStatus.Exists:
// Successfully created.
break;
default:
// Could not be created.
break;
}
}For more details, please refer to the .NET client reference page.
Go
Go Client breaking changes
The TigerBeetle Go Client 0.17.0 introduced the
following breaking changes:
The enum types
CreateAccountResultandCreateTransferResult, with the status codes for thecreate_accountsandcreate_transfersoperations respectively, were renamed toCreateAccountStatusandCreateTransferStatus.The enum values
AccountOKandTransferOK, were replaced by the new status codesAccountCreatedandTransferCreated, which indicates the event was successfully created by the operation.Type Before After Enum CreateAccountResultCreateAccountStatusEnum Value AccountOKAccountCreatedEnum CreateTransferResultCreateTransferStatusEnum Value TransferOKTransferCreatedThe result types
AccountEventResultandTransferEventResultwere renamed toCreateAccountResultandCreateTransferResult.The field
Indexwas removed, since each result value corresponds to an event in the batch at the same index.Additional changes include the new
Timestampfield and renaming theResultfield toStatus, reflecting the change to the associated enums.Type Before After Type AccountEventResultCreateAccountResultField AccountEventResult.Indexremoved Field NA CreateAccountResult.TimestampField AccountEventResult.ResultCreateAccountResult.StatusType TransferEventResultCreateTransferResultField TransferEventResult.Indexremoved Field NA CreateTransferResult.TimestampField TransferEventResult.ResultCreateTransferResult.StatusThe
typesanderrorspackages were removed, consolidating all definitions under the roottigerbeetle_gopackage.The
Errtypes were removed in favor of simple value declarations for error codes, allowing the use of idiomatic constructions such aserrors.Is(err, ErrTooMuchData).Conversions between
UInt128andbig.Intnow return and accept a pointer to a big integer*big.Int, making the API more idiomatic.Type Before After Function BigInt() big.IntBigInt() *big.IntFunction BigIntToUint128(value big.Int) Uint128BigIntToUint128(value *big.Int) Uint128
Example:
Before:
import (
. "github.com/tigerbeetle/tigerbeetle-go"
. "github.com/tigerbeetle/tigerbeetle-go/pkg/types"
)
var transferErrors []TransferEventResult
var err error
transferErrors, err = client.CreateTransfers(transfers);
if err != nil {
// Request error ...
}
if len(transferErrors) > 0 {
// Error handling ...
}After:
import (
. "github.com/tigerbeetle/tigerbeetle-go"
)
var transferResults []CreateTransferResult
var err error
transferResults, err = client.CreateTransfers(transfers);
if err != nil {
// Request error ...
}
for _, result := range transferResults {
switch result.Status {
case TransferCreated, TransferExists:
// Successfully created.
default:
// Could not be created.
}
}For more details, please refer to the Go client reference page.
Java
Java Client breaking changes
The TigerBeetle Java Client 0.17.0 introduced the
following breaking changes:
The enum types
CreateAccountResultandCreateTransferResult, with the status codes for thecreate_accountsandcreate_transfersoperations respectively, were renamed toCreateAccountStatusandCreateTransferStatus.The enum value
Ok, present in both enum types, was replaced by the new status codeCreated, which indicates that the event was successfully created.Type Before After Enum CreateAccountResultCreateAccountStatusEnum Value CreateAccountResult.OkCreateAccountStatus.CreatedEnum CreateTransferResultCreateTransferStatusEnum Value CreateTransferResult.OkCreateTransferStatus.CreatedThe result types
CreateAccountResultBatchandCreateTransferResultBatch, had thegetIndex()property removed, since each result value corresponds to one event in the batch at the same index.Additional changes include the new
getTimestamp()property and renaming thegetResult()property togetStatus(), reflecting the change to the associated enums.Type Before After Method CreateAccountResultBatch.getIndex()removed Method NA CreateAccountResultBatch.getTimestamp()Method CreateAccountResultBatch.getResult()CreateAccountResultBatch.getStatus()Method CreateTransferResultBatch.getIndex()removed Method NA CreateTransferResultBatch.getTimestamp()Method CreateTransferResultBatch.getResult()CreateTransferResultBatch.getStatus()All the blocking methods of the
Clientclass (such ascreateAccounts,createTransfers, and others) may throw the checked exceptionInterruptedExceptionto signal that the waiting thread was interrupted by the Java environment. The non-blocking versions of the same methods that return aCompletableFuture<T>remain unchanged.New exceptions were introduced for conditions that can be handled by the application. The
PacketStatusenum is now internal and theRequestExceptionwas removed.All operations throw
ClientClosedExceptioninstead ofIllegalStateExceptionif the client is closed.Type Before After Enum PacketStatusremoved Exception RequestExceptionabstract class Exception ClientClosedExceptionextends RequestExceptionException ClientEvictedExceptionException ClientReleaseExceptionException TooMuchDataException
Example:
Before:
CreateTransferResultBatch transferErrors = client.createTransfers(transfers);
if (transferErrors.getLength() > 0) {
// Error handling ...
}After:
try {
CreateTransferResultBatch transferResults = client.createTransfers(transfers);
assert transferResults.getLength() == transfers.getLength();
while (transferResults.next()) {
switch (transferResults.getStatus()) {
case Created:
case Exists:
// Successfully created.
break;
default:
// Could not be created.
break;
}
}
} catch (InterruptedException exception) {
// The thread was interrupted.
}For more details, please refer to the Java client reference page.
Node.js
Node.js Client breaking changes
The TigerBeetle Node.js Client 0.17.0 introduced the
following breaking changes:
The enum types
CreateAccountErrorandCreateTransferError, with the status codes for thecreate_accountsandcreate_transfersoperations respectively, were renamed toCreateAccountStatusandCreateTransferStatus.The enum value
ok, present in both enum types, was replaced by the new status codecreated, which indicates that the event was successfully created.Type Before After Enum CreateAccountErrorCreateAccountStatusEnum Value CreateAccountError.okCreateAccountStatus.createdEnum CreateTransferErrorCreateTransferStatusEnum Value CreateTransferError.okCreateTransferStatus.createdThe result types
CreateAccountsErrorandCreateTransfersErrorwere renamed toCreateAccountResultandCreateTransferResult.The field
indexwas removed, since each result value corresponds to an event in the batch at the same index.Additional changes include the new
timestampfield and renaming theresultfield tostatus, reflecting the change to the associated enums.Type Before After Type CreateAccountsErrorCreateAccountResultField CreateAccountsError.indexremoved Field NA CreateAccountResult.timestampField CreateAccountsError.resultCreateAccountResult.statusType CreateTransfersErrorCreateTransferResultField CreateTransfersError.indexremoved Field NA CreateTransferResult.timestampField CreateTransfersError.resultCreateTransferResult.statusNew error type
RequestErrorwas introduced for conditions that can be handled by the application. Match theRequestError.codeproperty against the constants defined inErrorCodesto determine the specific failure.Type Before After Type ErrorCodesError RequestError
Example:
Before:
const transferErrors: CreateTransfersError[] = await client.createTransfers(transfers);
if (transferErrors.length > 0) {
// Error handling ...
}After:
const transferResults: CreateTransferResult[] = await client.createTransfers(transfers);
assert.strictEqual(transferResults.length, transfers.length);
for (const result of transferResults) {
switch (result.status) {
case CreateTransferStatus.created:
case CreateTransferStatus.exists:
// Successfully created.
break;
default:
// Could not be created.
break;
}
}For more details, please refer to the Node.js client reference page.
Python
Python Client breaking changes
The TigerBeetle Python Client 0.17.0 introduced the
following breaking changes:
The enum types
CreateAccountResultandCreateTransferResult, with the status codes for thecreate_accountsandcreate_transfersoperations respectively, were renamed toCreateAccountStatusandCreateTransferStatus.The enum value
OK, present in both enum types, was replaced by the new status codeCREATED, which indicates that the event was successfully created.Type Before After Enum CreateAccountResultCreateAccountStatusEnum Value CreateAccountResult.OKCreateAccountStatus.CREATEDEnum CreateTransferResultCreateTransferStatusEnum Value CreateTransferResult.OKCreateTransferStatus.CREATEDThe result types
CreateAccountsResultandCreateTransfersResultwere renamed to the singular form,CreateAccountResultandCreateTransferResult.The field
indexwas removed, since each result value corresponds to an event in the batch at the same index.Additional changes include the new
timestampfield and renaming theresultfield tostatus, reflecting the change to the associated enums.Type Before After Type CreateAccountsResultCreateAccountResultField CreateAccountsResult.indexremoved Field NA CreateAccountResult.timestampField CreateAccountsResult.resultCreateAccountResult.statusType CreateTransfersResultCreateTransferResultField CreateTransfersResult.indexremoved Field NA CreateTransferResult.timestampField CreateTransfersResult.resultCreateTransferResult.statusThe constant
amount_maxwas renamed toAMOUNT_MAX.New exceptions were introduced for conditions that can be handled by the application. The
PacketStatusenum is now internal and thePacketErrorexception was removed.Type Before After Enum PacketStatusremoved Exception PacketErrorremoved Exception ClientEvictedErrorException ClientReleaseTooLowErrorException ClientReleaseTooHighErrorException TooMuchDataErrorRemoved all default initialization values from the types
AccountFilterandQueryFilter.
Example:
Before:
transfer_errors = client.create_transfers(transfers)
if len(transfer_errors) > 0:
# Error handling ...After:
transfer_results = client.create_transfers(transfers)
assert len(transfer_results) == len(transfers)
for result in transfer_results:
if result.status == tb.CreateAccountResult.CREATED or \
result.status == tb.CreateAccountResult.EXISTS:
# Successfully created.
else:
# Could not be created.For more details, please refer to the Python client reference page.
Rust
Rust Client breaking changes
The TigerBeetle Rust Client 0.17.0 also introduced the
new API. However, the Rust client is not yet publicly available on
Crates.io at the time of this release, so they are not considered
breaking changes.
For more details, please refer to the Rust client reference page.
0.16.33
Oldest
supported client version is 0.16.4
Please make sure that all of your clients are running on at
0.16.4 or newer before upgrading to this release!
0.16.4
Transient Failures
Clients have the strong guarantee that a Transfer.id
that has once failed due to a transient error code will never succeed
again if retried.
Transient failures occur when semantically valid transfers fail due
to reasons that depend exclusively on the database status. For example,
when an account does not have enough credits to fulfill the
transfer.
Please refer to the documentation for a complete list of all transient failures.
As of 0.16.4:
New precedence order for the
create_transfersandcreate_accountserror codes. The idempotency checks (e.g., allexists_*cases) are now validated prior to the semantical checks.For example, when submitting a
transferwith theidof an existing one, clients might receiveexists_with_different_<field_name>instead of<field_name>_must_not_be_zero.This is not a breaking API change and affects all supported client versions.
create_transfersnow returnsexists_with_different_ledgerReflecting the new precedence order change.This is a breaking API change which is gated in the state machine by the client’s release. Clients of previous versions will receive
transfer_must_have_the_same_ledger_as_accountsinstead.Added a new result code
id_already_failed. It is returned bycreate_transferswhen theTransfer.idwas already used in a previous attempt that resulted in a transient failure.This is a breaking API change which is gated in the state machine by the client’s release. Clients of previous versions will be able to successfully create transfers submitted with an
idthat previously failed, since it passes all validations.
0.16.0
Zero-amount transfers
Zero-amount transfers are now permitted.
This is a breaking API change which is gated in the state machine by the client’s release.
As of 0.16.0:
Clients no longer return
amount_must_not_be_zerotocreate_transfers.Balancing transfers no longer use
amount=0as a sentinel value to represent “transfer as much as possible”. For that purpose, useAMOUNT_MAX(exact constant name depends on client implementation) instead.Post-pending transfers no longer use
amount=0as a sentinel value to represent “transfer full pending amount”. For that purpose, useAMOUNT_MAXinstead. In0.16.0, sending a post-pending transfer withamount=0will successfully postamount=0, voiding the remainder (i.e. voiding the whole pending amount).