WhatsApp-Logger-Self-Hosted-

A privacy-focused, self-hosted...
Log | Files | Refs | Activity | README | LICENSE

root / src / cache.js

cache.js (3691B)


      1 const { db } = require('./firebase');
      2 const { EXCLUDED_JIDS } = require('./config');
      3 const { clients } = require('./sseManager');
      4 
      5 // --- IN-MEMORY CACHE ---
      6 let chatsCache = new Map();      // chatId -> chat data
      7 let messagesCache = new Map();   // chatId -> Map(msgId -> message data)
      8 let cacheReady = false;
      9 let consecutiveCacheFailures = 0;
     10 
     11 async function warmCache() {
     12     try {
     13         console.log("System: Warming cache from Firestore...");
     14 
     15         // 1. Fetch Chats
     16         const chatsSnap = await db.collection('Chats').get();
     17         chatsSnap.forEach(doc => {
     18             if (!EXCLUDED_JIDS.has(doc.id)) {
     19                 chatsCache.set(doc.id, { id: doc.id, ...doc.data() });
     20             }
     21         });
     22 
     23         // 2. Fetch all Messages via CollectionGroup
     24         const msgsSnap = await db.collectionGroup('Messages').get();
     25         msgsSnap.forEach(doc => {
     26             const chatId = doc.ref.parent.parent.id;
     27             if (!messagesCache.has(chatId)) messagesCache.set(chatId, new Map());
     28             messagesCache.get(chatId).set(doc.id, doc.data());
     29         });
     30 
     31         cacheReady = true;
     32         consecutiveCacheFailures = 0;
     33         console.log(`System: Cache warm. ${chatsCache.size} chats, ${msgsSnap.size} messages.`);
     34 
     35         // 3. Start Permanent Listeners
     36         startPermanentListeners();
     37 
     38     } catch (err) {
     39         consecutiveCacheFailures++;
     40         const backoff = Math.min(5000 * Math.pow(2, consecutiveCacheFailures), 300000); // Max 5 min
     41         console.error(`System: Cache warm failed (attempt ${consecutiveCacheFailures}). Retrying in ${backoff / 1000}s.`, err.message);
     42         setTimeout(warmCache, backoff);
     43     }
     44 }
     45 
     46 function startPermanentListeners() {
     47     // Shared Permanent Listener for Chats
     48     db.collection('Chats').onSnapshot(snapshot => {
     49         const changes = [];
     50         snapshot.docChanges().forEach(change => {
     51             if (EXCLUDED_JIDS.has(change.doc.id)) return;
     52             const data = { id: change.doc.id, ...change.doc.data() };
     53             chatsCache.set(change.doc.id, data);
     54             changes.push({ type: change.type, doc: data });
     55         });
     56         if (changes.length > 0) {
     57             const payload = `event: update\ndata: ${JSON.stringify(changes)}\n\n`;
     58             clients.chats.forEach(res => { try { res.write(payload); } catch (e) {} });
     59         }
     60     });
     61 
     62     // Shared Permanent Listener for Messages
     63     db.collectionGroup('Messages').onSnapshot(snapshot => {
     64         snapshot.docChanges().forEach(change => {
     65             const chatId = change.doc.ref.parent.parent.id;
     66             if (!messagesCache.has(chatId)) messagesCache.set(chatId, new Map());
     67 
     68             const data = change.doc.data();
     69             messagesCache.get(chatId).set(change.doc.id, data);
     70 
     71             const chatClients = clients.messages.get(chatId);
     72             if (chatClients) {
     73                 const payload = `event: update\ndata: ${JSON.stringify([{ type: change.type, doc: data }])}\n\n`;
     74                 chatClients.forEach(res => { try { res.write(payload); } catch (e) {} });
     75             }
     76 
     77             // Broadcast to global sync clients too, stamped with chatId since
     78             // the raw Firestore doc doesn't carry it (it's derived from the doc path).
     79             if (clients.sync.size > 0) {
     80                 const syncData = { ...data, chatId };
     81                 const syncPayload = `event: update\ndata: ${JSON.stringify([{ type: change.type, doc: syncData }])}\n\n`;
     82                 clients.sync.forEach(res => { try { res.write(syncPayload); } catch (e) {} });
     83             }
     84         });
     85     });
     86 }
     87 
     88 module.exports = {
     89     chatsCache,
     90     messagesCache,
     91     warmCache,
     92     isCacheReady: () => cacheReady
     93 };
© notamitgamer • Site Built: 2026-09-05 01:53:16 UTC • git-mirror commit: c170d72 [view raw info]
Originally created with stagit • modified by notamitgamer
Forked from github.com/notamitgamer/git-mirror