Transaction Management
Correlating logs across LWC → Apex → Flow boundaries using transaction management for end-to-end traceability.
Transaction Handling & Correlation
Start early (user entry points):
Triton.instance.startTransaction()
(Apex) ortriton.startTransaction()
(LWC).Resume across hops:
Capture the current transactionId in LWC (
triton.transactionId
) and pass it in Apex method params.In Apex entry, call
Triton.instance.resumeTransaction(txId)
if provided; otherwisewithCache()
can auto-resume if configured.
Stop & flush at natural boundaries: end of a long-running flow, batch
finish
, queueable completion, on modal close/navigation in LWC.
Apex (Controller Entry)
@AuraEnabled(cacheable=false)
public static List<Opportunity> loadOpps(Id accountId, String txId) {
if (String.isNotBlank(txId)) Triton.instance.resumeTransaction(txId);
else Triton.instance.startTransaction();
// Set up template for opportunity loading
Triton.instance.setTemplate(
Triton.makeBuilder()
.category(TritonTypes.Category.Apex)
.type(TritonTypes.Type.Backend)
.area(TritonTypes.Area.OpportunityManagement)
.relatedObject(accountId)
);
try {
// ... do work
Triton.instance.log(
Triton.instance.fromTemplate()
.level(TritonTypes.Level.INFO)
.summary('Loaded opportunities')
.details('accountId=' + accountId)
);
return [SELECT Id, Name, Amount FROM Opportunity WHERE AccountId = :accountId LIMIT 200];
} catch (Exception e) {
Triton.instance.log(
Triton.instance.fromTemplate()
.exception(e)
);
throw e;
} finally {
Triton.instance.stopTransaction();
}
}
LWC (Passing Transaction Across)
import loadOpps from '@salesforce/apex/OppController.loadOpps';
const triton = new Triton().bindToComponent('c-opportunity-list');
const txId = triton.startTransaction();
// Set up template for opportunity operations
triton.setTemplate(
triton.makeBuilder()
.type(TYPE.FRONTEND)
.area(AREA.OPPORTUNITY_MANAGEMENT)
.relatedObjects([this.recordId])
);
try {
const data = await loadOpps({ accountId: this.recordId, txId });
triton.log(
triton.fromTemplate()
.summary('Opps rendered')
.details(`rows=${data.length}`)
);
} catch (error) {
triton.logNow(
triton.fromTemplate()
.exception(error)
.summary('Failed to load opps')
);
} finally {
triton.stopTransaction();
}
Real-World Example: Multi-Step Lead Conversion Process
// Lead conversion LWC with transaction correlation
export default class LeadConversionWizard extends LightningElement {
triton;
connectedCallback() {
this.triton = new Triton().bindToComponent('c-lead-conversion-wizard');
this.triton.startTransaction();
// Set up template for lead conversion operations
this.triton.setTemplate(
this.triton.makeBuilder()
.type(TYPE.FRONTEND)
.area(AREA.LEAD_CONVERSION)
.relatedObjects([this.recordId])
);
}
async handleLeadConversion() {
try {
// Step 1: Validate lead data
await this.validateLeadData();
// Step 2: Create account and contact
const accountResult = await createAccount({
accountData: this.accountData,
txId: this.triton.transactionId
});
// Step 3: Create opportunity
const oppResult = await createOpportunity({
oppData: this.oppData,
accountId: accountResult.Id,
txId: this.triton.transactionId
});
// Step 4: Update lead status
await updateLeadStatus({
leadId: this.recordId,
status: 'Converted',
txId: this.triton.transactionId
});
this.triton.log(
this.triton.fromTemplate()
.summary('Lead conversion completed')
.details(JSON.stringify({
accountId: accountResult.Id,
opportunityId: oppResult.Id,
leadId: this.recordId
}))
.relatedObjects([accountResult.Id, oppResult.Id])
);
} catch (error) {
await this.triton.logNow(
this.triton.fromTemplate()
.exception(error)
.summary('Lead conversion failed')
);
} finally {
this.triton.stopTransaction();
}
}
}
// Apex controller with transaction resumption
public class LeadConversionController {
@AuraEnabled
public static Account createAccount(AccountData accountData, String txId) {
// Resume transaction from LWC
if (String.isNotBlank(txId)) {
Triton.instance.resumeTransaction(txId);
} else {
Triton.instance.startTransaction();
}
// Set up template for lead conversion operations
Triton.instance.setTemplate(
Triton.makeBuilder()
.category(TritonTypes.Category.Apex)
.type(TritonTypes.Type.Backend)
.area(TritonTypes.Area.LeadConversion)
.relatedObject(accountData.leadId)
);
try {
Account newAccount = new Account(
Name = accountData.name,
Industry = accountData.industry,
BillingCity = accountData.city
);
insert newAccount;
Triton.instance.log(
Triton.instance.fromTemplate()
.level(TritonTypes.Level.INFO)
.summary('Account created for lead conversion')
.details('accountId=' + newAccount.Id + ', name=' + accountData.name)
.relatedObject(newAccount.Id)
);
return newAccount;
} catch (Exception e) {
Triton.instance.log(
Triton.instance.fromTemplate()
.exception(e)
.summary('Account creation failed')
);
throw e;
}
}
}
Transaction ID Flow
Understanding how the transaction ID connects logs across contexts is crucial:
LWC Initialization
Direct Params: Transaction ID is generated when first log is created
Cache: Transaction ID is generated and automatically cached
Apex Execution
Direct Params: Transaction ID is passed via method parameter and resumed
Cache: Transaction ID is automatically retrieved from cache
Flow Execution
The Flow's Interview GUID is automatically associated with the transaction
All Flow logs are grouped under the same transaction
Best Practices
Transaction Lifecycle
Start early: Begin transactions at user entry points
Resume consistently: Always resume transactions in Apex when txId is provided
Stop properly: End transactions at natural boundaries
Handle failures: Ensure transactions are stopped even when errors occur
Correlation Strategies
Direct parameter passing: Explicitly pass transaction IDs for simple scenarios
Platform cache: Use cache for complex, multi-component scenarios
Interview GUID: Always use Flow Interview GUID for Flow correlation
Error handling: Maintain transaction context even during failures
Performance Considerations
Cache availability: Check if platform cache is enabled before using cache-based correlation
Memory management: Be aware of transaction context memory usage in long-running processes
Boundary management: Stop transactions promptly to free resources
By mastering transaction management, you'll create complete execution traces that span across all Salesforce technologies, enabling powerful debugging and monitoring capabilities.
Last updated