import { createHash } from "node:crypto"; import { Pool } from "pg"; import { ILibraries, ILibrariesMap, IVersion, IVersionPool } from "../types/versionlist.types.js"; export class VersionListController { versionCache: IVersion[]; private pool: Pool; hashList: string[]; libmap: Map; constructor(pool: Pool) { this.pool = pool; this.versionCache = []; this.hashList = ["md5", "sha1", "sha256"]; this.libmap = new Map(); this._refreshCache(); // 初始化缓存 setInterval(this._refreshCache.bind(this), 1000 * 60 * 60 * 2); // 2小时刷新缓存(傻逼this) setInterval(this._refreshLib.bind(this),1000*60*60*1) // 1小时刷新libmap } async getVersionList() { if (this.versionCache.length === 0) { await this._refreshCache(); } console.log("use cache"); return this.versionCache; } private async _refreshCache() { const arr: any[] = []; const result = ( await this.pool.query(` SELECT mcversion."version", mcversion."Type", mcversion."Date", array_agg(DISTINCT variation.arch) as arch, variation."OSbuild" FROM variation LEFT JOIN mcversion ON mcversion.id = variation."MCVId" GROUP BY mcversion."version", mcversion."Type", mcversion."Date", variation."OSbuild" ORDER BY "Date" DESC `) ).rows; result.forEach((row: IVersionPool) => { const url: string[] = []; for (const arch of row.arch) { url.push(`./mc/version/${row.version}/${arch}`); } arr.push({ id: row.version, type: row.Type, BuildType: "UWP", OSBuild: row.OSbuild, Arch: row.arch, url, time: row.Date, }); }); this.versionCache = arr; } async getLibraries(id: string, arch: string) { const archs = ["x64", "x86", "arm"]; if ( !archs.includes(arch) || this.versionCache.filter((v) => v.id === id).length === 0 ) { return; } const ver = `${id}-${arch}` let value = this.libmap.get(ver) if (value){ value.hits++ console.log("lib hits"+value.hits) return {libraries:value.libraries} } const r = ( await this.pool.query( ` SELECT variation.id FROM variation LEFT JOIN mcversion ON mcversion.id = variation."MCVId" WHERE mcversion."versionHash" = $1 AND variation.arch = $2 LIMIT 1 `, [createHash("sha256").update(id).digest(), arch] ) ).rows; // 获取版本id const data: ILibraries[] = ( await this.pool.query( ` SELECT "filePathName"."pathName", "filesHash"."size", ${this.hashList .map((hash) => `encode("filesHash"."${hash}", 'hex') as "${hash}"`) .join(", ")} FROM variation_files_data LEFT JOIN files ON files.id = variation_files_data."filesId" LEFT JOIN "filePathName" ON "filePathName".id = files."pathNameId" LEFT JOIN "filesHash" ON "filesHash".id = files."hashId" WHERE variation_files_data."variationId" = $1 `, [r[0].id] ) ).rows; //获取信息 this.libmap.set(ver,{libraries:data,hits:0}) //初始化 return { libraries: data}; } _refreshLib(){ this.libmap.forEach((val,key)=>{ if (val.hits<15){ this.libmap.delete(key); } }) } }