# Buffering & Flushing

## Understanding Buffering vs Flushing

* **Apex:**
  * `addLog(builder)` buffers.
  * `log(builder)` **flushes immediately** (use at key boundaries or errors).
  * Triton sets stack trace & operation automatically when missing, and appends **governor limit** info via the builder.
* **LWC:**
  * `triton.log(builder)` buffers in memory.
  * `triton.logNow(builder)` flushes that one immediately.
  * Triton's LWC **TransactionManager** auto-flushes after idle periods; still **flush on navigation/unload** when practical.

## Real-World Example: Financial Transaction Processing

```apex
public class PaymentProcessor {
    public static void processPayment(Id accountId, Decimal amount) {
        Long startTime = System.now().getTime();
        
        // Set up template for all payment processing logs
        Triton.instance.setTemplate(
            Triton.makeBuilder()
                .category(TritonTypes.Category.Integration)
                .type(TritonTypes.Type.Backend)
                .area(TritonTypes.Area.PaymentProcessing)
                .relatedObject(accountId)
        );
        
        // Buffer routine operations using template
        Triton.instance.addLog(
            Triton.instance.fromTemplate()
                .level(TritonTypes.Level.DEBUG)
                .summary('Payment processing started')
                .details('accountId=' + accountId + ', amount=' + amount)
        );
        
        try {
            // First, make the callout to payment gateway
            HttpRequest req = new HttpRequest();
            req.setEndpoint('https://api.paymentgateway.com/process');
            req.setMethod('POST');
            req.setHeader('Content-Type', 'application/json');
            req.setBody(JSON.serialize(new Map<String, Object>{
                'accountId' => accountId,
                'amount' => amount,
                'currency' => 'USD'
            }));
            
            HttpResponse response = new Http().send(req);
            
            if (response.getStatusCode() == 200) {
                // Parse successful response
                Map<String, Object> responseData = (Map<String, Object>)JSON.deserializeUntyped(response.getBody());
                
                // Now perform DML after successful callout
                Payment__c payment = new Payment__c(
                    Account__c = accountId,
                    Amount__c = amount,
                    Status__c = 'Completed'
                );
                insert payment;
                
                // Buffer success milestone using template
                Triton.instance.addLog(
                    Triton.instance.fromTemplate()
                        .level(TritonTypes.Level.INFO)
                        .summary('Payment processed successfully')
                        .details('paymentId=' + payment.Id)
                        .relatedObject(payment.Id)
                        .integrationPayload(req, response)
                        .duration(System.now().getTime() - startTime)
                );
                
            } else {
                // Immediately flush critical error using template
                Triton.instance.log(
                    Triton.instance.fromTemplate()
                        .exception(new PaymentException('Gateway error: ' + response.getStatusCode()))
                        .summary('Payment gateway failed')
                        .integrationPayload(req, response)
                );
            }
            
        } catch (Exception e) {
            // Immediately flush critical errors using template
            Triton.instance.log(
                Triton.instance.fromTemplate()
                    .exception(e)
                    .summary('Payment processing failed')
            );
            throw e;
        } finally {
            // Flush all buffered logs at transaction boundary
            Triton.instance.flush();
        }
    }
}
```

## LWC Buffering Example

```js
// E-commerce checkout component with smart buffering
export default class CheckoutComponent extends LightningElement {
    triton;
    
    connectedCallback() {
        this.triton = new Triton().bindToComponent('c-checkout');
        
        // Set up template for all checkout operations
        this.triton.setTemplate(
            this.triton.makeBuilder()
                .type(TYPE.FRONTEND)
                .area(AREA.COMMUNITY)
        );
    }
    
    async handleCheckout() {
        // Buffer routine debug info
        this.triton.log(
            this.triton.fromTemplate()
                .level(LEVEL.DEBUG)
                .summary('Checkout initiated')
                .details(JSON.stringify({ 
                    cartItems: this.cartItems.length,
                    totalAmount: this.totalAmount 
                }))
        );
        
        try {
            // Process checkout steps
            await this.validateInventory();
            await this.processPayment();
            await this.createOrder();
            
            // Buffer success milestone
            this.triton.log(
                this.triton.fromTemplate()
                    .level(LEVEL.INFO)
                    .summary('Checkout completed successfully')
                    .details(JSON.stringify({ orderId: this.orderId }))
            );
            
        } catch (error) {
            // Immediately flush critical errors
            await this.triton.logNow(
                this.triton.fromTemplate()
                    .exception(error)
                    .summary('Checkout failed')
            );
            
            // Show user-friendly error
            this.showErrorMessage('Checkout failed. Please try again or contact support.');
        }
    }
    
    disconnectedCallback() {
        // Flush any remaining logs when component is destroyed
        this.triton.flush();
    }
}
```

