Overview

MentraOS Cloud uses a Manager pattern to organize functionality within UserSessions. Each manager is responsible for a specific domain of functionality, encapsulating related state, logic, and operations. This pattern promotes separation of concerns, maintainability, and testability.

Architecture

Manager Characteristics

Common Patterns

All managers follow these patterns:
  1. Constructor Pattern
    constructor(userSession: UserSession) {
      this.userSession = userSession;
      this.logger = userSession.logger.child({ manager: 'ManagerName' });
      // Initialize manager-specific state
    }
    
  2. Disposal Pattern
    dispose(): void {
      // Clear intervals/timeouts
      // Release resources
      // Clear event listeners
      // Reset state
    }
    
  3. Session Reference
    • Each manager holds a reference to its parent UserSession
    • Allows access to other managers when needed
    • Provides context for operations

Manager Categories

1. Hardware Managers

Managers that interface with smart glasses hardware:

2. Processing Managers

Managers that process data streams:

3. Control Managers

Managers that coordinate system behavior:

Manager Interactions

Direct Communication

Managers can interact through the UserSession:
// In AudioManager
processAudioData(data: ArrayBuffer) {
  // Process audio...
  
  // Trigger transcription if needed
  if (this.userSession.transcriptionManager.isActive()) {
    this.userSession.transcriptionManager.processAudio(data);
  }
}

Event-Based Communication

Some managers use events for loose coupling:
// In TranscriptionManager
onTranscriptionComplete(text: string) {
  // Emit event that other managers can listen to
  this.emit('transcription', { text, timestamp: Date.now() });
}

Shared State

Managers access shared state through UserSession:
// Check if apps are running
if (this.userSession.runningApps.size > 0) {
  // Perform app-specific logic
}

Lifecycle Management

Initialization

Managers are created when UserSession is instantiated:
// In UserSession constructor
this.appManager = new AppManager(this);
this.audioManager = new AudioManager(this);
this.displayManager = new DisplayManager(this);
// ... other managers

Active Operation

During session lifetime:
  • Managers respond to incoming messages
  • Process data streams
  • Maintain internal state
  • Coordinate with other managers

Cleanup

When session ends, all managers are disposed:
// In UserSession.dispose()
if (this.appManager) this.appManager.dispose();
if (this.audioManager) this.audioManager.dispose();
// ... dispose all managers

Best Practices

1. Single Responsibility

Each manager should focus on one domain:
  • ✅ AudioManager handles only audio
  • ❌ AudioManager shouldn’t manage display

2. Proper Resource Management

class ExampleManager {
  private intervalId?: Timer;
  
  startProcessing() {
    this.intervalId = setInterval(() => {
      // Process...
    }, 1000);
  }
  
  dispose() {
    if (this.intervalId) {
      clearInterval(this.intervalId);
      this.intervalId = undefined;
    }
  }
}

3. Error Isolation

Errors in one manager shouldn’t crash others:
try {
  await this.performOperation();
} catch (error) {
  this.logger.error('Operation failed:', error);
  // Handle gracefully, don't propagate
}

4. Logging Context

Always use contextual logging:
this.logger = userSession.logger.child({ 
  manager: 'AudioManager',
  userId: userSession.userId 
});

Common Manager Methods

State Queries

isActive(): boolean
getStatus(): ManagerStatus
getCurrentState(): StateObject

Configuration

updateSettings(settings: ManagerSettings): void
setEnabled(enabled: boolean): void

Data Processing

processData(data: DataType): void
handleMessage(message: MessageType): void

Cleanup

dispose(): void
reset(): void
clearBuffers(): void

Threading Considerations

  • All managers run in the Bun runtime event loop
  • Long operations should be async or use workers
  • Avoid blocking operations
  • Use timers for periodic tasks

Testing Managers

Managers should be testable in isolation:
// Mock UserSession for testing
const mockSession = {
  userId: 'test-user',
  logger: mockLogger,
  websocket: mockWebSocket,
  // ... other required properties
};

const manager = new AudioManager(mockSession);
// Test manager behavior

Performance Guidelines

  1. Buffer Management: Clear old data regularly
  2. Event Throttling: Limit high-frequency events
  3. Resource Pooling: Reuse expensive resources
  4. Lazy Initialization: Create resources only when needed

Manager Documentation

Each manager has detailed documentation: