All files / src/cron closedRooms.js

100% Statements 37/37
100% Branches 10/10
100% Functions 5/5
100% Lines 31/31

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66              1x 1x     8x   8x   8x     7x 32x 32x     7x   5x 5x 25x   25x   25x 26x 25x 2x 502x 2x       24x   24x 24x 24x 1x 1x 1x       24x 24x   1x             5x     1x  
/**
 * Cron: Delete closed rooms older than 7 days.
 *
 * Queries up to 200 rooms with state=='CLOSED', filters by closedAt > 7 days ago,
 * then deletes up to 20 per run (room doc + subcollections: messages, seatRequests).
 */
 
const { db } = require('../utils/firebase');
const log = require('../utils/log');
 
async function closedRooms() {
  const sevenDaysAgo = Date.now() - 7 * 24 * 60 * 60 * 1000;
 
  const snapshot = await db.collection('rooms').where('state', '==', 'CLOSED').limit(200).get();
 
  if (snapshot.empty) return;
 
  // Only delete rooms closed more than 7 days ago — cap at 20 per run
  const old = snapshot.docs
    .map((d) => ({ id: d.id, ...d.data() }))
    .filter((r) => r.closedAt && r.closedAt < sevenDaysAgo)
    .slice(0, 20);
 
  if (old.length === 0) return;
 
  let deleted = 0;
  for (const room of old) {
    try {
      // Delete all messages (paginated to handle rooms with 500+ messages)
      const messagesRef = db.collection(`rooms/${room.id}/messages`);
      let msgSnap;
      do {
        msgSnap = await messagesRef.limit(500).get();
        if (msgSnap.empty) break;
        const batch = db.batch();
        msgSnap.docs.forEach((d) => batch.delete(d.ref));
        await batch.commit();
      } while (msgSnap.size === 500);
 
      // Delete all seat requests (paginated)
      const seatsRef = db.collection(`rooms/${room.id}/seatRequests`);
      let seatSnap;
      do {
        seatSnap = await seatsRef.limit(500).get();
        if (seatSnap.empty) break;
        const batch = db.batch();
        seatSnap.docs.forEach((d) => batch.delete(d.ref));
        await batch.commit();
      } while (seatSnap.size === 500);
 
      // Delete the room doc itself
      await db.doc(`rooms/${room.id}`).delete();
      deleted++;
    } catch (err) {
      log.error('cron', 'closedRooms: failed to delete room', {
        roomId: room.id,
        error: err.message,
      });
    }
  }
 
  log.info('cron', 'closedRooms: cleaned up old closed rooms', { deleted, total: old.length });
}
 
module.exports = closedRooms;