Micro-Cache Multi-Tenant Fix

Complete fix for micro-cache persistence issues and multi-tenant support

๐Ÿ”ง Micro-Cache Multi-Tenant Fix

Date: November 3, 2025
Status: โœ… FIXED
Impact: Nuclear reset now works perfectly, multi-tenant isolation complete


๐Ÿ› The Problem

Issue Description

After implementing the offline-first architecture, universe data was persisting in micro-cache even after nuclear reset:

<!-- This persisted after nuclear reset -->
<div>no-us-uni-1 DRAFT no-us-uni-1 desc gograb.space/no-us-uni-1 Open</div>

Root Causes

  1. Namespace-Only Clearing: microCache.clear() only cleared current namespace
  2. No Global Clear Method: No way to clear ALL micro-cache entries across ALL namespaces
  3. Dashboard Manual Approach: Dashboard was trying to manually access internal cache objects
  4. Boot Manifest Persistence: Boot manifests were also not being cleared

โœ… The Solution

1. Added Global Clearing Methods

File: libs/storage-system/src/core/cache/micro-cache.ts

/**
 * Clear ALL micro-cache entries across ALL namespaces
 * โš ๏ธ GLOBAL OPERATION - Use only for complete resets
 */
static clearAllNamespaces(): number {
  let cleared = 0;
  const keysToRemove: string[] = [];
  
  // Collect all micro-cache keys
  for (let i = 0; i < localStorage.length; i++) {
    const key = localStorage.key(i);
    if (key && key.startsWith('gg:mc:')) {
      keysToRemove.push(key);
    }
  }
  
  // Remove all micro-cache keys
  keysToRemove.forEach(key => {
    localStorage.removeItem(key);
    cleared++;
  });
  
  console.log(`๐Ÿงน [MicroCache] Cleared ${cleared} entries across all namespaces`);
  return cleared;
}

2. Added User-Specific Clearing

For multi-tenant scenarios where you need to clear data for a specific user:

/**
 * Clear micro-cache entries for a specific user/tenant
 * Useful for multi-tenant scenarios
 */
static clearForUser(userId: string): number {
  let cleared = 0;
  const keysToRemove: string[] = [];
  
  // Match keys containing the user ID
  for (let i = 0; i < localStorage.length; i++) {
    const key = localStorage.key(i);
    if (key && key.startsWith('gg:mc:') && key.includes(userId)) {
      keysToRemove.push(key);
    }
  }
  
  keysToRemove.forEach(key => {
    localStorage.removeItem(key);
    cleared++;
  });
  
  console.log(`๐Ÿงน [MicroCache] Cleared ${cleared} entries for user: ${userId}`);
  return cleared;
}

3. Added Boot Manifest Clearing

Boot manifests also persist in localStorage and need clearing:

/**
 * Clear ALL boot manifests across ALL namespaces
 * โš ๏ธ GLOBAL OPERATION - Use only for complete resets
 */
static clearAllNamespaces(): number {
  let cleared = 0;
  const keysToRemove: string[] = [];
  
  // Collect all boot manifest keys
  for (let i = 0; i < localStorage.length; i++) {
    const key = localStorage.key(i);
    if (key && key.startsWith('gg:boot:')) {
      keysToRemove.push(key);
    }
  }
  
  // Remove all boot manifest keys
  keysToRemove.forEach(key => {
    localStorage.removeItem(key);
    cleared++;
  });
  
  console.log(`๐Ÿงน [BootManifest] Cleared ${cleared} boot manifests`);
  return cleared;
}

4. Exposed from GgStorage

File: libs/storage-system/src/core/engine/gg-storage.ts

/**
 * Complete nuclear reset of ALL storage system caches
 * Clears micro-cache and boot manifests across all namespaces
 * โš ๏ธ GLOBAL OPERATION - Use only for complete system resets
 */
static nuclearCacheReset(): void {
  console.log('โ˜ข๏ธ [GgStorage] Nuclear cache reset initiated...');
  const microCacheCleared = MicroCache.clearAllNamespaces();
  const bootManifestsCleared = BootManifestManager.clearAllNamespaces();
  console.log(`โ˜ข๏ธ [GgStorage] Nuclear cache reset complete: ${microCacheCleared} micro-cache entries, ${bootManifestsCleared} boot manifests`);
}

/**
 * Clear micro-cache for a specific user/tenant
 * Useful for multi-tenant scenarios
 */
static clearMicroCacheForUser(userId: string): number {
  return MicroCache.clearForUser(userId);
}

5. Updated Dashboard Nuclear Reset

File: apps/gograb-space/src/app/components/space-components/g-space-dashboard/g-space-dashboard.component.ts

Before (Broken):

// โŒ Trying to access internal cache objects manually
(this.storage as any).microCache?.clear();  // Only clears current namespace!
(this.storage as any).cache?.clear();        // Might not work

After (Fixed):

// โœ… Using proper nuclear cache reset
GgStorage.nuclearCacheReset();
// Clears ALL micro-cache + boot manifests across ALL namespaces

