or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

authentication.mddriver-management.mderror-handling.mdgraph-types.mdindex.mdreactive-programming.mdsession-operations.mdtemporal-types.mdtransaction-management.md

transaction-management.mddocs/

0

# Transaction Management

1

2

Transaction handling including explicit transactions and managed transactions with automatic retry logic for robust database operations.

3

4

## Capabilities

5

6

### Explicit Transaction Control

7

8

Manual transaction management with full control over commit and rollback operations.

9

10

```typescript { .api }

11

interface Transaction {

12

/**

13

* Run a Cypher query within the transaction

14

* @param query - The Cypher query string

15

* @param parameters - Query parameters as key-value pairs

16

* @returns Promise resolving to query result

17

*/

18

run(query: string, parameters?: Parameters): Promise<Result>;

19

20

/** Commit the transaction and make changes permanent */

21

commit(): Promise<void>;

22

23

/** Rollback the transaction and discard changes */

24

rollback(): Promise<void>;

25

26

/** Check if the transaction is still open and active */

27

isOpen(): boolean;

28

}

29

```

30

31

**Usage Examples:**

32

33

```typescript

34

const session = neo4jDriver.session();

35

36

// Basic transaction usage

37

const tx = await session.beginTransaction();

38

try {

39

const result = await tx.run(

40

"CREATE (p:Person {name: $name}) RETURN p",

41

{ name: "Alice" }

42

);

43

44

await tx.commit();

45

console.log("Transaction committed");

46

} catch (error) {

47

await tx.rollback();

48

console.error("Transaction rolled back:", error);

49

} finally {

50

await session.close();

51

}

52

53

// Complex multi-step transaction

54

const complexTx = await session.beginTransaction({

55

timeout: 60000, // 1 minute timeout

56

metadata: { operation: "user_registration" }

57

});

58

59

try {

60

// Step 1: Create user

61

const userResult = await complexTx.run(`

62

CREATE (u:User {id: randomUUID(), email: $email, createdAt: datetime()})

63

RETURN u.id AS userId

64

`, { email: "user@example.com" });

65

66

const userId = userResult.records[0].get("userId");

67

68

// Step 2: Create user profile

69

await complexTx.run(`

70

MATCH (u:User {id: $userId})

71

CREATE (u)-[:HAS_PROFILE]->(p:Profile {

72

firstName: $firstName,

73

lastName: $lastName,

74

updatedAt: datetime()

75

})

76

`, {

77

userId,

78

firstName: "John",

79

lastName: "Doe"

80

});

81

82

// Step 3: Add to default groups

83

await complexTx.run(`

84

MATCH (u:User {id: $userId}), (g:Group {name: 'users'})

85

CREATE (u)-[:MEMBER_OF]->(g)

86

`, { userId });

87

88

await complexTx.commit();

89

console.log(`User ${userId} registered successfully`);

90

} catch (error) {

91

await complexTx.rollback();

92

console.error("User registration failed:", error);

93

} finally {

94

await session.close();

95

}

96

```

97

98

### Managed Transactions

99

100

Managed transactions with automatic retry logic and simplified error handling.

101

102

```typescript { .api }

103

interface ManagedTransaction {

104

/**

105

* Run a Cypher query within the managed transaction

106

* @param query - The Cypher query string

107

* @param parameters - Query parameters as key-value pairs

108

* @returns Promise resolving to query result

109

*/

110

run(query: string, parameters?: Parameters): Promise<Result>;

111

}

112

113

interface Session {

114

/**

115

* Execute a read transaction with automatic retry logic

116

* @param work - Function containing read operations

117

* @param config - Optional transaction configuration

118

* @returns Promise resolving to the work function result

119

*/

120

executeRead<T>(

121

work: (tx: ManagedTransaction) => Promise<T>,

122

config?: TransactionConfig

123

): Promise<T>;

124

125

/**

126

* Execute a write transaction with automatic retry logic

127

* @param work - Function containing write operations

128

* @param config - Optional transaction configuration

129

* @returns Promise resolving to the work function result

130

*/

131

executeWrite<T>(

132

work: (tx: ManagedTransaction) => Promise<T>,

133

config?: TransactionConfig

134

): Promise<T>;

135

}

136

```

137

138

**Usage Examples:**

139

140

```typescript

141

const session = neo4jDriver.session();

142

143

try {

144

// Read transaction - automatically retried on failure

145

const users = await session.executeRead(async tx => {

146

const result = await tx.run(`

147

MATCH (u:User)-[:HAS_PROFILE]->(p:Profile)

148

WHERE u.createdAt > datetime({year: 2023})

149

RETURN u.email, p.firstName, p.lastName

150

ORDER BY u.createdAt DESC

151

LIMIT 100

152

`);

153

154

return result.records.map(record => ({

155

email: record.get("u.email"),

156

firstName: record.get("p.firstName"),

157

lastName: record.get("p.lastName")

158

}));

159

});

160

161

console.log(`Found ${users.length} recent users`);

162

163

// Write transaction with retry logic

164

const orderId = await session.executeWrite(async tx => {

165

// Create order

166

const orderResult = await tx.run(`

167

CREATE (o:Order {

168

id: randomUUID(),

169

status: 'pending',

170

createdAt: datetime(),

171

total: $total

172

})

173

RETURN o.id AS orderId

174

`, { total: 99.99 });

175

176

const id = orderResult.records[0].get("orderId");

177

178

// Add order items

179

await tx.run(`

180

MATCH (o:Order {id: $orderId})

181

UNWIND $items AS item

182

CREATE (o)-[:CONTAINS]->(oi:OrderItem {

183

productId: item.productId,

184

quantity: item.quantity,

185

price: item.price

186

})

187

`, {

188

orderId: id,

189

items: [

190

{ productId: "prod-123", quantity: 2, price: 49.99 },

191

{ productId: "prod-456", quantity: 1, price: 0.01 } // Tax adjustment

192

]

193

});

194

195

return id;

196

}, {

197

timeout: 30000,

198

metadata: { operation: "create_order", version: "v2" }

199

});

200

201

console.log(`Created order: ${orderId}`);

202

} finally {

203

await session.close();

204

}

205

```

206

207

### Transaction Configuration

208

209

Configuration options for controlling transaction behavior.

210

211

```typescript { .api }

212

interface TransactionConfig {

213

/** Transaction timeout in milliseconds */

214

timeout?: number;

215

216

/**

217

* Transaction metadata for monitoring and debugging

218

* Useful for tracking operations in Neo4j logs

219

*/

220

metadata?: Record<string, any>;

221

}

222

```

223

224

**Usage Examples:**

225

226

```typescript

227

// Long-running transaction with custom timeout

228

await session.executeWrite(async tx => {

229

// Bulk data import operation

230

const result = await tx.run(`

231

LOAD CSV WITH HEADERS FROM $csvUrl AS row

232

CREATE (p:Product {

233

id: row.id,

234

name: row.name,

235

price: toFloat(row.price),

236

category: row.category,

237

importedAt: datetime()

238

})

239

`, { csvUrl: "file:///import/products.csv" });

240

241

return result.summary.counters.nodesCreated;

242

}, {

243

timeout: 300000, // 5 minutes for large import

244

metadata: {

245

operation: "bulk_import",

246

source: "products.csv",

247

batchId: "batch-001"

248

}

249

});

250

251

// Transaction with detailed metadata

252

await session.executeWrite(async tx => {

253

await tx.run(`

254

MATCH (u:User {id: $userId})

255

SET u.lastLogin = datetime(),

256

u.loginCount = coalesce(u.loginCount, 0) + 1

257

`, { userId: "user-123" });

258

}, {

259

metadata: {

260

operation: "user_login",

261

userId: "user-123",

262

timestamp: new Date().toISOString(),

263

source: "web_app"

264

}

265

});

266

```

267

268

### Transaction Best Practices

269

270

**Retry Logic:**

271

Managed transactions automatically retry on transient errors like connection issues or deadlocks. The driver uses exponential backoff and respects cluster topology changes.

272

273

**Read vs Write Transactions:**

274

- Use `executeRead` for queries that only read data

275

- Use `executeWrite` for queries that modify data

276

- This enables proper routing in cluster environments

277

278

**Transaction Size:**

279

- Keep transactions small and focused

280

- Avoid long-running transactions that hold locks

281

- Consider breaking large operations into smaller transactions

282

283

**Error Handling:**

284

- Managed transactions handle retryable errors automatically

285

- Non-retryable errors (like constraint violations) are thrown immediately

286

- Always handle business logic errors in your work function

287

288

**Performance Tips:**

289

- Use parameters instead of string concatenation

290

- Batch related operations in single transactions

291

- Use UNWIND for bulk operations

292

- Profile queries to optimize performance

293

294

```typescript

295

// Good: Focused transaction

296

await session.executeWrite(async tx => {

297

await tx.run(`

298

MATCH (u:User {id: $userId})

299

SET u.status = $status, u.updatedAt = datetime()

300

`, { userId, status: "active" });

301

});

302

303

// Good: Bulk operation with UNWIND

304

await session.executeWrite(async tx => {

305

await tx.run(`

306

UNWIND $users AS user

307

MERGE (u:User {id: user.id})

308

SET u.email = user.email, u.updatedAt = datetime()

309

`, { users: userBatch });

310

});

311

312

// Avoid: Transaction too large

313

await session.executeWrite(async tx => {

314

// Too many operations in single transaction

315

for (const user of allUsers) { // Could be thousands

316

await tx.run("CREATE (u:User $props)", { props: user });

317

}

318

});

319

```