Saltar a contenido

Sistema de caché

pyvenezuela incluye un sistema de caché que evita peticiones repetidas a los servicios externos. Por defecto usa un caché en memoria (InMemoryCache), pero puedes implementar tu propio backend.

Caché por defecto

La función get_rates_by_bcv() usa automáticamente un caché en memoria compartido con un TTL de 8 horas:

from pyvenezuela import get_rates_by_bcv

# Primera llamada: hace la petición al BCV
rates = get_rates_by_bcv()

# Segunda llamada: retorna el valor cacheado (sin petición HTTP)
rates = get_rates_by_bcv()

Si el sitio del BCV no está disponible al intentar actualizar la caché, se retorna el último valor válido almacenado (comportamiento use_expired=True).


Implementar un caché personalizado

Para usar un backend diferente (Redis, Memcached, base de datos, etc.), extiende la clase abstracta Cache:

from typing import Any, Optional
from pyvenezuela.cache import Cache
from pyvenezuela.schemas.cache import CacheValueModel
import time


class RedisCache(Cache):
    def __init__(self, redis_client):
        self.redis = redis_client

    def get(self, key: str) -> Optional[CacheValueModel]:
        data = self.redis.get(key)
        if data is None:
            return None
        return CacheValueModel.model_validate_json(data)

    def set(self, key: str, value: Any, ttl_in_seconds: int) -> None:
        model = CacheValueModel(
            value=value,
            expires_at=time.time() + ttl_in_seconds,
        )
        self.redis.setex(key, ttl_in_seconds, model.model_dump_json())

Usar el caché personalizado con el decorador

El decorador cached puede usarse con cualquier implementación de Cache:

from pyvenezuela.cache import Cache
from pyvenezuela.decorators import cached
from pyvenezuela.clients import bcv

redis_cache = RedisCache(redis_client=my_redis)


@cached(
    cache=redis_cache,
    cached_key="bcv_rates",
    ttl_in_seconds=8 * 60 * 60,  # 8 horas
    use_expired=True,
)
def get_rates_con_redis():
    return bcv.get_rates_by_bcv.__wrapped__()

API de caché

Cache (clase abstracta)

from pyvenezuela.cache import Cache
from pyvenezuela.schemas.cache import CacheValueModel

class Cache:
    def get(self, key: str) -> Optional[CacheValueModel]: ...
    def set(self, key: str, value: Any, ttl_in_seconds: int) -> None: ...

InMemoryCache

Implementación en memoria incluida en la librería.

from pyvenezuela.cache import InMemoryCache

cache = InMemoryCache()
cache.set("mi_clave", {"dato": 42}, ttl_in_seconds=300)
valor = cache.get("mi_clave")

CacheValueModel

Modelo interno que almacena el valor y su tiempo de expiración.

from pyvenezuela.schemas.cache import CacheValueModel

model: CacheValueModel
model.value       # Any — el valor almacenado
model.expires_at  # float — timestamp Unix de expiración

Decorador cached

from pyvenezuela.decorators import cached
from pyvenezuela.cache import InMemoryCache

cache = InMemoryCache()


@cached(
    cache=cache,
    cached_key="clave_unica",
    ttl_in_seconds=3600,
    use_expired=False,  # Si True, retorna el valor expirado cuando falla la actualización
)
def mi_funcion():
    return datos_costosos()

Parámetros del decorador:

Parámetro Tipo Descripción
cache Cache Instancia del backend de caché
cached_key str Clave única para este valor en el caché
ttl_in_seconds int Tiempo de vida del caché en segundos
use_expired bool Si True, retorna el último valor aunque haya expirado cuando la función falla

Tip

Usa use_expired=True para funciones que consultan servicios externos poco confiables. Así el sistema degrada graciosamente en lugar de retornar None.