PERFORMANCE LOOP FIX

Comprehensive guidelines for AI-assisted development within the Editor platform

๐Ÿšจ CRITICAL FIX: Infinite Performance Metrics Loop

Emergency fix for recursive database operations that killed the app


๐Ÿ”ฅ Critical Issue Report

Severity: ๐Ÿšจ CRITICAL - App becomes completely unusable
Impact: Infinite loop causing browser crash and complete application failure
User Report: "I got an infinite amount (loop) of messages that killed our app"

Error Pattern

โœ… Upserted record in performance-metrics: metric_1753724371256_aeq604dki
โœ… Upserted record in performance-metrics: metric_1753724371256_5b5cvknb8
โœ… Upserted record in performance-metrics: metric_1753724371257_6qnfjflf6
โœ… Upserted record in performance-metrics: metric_1753724371257_e9j9xpign
[INFINITE LOOP CONTINUES...]

๐Ÿ” Root Cause Analysis

The Infinite Recursion Chain

The issue was caused by recursive performance tracking in the LocalDatabaseService:

graph TB
    A[User creates block] --> B[upsert called]
    B --> C[recordPerformanceMetric triggered]
    C --> D[upsert 'performance-metrics']
    D --> E[recordPerformanceMetric triggered again]
    E --> D
    
    style A fill:#e1f5fe
    style D fill:#ffebee
    style E fill:#ffebee

Technical Breakdown

  1. Initial Trigger: User creates a block
  2. Database Operation: upsert() method called to save block
  3. Performance Tracking: recordPerformanceMetric() automatically triggered
  4. Metrics Storage: Performance metric stored via upsert('performance-metrics', ...)
  5. Recursion: That upsert triggers recordPerformanceMetric() again
  6. Infinite Loop: Steps 4-5 repeat infinitely until browser crashes

Code Location

File: apps/singularity/src/app/core/services/local-database.service.ts

Before (Problematic Code):

// Line 370: Every upsert triggers performance recording
tap(() => this.recordPerformanceMetric('upsert', startTime, true, { storeName, id: data.id })),

// Line 649: Performance recording stores in database (causing recursion)
private recordPerformanceMetric(operation: string, startTime: number, success: boolean, details?: any): void {
  // ... create metric object
  
  // ๐Ÿšจ PROBLEM: This triggers another upsert, causing infinite recursion
  this.upsert('performance-metrics', { ...metric, id: `...` })
    .subscribe({
      error: (error) => console.warn('Failed to record performance metric:', error)
    });
}

โœ… Fix Applied

Recursion Prevention Guard

Added a recursion guard to prevent performance metrics from tracking themselves:

/**
 * Record performance metrics (with recursion prevention)
 */
private recordPerformanceMetric(operation: string, startTime: number, success: boolean, details?: any): void {
  // ๐Ÿ›ก๏ธ CRITICAL: Prevent infinite recursion - don't record metrics for performance-metrics operations
  if (details?.storeName === 'performance-metrics') {
    return; // Exit early, don't track metrics for metrics operations
  }

  const metric: PerformanceMetric = {
    operation,
    timestamp: new Date(),
    duration: performance.now() - startTime,
    success,
    details
  };

  // Store in performance metrics (async, don't block, with recursion protection)
  this.upsert('performance-metrics', { ...metric, id: `metric_${Date.now()}_${Math.random().toString(36).substr(2, 9)}` })
    .subscribe({
      error: (error) => console.warn('Failed to record performance metric:', error)
    });
}

Fix Logic

  1. Guard Check: Before recording metrics, check if the operation is on 'performance-metrics' store
  2. Early Return: If yes, return immediately without recording (prevents recursion)
  3. Normal Flow: For all other operations, record metrics as usual

๐Ÿงช Testing Strategy

Immediate Verification

  1. Clear Browser Storage: DevTools โ†’ Application โ†’ Storage โ†’ Clear storage
  2. Navigate to Logic Builder: Go to /logic-builder
  3. Create Test Block: Click "Create Test Block"
  4. Monitor Console: Should see NO infinite performance metric messages

Expected Behavior

โœ… Success Indicators:

โŒ Failure Indicators:


๐Ÿ“Š Performance Impact Analysis

Before Fix (Broken)

After Fix (Working)


๐Ÿ›ก๏ธ Prevention Strategies

Code Review Guidelines

  1. Recursive Operation Awareness: Always check if operations can trigger themselves
  2. Performance Tracking: Be cautious when tracking operations that store data
  3. Guard Clauses: Implement recursion prevention for performance monitoring
  4. Testing: Test performance features under real usage scenarios

NGXS Best Practices

Based on NGXS vs NgRx comparison, NGXS provides more opinionated state management which helps prevent such issues through structured approaches to side effects and state updates.

Key Principles:

Database Operation Patterns

// โœ… GOOD: Conditional performance tracking
private recordPerformanceMetric(operation: string, startTime: number, success: boolean, details?: any): void {
  // Prevent recursion for self-referential operations
  if (details?.storeName === 'performance-metrics') {
    return;
  }
  // ... rest of implementation
}

// โŒ BAD: Unconditional tracking that can cause recursion
private recordPerformanceMetric(operation: string, startTime: number, success: boolean, details?: any): void {
  // No guard - can cause infinite recursion
  this.upsert('performance-metrics', metric);
}

๐ŸŽฏ Lessons Learned

Critical Insights

  1. Performance Monitoring Can Be Dangerous: Monitoring systems can become the bottleneck
  2. Recursion Prevention is Mandatory: Always guard against self-referential operations
  3. Early Detection is Key: Performance issues should be caught in development
  4. User Feedback is Invaluable: The user caught this critical issue immediately

Development Practices


๐ŸŽ‰ Resolution Status

โœ… FIXED - Infinite loop eliminated with recursion prevention guard
โœ… TESTED - Performance metrics work correctly without recursion
โœ… DOCUMENTED - Full analysis and prevention strategies documented
โœ… STABLE - App performance restored to normal operation

The application is now safe from recursive performance tracking loops! ๐Ÿš€


๐Ÿ”ฎ Future Enhancements

Monitoring Improvements

Error Resilience