---
description: 
globs: 
alwaysApply: false
---
## REDI Duplicate Identifier Prevention in Univer CE

### **Problem Analysis**
- **Root Cause**: REDI dependency injection system retains global service identifiers in memory even after Univer instance disposal
- **Trigger**: Component remounting causes duplicate service registration attempts
- **Symptoms**: "Identifier [service-name] already exists" console errors

### **Core Prevention Patterns**

#### **1. Global Instance Management**
```typescript
// ✅ DO: Use singleton pattern with proper state tracking
const UniverseManager = {
  async createInstance(container: HTMLElement): Promise<any> {
    const state = getGlobalState();
    
    // Check existing instance with complete validation
    if (state.instance && state.univerAPI && 
        !state.isInitializing && !state.isDisposing) {
      return { univer: state.instance, univerAPI: state.univerAPI };
    }
    
    // Wait for ongoing operations
    if (state.isInitializing && state.initializationPromise) {
      return state.initializationPromise;
    }
  }
};

// ❌ DON'T: Create new instances without checking global state
const univer = createUniver({ /* config */ }); // Direct creation
```

#### **2. Component Mount Lifecycle**
```typescript
// ✅ DO: Smart initialization with state checks
useEffect(() => {
  const existingUniver = UniverseManager.getInstance();
  const state = getGlobalState();
  
  // Reuse existing instance if available and stable
  if (existingUniver && state.univerAPI && 
      !UniverseManager.isInitializing() && !UniverseManager.isDisposing()) {
    setIsInitialized(true);
    return;
  }
  
  // Wait for ongoing operations
  if (UniverseManager.isInitializing() || UniverseManager.isDisposing()) {
    const waitTimer = setInterval(() => {
      if (!UniverseManager.isInitializing() && !UniverseManager.isDisposing()) {
        clearInterval(waitTimer);
        // Check and initialize as needed
      }
    }, 100);
    return () => clearInterval(waitTimer);
  }
}, []); // Empty dependency array to prevent re-execution

// ❌ DON'T: Include dependencies that cause re-initialization
useEffect(() => {
  initializeUniver();
}, [initializeUniver]); // This causes re-execution on every render
```

#### **3. Complete Cleanup Strategy**
```typescript
// ✅ DO: Implement thorough REDI state cleanup
forceReset(): void {
  // Standard disposal
  if (state.instance) {
    state.instance.dispose();
  }
  
  // REDI global state cleanup attempt
  if (typeof window !== "undefined") {
    const globalKeys = Object.keys(window).filter(key => 
      key.includes('redi') || key.includes('REDI') || 
      key.includes('univerjs') || key.includes('univer')
    );
    
    globalKeys.forEach(key => {
      try {
        delete (window as any)[key];
      } catch (e) {
        console.warn(`Global key ${key} cleanup failed:`, e);
      }
    });
  }
  
  // Reset all state flags
  Object.assign(state, {
    instance: null,
    univerAPI: null,
    isInitializing: false,
    isDisposing: false,
    initializationPromise: null,
    lastContainerId: null,
  });
}
```

### **4. State Validation Patterns**
```typescript
// ✅ DO: Multi-level state validation
const isInstanceReady = (state: GlobalUniverState): boolean => {
  return !!(
    state.instance && 
    state.univerAPI && 
    !state.isInitializing && 
    !state.isDisposing &&
    state.lastContainerId
  );
};

// ❌ DON'T: Simple existence check
if (state.instance) { /* insufficient validation */ }
```

### **5. Debug Tools Integration**
```typescript
// ✅ DO: Provide comprehensive debugging tools
window.__UNIVER_DEBUG__ = {
  getGlobalUniver: () => UniverseManager.getInstance(),
  getGlobalState: () => getGlobalState(),
  forceReset: () => UniverseManager.forceReset(),
  completeCleanup: () => UniverseManager.completeCleanup(),
};
```

### **Error Resolution Steps**
1. **Immediate**: Call `window.__UNIVER_DEBUG__.completeCleanup()` in console
2. **Prevention**: Use empty dependency arrays in useEffect for initialization
3. **Validation**: Always check both `instance` and `univerAPI` existence
4. **Cleanup**: Implement thorough REDI global state cleanup in disposal methods

### **Common Anti-Patterns to Avoid**
- ❌ Re-initializing on every component render
- ❌ Not waiting for ongoing initialization/disposal operations
- ❌ Incomplete state validation before reuse
- ❌ Missing REDI global state cleanup
- ❌ Using complex dependency arrays in initialization useEffect

### **Best Practices**
- ✅ Implement singleton pattern with proper state management
- ✅ Use polling-based waiting for state transitions
- ✅ Provide debug tools for runtime state inspection
- ✅ Separate initialization concerns from component lifecycle
- ✅ Implement both standard and emergency cleanup methods