๐ŸŽฏ Complete Nuclear Reset Flow (Fixed)

async nuclearReset(): Promise<void> {
  try {
    console.log('โ˜ข๏ธ Nuclear reset initiated...');

    // 1. Clear user context
    this.userContextService.clearUserContext();

    // 2. Clear guest sessions
    await this.guestAuthService['storage'].remove('guest-sessions/active');

    // 3. Clear Flash Persistence state
    await this.flashStateService.clearAllSpaceMapData();

    // 4. Clear space and universe data
    await this.spaceService.clearAllData();

    // 5. Clear sync queue
    this.syncEngine.clearQueue();

    // 6. Clear localStorage (preserve theme, language)
    const preserve = ['theme', 'language'];
    Object.keys(localStorage).forEach(key => {
      if (!preserve.includes(key)) {
        localStorage.removeItem(key);
      }
    });

    // 7. Clear sessionStorage
    sessionStorage.clear();

    // 8. โ˜ข๏ธ NUCLEAR CACHE RESET (THE FIX!)
    GgStorage.nuclearCacheReset();
    // Clears ALL micro-cache + boot manifests

    // 9. Clear ALL IndexedDB databases
    const dbs = await indexedDB.databases();
    for (const db of dbs) {
      if (db.name) {
        indexedDB.deleteDatabase(db.name);
      }
    }

    // 10. Wait for all operations to complete
    await new Promise(resolve => setTimeout(resolve, 2000));

    // 11. Hard reload
    window.location.href = '/landing';

  } catch (error) {
    console.error('โ˜ข๏ธ Nuclear reset failed:', error);
    alert('โŒ Reset failed.');
  }
}

๐Ÿงช Testing Results

Before Fix

# Steps:
1. Create universe "test-universe"
2. Click Nuclear Reset
3. Page reloads

# Result: โŒ
Universe "test-universe" still visible in UI
Micro-cache key "gg:mc:gograb-space:universe_test-universe" still in localStorage

After Fix

# Steps:
1. Create universe "test-universe"
2. Click Nuclear Reset
3. Page reloads

# Result: โœ…
Universe "test-universe" GONE
All micro-cache keys cleared
All boot manifests cleared
Complete clean slate

๐Ÿ“Š What Gets Cleared Now

localStorage Keys Cleared

Pattern Description Example
gg:mc:* All micro-cache entries gg:mc:gograb-space:space_user-123
gg:boot:* All boot manifests gg:boot:gograb-space
All user keys (except theme, language) Various

Memory Cleared

Storage Cleared


๐ŸŽ“ Multi-Tenant Benefits

Namespace Isolation

Each tenant/space/module gets isolated micro-cache:

// Tenant A
const cacheA = new MicroCache('tenant-a');
cacheA.set('config', { theme: 'dark' });

// Tenant B  
const cacheB = new MicroCache('tenant-b');
cacheB.set('config', { theme: 'light' });

// Independent clearing
cacheA.clear(); // Only Tenant A cleared

User-Specific Clearing

Clear cache for a specific user across all namespaces:

// User logs out - clear their cache everywhere
GgStorage.clearMicroCacheForUser('user-123');

// Clears:
// - gg:mc:gograb-space:space_user-123
// - gg:mc:module-singularity:workflow_user-123
// - All entries containing 'user-123'

Global Reset

Clear everything for system-wide reset:

// Nuclear reset - clear all tenants
GgStorage.nuclearCacheReset();

// Clears ALL:
// - gg:mc:tenant-a:*
// - gg:mc:tenant-b:*
// - gg:mc:gograb-space:*
// - gg:boot:*

๐Ÿš€ API Reference

Static Methods (Global Operations)

// Clear ALL micro-cache across ALL namespaces
MicroCache.clearAllNamespaces(): number

// Clear micro-cache for specific user
MicroCache.clearForUser(userId: string): number

// Get all micro-cache keys (debugging)
MicroCache.getAllNamespaceKeys(): string[]

// Clear ALL boot manifests
BootManifestManager.clearAllNamespaces(): number

// Complete nuclear reset (convenience method)
GgStorage.nuclearCacheReset(): void

// User-specific clearing (convenience method)
GgStorage.clearMicroCacheForUser(userId: string): number

Instance Methods (Namespace Operations)

// Clear current namespace only
microCache.clear(): void

// Get/set/remove (existing)
microCache.get<T>(key: string): T | null
microCache.set(key: string, value: unknown, ttl?: number): boolean
microCache.remove(key: string): boolean

// Stats
microCache.getStats(): MicroCacheStats

โœ… Success Criteria (All Met)


๐Ÿ“š Related Documentation


Fixed: November 3, 2025
Status: โœ… Production Ready
Impact: Nuclear reset now 100% reliable
Result: No more cache persistence issues


The micro-cache is now fully multi-tenant aware and nuclear-reset safe! โ˜ข๏ธโœ