or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

atomic-operations.mdconfiguration.mdcore-operations.mddirectory-layer.mdindex.mdkey-value-ops.mdsubspaces.mdtransactions.md

transactions.mddocs/

0

# Transaction Management

1

2

Transaction lifecycle management including creation, execution, error handling, and retry logic with optimistic concurrency control. FoundationDB transactions provide ACID guarantees across the distributed system.

3

4

## Capabilities

5

6

### Transaction Lifecycle

7

8

Basic transaction operations for managing the transaction state and completing operations.

9

10

```c { .api }

11

/**

12

* Commit the transaction and make changes durable

13

* @param tr Transaction handle

14

* @return Future that completes when commit finishes

15

*/

16

FDBFuture* fdb_transaction_commit(FDBTransaction* tr);

17

18

/**

19

* Cancel the transaction, aborting all changes

20

* @param tr Transaction handle

21

*/

22

void fdb_transaction_cancel(FDBTransaction* tr);

23

24

/**

25

* Reset transaction to initial state, clearing all changes

26

* @param tr Transaction handle

27

*/

28

void fdb_transaction_reset(FDBTransaction* tr);

29

30

/**

31

* Get the committed version after successful commit

32

* @param tr Transaction handle

33

* @param out_version Pointer to store committed version

34

* @return Error code (0 for success)

35

*/

36

fdb_error_t fdb_transaction_get_committed_version(FDBTransaction* tr, int64_t* out_version);

37

```

38

39

```python { .api }

40

class Transaction:

41

def commit(self) -> Future:

42

"""

43

Commit the transaction

44

45

Returns:

46

Future that completes when commit finishes

47

"""

48

49

def cancel(self) -> None:

50

"""Cancel the transaction, aborting all changes"""

51

52

def reset(self) -> None:

53

"""Reset transaction to initial state"""

54

55

def get_committed_version(self) -> int:

56

"""

57

Get committed version after successful commit

58

59

Returns:

60

Committed version number

61

"""

62

```

63

64

```java { .api }

65

// Java API

66

public interface Transaction {

67

public CompletableFuture<Void> commit():

68

/**

69

* Commit the transaction asynchronously

70

* @return CompletableFuture that completes when commit finishes

71

*/

72

73

public void cancel():

74

/**

75

* Cancel the transaction

76

*/

77

78

public void reset():

79

/**

80

* Reset transaction to initial state

81

*/

82

83

public long getCommittedVersion():

84

/**

85

* Get committed version after successful commit

86

* @return Committed version number

87

*/

88

}

89

```

90

91

```go { .api }

92

// Go API

93

type Transaction interface {

94

Commit() FutureNil:

95

/**

96

* Commit the transaction

97

* @return Future that completes when commit finishes

98

*/

99

100

Cancel():

101

/**

102

* Cancel the transaction

103

*/

104

105

Reset():

106

/**

107

* Reset transaction to initial state

108

*/

109

110

GetCommittedVersion() (int64, error):

111

/**

112

* Get committed version after successful commit

113

* @return Committed version and error

114

*/

115

}

116

```

117

118

### Error Handling and Retry Logic

119

120

Handle transaction errors and implement retry logic for transient failures.

121

122

```c { .api }

123

/**

124

* Handle transaction errors and determine if retry is possible

125

* @param tr Transaction handle

126

* @param error Error code from previous operation

127

* @return Future that completes when error handling is done

128

*/

129

FDBFuture* fdb_transaction_on_error(FDBTransaction* tr, fdb_error_t error);

130

```

131

132

```python { .api }

133

class Transaction:

134

def on_error(self, error: FDBError) -> Future:

135

"""

136

Handle transaction error and prepare for retry if possible

137

138

Args:

139

error: FDBError from previous operation

140

141

Returns:

142

Future that completes when retry is ready or raises if not retryable

143

"""

144

145

def transactional(func: Callable) -> Callable:

146

"""

147

Decorator that automatically handles transaction retry logic

148

149

Args:

150

func: Function that takes Transaction as first argument

151

152

Returns:

153

Wrapped function that handles retries automatically

154

"""

155

```

156

157

```java { .api }

158

// Java API

159

public interface Transaction {

160

public CompletableFuture<Void> onError(FDBException error):

161

/**

162

* Handle transaction error and prepare for retry

163

* @param error Exception from previous operation

164

* @return CompletableFuture for retry preparation

165

*/

166

}

167

168

public interface Database {

169

public <T> T run(Function<Transaction, T> retryable):

170

/**

171

* Execute function with automatic retry logic

172

* @param retryable Function to execute in transaction

173

* @return Result of function execution

174

*/

175

176

public <T> CompletableFuture<T> runAsync(Function<Transaction, CompletableFuture<T>> retryable):

177

/**

178

* Execute async function with automatic retry logic

179

* @param retryable Async function to execute in transaction

180

* @return CompletableFuture with result

181

*/

182

}

183

```

184

185

```go { .api }

186

// Go API

187

type Transaction interface {

188

OnError(err Error) FutureNil:

189

/**

190

* Handle transaction error and prepare for retry

191

* @param err Error from previous operation

192

* @return Future for retry preparation

193

*/

194

}

195

196

type Transactor interface {

197

Transact(func(Transaction) (interface{}, error)) (interface{}, error):

198

/**

199

* Execute function with automatic retry logic

200

* @param fn Function to execute in transaction context

201

* @return Result and error

202

*/

203

}

204

```

205

206

### Version Management

207

208

Manage read and write versions for controlling transaction consistency and timestamps.

209

210

```c { .api }

211

/**

212

* Set the read version for the transaction

213

* @param tr Transaction handle

214

* @param version Version to use for reads

215

*/

216

void fdb_transaction_set_read_version(FDBTransaction* tr, int64_t version);

217

218

/**

219

* Get the read version that will be used for this transaction

220

* @param tr Transaction handle

221

* @return Future containing the read version

222

*/

223

FDBFuture* fdb_transaction_get_read_version(FDBTransaction* tr);

224

225

/**

226

* Get a versionstamp for this transaction

227

* @param tr Transaction handle

228

* @return Future containing the versionstamp

229

*/

230

FDBFuture* fdb_transaction_get_versionstamp(FDBTransaction* tr);

231

```

232

233

```python { .api }

234

class Transaction:

235

def set_read_version(self, version: int) -> None:

236

"""

237

Set the read version for this transaction

238

239

Args:

240

version: Version number to use for reads

241

"""

242

243

def get_read_version(self) -> Future:

244

"""

245

Get the read version for this transaction

246

247

Returns:

248

Future containing read version number

249

"""

250

251

def get_versionstamp(self) -> Future:

252

"""

253

Get a versionstamp for this transaction

254

255

Returns:

256

Future containing 10-byte versionstamp

257

"""

258

```

259

260

```java { .api }

261

// Java API

262

public interface Transaction {

263

public void setReadVersion(long version):

264

/**

265

* Set the read version for this transaction

266

* @param version Version number to use for reads

267

*/

268

269

public CompletableFuture<Long> getReadVersion():

270

/**

271

* Get the read version for this transaction

272

* @return CompletableFuture with read version

273

*/

274

275

public CompletableFuture<byte[]> getVersionstamp():

276

/**

277

* Get a versionstamp for this transaction

278

* @return CompletableFuture with 10-byte versionstamp

279

*/

280

}

281

```

282

283

```go { .api }

284

// Go API

285

type Transaction interface {

286

SetReadVersion(version int64):

287

/**

288

* Set the read version for this transaction

289

* @param version Version number to use for reads

290

*/

291

292

GetReadVersion() FutureInt64:

293

/**

294

* Get the read version for this transaction

295

* @return Future with read version

296

*/

297

298

GetVersionstamp() FutureKey:

299

/**

300

* Get a versionstamp for this transaction

301

* @return Future with 10-byte versionstamp

302

*/

303

}

304

```

305

306

### Conflict Range Management

307

308

Manage read and write conflict ranges to control transaction conflict detection.

309

310

