From 8fa741cc1b9c737b5719fa50a624b195a17ed009 Mon Sep 17 00:00:00 2001 From: richarjiang Date: Sat, 6 Dec 2025 10:05:12 +0800 Subject: [PATCH] =?UTF-8?q?refactor(expo-updates):=20=E4=BC=98=E5=8C=96has?= =?UTF-8?q?h=E8=AE=A1=E7=AE=97=E5=92=8C=E5=B9=B6=E8=A1=8C=E5=A4=84?= =?UTF-8?q?=E7=90=86=E9=80=BB=E8=BE=91=EF=BC=8C=E6=8F=90=E5=8D=87=E6=80=A7?= =?UTF-8?q?=E8=83=BD=E5=92=8C=E8=B0=83=E8=AF=95=E8=83=BD=E5=8A=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/expo-updates/expo-updates.service.ts | 43 ++++++++++++++---------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/src/expo-updates/expo-updates.service.ts b/src/expo-updates/expo-updates.service.ts index cf0b021..00942b7 100644 --- a/src/expo-updates/expo-updates.service.ts +++ b/src/expo-updates/expo-updates.service.ts @@ -177,11 +177,12 @@ export class ExpoUpdatesService { responseType: 'arraybuffer', timeout: 30000, }); - const hash = crypto.createHash('sha256').update(response.data).digest('base64url'); + const hash = crypto.createHash('sha256').update(Buffer.from(response.data)).digest('base64url'); // 缓存 hash this.hashCache.set(cacheKey, { hash, timestamp: Date.now() }); + logger.debug(`Calculated hash for ${url}: ${hash}`); return hash; } catch (error) { logger.error(`Failed to calculate hash for ${url}: ${error.message}`); @@ -202,23 +203,31 @@ export class ExpoUpdatesService { } const assetList = Array.from(uniqueAssets.values()); + logger.info(`Building ${assetList.length} unique assets`); - // 并行计算所有 asset 的 hash - const results = await Promise.all( - assetList.map(async (asset) => { - const url = baseUrl + asset.path; - const key = asset.path.split('/').pop() || ''; // 使用文件名作为 key - const hash = await this.calculateFileHash(url); - - return { - hash, - key, - contentType: this.getContentType(asset.ext), - fileExtension: `.${asset.ext}`, - url, - }; - }) - ); + // 分批并行计算(每批10个,避免并发过多) + const batchSize = 10; + const results: AssetMetadata[] = []; + + for (let i = 0; i < assetList.length; i += batchSize) { + const batch = assetList.slice(i, i + batchSize); + const batchResults = await Promise.all( + batch.map(async (asset) => { + const url = baseUrl + asset.path; + const key = asset.path.split('/').pop() || ''; // 使用文件名作为 key + const hash = await this.calculateFileHash(url); + + return { + hash, + key, + contentType: this.getContentType(asset.ext), + fileExtension: `.${asset.ext}`, + url, + }; + }) + ); + results.push(...batchResults); + } return results; }