From 973b76a5f0999190bf211d01962882cd69cbafbb Mon Sep 17 00:00:00 2001 From: xion Date: Fri, 11 Oct 2024 22:10:30 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E7=BC=93=E5=AD=98?= =?UTF-8?q?=E4=B8=8B=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.config.json5 | 2 +- package.json | 4 ++-- pnpm-lock.yaml | 38 +++++++++++++++---------------- src/module/get-user-app.ts | 46 ++++++++++++++++++++++++++------------ src/module/index.ts | 31 ++++++++++++++++--------- src/utils/sleep.ts | 1 + 6 files changed, 75 insertions(+), 47 deletions(-) create mode 100644 src/utils/sleep.ts diff --git a/app.config.json5 b/app.config.json5 index 059399e..f13b51f 100644 --- a/app.config.json5 +++ b/app.config.json5 @@ -2,7 +2,7 @@ port: 3005, api: { host: 'localhost:4000', // 后台代理 - testHost: 'localhost:4000', + path: '/api/router', }, allowedOrigins: ['localhost', 'xiongxiao.me', 'zxj.im'], domain: 'kevisual.xiongxiao.me', diff --git a/package.json b/package.json index df04623..8a66ce6 100644 --- a/package.json +++ b/package.json @@ -19,13 +19,13 @@ "@rollup/plugin-json": "^6.1.0", "@rollup/plugin-node-resolve": "^15.3.0", "@rollup/plugin-typescript": "^12.1.0", - "@types/node": "^22.7.4", + "@types/node": "^22.7.5", "cross-env": "^7.0.3", "nodemon": "^3.1.7", "rollup": "^4.24.0", "ts-lib": "^0.0.5", "tslib": "^2.7.0", - "typescript": "^5.6.2" + "typescript": "^5.6.3" }, "dependencies": { "@abearxiong/use-config": "^0.0.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6f54ed6..bdf2328 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -16,7 +16,7 @@ importers: version: 0.0.2 '@abearxiong/use-file-store': specifier: ^0.0.1 - version: 0.0.1(typescript@5.6.2) + version: 0.0.1(typescript@5.6.3) ioredis: specifier: ^5.4.1 version: 5.4.1 @@ -35,10 +35,10 @@ importers: version: 15.3.0(rollup@4.24.0) '@rollup/plugin-typescript': specifier: ^12.1.0 - version: 12.1.0(rollup@4.24.0)(tslib@2.7.0)(typescript@5.6.2) + version: 12.1.0(rollup@4.24.0)(tslib@2.7.0)(typescript@5.6.3) '@types/node': - specifier: ^22.7.4 - version: 22.7.4 + specifier: ^22.7.5 + version: 22.7.5 cross-env: specifier: ^7.0.3 version: 7.0.3 @@ -55,8 +55,8 @@ importers: specifier: ^2.7.0 version: 2.7.0 typescript: - specifier: ^5.6.2 - version: 5.6.2 + specifier: ^5.6.3 + version: 5.6.3 packages: @@ -234,8 +234,8 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - '@types/node@22.7.4': - resolution: {integrity: sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==} + '@types/node@22.7.5': + resolution: {integrity: sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==} '@types/resolve@1.20.2': resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} @@ -738,8 +738,8 @@ packages: tslib@2.7.0: resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==} - typescript@5.6.2: - resolution: {integrity: sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==} + typescript@5.6.3: + resolution: {integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==} engines: {node: '>=14.17'} hasBin: true @@ -785,10 +785,10 @@ snapshots: '@abearxiong/use-config@0.0.2': {} - '@abearxiong/use-file-store@0.0.1(typescript@5.6.2)': + '@abearxiong/use-file-store@0.0.1(typescript@5.6.3)': dependencies: json5: 2.2.3 - ts-loader: 9.5.1(typescript@5.6.2)(webpack@5.95.0) + ts-loader: 9.5.1(typescript@5.6.3)(webpack@5.95.0) webpack: 5.95.0 transitivePeerDependencies: - '@swc/core' @@ -849,11 +849,11 @@ snapshots: optionalDependencies: rollup: 4.24.0 - '@rollup/plugin-typescript@12.1.0(rollup@4.24.0)(tslib@2.7.0)(typescript@5.6.2)': + '@rollup/plugin-typescript@12.1.0(rollup@4.24.0)(tslib@2.7.0)(typescript@5.6.3)': dependencies: '@rollup/pluginutils': 5.1.2(rollup@4.24.0) resolve: 1.22.8 - typescript: 5.6.2 + typescript: 5.6.3 optionalDependencies: rollup: 4.24.0 tslib: 2.7.0 @@ -918,7 +918,7 @@ snapshots: '@types/json-schema@7.0.15': {} - '@types/node@22.7.4': + '@types/node@22.7.5': dependencies: undici-types: 6.19.8 @@ -1210,7 +1210,7 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 22.7.4 + '@types/node': 22.7.5 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -1399,19 +1399,19 @@ snapshots: ts-lib@0.0.5: {} - ts-loader@9.5.1(typescript@5.6.2)(webpack@5.95.0): + ts-loader@9.5.1(typescript@5.6.3)(webpack@5.95.0): dependencies: chalk: 4.1.2 enhanced-resolve: 5.17.1 micromatch: 4.0.8 semver: 7.6.3 source-map: 0.7.4 - typescript: 5.6.2 + typescript: 5.6.3 webpack: 5.95.0 tslib@2.7.0: {} - typescript@5.6.2: {} + typescript@5.6.3: {} undefsafe@2.0.5: {} diff --git a/src/module/get-user-app.ts b/src/module/get-user-app.ts index a644b7a..a8d824f 100644 --- a/src/module/get-user-app.ts +++ b/src/module/get-user-app.ts @@ -9,9 +9,9 @@ import { pipeline } from 'stream'; import { promisify } from 'util'; const pipelineAsync = promisify(pipeline); -const { resources, api } = useConfig<{ resources: string; api: { host: string; testHost: string } }>(); +const { resources, api } = useConfig<{ resources: string; api: { host: string; path: string } }>(); const fileStore = useFileStore('upload'); - +const status: { [key: string]: boolean } = {}; const demoData = { user: 'root', key: 'codeflow', @@ -40,6 +40,7 @@ type UserAppOptions = { user: string; app: string; }; + export class UserApp { user: string; app: string; @@ -82,10 +83,8 @@ export class UserApp { } // 获取域名对应的用户和应用 - const isDev = process.env.NODE_ENV === 'development'; - const fetchTestUrl = 'http://' + api.testHost + '/api/router'; - const fetchUrl = 'http://' + api.host + '/api/router'; - const fetchRes = await fetch(isDev ? fetchTestUrl : fetchUrl, { + const fetchUrl = 'http://' + api.host + api.path; + const fetchRes = await fetch(fetchUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', @@ -114,14 +113,26 @@ export class UserApp { redis.set(key, data.user + ':' + data.app, 'EX', 60 * 60 * 24 * 7); // 24小时 return data; } + async setLoaded() { + const app = this.app; + const user = this.user; + const key = 'user:app:' + app + ':' + user; + if (status[key]) { + status[key] = false; + } + } async setCacheData() { const app = this.app; const user = this.user; const key = 'user:app:' + app + ':' + user; - const isDev = process.env.NODE_ENV === 'development'; - const fetchTestUrl = 'http://' + api.testHost + '/api/router'; - const fetchUrl = 'http://' + api.host + '/api/router'; - const fetchRes = await fetch(isDev ? fetchTestUrl : fetchUrl, { + const fetchUrl = 'http://' + api.host + api.path; + if (status[key]) { + return { + loading: true, + }; + } + status[key] = true; + const fetchRes = await fetch(fetchUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', @@ -137,7 +148,8 @@ export class UserApp { }).then((res) => res.json()); if (fetchRes?.code !== 200) { console.log('fetchRes is error', fetchRes); - return false; + this.setLoaded(); + return { code: 500, message: 'fetchRes is error' }; } const fetchData = fetchRes.data; if (!fetchData.type) { @@ -147,12 +159,17 @@ export class UserApp { } if (fetchData.status !== 'running') { console.error('fetchData status is not running', fetchData.user, fetchData.key); - return null; + this.setLoaded(); + return { + code: 500, + message: 'fetchData status is not running', + }; } const value = await downloadUserAppFiles(user, app, fetchData); if (value.data.files.length === 0) { console.error('root files length is zero', user, app); - return false; + this.setLoaded(); + return { code: 404 }; } let valueIndexHtml = value.data.files.find((file) => file.name === 'index.html'); if (!valueIndexHtml) { @@ -172,8 +189,9 @@ export class UserApp { data[file.name] = file.path; }); await redis.hset('user:app:set:' + app + ':' + user, data); + this.setLoaded(); - return true; + return { code: 200, data: valueIndexHtml.path }; } async getAllCacheData() { const app = this.app; diff --git a/src/module/index.ts b/src/module/index.ts index ccb79c7..d343aab 100644 --- a/src/module/index.ts +++ b/src/module/index.ts @@ -7,6 +7,7 @@ import fs from 'fs'; import { useConfig } from '@abearxiong/use-config'; import { redis } from './redis/redis.ts'; import { getContentType } from './get-content-type.ts'; +import { sleep } from '@/utils/sleep.ts'; const { api, domain, allowedOrigins } = useConfig<{ api: { host: string; @@ -128,30 +129,38 @@ export const handleRequest = async (req: http.IncomingMessage, res: http.ServerR let isExist = await userApp.getExist(); if (!isExist) { try { - const hasApp = await userApp.setCacheData(); - if (!hasApp) { + const { code, loading, data } = await userApp.setCacheData(); + if (loading) { + res.writeHead(200, { 'Content-Type': 'text/html' }); + res.write('Loading App\n'); + res.end(); + return; + } + if (code !== 200) { res.writeHead(404, { 'Content-Type': 'text/html' }); res.write('Not Found App\n'); res.end(); return; } + await sleep(1000); + isExist = data; // 设置缓存后再次获取 + if (!isExist) { + res.writeHead(404, { 'Content-Type': 'text/html' }); + res.write('Not Found App Index Page\n'); + res.end(); + return; + } } catch (error) { console.error('setCacheData error', error); res.writeHead(500, { 'Content-Type': 'text/html' }); res.write('Server Error\n'); res.end(); - return; - } - - isExist = await userApp.getExist(); - if (!isExist) { - res.writeHead(404, { 'Content-Type': 'text/html' }); - res.write('Not Found App Index Page\n'); - res.end(); + userApp.setLoaded(); return; } } - const indexFile = isExist; + const indexFile = isExist; // 已经必定存在了 + let appFileUrl: string; if (domainApp) { appFileUrl = (url + '').replace(`/`, ''); diff --git a/src/utils/sleep.ts b/src/utils/sleep.ts new file mode 100644 index 0000000..fe57bb6 --- /dev/null +++ b/src/utils/sleep.ts @@ -0,0 +1 @@ +export const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));