# Complete Cache Invalidation for All System Mappings ## Issue Company 29683395 (TK Plastics) was not showing Addigy (ARMM) devices even though: - 3 Addigy org mappings existed in the database - The API code was correct to fetch Addigy devices - The cache was returning stale data from before the mappings were added ## Root Cause The cache key only included RMM mapping count: ``` rmm-devices:29683395:active:mappings-2 ``` When Addigy or Auvik mappings were added, the cache key didn't change, so the system continued serving cached data with 0 Addigy/Auvik devices. ## Database Verification ### Company 29683395 Mappings: - **RMM Sites**: 2 mappings - TK Plastics (612f6b1f-9228-4e2a-8e63-f0ec5d0b6aaa) - TK Plastics - Kaercher (aba39a7b-d9b3-4eff-88e4-4d0182d478cb) - **Auvik Tenants**: 1 mapping - tkplastics (1228237269652810493) - **Addigy Orgs**: 3 mappings - TK Plastics (b194ffe7-c354-4cb0-a5e5-c99876729b4b) - TK - iPads (393f67b0-5449-41b4-a5f2-f72de849c5d5) - TK - Macs (36f89454-6dbf-4c03-8843-3dfc34b9534f) ## Solution Updated the cache key to include mapping counts for ALL three external systems: ### Before: ```typescript const cacheKey = `rmm-devices:${companyId}:${activeFilter}:mappings-${mappingCount}`; ``` ### After: ```typescript const cacheKey = `rmm-devices:${companyId}:${activeFilter}:rmm-${rmmMappingCount}:auvik-${auvikMappingCount}:addigy-${addigyMappingCount}`; ``` ### Implementation: ```typescript // Get mapping counts to include in cache key (so cache invalidates when mappings change) let rmmMappingCount = 0; let auvikMappingCount = 0; let addigyMappingCount = 0; if (companyId) { // RMM site mappings const rmmMappingsResult = await pool.query( 'SELECT COUNT(*) as count FROM rmm_site_mappings WHERE company_id = $1', [parseInt(companyId)] ); rmmMappingCount = parseInt(rmmMappingsResult.rows[0]?.count || '0'); // Auvik tenant mappings const auvikMappingsResult = await pool.query( 'SELECT COUNT(*) as count FROM auvik_tenant_mappings WHERE autotask_company_id = $1', [parseInt(companyId)] ); auvikMappingCount = parseInt(auvikMappingsResult.rows[0]?.count || '0'); // Addigy org mappings const addigyMappingsResult = await pool.query( 'SELECT COUNT(*) as count FROM addigy_org_mappings WHERE autotask_company_id = $1', [parseInt(companyId)] ); addigyMappingCount = parseInt(addigyMappingsResult.rows[0]?.count || '0'); } ``` ## Cache Key Examples ### For Company 29683395: - **Old key**: `rmm-devices:29683395:active:mappings-2` - **New key**: `rmm-devices:29683395:active:rmm-2:auvik-1:addigy-3` ### Cache Invalidation Scenarios: 1. **Add RMM site mapping**: `rmm-2` → `rmm-3` (cache invalidated) 2. **Add Auvik tenant mapping**: `auvik-1` → `auvik-2` (cache invalidated) 3. **Add Addigy org mapping**: `addigy-3` → `addigy-4` (cache invalidated) 4. **Remove any mapping**: Count decreases, cache invalidated ## Benefits 1. **Automatic Cache Invalidation**: Cache automatically expires when ANY system mapping changes 2. **No Manual Cache Clearing**: No need to manually clear cache or use skipCache parameter 3. **Accurate Data**: Users always see current device data after mapping changes 4. **System Consistency**: All three external systems (RMM, NMS, ARMM) are treated equally ## Files Modified - `/app/api/rmm-devices/route.ts` - Updated cache key generation logic ## Testing After deploying: 1. The cache key for company 29683395 will change from `rmm-devices:29683395:active:mappings-2` to `rmm-devices:29683395:active:rmm-2:auvik-1:addigy-3` 2. This will trigger a fresh API call 3. Addigy devices from all 3 mapped organizations will be fetched and displayed 4. Future mapping changes will automatically invalidate the cache ## Related Documentation - `/docs/fixes/rmm-cache-invalidation-fix.md` - Initial RMM cache fix - `/docs/fixes/all-systems-inventory-display.md` - All systems display implementation - `/docs/rmm-multi-site-integration.md` - RMM multi-site architecture