```c { .api }

311

/**

312

* Add a conflict range to the transaction

313

* @param tr Transaction handle

314

* @param begin_key_name Start of key range

315

* @param begin_key_name_length Length of start key

316

* @param end_key_name End of key range (exclusive)

317

* @param end_key_name_length Length of end key

318

* @param type Type of conflict range (read or write)

319

* @return Error code (0 for success)

320

*/

321

fdb_error_t fdb_transaction_add_conflict_range(FDBTransaction* tr,

322

uint8_t const* begin_key_name, int begin_key_name_length,

323

uint8_t const* end_key_name, int end_key_name_length,

324

FDBConflictRangeType type);

325

```

326

327

```python { .api }

328

class Transaction:

329

def add_read_conflict_range(self, begin: bytes, end: bytes) -> None:

330

"""

331

Add a read conflict range

332

333

Args:

334

begin: Start of key range (inclusive)

335

end: End of key range (exclusive)

336

"""

337

338

def add_write_conflict_range(self, begin: bytes, end: bytes) -> None:

339

"""

340

Add a write conflict range

341

342

Args:

343

begin: Start of key range (inclusive)

344

end: End of key range (exclusive)

345

"""

346

347

def add_read_conflict_key(self, key: bytes) -> None:

348

"""

349

Add a single key read conflict range

350

351

Args:

352

key: Key to add to read conflict set

353

"""

354

355

def add_write_conflict_key(self, key: bytes) -> None:

356

"""

357

Add a single key write conflict range

358

359

Args:

360

key: Key to add to write conflict set

361

"""

362

```

363

364

```java { .api }

365

// Java API

366

public interface Transaction {

367

public void addReadConflictRange(byte[] begin, byte[] end):

368

/**

369

* Add a read conflict range

370

* @param begin Start of key range (inclusive)

371

* @param end End of key range (exclusive)

372

*/

373

374

public void addWriteConflictRange(byte[] begin, byte[] end):

375

/**

376

* Add a write conflict range

377

* @param begin Start of key range (inclusive)

378

* @param end End of key range (exclusive)

379

*/

380

381

public void addReadConflictKey(byte[] key):

382

/**

383

* Add a single key read conflict range

384

* @param key Key to add to read conflict set

385

*/

386

387

public void addWriteConflictKey(byte[] key):

388

/**

389

* Add a single key write conflict range

390

* @param key Key to add to write conflict set

391

*/

392

}

393

```

394

395

```go { .api }

396

// Go API

397

type Transaction interface {

398

AddReadConflictRange(begin, end Key) error:

399

/**

400

* Add a read conflict range

401

* @param begin Start of key range

402

* @param end End of key range

403

* @return Error if operation fails

404

*/

405

406

AddWriteConflictRange(begin, end Key) error:

407

/**

408

* Add a write conflict range

409

* @param begin Start of key range

410

* @param end End of key range

411

* @return Error if operation fails

412

*/

413

414

AddReadConflictKey(key Key) error:

415

/**

416

* Add a single key read conflict range

417

* @param key Key to add to read conflict set

418

* @return Error if operation fails

419

*/

420

421

AddWriteConflictKey(key Key) error:

422

/**

423

* Add a single key write conflict range

424

* @param key Key to add to write conflict set

425

* @return Error if operation fails

426

*/

427

}

428

```

429

430

### Transaction Size and Performance

431

432

Monitor and manage transaction size for optimal performance.

433

434

```c { .api }

435

/**

436

* Get approximate size of the transaction in bytes

437

* @param tr Transaction handle

438

* @return Future containing approximate transaction size

439

*/

440

FDBFuture* fdb_transaction_get_approximate_size(FDBTransaction* tr);

441

```

442

443

```python { .api }

444

class Transaction:

445

def get_approximate_size(self) -> Future:

446

"""

447

Get approximate size of the transaction

448

449

Returns:

450

Future containing transaction size in bytes

451

"""

452

```

453

454

