feat(adapters): TMDB 列表与筛选、豆瓣榜单 / 标签 / 筛选 / 搜索、bgm 浏览与趋势,豆瓣 / bgm 请求缓存端口
- TMDB:流行趋势(日 / 周)、电影 / 剧集榜单、discover 参数映射、分页搜索;列表类请求 TTL 6 小时 - 豆瓣 / bgm:列表与搜索请求经 MetaRequestCache 与限流,失败(403 / 风控页)不缓存 - contracts:发现页条目、分页、查询校验与筛选字典;storage.cacheTtl 追加 meta* 字段 - testkit:mock TMDB 加列表接口 Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
This commit is contained in:
1 parent
27514f4985
commit
e46eb0e3c3
13 files changed
+1344
-91
No files matched your search
@@ -101,8 +101,10 @@ export interface TmdbConfig {
|
||||
/**
|
||||
* 默认 max 1024、ttl 24h;空结果(搜索 0 条)用 emptyTtlMs,默认 30min(对照 MP EMPTY_RESULT_CACHE_TTL);
|
||||
* searchTtlMs:/search/、/find/ 请求的 TTL(缺省同 ttlMs),其余(详情 / 季)用 ttlMs。
|
||||
* listTtlMs:流行趋势 / 热门 / 正在上映等列表与 /discover/ 的 TTL(缺省 6 小时且不超过 ttlMs;列表会变,不能按详情缓存 30 天),
|
||||
* 这类请求的空结果 TTL 也不超过它。
|
||||
*/
|
||||
cache?: { max?: number; ttlMs?: number; searchTtlMs?: number; emptyTtlMs?: number };
|
||||
cache?: { max?: number; ttlMs?: number; searchTtlMs?: number; emptyTtlMs?: number; listTtlMs?: number };
|
||||
/**
|
||||
* 跨进程共享的请求缓存(服务端传 PG 缓存);给了就不再用进程内 LRU。
|
||||
* 语义对照 MP @cached(skip_none、业务失败不缓存、results 为空按 emptyTtlMs)。
|
||||
@@ -134,6 +136,11 @@ export function tmdbRequestKey(path: string, params: Record<string, string | und
|
||||
return `${path}?${requestQuery(params)}`;
|
||||
}
|
||||
|
||||
/** 列表类请求(发现页):流行趋势、按条件筛选、电影 / 剧集榜单 */
|
||||
export const isTmdbListPath = (path: string) =>
|
||||
/^\/(trending|discover)\//.test(path) ||
|
||||
/^\/(movie|tv)\/(popular|now_playing|upcoming|top_rated|on_the_air|airing_today)$/.test(path);
|
||||
|
||||
/** 空结果(搜索 0 条)用短 TTL(对照 MP EMPTY_RESULT_CACHE_TTL) */
|
||||
const isEmptyResult = (v: unknown) =>
|
||||
Array.isArray((v as Json | null)?.results) && ((v as Json).results as unknown[]).length === 0;
|
||||
@@ -176,9 +183,13 @@ export class TmdbClient {
|
||||
private async get<T>(path: string, params: Record<string, string | undefined>): Promise<T> {
|
||||
const qs = requestQuery(params);
|
||||
const key = `${path}?${qs}`;
|
||||
const emptyTtl = this.cfg.cache?.emptyTtlMs ?? 30 * 60_000;
|
||||
let emptyTtl = this.cfg.cache?.emptyTtlMs ?? 30 * 60_000;
|
||||
const baseTtl = this.cfg.cache?.ttlMs ?? 24 * 3600_000;
|
||||
const ttl = /^\/(search|find)\//.test(path) ? (this.cfg.cache?.searchTtlMs ?? baseTtl) : baseTtl;
|
||||
let ttl = /^\/(search|find)\//.test(path) ? (this.cfg.cache?.searchTtlMs ?? baseTtl) : baseTtl;
|
||||
if (isTmdbListPath(path)) {
|
||||
ttl = this.cfg.cache?.listTtlMs ?? Math.min(baseTtl, 6 * 3600_000);
|
||||
emptyTtl = Math.min(emptyTtl, ttl);
|
||||
}
|
||||
if (this.cfg.sharedCache) {
|
||||
const shared = this.cfg.sharedCache;
|
||||
const hit = await shared.get(key);
|
||||
|
||||
Reference in new issue
Block a user