feat:缓存与hash下载
This commit is contained in:
@@ -1,16 +1,20 @@
|
|||||||
import { createHash } from "node:crypto";
|
import { createHash } from "node:crypto";
|
||||||
import { Pool } from "pg";
|
import { Pool } from "pg";
|
||||||
|
import { ILibraries, ILibrariesMap, IVersion, IVersionPool } from "../types/versionlist.types.js";
|
||||||
|
|
||||||
export class VersionListController {
|
export class VersionListController {
|
||||||
versionCache: Version[];
|
versionCache: IVersion[];
|
||||||
private pool: Pool;
|
private pool: Pool;
|
||||||
hashList: string[];
|
hashList: string[];
|
||||||
|
libmap: Map<string, ILibrariesMap>;
|
||||||
constructor(pool: Pool) {
|
constructor(pool: Pool) {
|
||||||
this.pool = pool;
|
this.pool = pool;
|
||||||
this.versionCache = [];
|
this.versionCache = [];
|
||||||
this.hashList = ["md5", "sha1", "sha256"];
|
this.hashList = ["md5", "sha1", "sha256"];
|
||||||
|
this.libmap = new Map();
|
||||||
this._refreshCache(); // 初始化缓存
|
this._refreshCache(); // 初始化缓存
|
||||||
setInterval(this._refreshCache, 1000 * 60 * 60 * 2); // 2小时刷新缓存
|
setInterval(this._refreshCache, 1000 * 60 * 60 * 2); // 2小时刷新缓存
|
||||||
|
setInterval(this._refreshLib,1000*60*60*1) // 1小时刷新libmap
|
||||||
}
|
}
|
||||||
|
|
||||||
async getVersionList() {
|
async getVersionList() {
|
||||||
@@ -36,19 +40,19 @@ GROUP BY mcversion."version", mcversion."Type", mcversion."Date", variation."OSb
|
|||||||
ORDER BY "Date" DESC
|
ORDER BY "Date" DESC
|
||||||
`)
|
`)
|
||||||
).rows;
|
).rows;
|
||||||
result.forEach((row: VersionPool) => {
|
result.forEach((row: IVersionPool) => {
|
||||||
const url: string[] = [];
|
const url: string[] = [];
|
||||||
for (const arch of row.arch) {
|
for (const arch of row.arch) {
|
||||||
url.push(`./mc/version/${row.version}/${arch}`);
|
url.push(`./mc/version/${row.version}/${arch}`);
|
||||||
|
}
|
||||||
arr.push({
|
arr.push({
|
||||||
id: row.version,
|
id: row.version,
|
||||||
type: row.Type,
|
type: row.Type,
|
||||||
BuildType: "UWP",
|
BuildType: "UWP",
|
||||||
Arch: ["x64", "x86"],
|
Arch: row.arch,
|
||||||
url,
|
url,
|
||||||
time: row.Date,
|
time: row.Date,
|
||||||
});
|
});
|
||||||
}
|
|
||||||
});
|
});
|
||||||
this.versionCache = arr;
|
this.versionCache = arr;
|
||||||
}
|
}
|
||||||
@@ -61,6 +65,15 @@ ORDER BY "Date" DESC
|
|||||||
) {
|
) {
|
||||||
return;
|
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 = (
|
const r = (
|
||||||
await this.pool.query(
|
await this.pool.query(
|
||||||
`
|
`
|
||||||
@@ -75,12 +88,14 @@ LIMIT 1
|
|||||||
)
|
)
|
||||||
).rows; // 获取版本id
|
).rows; // 获取版本id
|
||||||
|
|
||||||
const data = (
|
const data: ILibraries[] = (
|
||||||
await this.pool.query(
|
await this.pool.query(
|
||||||
`
|
`
|
||||||
SELECT "filePathName"."pathName",
|
SELECT "filePathName"."pathName",
|
||||||
"filesHash"."size",
|
"filesHash"."size",
|
||||||
${this.hashList.map(hash => `encode("filesHash"."${hash}", 'hex') as "${hash}"`).join(', ')}
|
${this.hashList
|
||||||
|
.map((hash) => `encode("filesHash"."${hash}", 'hex') as "${hash}"`)
|
||||||
|
.join(", ")}
|
||||||
FROM variation_files_data
|
FROM variation_files_data
|
||||||
LEFT JOIN files ON files.id = variation_files_data."filesId"
|
LEFT JOIN files ON files.id = variation_files_data."filesId"
|
||||||
LEFT JOIN "filePathName" ON "filePathName".id = files."pathNameId"
|
LEFT JOIN "filePathName" ON "filePathName".id = files."pathNameId"
|
||||||
@@ -89,22 +104,16 @@ WHERE variation_files_data."variationId" = $1
|
|||||||
`,
|
`,
|
||||||
[r[0].id]
|
[r[0].id]
|
||||||
)
|
)
|
||||||
).rows;
|
).rows; //获取信息
|
||||||
console.log(data);
|
this.libmap.set(ver,{libraries:data,hits:0}) //初始化
|
||||||
return data;
|
return { libraries: data};
|
||||||
}
|
|
||||||
}
|
|
||||||
interface VersionPool {
|
|
||||||
id: number;
|
|
||||||
version: string;
|
|
||||||
Type: string;
|
|
||||||
Date: string;
|
|
||||||
arch: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Version {
|
_refreshLib(){
|
||||||
id: string;
|
this.libmap.forEach((val,key)=>{
|
||||||
type: string;
|
if (val.hits<15){
|
||||||
url: string;
|
this.libmap.delete(key);
|
||||||
time: string;
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
import express from "express";
|
import express from "express";
|
||||||
import config from "./utils/config.js";
|
import config from "./utils/config.js";
|
||||||
import versionlistRouter from "./router/versionlist.router.js";
|
import versionlistRouter from "./router/versionlist.router.js";
|
||||||
|
import downloadRouter from "./router/download.router.js";
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
|
|
||||||
app.use('/mc',versionlistRouter)
|
app.use('/mc',versionlistRouter)
|
||||||
|
app.use('/download',downloadRouter)
|
||||||
app.listen(config.express.port,()=>{
|
app.listen(config.express.port,()=>{
|
||||||
console.log(`server is running on port ${config.express.port}`);
|
console.log(`server is running on port ${config.express.port}`);
|
||||||
})
|
})
|
||||||
9
src/middleware/download.mw.ts
Normal file
9
src/middleware/download.mw.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { Request, Response, NextFunction } from "express";
|
||||||
|
export function hashMiddleware(req:Request,res:Response,next:NextFunction){
|
||||||
|
if (req.params.hash.length !== 32){
|
||||||
|
res.sendStatus(400);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
next();
|
||||||
|
return;
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import { Router, Request, Response } from "express";
|
||||||
|
//import pool from "../utils/pgsql.js";
|
||||||
|
import { hashMiddleware } from "../middleware/download.mw.js";
|
||||||
|
|
||||||
|
const router = Router();
|
||||||
|
|
||||||
|
//const map = new Map<string,string>();
|
||||||
|
router.get("/:hash",hashMiddleware,(req:Request,res:Response)=>{
|
||||||
|
const hash = req.params.hash;
|
||||||
|
const hash1 = hash.substring(0,2)
|
||||||
|
res.redirect(302,`r2.cloudflare.com/${hash1}/${hash}`)
|
||||||
|
})
|
||||||
|
|
||||||
|
export default router;
|
||||||
@@ -6,8 +6,8 @@ const versionListController = new VersionListController(pool);
|
|||||||
const router = Router();
|
const router = Router();
|
||||||
|
|
||||||
router.get("/version_manifest", async (req: Request, res: Response) => {
|
router.get("/version_manifest", async (req: Request, res: Response) => {
|
||||||
const version = await versionListController.getVersionList();
|
const versions = await versionListController.getVersionList();
|
||||||
res.status(200).json({ version });
|
res.status(200).json({ versions });
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get("/version/:id/:arch", async (req: Request, res: Response) => {
|
router.get("/version/:id/:arch", async (req: Request, res: Response) => {
|
||||||
@@ -18,6 +18,6 @@ router.get("/version/:id/:arch", async (req: Request, res: Response) => {
|
|||||||
res.sendStatus(404);
|
res.sendStatus(404);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
res.status(200).json({ libraries });
|
res.status(200).json(libraries);
|
||||||
})
|
})
|
||||||
export default router;
|
export default router;
|
||||||
|
|||||||
27
src/types/versionlist.types.ts
Normal file
27
src/types/versionlist.types.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
export interface IVersionPool {
|
||||||
|
id: number;
|
||||||
|
version: string;
|
||||||
|
Type: string;
|
||||||
|
Date: string;
|
||||||
|
arch: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IVersion {
|
||||||
|
id: string;
|
||||||
|
type: string;
|
||||||
|
url: string;
|
||||||
|
time: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ILibraries {
|
||||||
|
pathName: string;
|
||||||
|
size: number;
|
||||||
|
md5: string;
|
||||||
|
sha1: string;
|
||||||
|
sha256: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ILibrariesMap {
|
||||||
|
libraries: ILibraries[];
|
||||||
|
hits: number;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user