refactor: unify stream caching settings and update related policies

- Consolidated public and private stream TTL settings into a single HTTP_CACHE_STREAMS_TTL.
- Updated cache policies to reflect the new unified stream caching approach.
- Adjusted logging to display the new stream TTL setting.
- Revised documentation to clarify caching behavior for all stream results.
This commit is contained in:
g0ldyy
2026-01-11 14:57:19 +01:00
parent 6b9dbcdab3
commit 0fb3063107
6 changed files with 17 additions and 56 deletions
+4 -9
View File
@@ -277,15 +277,10 @@ STREMTHRU_URL=https://stremthru.13377001.xyz # needed to use debrid services
HTTP_CACHE_ENABLED=False # Master switch for HTTP cache headers HTTP_CACHE_ENABLED=False # Master switch for HTTP cache headers
# PUBLIC streams TTL (for /stream/movie/tt1234567.json without user config) # STREAMS streams TTL (for /stream/movie/tt1234567.json)
# These can be cached at edge and shared between all users. # These results are cached at edge and shared between all users.
# Higher = less origin traffic, lower = fresher results # Higher = less traffic to origin, Lower = faster updates for new content
HTTP_CACHE_PUBLIC_STREAMS_TTL=300 # 5 minutes (recommended: 120-600) HTTP_CACHE_STREAMS_TTL=300 # 5 minutes
# PRIVATE streams TTL (for /{config}/stream/... with user config)
# Only cached in user's browser (private cache).
# These contain user-specific debrid availability info.
HTTP_CACHE_PRIVATE_STREAMS_TTL=60 # 1 minute (recommended: 30-120)
# Stale-While-Revalidate: serve stale content while fetching fresh in background # Stale-While-Revalidate: serve stale content while fetching fresh in background
# Improves perceived performance - users get instant response with cached data # Improves perceived performance - users get instant response with cached data
+7 -29
View File
@@ -5,7 +5,7 @@ from urllib.parse import quote
import aiohttp import aiohttp
from fastapi import APIRouter, BackgroundTasks, Request from fastapi import APIRouter, BackgroundTasks, Request
from comet.core.config_validation import config_check, is_default_config from comet.core.config_validation import config_check
from comet.core.logger import logger from comet.core.logger import logger
from comet.core.models import database, settings, trackers from comet.core.models import database, settings, trackers
from comet.debrid.exceptions import DebridAuthError from comet.debrid.exceptions import DebridAuthError
@@ -30,7 +30,6 @@ streams = APIRouter()
def _build_stream_response( def _build_stream_response(
request: Request, request: Request,
content: dict, content: dict,
is_public: bool = False,
is_empty: bool = False, is_empty: bool = False,
vary_headers: list = None, vary_headers: list = None,
): ):
@@ -45,12 +44,9 @@ def _build_stream_response(
if is_empty: if is_empty:
cache_policy = CachePolicies.empty_results() cache_policy = CachePolicies.empty_results()
vary = ["Accept", "Accept-Encoding"] vary = ["Accept", "Accept-Encoding"]
elif is_public:
cache_policy = CachePolicies.public_torrents()
vary = ["Accept", "Accept-Encoding"]
else: else:
cache_policy = CachePolicies.private_streams() cache_policy = CachePolicies.streams()
vary = ["Accept", "Accept-Encoding", "Authorization"] vary = ["Accept", "Accept-Encoding"]
if vary_headers: if vary_headers:
vary.extend(vary_headers) vary.extend(vary_headers)
@@ -177,17 +173,11 @@ async def stream(
b64config: str = None, b64config: str = None,
chilllink: bool = False, chilllink: bool = False,
): ):
is_public_request = b64config is None
if media_type not in ["movie", "series"]: if media_type not in ["movie", "series"]:
return _build_stream_response( return _build_stream_response(request, {"streams": []}, is_empty=True)
request, {"streams": []}, is_public=True, is_empty=True
)
if "tmdb:" in media_id: if "tmdb:" in media_id:
return _build_stream_response( return _build_stream_response(request, {"streams": []}, is_empty=True)
request, {"streams": []}, is_public=True, is_empty=True
)
media_id = media_id.replace("imdb_id:", "") media_id = media_id.replace("imdb_id:", "")
@@ -202,12 +192,7 @@ async def stream(
} }
] ]
} }
return _build_stream_response( return _build_stream_response(request, error_response, is_empty=True)
request, error_response, is_public=True, is_empty=True
)
if is_default_config(config):
is_public_request = True
is_torrent = config["debridService"] == "torrent" is_torrent = config["debridService"] == "torrent"
if settings.DISABLE_TORRENT_STREAMS and is_torrent: if settings.DISABLE_TORRENT_STREAMS and is_torrent:
@@ -218,9 +203,7 @@ async def stream(
if settings.TORRENT_DISABLED_STREAM_URL: if settings.TORRENT_DISABLED_STREAM_URL:
placeholder_stream["url"] = settings.TORRENT_DISABLED_STREAM_URL placeholder_stream["url"] = settings.TORRENT_DISABLED_STREAM_URL
return _build_stream_response( return _build_stream_response(request, {"streams": [placeholder_stream]})
request, {"streams": [placeholder_stream]}, is_public=is_public_request
)
connector = aiohttp.TCPConnector(limit=0) connector = aiohttp.TCPConnector(limit=0)
async with aiohttp.ClientSession(connector=connector) as session: async with aiohttp.ClientSession(connector=connector) as session:
@@ -247,7 +230,6 @@ async def stream(
} }
] ]
}, },
is_public=True,
is_empty=True, is_empty=True,
) )
@@ -356,7 +338,6 @@ async def stream(
} }
] ]
}, },
is_public=True,
is_empty=True, is_empty=True,
) )
@@ -475,7 +456,6 @@ async def stream(
} }
] ]
}, },
is_public=True,
is_empty=True, is_empty=True,
) )
@@ -558,7 +538,6 @@ async def stream(
} }
] ]
}, },
is_public=False,
is_empty=True, is_empty=True,
) )
@@ -675,6 +654,5 @@ async def stream(
return _build_stream_response( return _build_stream_response(
request, request,
{"streams": final_streams}, {"streams": final_streams},
is_public=is_public_request or not has_results,
is_empty=not has_results, is_empty=not has_results,
) )
+1 -1
View File
@@ -436,7 +436,7 @@ def log_startup_info(settings):
logger.log("COMET", f"Custom Header HTML: {bool(settings.CUSTOM_HEADER_HTML)}") logger.log("COMET", f"Custom Header HTML: {bool(settings.CUSTOM_HEADER_HTML)}")
http_cache_info = ( http_cache_info = (
f" - Public Streams TTL: {settings.HTTP_CACHE_PUBLIC_STREAMS_TTL}s - Private Streams TTL: {settings.HTTP_CACHE_PRIVATE_STREAMS_TTL}s - Manifest TTL: {settings.HTTP_CACHE_MANIFEST_TTL}s - Configure TTL: {settings.HTTP_CACHE_CONFIGURE_TTL}s - SWR: {settings.HTTP_CACHE_STALE_WHILE_REVALIDATE}s" f" - Streams TTL: {settings.HTTP_CACHE_STREAMS_TTL}s - Manifest TTL: {settings.HTTP_CACHE_MANIFEST_TTL}s - Configure TTL: {settings.HTTP_CACHE_CONFIGURE_TTL}s - SWR: {settings.HTTP_CACHE_STALE_WHILE_REVALIDATE}s"
if settings.HTTP_CACHE_ENABLED if settings.HTTP_CACHE_ENABLED
else "" else ""
) )
+1 -2
View File
@@ -138,8 +138,7 @@ class AppSettings(BaseSettings):
RATELIMIT_RETRY_BASE_DELAY: Optional[float] = 1.0 RATELIMIT_RETRY_BASE_DELAY: Optional[float] = 1.0
RTN_FILTER_DEBUG: Optional[bool] = False RTN_FILTER_DEBUG: Optional[bool] = False
HTTP_CACHE_ENABLED: Optional[bool] = False HTTP_CACHE_ENABLED: Optional[bool] = False
HTTP_CACHE_PUBLIC_STREAMS_TTL: Optional[int] = 300 HTTP_CACHE_STREAMS_TTL: Optional[int] = 300
HTTP_CACHE_PRIVATE_STREAMS_TTL: Optional[int] = 60
HTTP_CACHE_STALE_WHILE_REVALIDATE: Optional[int] = 60 HTTP_CACHE_STALE_WHILE_REVALIDATE: Optional[int] = 60
HTTP_CACHE_MANIFEST_TTL: Optional[int] = 86400 HTTP_CACHE_MANIFEST_TTL: Optional[int] = 86400
HTTP_CACHE_CONFIGURE_TTL: Optional[int] = 86400 HTTP_CACHE_CONFIGURE_TTL: Optional[int] = 86400
+3 -14
View File
@@ -154,13 +154,13 @@ def not_modified_response(etag: str):
class CachePolicies: class CachePolicies:
@staticmethod @staticmethod
def public_torrents(): def streams():
""" """
For public torrent lists (without user config). For all stream results.
Cache for a short time at CDN, revalidate often. Cache for a short time at CDN, revalidate often.
""" """
ttl = settings.HTTP_CACHE_PUBLIC_STREAMS_TTL ttl = settings.HTTP_CACHE_STREAMS_TTL
swr = settings.HTTP_CACHE_STALE_WHILE_REVALIDATE swr = settings.HTTP_CACHE_STALE_WHILE_REVALIDATE
return ( return (
@@ -172,17 +172,6 @@ class CachePolicies:
.stale_if_error(300) .stale_if_error(300)
) )
@staticmethod
def private_streams():
"""
For user-specific stream results (with b64config).
Private cache only, short TTL.
"""
ttl = settings.HTTP_CACHE_PRIVATE_STREAMS_TTL
return CacheControl().private().max_age(ttl).must_revalidate()
@staticmethod @staticmethod
def manifest(): def manifest():
""" """
+1 -1
View File
@@ -3,7 +3,7 @@
To optimize performance, configure Cloudflare to offload traffic from your server. We use **Cache Rules** to cache responses while respecting the application's cache headers. To optimize performance, configure Cloudflare to offload traffic from your server. We use **Cache Rules** to cache responses while respecting the application's cache headers.
## 1. Streams (Cache Rule) ## 1. Streams (Cache Rule)
Cache all stream results (public and private). Comet controls the TTL via headers. Cache all stream results. Comet controls the TTL via headers.
* **Rule Name**: Streams * **Rule Name**: Streams
* **Expression**: `(http.request.uri.path contains "/stream/")` * **Expression**: `(http.request.uri.path contains "/stream/")`