File size: 2,050 Bytes
0684e4d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
/**
 * Simple in-memory cache for MongoDB queries.
 * TTL-based, auto-evicts expired entries.
 * Reduces DB load for frequent reads (wallet checks, leaderboard, etc.)
 */
const User = require('../models/User');

const cache = new Map();
const DEFAULT_TTL = 15000; // 15 seconds
const LEADERBOARD_TTL = 30000; // 30 seconds

function getCacheKey(type, id) { return `${type}:${id}`; }

function setCache(key, data, ttl = DEFAULT_TTL) {
    cache.set(key, { data, expires: Date.now() + ttl });
}

function getCache(key) {
    const entry = cache.get(key);
    if (!entry) return null;
    if (Date.now() > entry.expires) { cache.delete(key); return null; }
    return entry.data;
}

function invalidate(userId) {
    // Clear all cache entries for this user
    for (const [key] of cache) {
        if (key.includes(userId)) cache.delete(key);
    }
}

// Periodic cleanup of expired entries (every 60s)
setInterval(() => {
    const now = Date.now();
    for (const [key, entry] of cache) {
        if (now > entry.expires) cache.delete(key);
    }
}, 60000);

/**
 * Get user with cache. Returns lean object.
 */
async function getUser(userId) {
    const key = getCacheKey('user', userId);
    const cached = getCache(key);
    if (cached) return cached;
    const user = await User.findOne({ userId }).lean().maxTimeMS(5000);
    if (user) setCache(key, user);
    return user;
}

/**
 * Get or create user.
 */
async function getOrCreateUser(userId, extra = {}) {
    let user = await getUser(userId);
    if (!user) {
        user = (await User.create({ userId, ...extra })).toObject();
        setCache(getCacheKey('user', userId), user);
    }
    return user;
}

/**
 * Update user and invalidate cache.
 */
async function saveUser(userId, updateFn) {
    let user = await User.findOne({ userId }) || await User.create({ userId });
    await updateFn(user);
    await user.save();
    invalidate(userId);
    return user;
}

module.exports = { getUser, getOrCreateUser, saveUser, invalidate, setCache, getCache, getCacheKey, LEADERBOARD_TTL };