All files / services/shared cache.js

81.25% Statements 65/80
50% Branches 9/18
75% Functions 6/8
81.25% Lines 65/80

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 67 68 69 70 71 72 73 74 75 76 77 78 79 80 812x 2x 1x 1x 1x 1x 1x 1x 1x 1x 1x 2x 2x 2x 6x 6x 1x 1x 1x 1x 1x 1x   1x 1x 6x 6x 2x 27x 27x     27x 27x 27x 2x 6x 6x 6x 6x 2x 3x 3x 3x 3x 3x 3x       3x 2x 3x 3x 3x 3x   3x 3x 3x 3x 3x       3x 2x           2x 2x 2x 2x 2x 2x 2x 2x  
const crypto = require('crypto');
 
function getRedisUrl() {
  if (process.env.REDIS_URL) return process.env.REDIS_URL;
  const host = process.env.REDIS_HOST || 'redis';
  const port = process.env.REDIS_PORT || 6379;
  const password = process.env.REDIS_PASSWORD
    ? `:${encodeURIComponent(process.env.REDIS_PASSWORD)}@`
    : '';
  return `redis://${password}${host}:${port}`;
}
 
let redisClient = null;
 
function getRedis() {
  if (!redisClient) {
    const Redis = require('ioredis');
    redisClient = new Redis(getRedisUrl(), {
      retryStrategy: (times) => Math.min(times * 50, 2000),
      maxRetriesPerRequest: 3,
    });
    redisClient.on('error', (err) => {
      console.error('[Cache] Redis error:', err.message);
    });
  }
  return redisClient;
}
 
function computeHash(content) {
  if (content === null || content === undefined) {
    return crypto.createHash('sha256').update('').digest('hex');
  }
  const str = typeof content === 'string' ? content : JSON.stringify(content);
  return crypto.createHash('sha256').update(str).digest('hex');
}
 
function buildKey(level, ...parts) {
  const cleanParts = parts.filter(Boolean).map((p) => String(p));
  return `cache:${[level, ...cleanParts].join(':')}`;
}
 
async function getFromCache(key) {
  try {
    const redis = getRedis();
    const value = await redis.get(key);
    return value;
  } catch (err) {
    console.error(`[Cache] getFromCache error for key ${key}:`, err.message);
    return null;
  }
}
 
async function setToCache(key, value, ttlSeconds) {
  try {
    const redis = getRedis();
    if (ttlSeconds) {
      await redis.setex(key, ttlSeconds, value);
    } else {
      await redis.set(key, value);
    }
    return true;
  } catch (err) {
    console.error(`[Cache] setToCache error for key ${key}:`, err.message);
    return false;
  }
}
 
async function invalidateJobCache(jobId) {
  // Cache cleanup is done via MongoDB metadata.cacheKeys in the job cleanup endpoint
  console.log(`[Cache] invalidateJobCache called for job ${jobId} — cleanup handled by job-manager-service`);
  return 0;
}
 
module.exports = {
  computeHash,
  buildKey,
  getFromCache,
  setToCache,
  invalidateJobCache,
};