File size: 3,627 Bytes
f577535
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import time
from functools import wraps
from typing import Dict, Any, Callable

_cache: Dict[str, Any] = {}

CACHE_DURATION = 900  # 15 minutes - default
LOGIN_CACHE_DURATION = 3600  # 1 hour - user login sessions and auth data
USER_DATA_CACHE_DURATION = 1800  # 30 minutes - user profile data
WATCHLIST_STATS_CACHE_DURATION = 600  # 10 minutes - watchlist statistics


def cache_result(duration: int = CACHE_DURATION) -> Callable:
    """

    Decorator to cache function results with configurable duration.

    

    Args:

        duration: Cache duration in seconds (default: 15 minutes)

    

    Returns:

        Decorated function with caching capability

    """
    def decorator(func: Callable) -> Callable:
        @wraps(func)
        def wrapper(*args, **kwargs):
            cache_key = f"{func.__module__}.{func.__name__}:{str(args)}:{str(sorted(kwargs.items()))}"
            
            # Check if cached result exists and is still valid
            if cache_key in _cache:
                cached_data, timestamp = _cache[cache_key]
                if time.time() - timestamp < duration:
                    return cached_data
            
            # Execute function and cache result
            result = func(*args, **kwargs)
            _cache[cache_key] = (result, time.time())
            return result
        return wrapper
    return decorator


def cache_user_data(duration: int = USER_DATA_CACHE_DURATION) -> Callable:
    """Cache user profile data with longer TTL."""
    return cache_result(duration)


def cache_login_data(duration: int = LOGIN_CACHE_DURATION) -> Callable:
    """Cache login session data with even longer TTL."""
    return cache_result(duration)


def cache_watchlist_stats(duration: int = WATCHLIST_STATS_CACHE_DURATION) -> Callable:
    """Cache watchlist statistics with moderate TTL."""
    return cache_result(duration)


def clear_user_cache(user_id: int) -> None:
    """

    Clear all cache entries related to a specific user_id.

    

    Args:

        user_id: The user ID whose cache entries should be cleared

    """
    global _cache
    user_id_str = str(user_id)
    keys_to_remove = [key for key in _cache if user_id_str in key]
    for key in keys_to_remove:
        del _cache[key]


def clear_old_cache(max_age: int = 1800) -> int:
    """

    Clear cache entries older than the specified age.

    

    Args:

        max_age: Maximum age in seconds (default: 30 minutes)

    

    Returns:

        Number of cache entries cleared

    """
    global _cache
    current_time = time.time()
    keys_to_remove = []
    
    for key, (data, timestamp) in _cache.items():
        if current_time - timestamp > max_age:
            keys_to_remove.append(key)
    
    for key in keys_to_remove:
        del _cache[key]
    
    return len(keys_to_remove)


def get_cache_stats() -> Dict[str, Any]:
    """

    Get statistics about the current cache state.

    

    Returns:

        Dictionary containing cache statistics

    """
    current_time = time.time()
    total_entries = len(_cache)
    
    if total_entries == 0:
        return {
            "total_entries": 0,
            "oldest_entry_age": 0,
            "newest_entry_age": 0,
            "average_age": 0
        }
    
    ages = [current_time - timestamp for _, timestamp in _cache.values()]
    
    return {
        "total_entries": total_entries,
        "oldest_entry_age": max(ages),
        "newest_entry_age": min(ages),
        "average_age": sum(ages) / len(ages)
    }