UNPKG

cnpmcore

Version:

Private NPM Registry for Enterprise

341 lines 36.1 kB
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; import fs from 'node:fs/promises'; import { AccessLevel, Inject, SingletonProto } from 'egg'; import { sortBy } from 'lodash-es'; import binaries from "../../../config/binaries.js"; import { AbstractService } from "../../common/AbstractService.js"; import { AbstractBinary } from "../../common/adapter/binary/AbstractBinary.js"; import { platforms } from "../../common/adapter/binary/PuppeteerBinary.js"; import { BinaryType } from "../../common/enum/Binary.js"; import { TaskState, TaskType } from "../../common/enum/Task.js"; import { isTimeoutError } from "../../common/ErrorUtil.js"; import { downloadToTempfile } from "../../common/FileUtil.js"; import { Binary } from "../entity/Binary.js"; import { Task } from "../entity/Task.js"; function isoNow() { return new Date().toISOString(); } let BinarySyncerService = class BinarySyncerService extends AbstractService { // canvas/v2.6.1/canvas-v2.6.1-node-v57-linux-glibc-x64.tar.gz // -> node-canvas-prebuilt/v2.6.1/node-canvas-prebuilt-v2.6.1-node-v57-linux-glibc-x64.tar.gz // canvas 历史版本的 targetName 可能是 category 需要兼容 async findBinary(targetName, parent, name) { return await this.binaryRepository.findBinary(targetName, parent, name); } async listDirBinaries(binary, options) { return await this.binaryRepository.listBinaries(binary.category, `${binary.parent}${binary.name}`, options); } async listRootBinaries(binaryName) { // 通常 binaryName 和 category 是一样的,但是有些特殊的 binaryName 会有多个 category,比如 canvas // 所以查询 canvas 的时候,需要将 binaryName 和 category 的数据都查出来 const { category } = binaries[binaryName]; const reqs = [this.binaryRepository.listBinaries(binaryName, '/')]; if (category && category !== binaryName) { reqs.push(this.binaryRepository.listBinaries(category, '/')); } const [rootBinary, categoryBinary] = await Promise.all(reqs); const versions = new Set(rootBinary.map((b) => b.name)); if (categoryBinary) { for (const b of categoryBinary) { const version = b.name; // 只将没有的版本添加进去 if (!versions.has(version)) { rootBinary.push(b); } } } return rootBinary; } async downloadBinary(binary) { return await this.nfsAdapter.getDownloadUrlOrStream(binary.storePath); } async createTask(binaryName, lastData) { // chromium-browser-snapshots 产物极大,完整遍历 s3 bucket 耗时会太长 // 必须从上次同步的 revision 之后开始遍历 // 如果需要补偿数据,可以 if (binaryName === 'chromium-browser-snapshots') { lastData = lastData || {}; for (const platform of platforms) { if (lastData[platform]) continue; const binaryDir = await this.binaryRepository.findLatestBinaryDir('chromium-browser-snapshots', `/${platform}/`); if (binaryDir) { lastData[platform] = binaryDir.name.slice(0, -1); } } const latestBinary = await this.binaryRepository.findLatestBinary('chromium-browser-snapshots'); if (latestBinary && !lastData.lastSyncTime) { lastData.lastSyncTime = latestBinary.date; } } try { return await this.taskService.createTask(Task.createSyncBinary(binaryName, lastData), false); } catch (e) { this.logger.error('[BinarySyncerService.createTask] binaryName: %s, error: %s', binaryName, e); } } async findTask(taskId) { return (await this.taskService.findTask(taskId)); } async findTaskLog(task) { return await this.taskService.findTaskLog(task); } async findExecuteTask() { return (await this.taskService.findExecuteTask(TaskType.SyncBinary)); } async executeTask(task) { const binaryName = task.targetName; const binaryAdapter = await this.getBinaryAdapter(binaryName); const logUrl = `${this.config.cnpmcore.registry}/-/binary/${binaryName}/syncs/${task.taskId}/log`; let logs = []; logs.push(`[${isoNow()}] 🚧🚧🚧🚧🚧 Start sync binary "${binaryName}" 🚧🚧🚧🚧🚧`); if (!binaryAdapter) { task.error = 'unknow binaryName'; logs.push(`[${isoNow()}] ❌ Synced "${binaryName}" fail, ${task.error}, log: ${logUrl}`); logs.push(`[${isoNow()}] ❌❌❌❌❌ "${binaryName}" ❌❌❌❌❌`); this.logger.error('[BinarySyncerService.executeTask:fail] taskId: %s, targetName: %s, %s', task.taskId, task.targetName, task.error); await this.taskService.finishTask(task, TaskState.Fail, logs.join('\n')); return; } await this.taskService.appendTaskLog(task, logs.join('\n')); logs = []; this.logger.info('[BinarySyncerService.executeTask:start] taskId: %s, targetName: %s, log: %s', task.taskId, task.targetName, logUrl); try { const [hasDownloadError] = await this.syncDir(binaryAdapter, task, '/'); logs.push(`[${isoNow()}] 🟢 log: ${logUrl}`); logs.push(`[${isoNow()}] 🟢🟢🟢🟢🟢 "${binaryName}" 🟢🟢🟢🟢🟢`); await this.taskService.finishTask(task, TaskState.Success, logs.join('\n')); // 确保没有下载异常才算 success await binaryAdapter.finishFetch(!hasDownloadError, binaryName); this.logger.info('[BinarySyncerService.executeTask:success] taskId: %s, targetName: %s, log: %s, hasDownloadError: %s', task.taskId, task.targetName, logUrl, hasDownloadError); } catch (err) { task.error = `${err.name}: ${err.message}`; logs.push(`[${isoNow()}] ❌ Synced "${binaryName}" fail, ${task.error}, log: ${logUrl}`); logs.push(`[${isoNow()}] ❌❌❌❌❌ "${binaryName}" ❌❌❌❌❌`); if (isTimeoutError(err)) { this.logger.warn('[BinarySyncerService.executeTask:fail] taskId: %s, targetName: %s, %s', task.taskId, task.targetName, task.error); this.logger.warn(err); } else { this.logger.error('[BinarySyncerService.executeTask:fail] taskId: %s, targetName: %s, %s', task.taskId, task.targetName, task.error); this.logger.error(err); } await binaryAdapter.finishFetch(false, binaryName); await this.taskService.finishTask(task, TaskState.Fail, logs.join('\n')); } } async syncDir(binaryAdapter, task, dir, parentIndex = '', latestVersionParent = '/') { const binaryName = task.targetName; const result = await binaryAdapter.fetch(dir, binaryName, task.data); let hasDownloadError = false; let hasItems = false; if (result && result.items.length > 0) { hasItems = true; let logs = []; const startTime = Date.now(); const { newItems, latestVersionDir } = await this.diff(binaryName, dir, result.items, latestVersionParent); const useTime = Date.now() - startTime; logs.push(`[${isoNow()}][${dir}] 🚧 Syncing diff: ${result.items.length} => ${newItems.length}, Binary class: ${binaryAdapter.constructor.name}, use: ${useTime}ms`); // re-check latest version for (const [index, { item, reason }] of newItems.entries()) { if (item.isDir) { logs.push(`[${isoNow()}][${dir}] 🚧 [${parentIndex}${index}] Start sync dir ${JSON.stringify(item)}, reason: ${reason}`); await this.taskService.appendTaskLog(task, logs.join('\n')); logs = []; const [hasError, hasSubItems] = await this.syncDir(binaryAdapter, task, `${dir}${item.name}`, `${parentIndex}${index}.`, latestVersionDir); if (hasError) { hasDownloadError = true; } else if (hasSubItems) { // if any file download error, let dir sync again next time // if empty dir, don't save it await this.saveBinaryItem(item); } } else { // download to nfs logs.push(`[${isoNow()}][${dir}] 🚧 [${parentIndex}${index}] Downloading ${JSON.stringify(item)}, reason: ${reason}`); // skip exists binary file const existsBinary = await this.binaryRepository.findBinary(item.category, item.parent, item.name); if (existsBinary && existsBinary.date === item.date) { logs.push(`[${isoNow()}][${dir}] 🟢 [${parentIndex}${index}] binary file exists, skip download, binaryId: ${existsBinary.binaryId}`); this.logger.info('[BinarySyncerService.syncDir:skipDownload] binaryId: %s exists, storePath: %s', existsBinary.binaryId, existsBinary.storePath); continue; } await this.taskService.appendTaskLog(task, logs.join('\n')); logs = []; let localFile = ''; try { const { tmpfile, headers, timing } = await downloadToTempfile(this.httpClient, this.config.dataDir, item.sourceUrl, { ignoreDownloadStatuses: item.ignoreDownloadStatuses }); const log = `[${isoNow()}][${dir}] 🟢 [${parentIndex}${index}] HTTP content-length: ${headers['content-length']}, timing: ${JSON.stringify(timing)}, ${item.sourceUrl} => ${tmpfile}`; logs.push(log); this.logger.info('[BinarySyncerService.syncDir:downloadToTempfile] %s', log); localFile = tmpfile; const binary = await this.saveBinaryItem(item, tmpfile); logs.push(`[${isoNow()}][${dir}] 🟢 [${parentIndex}${index}] Synced file success, binaryId: ${binary.binaryId}`); await this.taskService.appendTaskLog(task, logs.join('\n')); logs = []; } catch (err) { if (err.name === 'DownloadNotFoundError') { this.logger.info('Not found %s, skip it', item.sourceUrl); logs.push(`[${isoNow()}][${dir}] 🧪️ [${parentIndex}${index}] Download ${item.sourceUrl} not found, skip it`); } else { if (err.name === 'DownloadStatusInvalidError') { this.logger.warn('Download binary %s %s', item.sourceUrl, err); } else { this.logger.error('Download binary %s %s', item.sourceUrl, err); } hasDownloadError = true; logs.push(`[${isoNow()}][${dir}] ❌ [${parentIndex}${index}] Download ${item.sourceUrl} error: ${err}`); } await this.taskService.appendTaskLog(task, logs.join('\n')); logs = []; } finally { if (localFile) { await fs.rm(localFile, { force: true }); } } } } if (hasDownloadError) { logs.push(`[${isoNow()}][${dir}] ❌ Synced dir fail`); } else { logs.push(`[${isoNow()}][${dir}] 🟢 Synced dir success, hasItems: ${hasItems}`); } await this.taskService.appendTaskLog(task, logs.join('\n')); } return [hasDownloadError, hasItems]; } // see https://github.com/cnpm/cnpmcore/issues/556 // 上游可能正在发布新版本、同步流程中断,导致同步的时候,文件列表不一致 // 如果的当前目录命中 latestVersionParent 父目录,那么就再校验一下当前目录 // 如果 existsItems 为空或者经过修改,那么就不需要 revalidate 了 async diff(binaryName, dir, fetchItems, latestVersionParent = '/') { // Use optimized query that only fetches name and date columns // This avoids Bone constructor overhead for each row const existsItems = await this.binaryRepository.listBinaryNameAndDates(binaryName, dir); const existsMap = new Map(); for (const item of existsItems) { existsMap.set(item.name, item); } const diffItems = []; let latestItem; for (const item of fetchItems) { const existsItem = existsMap.get(item.name); if (!existsItem) { diffItems.push({ item: this.createBinary(binaryName, dir, item), reason: 'new item', }); } else if (existsItem.date !== item.date) { // Date changed, create new Binary entity with updated info diffItems.push({ item: this.createBinary(binaryName, dir, item, existsItem), reason: `date diff, local: ${JSON.stringify(existsItem.date)}, remote: ${JSON.stringify(item.date)}`, }); } else if (dir.endsWith(latestVersionParent)) { if (!latestItem) { latestItem = sortBy(fetchItems, ['date']).pop(); } const isLatestItem = latestItem?.name === item.name; if (isLatestItem && item.isDir) { // Revalidate latest version directory diffItems.push({ item: this.createBinary(binaryName, dir, item, existsItem), reason: `revalidate latest version, latest parent dir is ${latestVersionParent}, current dir is ${dir}, current name is ${item.name}`, }); latestVersionParent = `${latestVersionParent}${item.name}`; } } } return { newItems: diffItems, latestVersionDir: latestVersionParent, }; } createBinary(binaryName, dir, fetchItem, existsItem) { const bin = Binary.create({ category: binaryName, parent: dir, name: fetchItem.name, isDir: fetchItem.isDir, size: 0, date: fetchItem.date, sourceUrl: fetchItem.url, ignoreDownloadStatuses: fetchItem.ignoreDownloadStatuses, }); if (existsItem) { bin.id = existsItem.id; // keep binaryId not changed bin.binaryId = existsItem.binaryId; } return bin; } async saveBinaryItem(binary, tmpfile) { if (tmpfile) { const stat = await fs.stat(tmpfile); binary.size = stat.size; await this.nfsAdapter.uploadFile(binary.storePath, tmpfile); this.logger.info('[BinarySyncerService.saveBinaryItem:uploadFile] binaryId: %s, size: %d, %s => %s', binary.binaryId, stat.size, tmpfile, binary.storePath); } await this.binaryRepository.saveBinary(binary); return binary; } async getBinaryAdapter(binaryName) { const config = this.config.cnpmcore; const binaryConfig = binaries[binaryName]; let binaryAdapter; if (config.sourceRegistryIsCNpm) { binaryAdapter = await this.eggObjectFactory.getEggObject(AbstractBinary, BinaryType.Api); } else { binaryAdapter = await this.eggObjectFactory.getEggObject(AbstractBinary, binaryConfig.type); } await binaryAdapter.initFetch(binaryName); return binaryAdapter; } }; __decorate([ Inject(), __metadata("design:type", Function) ], BinarySyncerService.prototype, "binaryRepository", void 0); __decorate([ Inject(), __metadata("design:type", Function) ], BinarySyncerService.prototype, "taskService", void 0); __decorate([ Inject(), __metadata("design:type", Function) ], BinarySyncerService.prototype, "httpClient", void 0); __decorate([ Inject(), __metadata("design:type", Function) ], BinarySyncerService.prototype, "nfsAdapter", void 0); __decorate([ Inject(), __metadata("design:type", Object) ], BinarySyncerService.prototype, "eggObjectFactory", void 0); BinarySyncerService = __decorate([ SingletonProto({ accessLevel: AccessLevel.PUBLIC, }) ], BinarySyncerService); export { BinarySyncerService }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQmluYXJ5U3luY2VyU2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2FwcC9jb3JlL3NlcnZpY2UvQmluYXJ5U3luY2VyU2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7QUFBQSxPQUFPLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUVsQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sRUFBRSxjQUFjLEVBQXFDLE1BQU0sS0FBSyxDQUFDO0FBQzdGLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFFbkMsT0FBTyxRQUFnRCxNQUFNLDZCQUE2QixDQUFDO0FBQzNGLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNsRSxPQUFPLEVBQUUsY0FBYyxFQUFtQixNQUFNLCtDQUErQyxDQUFDO0FBQ2hHLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxnREFBZ0QsQ0FBQztBQUUzRSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDekQsT0FBTyxFQUFFLFNBQVMsRUFBRSxRQUFRLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNoRSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDM0QsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFFOUQsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQzdDLE9BQU8sRUFBRSxJQUFJLEVBQXVCLE1BQU0sbUJBQW1CLENBQUM7QUFHOUQsU0FBUyxNQUFNO0lBQ2IsT0FBTyxJQUFJLElBQUksRUFBRSxDQUFDLFdBQVcsRUFBRSxDQUFDO0FBQ2xDLENBQUM7QUFLTSxJQUFNLG1CQUFtQixHQUF6QixNQUFNLG1CQUFvQixTQUFRLGVBQWU7SUFZdEQsOERBQThEO0lBQzlELDZGQUE2RjtJQUM3Riw0Q0FBNEM7SUFDckMsS0FBSyxDQUFD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