refactor: 迁移至 bashly CLI 与功能域模块结构
- CLI 定义迁移至 src/bashly.yml(bashly 1.4 生成参数解析),入口收敛为 src/root_command.sh - 源码按功能域重组:config/storage/integrate/media/pipeline,消除扁平散落 - 新增零依赖测试框架 tests/(123 用例)与 CI 流水线(lint + test + build + 产物一致性) - build.sh 支持版本单一来源注入与 --check 产物校验;新增 lint.sh(bash -n + shellcheck 零容忍) - 删除旧单文件 media_organizer.sh 与旧扁平模块
This commit is contained in:
1 parent
d978a13a83
commit
0df07ad0ae
48 files changed
+5813
-6812
No files matched your search
@@ -0,0 +1,113 @@
|
||||
# shellcheck shell=bash
|
||||
|
||||
################################################################################
|
||||
# TMDB API
|
||||
################################################################################
|
||||
|
||||
# 指定语言的 tmdb_api 封装(语言重试链用):局部覆盖 TMDB_LANG 后调用。
|
||||
# bash 动态作用域:tmdb_api 内读到的 $TMDB_LANG 为本次调用值;
|
||||
# 缓存 key/路径含语言段(cache_key 拼 lang、id 类路径带 .lang),语言切换天然隔离缓存。
|
||||
# 参数:lang(如 en-US) + 原 tmdb_api 全部参数。
|
||||
tmdb_api_lang() {
|
||||
local lang="$1"
|
||||
shift
|
||||
local TMDB_LANG="$lang"
|
||||
tmdb_api "$@"
|
||||
}
|
||||
|
||||
# 调用 TMDB API 并缓存结果。端点形如 "/search/movie",额外参数以 key=value 传入。
|
||||
# 先查缓存(命中且未过期直接返回),未命中才请求并写缓存。
|
||||
# 返回码约定:0=成功(含空结果的有效响应);1=新鲜空哨兵跳过请求;
|
||||
# 2=请求失败(curl 错误/HTTP 非 2xx,递增重试耗尽)——不写空哨兵(失败≠无结果)。
|
||||
# 返回原始 JSON 响应到 stdout。
|
||||
tmdb_api() {
|
||||
local endpoint="$1"
|
||||
shift
|
||||
local key path is_search
|
||||
key=$(cache_key "$@")
|
||||
path=$(cache_path "$endpoint" "$key")
|
||||
is_search=0
|
||||
[[ "$endpoint" == /search/* ]] && is_search=1
|
||||
|
||||
# --update-cache 修饰(整理时强制重取):跳过缓存读与空哨兵,直接请求并覆盖缓存
|
||||
local cached
|
||||
if [[ "${UPDATE_CACHE:-false}" != "true" ]] && cached=$(cache_get "$path" "$is_search"); then
|
||||
echo "$cached"
|
||||
return 0
|
||||
fi
|
||||
# 新鲜空哨兵:上次已确认空结果,CACHE_EMPTY_TTL_DAYS 内跳过请求(避免重复请求无效数据)
|
||||
if [[ "${UPDATE_CACHE:-false}" != "true" ]] && cache_empty_fresh "$path" "$is_search"; then
|
||||
[[ "$DEBUG_LEVEL" -ge 2 ]] && _log 调试 "缓存为空哨兵(新鲜),跳过请求: ${endpoint}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 并发去重(识别池多 worker 可能同时 miss 同一查询):
|
||||
# flock 跨进程互斥(内核锁,进程退出自动释放,无残留)→ 锁内双检缓存。
|
||||
# 锁文件放 /tmp(复用不删除;不污染缓存目录,干运行零持久化副作用)。
|
||||
local lockfile
|
||||
lockfile="/tmp/mo_lock_$(cache_key_hash "$path")"
|
||||
local locked=false
|
||||
if [[ "${UPDATE_CACHE:-false}" != "true" ]]; then
|
||||
exec 9>"$lockfile"
|
||||
flock 9
|
||||
locked=true
|
||||
# 双检:等待者可能在锁期间已写入缓存
|
||||
if cached=$(cache_get "$path" "$is_search"); then
|
||||
exec 9>&-
|
||||
echo "$cached"
|
||||
return 0
|
||||
fi
|
||||
if cache_empty_fresh "$path" "$is_search"; then
|
||||
exec 9>&-
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
local curl_args=(
|
||||
"--get" "-s"
|
||||
"--connect-timeout" "${TMDB_CURL_CONNECT_TIMEOUT}"
|
||||
"--max-time" "${TMDB_CURL_MAX_TIME}" "-fS"
|
||||
)
|
||||
if $TMDB_USE_BEARER; then
|
||||
curl_args+=("--header" "Authorization: Bearer ${TMDB_AUTH_TOKEN}")
|
||||
fi
|
||||
curl_args+=("--data-urlencode" "language=${TMDB_LANG}")
|
||||
if ! $TMDB_USE_BEARER; then
|
||||
curl_args+=("--data-urlencode" "api_key=${TMDB_AUTH_TOKEN}")
|
||||
fi
|
||||
local a
|
||||
for a in "$@"; do
|
||||
curl_args+=("--data-urlencode" "$a")
|
||||
done
|
||||
|
||||
local full_url="${TMDB_API_BASE_URL}${endpoint}"
|
||||
[[ "$DEBUG_LEVEL" -ge 2 ]] && _log 调试 "TMDB 请求: ${full_url}?..."
|
||||
|
||||
# 递增重试(2^n 封顶 16s):curl 的 --retry-delay 为固定延迟,这里手写循环
|
||||
local result=""
|
||||
local attempt=0 delay=1
|
||||
while true; do
|
||||
if result=$(curl "${curl_args[@]}" "$full_url" 2>&1); then
|
||||
break
|
||||
fi
|
||||
attempt=$((attempt + 1))
|
||||
if ((attempt > TMDB_CURL_RETRY)); then
|
||||
_log 错误 "TMDB 请求失败(重试 ${TMDB_CURL_RETRY} 次后): ${full_url} 错误: ${result}"
|
||||
return 2
|
||||
fi
|
||||
_log 警告 "TMDB 请求失败,${delay}s 后重试(${attempt}/${TMDB_CURL_RETRY}): ${full_url}"
|
||||
sleep "$delay"
|
||||
((delay *= 2))
|
||||
[[ $delay -gt 16 ]] && delay=16
|
||||
done
|
||||
# 搜索空结果 → 写 3 天短 TTL 哨兵(查无此片;新片出现后自动重试);否则正常写缓存
|
||||
if [[ "$is_search" == "1" ]] && ! echo "$result" | jq -e '.results | length > 0' >/dev/null 2>&1; then
|
||||
cache_put_empty "$path" "$is_search" "$key"
|
||||
else
|
||||
cache_put "$path" "$result" "$is_search" "$key"
|
||||
fi
|
||||
if $locked; then
|
||||
exec 9>&-
|
||||
fi
|
||||
echo "$result"
|
||||
}
|
||||
Reference in new issue
Block a user