```java { .api }

455

// Java API

456

public interface Transaction {

457

public CompletableFuture<Long> getApproximateSize():

458

/**

459

* Get approximate size of the transaction

460

* @return CompletableFuture with transaction size in bytes

461

*/

462

}

463

```

464

465

```go { .api }

466

// Go API

467

type Transaction interface {

468

GetApproximateSize() FutureInt64:

469

/**

470

* Get approximate size of the transaction

471

* @return Future with transaction size in bytes

472

*/

473

}

474

```

475

476

**Usage Examples:**

477

478

**Manual Transaction with Retry Logic (C):**

479

```c

480

void execute_with_retry(FDBDatabase* db) {

481

FDBTransaction* tr;

482

fdb_database_create_transaction(db, &tr);

483

484

while (1) {

485

// Set a value

486

fdb_transaction_set(tr, (uint8_t*)"key", 3, (uint8_t*)"value", 5);

487

488

// Try to commit

489

FDBFuture* commit_future = fdb_transaction_commit(tr);

490

fdb_error_t commit_err = fdb_future_block_until_ready(commit_future);

491

fdb_future_destroy(commit_future);

492

493

if (commit_err == 0) {

494

// Success!

495

break;

496

} else {

497

// Handle error and retry if possible

498

FDBFuture* error_future = fdb_transaction_on_error(tr, commit_err);

499

fdb_error_t retry_err = fdb_future_block_until_ready(error_future);

500

fdb_future_destroy(error_future);

501

502

if (retry_err != 0) {

503

// Not retryable, give up

504

break;

505

}

506

// Continue loop to retry

507

}

508

}

509

510

fdb_transaction_destroy(tr);

511

}

512

```

513

514

**Automatic Retry with Decorator (Python):**

515

```python

516

import fdb

517

518

fdb.api_version(630)

519

db = fdb.open()

520

521

@fdb.transactional

522

def update_counter(tr, key):

523

# Get current value

524

current = tr.get(key).wait()

525

count = int(current) if current else 0

526

527

# Increment and store

528

tr.set(key, str(count + 1).encode())

529

return count + 1

530

531

# This will automatically retry on conflicts

532

new_count = update_counter(db, b"counter")

533

print(f"New count: {new_count}")

534

```

535

536

**Database.run() with Automatic Retry (Java):**

537

```java

538

import com.apple.foundationdb.*;

539

540

FDB fdb = FDB.selectAPIVersion(630);

541

542

try (Database db = fdb.open()) {

543

// Automatic retry logic

544

Integer result = db.run(tr -> {

545

// Get current value

546

byte[] currentBytes = tr.get(Tuple.from("counter").pack()).join();

547

int current = currentBytes != null ? Integer.parseInt(new String(currentBytes)) : 0;

548

549

// Increment and store

550

int newValue = current + 1;

551

tr.set(Tuple.from("counter").pack(), String.valueOf(newValue).getBytes());

552

553

return newValue;

554

});

555

556

System.out.println("New count: " + result);

557

}

558

```

559

560

**Transactor Interface with Retry (Go):**

561

```go

562

package main

563

564

import (

565

"fmt"

566

"strconv"

567

"github.com/apple/foundationdb/bindings/go/src/fdb"

568

"github.com/apple/foundationdb/bindings/go/src/fdb/tuple"

569

)

570

571

func main() {

572

fdb.MustAPIVersion(630)

573

db := fdb.MustOpenDefault()

574

575

// Automatic retry logic

576

result, err := db.Transact(func(tr fdb.Transaction) (interface{}, error) {

577

// Get current value

578

key := tuple.Tuple{"counter"}.Pack()

579

currentBytes := tr.Get(fdb.Key(key)).MustGet()

580

581

current := 0

582

if currentBytes != nil {

583

current, _ = strconv.Atoi(string(currentBytes))

584

}

585

586

// Increment and store

587

newValue := current + 1

588

tr.Set(fdb.Key(key), []byte(strconv.Itoa(newValue)))

589

590

return newValue, nil

591

})

592

593

if err != nil {

594

panic(err)

595

}

596

597

fmt.Printf("New count: %d\n", result.(int))

598

}

599

```