diff --git a/metadata_relay/README.md b/metadata_relay/README.md index 26ad559..9c5173d 100644 --- a/metadata_relay/README.md +++ b/metadata_relay/README.md @@ -1,7 +1,7 @@ # MetadataRelay -This is a service that provides metadata for movies and TV shows. It caches the metadata to not overload the TMDB and -TVDB APIs. This service is used by MediaManager to fetch metadata for movies and TV shows. I (the developer) run a +This is a service that provides metadata for movies and TV shows. It is advisable to use a load balancer/CDN like +Cloudflare to cache requests as to not overload the TMDB/TVDB api. I (the developer) run a public instance of this service at https://metadata-relay.dorninger.co, but you can also run your own instance. @@ -9,19 +9,12 @@ own instance. ````yaml services: - valkey: - image: valkey/valkey:latest - restart: always - container_name: valkey - expose: - - 6379 metadata_relay: image: ghcr.io/maxdorninger/mediamanager/metadata_relay:latest restart: always environment: - TMDB_API_KEY= # you need not provide a TMDB API key, if you only want to use TVDB metadata, or the other way around - TVDB_API_KEY= - - VALKEY_HOST=valkey container_name: metadata_relay ports: - 8000:8000 diff --git a/metadata_relay/app/cache.py b/metadata_relay/app/cache.py deleted file mode 100644 index 2fbce3e..0000000 --- a/metadata_relay/app/cache.py +++ /dev/null @@ -1,65 +0,0 @@ -import json -import hashlib -import logging -from typing import Any, Optional -import valkey.asyncio as valkey -import os -from functools import wraps - -log = logging.getLogger(__name__) - -redis_client = valkey.Redis( - host=os.getenv("VALKEY_HOST", "localhost"), - port=int(os.getenv("VALKEY_PORT", 6379)), - db=int(os.getenv("VALKEY_DB", 0)), - decode_responses=True, -) - - -def generate_cache_key(prefix: str, *args, **kwargs) -> str: - key_data = f"{prefix}:{args}:{sorted(kwargs.items())}" - return hashlib.md5(key_data.encode()).hexdigest() - - -async def get_cached_response(cache_key: str) -> Optional[Any]: - try: - cached_data = await redis_client.get(cache_key) - if cached_data: - return json.loads(cached_data) - return None - except Exception as e: - log.error(f"Error getting cached response: {e}") - return None - - -async def set_cached_response(cache_key: str, data: Any, ttl: int = 3600) -> bool: - try: - await redis_client.setex(cache_key, ttl, json.dumps(data, default=str)) - return True - except Exception as e: - log.error(f"Error setting cached response: {e}") - return False - - -def cache_response(prefix: str, ttl: int = 3600): - def decorator(func): - @wraps(func) - async def wrapper(*args, **kwargs): - cache_key = generate_cache_key(prefix, *args, **kwargs) - - cached_response = await get_cached_response(cache_key) - if cached_response is not None: - log.info(f"Cache hit for key: {cache_key}") - return cached_response - - log.info(f"Cache miss for key: {cache_key}") - - response = await func(*args, **kwargs) - - await set_cached_response(cache_key, response, ttl) - - return response - - return wrapper - - return decorator diff --git a/metadata_relay/app/tmdb.py b/metadata_relay/app/tmdb.py index de9c2b4..d2b3afc 100644 --- a/metadata_relay/app/tmdb.py +++ b/metadata_relay/app/tmdb.py @@ -4,7 +4,6 @@ import os import tmdbsimple from tmdbsimple import TV, TV_Seasons, Movies, Trending, Search from fastapi import APIRouter -from .cache import cache_response log = logging.getLogger(__name__) @@ -17,36 +16,29 @@ else: tmdbsimple.API_KEY = tmdb_api_key @router.get("/tv/trending") - @cache_response("tmdb_tv_trending", ttl=7200) async def get_tmdb_trending_tv(): return Trending(media_type="tv").info() @router.get("/tv/search") - @cache_response("tmdb_tv_search", ttl=14400) async def search_tmdb_tv(query: str, page: int = 1): return Search().tv(page=page, query=query, include_adult=True) @router.get("/tv/shows/{show_id}") - @cache_response("tmdb_tv_show", ttl=28800) async def get_tmdb_show(show_id: int): return TV(show_id).info() @router.get("/tv/shows/{show_id}/{season_number}") - @cache_response("tmdb_tv_season", ttl=28800) async def get_tmdb_season(season_number: int, show_id: int): return TV_Seasons(season_number=season_number, tv_id=show_id).info() @router.get("/movies/trending") - @cache_response("tmdb_movies_trending", ttl=7200) async def get_tmdb_trending_movies(): return Trending(media_type="movie").info() @router.get("/movies/search") - @cache_response("tmdb_movies_search", ttl=14400) async def search_tmdb_movies(query: str, page: int = 1): return Search().movie(page=page, query=query, include_adult=True) @router.get("/movies/{movie_id}") - @cache_response("tmdb_movie", ttl=28800) async def get_tmdb_movie(movie_id: int): return Movies(movie_id).info() diff --git a/metadata_relay/app/tvdb.py b/metadata_relay/app/tvdb.py index a3532ca..0014786 100644 --- a/metadata_relay/app/tvdb.py +++ b/metadata_relay/app/tvdb.py @@ -3,7 +3,6 @@ import os import tvdb_v4_official import logging from fastapi import APIRouter -from .cache import cache_response log = logging.getLogger(__name__) @@ -17,36 +16,29 @@ else: tvdb_client = tvdb_v4_official.TVDB(tvdb_api_key) @router.get("/tv/trending") - @cache_response("tvdb_tv_trending", ttl=7200) async def get_tvdb_trending_tv(): return tvdb_client.get_all_series() @router.get("/tv/search") - @cache_response("tvdb_tv_search", ttl=14400) async def search_tvdb_tv(query: str): return tvdb_client.search(query) @router.get("/tv/shows/{show_id}") - @cache_response("tvdb_tv_show", ttl=28800) async def get_tvdb_show(show_id: int): return tvdb_client.get_series_extended(show_id) @router.get("/tv/seasons/{season_id}") - @cache_response("tvdb_tv_season", ttl=28800) async def get_tvdb_season(season_id: int): return tvdb_client.get_season_extended(season_id) @router.get("/movies/trending") - @cache_response("tvdb_movies_trending", ttl=7200) async def get_tvdb_trending_movies(): return tvdb_client.get_all_movies() @router.get("/movies/search") - @cache_response("tvdb_movies_search", ttl=14400) async def search_tvdb_movies(query: str): return tvdb_client.search(query) @router.get("/movies/{movie_id}") - @cache_response("tvdb_movie", ttl=28800) async def get_tvdb_movie(movie_id: int): return tvdb_client.get_movie_extended(movie_id)