fix(bangumi-data): 修复 Bangumi Data 开启可能不触发立即下载,并调整云部署数据丢失时下载时机 (#444)
* fix: Bangumi Data 按需下载下沉至消费路径并修复配置变更未触发下载与漏写 await 将 Bangumi Data 初始化从 worker.js 网关层整体移除,下沉为 searchBangumiData 消费路径上的按需下载触发(ensureBangumiDataReady):仅在真正读取缓存的路径 (4 源搜索/匹配/弹幕 + 全局跨季边界)触发,未配置消费源的部署(如仅 renren) 不会下载,云部署丢失内存时由数据请求重新触发。 新增 syncBangumiDataLifecycleOnConfigChange,在 USE_BANGUMI_DATA 由关到开时 立即触发一次下载、由开到关时释放缓存;接入 env-api 三处 handler 与 server.js 的 .env 监听器,覆盖前端保存与本地直接改文件两种启用路径。 修复 tmdb-util.js getTMDBChineseTitle 调用 searchBangumiData 漏写 await,使本地 Bangumi Data 中文名命中路径真实生效(此前 localMatches 为非同步 Promise、命中 恒不生效)。 移除无调用方的 ctx 参数(handleRequest 与 initBangumiData):上游在 fetch 边缘层 经数据层 ctx.waitUntil 延长后台下载,本分支将下载触发下沉至消费路径后不再深穿 ctx, 该参数及依赖它的 ctx.waitUntil 分支已无调用来源,移除以避免无调用来源的防御性代码。 * fix: 暴露 Bangumi Data 在途后台下载并由边缘运行时延长生命周期 下载触发下沉至消费路径后不再将 ctx 深穿至数据层,上游原本由数据层 ctx.waitUntil 延长的后台下载在边缘层失去接线,导致边缘 isolate 在响应返回后冻结会中断在途的 后台静默下载(仅影响刷新效率,不阻塞请求,靠幽灵死锁自愈兜底)。本提交改为在边缘层 暴露在途下载并延长生命周期: - initBangumiData 发起非阻塞刷新时把在途下载 Promise 写入模块级 currentBackgroundDownload, 下载完成即在 finally 中复位;新增 getBackgroundDownload 暴露该状态。 - 新增 extendBangumiDownloadLifecycle(ctx),仅在存在在途下载且运行时提供 waitUntil 时 注册,供边缘层在响应返回后延长 isolate 生命周期以容纳下载;无 ctx 的运行时自然 no-op。 - worker.js 的 Cloudflare Workers fetch 入口重新接收 ctx 参数,await handleRequest 后调用 extendBangumiDownloadLifecycle(ctx);vercel/netlify 入口无 ctx,不受影响。 - 集中下载启动逻辑为 startDownload,三处刷新分支复用,消除重复的锁与复位代码。 * chore: Bangumi Data 模块级 let 声明整理为末尾注释并合并分组空行 将 currentBackgroundDownload、activeDataSource、cachedCustomVersion 的独立注释 行改为声明末尾注释,与既有的 versionQueryPromise 风格统一;删除 data-source 组内 cachedOfficialVersion 与 versionQueryPromise 之间的多余空行,保留 cache 组与 data-source 组之间的逻辑分隔空行,使模块顶部状态声明更紧凑一致。 * fix: 补全 bangumi 测试注释块缺失的导入符号 测试注释块第一组的 bangumi-data-util 导入仅含 ensureBangumiDataReady 与 syncBangumiDataLifecycleOnConfigChange,但同组用例还使用了 initBangumiData 与 clearBangumiDataCache,解除注释后会因未导入而 ReferenceError。getTMDBChineseTitle 与 assert 已由 worker.test.js 顶部全局导入,无需重复。补全缺失的两个符号,使该注释块 解除注释即可经 node --test 运行,并已在沙箱真实下载下验证通过。 --------- Co-authored-by: huangxd- <649924757@qq.com>
This commit is contained in:
1 parent
7e5c8073e0
commit
9bfca7a8e9
6 files changed
+170
-36
No files matched your search
@@ -2,6 +2,7 @@ import { jsonResponse } from '../utils/http-util.js';
|
||||
import { log } from '../utils/log-util.js';
|
||||
import { HandlerFactory } from '../configs/handlers/handler-factory.js';
|
||||
import { globals } from '../configs/globals.js';
|
||||
import { syncBangumiDataLifecycleOnConfigChange } from '../utils/bangumi-data-util.js';
|
||||
import AIClient from '../utils/ai-util.js';
|
||||
|
||||
/**
|
||||
@@ -24,6 +25,10 @@ export async function handleSetEnv(request) {
|
||||
// 调用handler的setEnv方法
|
||||
const result = await handler.setEnv(key, value);
|
||||
|
||||
if (result && key === 'USE_BANGUMI_DATA') {
|
||||
syncBangumiDataLifecycleOnConfigChange(deployPlatform);
|
||||
}
|
||||
|
||||
if (result) {
|
||||
return jsonResponse({ success: true, message: `环境变量 ${key} 设置成功` });
|
||||
} else {
|
||||
@@ -55,6 +60,10 @@ export async function handleAddEnv(request) {
|
||||
// 调用handler的addEnv方法
|
||||
const result = await handler.addEnv(key, value);
|
||||
|
||||
if (result && key === 'USE_BANGUMI_DATA') {
|
||||
syncBangumiDataLifecycleOnConfigChange(deployPlatform);
|
||||
}
|
||||
|
||||
if (result) {
|
||||
return jsonResponse({ success: true, message: `环境变量 ${key} 添加成功` });
|
||||
} else {
|
||||
@@ -86,6 +95,10 @@ export async function handleDelEnv(request) {
|
||||
// 调用handler的delEnv方法
|
||||
const result = await handler.delEnv(key);
|
||||
|
||||
if (result && key === 'USE_BANGUMI_DATA') {
|
||||
syncBangumiDataLifecycleOnConfigChange(deployPlatform);
|
||||
}
|
||||
|
||||
if (result) {
|
||||
return jsonResponse({ success: true, message: `环境变量 ${key} 删除成功` });
|
||||
} else {
|
||||
|
||||
+7
-6
@@ -9,9 +9,9 @@ import { HttpsProxyAgent } from 'https-proxy-agent';
|
||||
import dotenv from 'dotenv';
|
||||
import { Request as NodeFetchRequest } from 'node-fetch';
|
||||
import { handleRequest } from './worker.js';
|
||||
import { Globals } from './configs/globals.js';
|
||||
import { Globals, globals } from './configs/globals.js';
|
||||
import { Envs } from './configs/envs.js';
|
||||
import { clearBangumiDataCache, initBangumiData } from './utils/bangumi-data-util.js';
|
||||
import { clearBangumiDataCache, initBangumiData, syncBangumiDataLifecycleOnConfigChange } from './utils/bangumi-data-util.js';
|
||||
import { getLocalCaches, judgeLocalCacheValid } from './utils/cache-util.js';
|
||||
import { getRedisCaches, judgeRedisValid } from './utils/redis-util.js';
|
||||
import { persistFavorites, refreshFavoriteByKeyword } from './apis/favorite-api.js';
|
||||
@@ -234,10 +234,11 @@ async function setupEnvWatcher() {
|
||||
console.log('[server] Environment variables reloaded successfully');
|
||||
console.log('[server] Updated keys:', Array.from(newEnvKeys).join(', '));
|
||||
|
||||
// 如果检测到关闭了 Bangumi Data 功能,主动释放内存与物理磁盘缓存
|
||||
if (process.env.USE_BANGUMI_DATA === 'false' || process.env.USE_BANGUMI_DATA === false) {
|
||||
clearBangumiDataCache(true);
|
||||
}
|
||||
// 配置变更后同步 Bangumi Data 生命周期:开启则立即确保缓存就绪(缺失则下载),
|
||||
// 关闭则释放缓存;先按真实配置同步内存开关,避免重载未刷新 globals 时状态滞后
|
||||
const bangumiEnabled = process.env.USE_BANGUMI_DATA === 'true' || process.env.USE_BANGUMI_DATA === true;
|
||||
globals.useBangumiData = bangumiEnabled;
|
||||
syncBangumiDataLifecycleOnConfigChange('node');
|
||||
|
||||
} catch (error) {
|
||||
console.log('[server] Error reloading configuration files:', error.message);
|
||||
|
||||
@@ -18,13 +18,11 @@ let downloadLockTime = 0;
|
||||
let memoryFootprintMB = '0.00';
|
||||
let hasLoggedCacheWarning = false;
|
||||
let charInvertedIndex = new Map();
|
||||
let currentBackgroundDownload = null; // 在途后台下载 Promise:由 initBangumiData 在发起非阻塞刷新时写入,供边缘层 ctx.waitUntil 延长 Serverless 生命周期
|
||||
|
||||
// 当前生效的数据源标识 ('custom' | 'official')
|
||||
let activeDataSource = 'custom';
|
||||
// 缓存已解析的版本号(进程内有效)
|
||||
let cachedCustomVersion = null;
|
||||
let activeDataSource = 'custom'; // 当前生效的数据源标识 ('custom' | 'official')
|
||||
let cachedCustomVersion = null; // 缓存已解析的版本号(进程内有效)
|
||||
let cachedOfficialVersion = null;
|
||||
|
||||
let versionQueryPromise = null; // 版本查询并发锁:serverless环境下冻结时异步信号可能不生效,共享同一Promise避免重复探测
|
||||
|
||||
// 定义缓存目录/文件名
|
||||
@@ -193,6 +191,46 @@ async function selectBestDataSource() {
|
||||
return versionQueryPromise;
|
||||
}
|
||||
|
||||
// 数据下载触发时机:仅在 searchBangumiData 消费路径进入时触发下载;开关关闭或无所消费源时不下载
|
||||
// 开启时复用 initBangumiData 加载/下载,并发调用等待同一就绪缓存而不重复请求
|
||||
export async function ensureBangumiDataReady(deployPlatform = globals.deployPlatform) {
|
||||
if (!globals.useBangumiData) return;
|
||||
await initBangumiData(deployPlatform, true);
|
||||
}
|
||||
|
||||
// 配置变更后同步 Bangumi Data 生命周期:开关开启立即下载(已缓存则幂等),关闭释放缓存
|
||||
// 调用前须保证 globals.useBangumiData 已反映最新配置(watcher 场景须先同步内存开关)
|
||||
export function syncBangumiDataLifecycleOnConfigChange(deployPlatform = globals.deployPlatform) {
|
||||
if (globals.useBangumiData) {
|
||||
initBangumiData(deployPlatform, true).catch(console.error);
|
||||
} else {
|
||||
clearBangumiDataCache(true);
|
||||
}
|
||||
}
|
||||
|
||||
// 读取在途后台下载 Promise,供边缘运行时在请求响应后延长生命周期(无在途时返回 null)
|
||||
export function getBackgroundDownload() {
|
||||
return currentBackgroundDownload;
|
||||
}
|
||||
|
||||
// 边缘运行时在响应返回后延长生命周期:仅在存在在途后台下载且运行时提供 waitUntil 时注册
|
||||
export function extendBangumiDownloadLifecycle(ctx) {
|
||||
if (ctx && typeof ctx.waitUntil === 'function' && currentBackgroundDownload) {
|
||||
ctx.waitUntil(currentBackgroundDownload);
|
||||
}
|
||||
}
|
||||
|
||||
// 发起后台静默下载并记录在途 Promise:下载完成时复位状态,供 getBackgroundDownload 暴露给边缘层
|
||||
function startDownload(cachePath) {
|
||||
isDownloading = true;
|
||||
downloadLockTime = Date.now();
|
||||
currentBackgroundDownload = downloadAndCache(cachePath).finally(() => {
|
||||
isDownloading = false;
|
||||
currentBackgroundDownload = null;
|
||||
});
|
||||
return currentBackgroundDownload;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化 Bangumi Data 数据源
|
||||
* 包含内存与磁盘双端缓存的生命周期校验,并在环境允许时持久化缓存数据
|
||||
@@ -201,7 +239,7 @@ async function selectBestDataSource() {
|
||||
* @param {boolean} isDataDependentRequest - 当前是否为强依赖数据的核心接口请求
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
export async function initBangumiData(deployPlatform, isDataDependentRequest = false, ctx = null) {
|
||||
export async function initBangumiData(deployPlatform, isDataDependentRequest = false) {
|
||||
if (!globals.useBangumiData) return;
|
||||
|
||||
let cachePath = null;
|
||||
@@ -237,9 +275,7 @@ export async function initBangumiData(deployPlatform, isDataDependentRequest = f
|
||||
// 当内存过期或配置强制更新时,仅在核心请求触发后台静默更新
|
||||
if (isDataDependentRequest && !isDownloading) {
|
||||
log("info", `[system] [Bangumi-Data] 内存数据${cacheDays === 0 ? '强制更新' : '已过期'},保留老数据服务本次请求,启动后台静默更新...`);
|
||||
isDownloading = true;
|
||||
downloadLockTime = Date.now();
|
||||
downloadAndCache(cachePath).finally(() => { isDownloading = false; });
|
||||
startDownload(cachePath);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -274,9 +310,7 @@ export async function initBangumiData(deployPlatform, isDataDependentRequest = f
|
||||
if (cacheDays === 0 || (Date.now() - stats.mtimeMs >= expireMs)) {
|
||||
if (isDataDependentRequest && !isDownloading) {
|
||||
log("info", `[system] [Bangumi-Data] 磁盘数据${cacheDays === 0 ? '强制更新' : '已过期'},保留老数据服务本次请求,启动后台静默更新...`);
|
||||
isDownloading = true;
|
||||
downloadLockTime = Date.now();
|
||||
downloadAndCache(cachePath).finally(() => { isDownloading = false; });
|
||||
startDownload(cachePath);
|
||||
}
|
||||
}
|
||||
return;
|
||||
@@ -289,19 +323,13 @@ export async function initBangumiData(deployPlatform, isDataDependentRequest = f
|
||||
// 内存与磁盘均无有效数据时的获取逻辑
|
||||
if (!isDownloading) {
|
||||
log("info", `[system] [Bangumi-Data] 未命中任何有效缓存,正在获取基础数据...`);
|
||||
isDownloading = true;
|
||||
downloadLockTime = Date.now();
|
||||
|
||||
const downloadPromise = downloadAndCache(cachePath).finally(() => { isDownloading = false; });
|
||||
const downloadPromise = startDownload(cachePath);
|
||||
|
||||
if (isDataDependentRequest) {
|
||||
await downloadPromise;
|
||||
} else {
|
||||
log("info", `[system] [Bangumi-Data] 当前非核心请求,数据获取转入后台异步执行`);
|
||||
if (ctx && typeof ctx.waitUntil === 'function') {
|
||||
log("info", `[system] [Bangumi-Data] 调用 ctx.waitUntil 延长 Serverless 生命周期`);
|
||||
ctx.waitUntil(downloadPromise);
|
||||
}
|
||||
}
|
||||
} else if (isDataDependentRequest) {
|
||||
log("info", `[system] [Bangumi-Data] 正在等待基础数据下载完成...`);
|
||||
@@ -503,6 +531,7 @@ async function downloadAndCache(cachePath) {
|
||||
* @returns {Array<Object>} 匹配的动漫条目数组
|
||||
*/
|
||||
export async function searchBangumiData(keyword, siteKeys) {
|
||||
await ensureBangumiDataReady();
|
||||
if (!memoryCache || !memoryCache.items) return [];
|
||||
|
||||
let searchPromise = queryCache.get(keyword);
|
||||
|
||||
@@ -593,7 +593,7 @@ export async function getTMDBChineseTitle(title, season = null, episode = null)
|
||||
// 优先尝试本地 Bangumi Data 转换
|
||||
if (globals.useBangumiData) {
|
||||
const cleanTitle = cleanSearchQuery(title);
|
||||
const localMatches = searchBangumiData(cleanTitle, ['tmdb', 'bangumi', 'anidb']);
|
||||
const localMatches = await searchBangumiData(cleanTitle, ['tmdb', 'bangumi', 'anidb']);
|
||||
if (localMatches && localMatches.length > 0) {
|
||||
const m = localMatches[0];
|
||||
// 找一个不全是外文的翻译作为中文名
|
||||
|
||||
+6
-10
@@ -5,13 +5,13 @@ import { getFavoriteCachesFromRedis, getRedisCaches, judgeRedisValid } from "./u
|
||||
import { cleanupExpiredIPs, findUrlById, getCommentCache, getLocalCaches, judgeLocalCacheValid } from "./utils/cache-util.js";
|
||||
import { formatDanmuResponse } from "./utils/danmu-util.js";
|
||||
import AIClient from './utils/ai-util.js';
|
||||
import { initBangumiData } from "./utils/bangumi-data-util.js";
|
||||
import { getBangumi, getComment, getCommentByUrl, getSegmentComment, matchAnime, searchAnime, searchEpisodes } from "./apis/dandan-api.js";
|
||||
import { handleFavoriteAdd, handleFavoriteList, handleFavoriteRefresh, handleFavoriteRemove, handleFavoriteSchedule } from "./apis/favorite-api.js";
|
||||
import { getFongmiDanmaku } from "./apis/clients/fongmi-api.js";
|
||||
import { handleConfig, handleUI, handleLogs, handleClearLogs, handleDeploy, handleClearCache, handleReqRecords, handleCacheAnimes } from "./apis/system-api.js";
|
||||
import { handleForwardTrace } from "./apis/forward-trace-api.js";
|
||||
import { handleSetEnv, handleAddEnv, handleDelEnv, handleAiVerify } from "./apis/env-api.js";
|
||||
import { extendBangumiDownloadLifecycle } from "./utils/bangumi-data-util.js";
|
||||
import { Segment } from "./models/dandan-model.js"
|
||||
import {
|
||||
handleCookieStatus,
|
||||
@@ -23,7 +23,7 @@ import {
|
||||
|
||||
let globals;
|
||||
|
||||
async function handleRequest(req, env, deployPlatform, clientIp, ctx) {
|
||||
async function handleRequest(req, env, deployPlatform, clientIp) {
|
||||
// 加载全局变量和环境变量配置
|
||||
globals = Globals.init(env);
|
||||
|
||||
@@ -31,13 +31,6 @@ async function handleRequest(req, env, deployPlatform, clientIp, ctx) {
|
||||
let path = url.pathname;
|
||||
const method = req.method;
|
||||
|
||||
// Bangumi Data 辅助函数,用于判断数据更新
|
||||
const isDataDependentRequest = path.includes('/search') || path.includes('/match') || path.includes('/danmaku');
|
||||
|
||||
if (globals.useBangumiData) {
|
||||
await initBangumiData(deployPlatform, isDataDependentRequest, ctx);
|
||||
}
|
||||
|
||||
globals.deployPlatform = deployPlatform;
|
||||
if (deployPlatform === "node") {
|
||||
await judgeLocalCacheValid(path, deployPlatform);
|
||||
@@ -754,7 +747,10 @@ export default {
|
||||
// 获取客户端的真实 IP
|
||||
const clientIp = request.headers.get('cf-connecting-ip') || request.headers.get('x-forwarded-for') || 'unknown';
|
||||
|
||||
return handleRequest(request, env, detectDeployPlatform(env), clientIp, ctx);
|
||||
const response = await handleRequest(request, env, detectDeployPlatform(env), clientIp);
|
||||
// 边缘运行时在响应返回后延长生命周期,容纳可能在途的 Bangumi Data 后台静默下载
|
||||
extendBangumiDownloadLifecycle(ctx);
|
||||
return response;
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -2850,6 +2850,101 @@ test('worker.js API endpoints', async (t) => {
|
||||
// });
|
||||
// });
|
||||
|
||||
// // 测试 Bangumi Data 数据下载时机(ensureBangumiDataReady)、配置变更触发下载(syncBangumiDataLifecycleOnConfigChange)
|
||||
// // 以及 getTMDBChineseTitle 漏写 await 的修复;与 envs RAW_ENV_KEYS 测试同为按需启用的内部测试
|
||||
// import { globals } from './configs/globals.js';
|
||||
// import { ensureBangumiDataReady, syncBangumiDataLifecycleOnConfigChange, initBangumiData, clearBangumiDataCache } from './utils/bangumi-data-util.js';
|
||||
// import fs from 'node:fs';
|
||||
// import path from 'node:path';
|
||||
//
|
||||
// test('bangumi-data 数据下载时机与配置变更触发下载', async (t) => {
|
||||
// const CACHE_DIR = path.join(process.cwd(), '.cache');
|
||||
// const CACHE_FILE = path.join(CACHE_DIR, 'bangumi-data-cache.json');
|
||||
// const FAKE_ITEM = {
|
||||
// title: 'FrobeniusTestAnime',
|
||||
// titleTranslate: { 'zh-Hans': ['弗罗贝尼乌斯测试动画', 'FrobeniusTestAnime'] },
|
||||
// sites: [{ site: 'tmdb', id: '999999' }],
|
||||
// _flatText: 'frobeniustestanime'
|
||||
// };
|
||||
// const reset = () => {
|
||||
// globals.useBangumiData = false;
|
||||
// clearBangumiDataCache(false);
|
||||
// if (fs.existsSync(CACHE_FILE)) fs.writeFileSync(CACHE_FILE, '', 'utf-8');
|
||||
// };
|
||||
//
|
||||
// await t.test('ensureBangumiDataReady 开关关闭时直接返回且不触发下载', async () => {
|
||||
// reset();
|
||||
// globals.useBangumiData = false;
|
||||
// await ensureBangumiDataReady('node');
|
||||
// assert.ok(true);
|
||||
// });
|
||||
//
|
||||
// await t.test('syncBangumiDataLifecycleOnConfigChange 开关关闭释放缓存、开启安全触发', async () => {
|
||||
// reset();
|
||||
// globals.useBangumiData = false;
|
||||
// assert.doesNotThrow(() => syncBangumiDataLifecycleOnConfigChange('node'));
|
||||
// fs.mkdirSync(CACHE_DIR, { recursive: true });
|
||||
// fs.writeFileSync(CACHE_FILE, JSON.stringify({ items: [FAKE_ITEM] }), 'utf-8');
|
||||
// globals.useBangumiData = true;
|
||||
// assert.doesNotThrow(() => syncBangumiDataLifecycleOnConfigChange('node'));
|
||||
// });
|
||||
//
|
||||
// await t.test('getTMDBChineseTitle 经 await 命中本地中文名(修复漏写 await)', async () => {
|
||||
// reset();
|
||||
// globals.useBangumiData = true;
|
||||
// const originalContent = fs.existsSync(CACHE_FILE) ? fs.readFileSync(CACHE_FILE, 'utf-8') : null;
|
||||
// fs.mkdirSync(CACHE_DIR, { recursive: true });
|
||||
// fs.writeFileSync(CACHE_FILE, JSON.stringify({ items: [FAKE_ITEM] }), 'utf-8');
|
||||
// try {
|
||||
// await initBangumiData('node', true);
|
||||
// const result = await getTMDBChineseTitle('FrobeniusTestAnime');
|
||||
// assert.equal(result, '弗罗贝尼乌斯测试动画');
|
||||
// } finally {
|
||||
// clearBangumiDataCache(false);
|
||||
// if (originalContent !== null) fs.writeFileSync(CACHE_FILE, originalContent, 'utf-8');
|
||||
// else fs.writeFileSync(CACHE_FILE, '', 'utf-8');
|
||||
// }
|
||||
// });
|
||||
// });
|
||||
|
||||
// // 测试 Bangumi Data 在途下载暴露与边缘生命周期延长(getBackgroundDownload / extendBangumiDownloadLifecycle)
|
||||
// // 与上方 bangumi 测试同为按需启用的内部测试;沙箱有网时真实下载以验证在途暴露、注册与清理
|
||||
// import { globals } from './configs/globals.js';
|
||||
// import { initBangumiData, getBackgroundDownload, extendBangumiDownloadLifecycle } from './utils/bangumi-data-util.js';
|
||||
// import assert from 'node:assert';
|
||||
// import fs from 'node:fs';
|
||||
// import path from 'node:path';
|
||||
//
|
||||
// test('bangumi-data 在途下载暴露与边缘生命周期延长', async (t) => {
|
||||
// const CACHE_DIR = path.join(process.cwd(), '.cache');
|
||||
// const CACHE_FILE = path.join(CACHE_DIR, 'bangumi-data-cache.json');
|
||||
// const hadCache = fs.existsSync(CACHE_DIR);
|
||||
//
|
||||
// // 空闲时无在途下载
|
||||
// assert.strictEqual(getBackgroundDownload(), null);
|
||||
//
|
||||
// await t.test('extendBangumiDownloadLifecycle 在无在途或 ctx 缺失时不注册', async () => {
|
||||
// const calls = [];
|
||||
// extendBangumiDownloadLifecycle(null);
|
||||
// extendBangumiDownloadLifecycle({ waitUntil: (p) => calls.push(p) });
|
||||
// assert.strictEqual(calls.length, 0);
|
||||
// });
|
||||
//
|
||||
// await t.test('在途下载被暴露、响应后由边缘 waitUntil 注册、完成后清理', async () => {
|
||||
// globals.useBangumiData = true;
|
||||
// // 启动真实下载(无 .cache 时走内存路径,不落地文件;有 .cache 则后台刷新),不在途时立即返回
|
||||
// const initPromise = initBangumiData('node', true);
|
||||
// const bg = getBackgroundDownload();
|
||||
// assert.ok(bg && typeof bg.then === 'function', '下载在途时应暴露 Promise');
|
||||
// const ctx = { waitUntil: (p) => { ctx.registered = p; } };
|
||||
// extendBangumiDownloadLifecycle(ctx);
|
||||
// assert.strictEqual(ctx.registered, bg, '边缘 waitUntil 应注册在途 Promise');
|
||||
// await bg; // 等待下载完成(兼容阻塞与后台两种路径)
|
||||
// assert.strictEqual(getBackgroundDownload(), null, '下载完成后应清理在途状态');
|
||||
// globals.useBangumiData = false;
|
||||
// if (!hadCache && fs.existsSync(CACHE_FILE)) fs.writeFileSync(CACHE_FILE, '', 'utf-8');
|
||||
// await initPromise.catch(() => {});
|
||||
// });
|
||||
// // 测试自定义文本类变量绕过 dotenv 注释截断(保留 # 等字符),对应 envs.js RAW_ENV_KEYS 修复
|
||||
// import { Envs } from './configs/envs.js';
|
||||
//
|
||||
|
||||
Reference in new issue
Block a user