brson · GitHub

@brson

@brson

matklad


// Prevent multiple tests from running in parallel -
// tests run a full tigerbeetle and that's a lot of resources.
static TEST_MUTEX: Mutex<()> = Mutex::new(());

Member

Not a fan of this, the tests should be fast! Would the following approach work for running the tests in parallel:

  • There's just a single database instance per test process
  • This instance is created lazily (could use https://doc.rust-lang.org/stable/std/sync/struct.OnceLock.html)
  • The database is spawned with "--addresses=0", so there's no need to run Drop for it, the database process will exit itself when the test process exits.
  • Individual tests concurrently hit this database.
  • To make sure that individual tests do not step on each other's toes, each test generates random ids using the id() function.

Ah, but we seem to miss the id() function? We should add one, see the JS impmlementaiton here:

export function id(): bigint {
// Ensure timestamp monotonically increases and generate a new random on each new timestamp.
let timestamp = Date.now()
if (timestamp <= idLastTimestamp) {
timestamp = idLastTimestamp
} else {
idLastTimestamp = timestamp
randomFillSync(idLastBuffer)
}
// Increment the u80 in idLastBuffer using carry arithmetic on u32s (as JS doesn't have fast u64).
const littleEndian = true
const randomLo32 = idLastBuffer.getUint32(0, littleEndian) + 1
const randomHi32 = idLastBuffer.getUint32(4, littleEndian) + (randomLo32 > 0xFFFFFFFF ? 1 : 0)
const randomHi16 = idLastBuffer.getUint16(8, littleEndian) + (randomHi32 > 0xFFFFFFFF ? 1 : 0)
if (randomHi16 > 0xFFFF) {
throw new Error('random bits overflow on monotonic increment')
}
// Store the incremented random monotonic and the timestamp into the buffer.
idLastBuffer.setUint32(0, randomLo32 & 0xFFFFFFFF, littleEndian)
idLastBuffer.setUint32(4, randomHi32 & 0xFFFFFFFF, littleEndian)
idLastBuffer.setUint16(8, randomHi16, littleEndian) // No need to mask since checked above.
idLastBuffer.setUint16(10, timestamp & 0xFFFF, littleEndian) // timestamp lo.
idLastBuffer.setUint32(12, (timestamp >>> 16) & 0xFFFFFFFF, littleEndian) // timestamp hi.
// Then return the buffer's contents as a little-endian u128 bigint.
const lo = idLastBuffer.getBigUint64(0, littleEndian)
const hi = idLastBuffer.getBigUint64(8, littleEndian)
return (hi << 64n) | lo
}

and the docs here:

https://docs.tigerbeetle.com/coding/data-modeling/#tigerbeetle-time-based-identifiers-recommended

Basically, the ID is a timestamp concatenated to a random nonce, and binary encoded in such a way that natural sorting corresponds to timestamp sorting. We do this to allow quickly checking "have we seen this ID before" in the database --- if the timestamp part is larger than any previously seen timestamp, the ID is guaranteed to be new. And, if clients have approximately correct clock, we'll always be hitting this hot path.

flags: tb::AccountFlags::History,
timestamp: 0,
}])
.await?;
Co-authored-by: Alex Kladov <aleksey.kladov@gmail.com>

@brson

@brson

@brson

@brson

@brson

@brson

This allows structs to be initialized with record update syntax.

@brson

@brson

@brson

@brson

@brson

matklad

matklad previously approved these changes Jul 15, 2025

Comment on lines +31 to +41

pub fn id() -> u128 {
let mut guard = GLOBAL_GENERATOR.lock().expect("global tbid generator");
match *guard {
None => {
*guard = Some(TbidGenerator::new());
drop(guard);
id()
}
Some(ref mut generator) => generator.next(),
}
}
let past_time_base = now - Duration::from_millis(2);
let past_time = past_time_base + Duration::from_millis(count);
count += 1;
idgen.next_from_system_time(past_time)
#[rustfmt::skip]
impl From<tbc::tb_create_accounts_result_t> for CreateAccountResult {
fn from(other: tbc::tb_create_accounts_result_t) -> CreateAccountResult {
impl From<u32> for CreateAccountResult {
Co-authored-by: Alex Kladov <aleksey.kladov@gmail.com>

@brson

@brson

@brson

@brson

@brson

@brson

@brson

@matklad

Merged via the queue into tigerbeetle:main with commit 79dc0f2

Aug 7, 2025

38 checks passed

michabp

//
// - https://github.com/tigerbeetle/tigerbeetle/blob/75f77b8b3280ce2f289cf42ae928945190fe4a2a/src/clients/node/src/index.ts#L161-L191
// - https://github.com/ulid/spec
pub fn id() -> u128 {

Read the original on github.com ↗