## When to Buffer vs Flush

### Buffer When:

* **Routine operations**: Normal processing steps, debug information
* **High-volume scenarios**: Processing multiple records in loops
* **Performance-critical paths**: Where logging overhead must be minimized
* **Non-critical information**: Debug logs, informational milestones

### Flush Immediately When:

* **Critical errors**: Exceptions that might prevent further processing
* **Transaction boundaries**: End of methods, batch chunks, queueable completion
* **User-facing failures**: Errors that affect user experience
* **Integration failures**: Callout errors, external service issues
* **Component teardown**: LWC component destruction

## Performance Considerations

### Apex Performance

* **Buffering reduces DML**: Multiple logs are sent together, reducing platform event overhead
* **Flush strategically**: Use `flush()` at natural boundaries to avoid memory buildup
* **Error scenarios**: Always flush on errors to ensure critical information is captured
* **Governor limits**: Monitor platform event limits in high-volume scenarios

### LWC Performance

* **Memory management**: Buffered logs consume memory until flushed
* **Auto-flush**: Triton automatically flushes after idle periods
* **Navigation events**: Flush on page navigation or component destruction
* **Error handling**: Use `logNow()` for critical errors to ensure immediate capture

## Best Practices

### Buffer Management

1. **Set clear boundaries**: Define when to flush based on logical transaction boundaries
2. **Monitor memory usage**: Be aware of buffered log volume in long-running processes
3. **Error handling**: Always flush on exceptions to preserve critical context
4. **Performance testing**: Measure the impact of buffering vs immediate flushing

### Flush Strategies

1. **Method boundaries**: Flush at the end of public methods
2. **Batch operations**: Flush after each batch chunk
3. **Queueable completion**: Flush at the end of queueable execution
4. **Component lifecycle**: Flush in LWC `disconnectedCallback()`
5. **Error scenarios**: Immediate flush for all exceptions

### Monitoring and Debugging

1. **Log volume**: Monitor the number of buffered vs flushed logs
2. **Memory usage**: Track memory consumption in long-running processes
3. **Error correlation**: Ensure errors are properly flushed for debugging
4. **Performance impact**: Measure the overhead of different buffering strategies

## Advanced Patterns

### Conditional Flushing

```apex
public void processRecords(List<SObject> records) {
    for (SObject record : records) {
        // Buffer routine processing
        Triton.instance.addLog(
            Triton.instance.fromTemplate()
                .summary('Processing record')
                .relatedObject(record.Id)
        );
        
        try {
            processRecord(record);
        } catch (Exception e) {
            // Flush immediately on error
            Triton.instance.log(
                Triton.instance.fromTemplate()
                    .exception(e)
                    .summary('Record processing failed')
            );
            throw e;
        }
    }
    
    // Flush all buffered logs at the end
    Triton.instance.flush();
}
```

### Smart Buffering with Limits

```apex
public class SmartBuffer {
    private static final Integer MAX_BUFFER_SIZE = 50;
    private static Integer bufferCount = 0;
    
    public static void addLog(TritonBuilder builder) {
        Triton.instance.addLog(builder);
        bufferCount++;
        
        // Flush when buffer gets too large
        if (bufferCount >= MAX_BUFFER_SIZE) {
            Triton.instance.flush();
            bufferCount = 0;
        }
    }
    
    public static void forceFlush() {
        Triton.instance.flush();
        bufferCount = 0;
    }
}
```

By mastering buffering and flushing strategies, you'll optimize performance while ensuring critical logs are never lost and debugging information is always available when needed.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://triton.pharos.ai/pharos-triton/triton-best-practices/buffering-and-flushing.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
