perf: 优化缓存下载
This commit is contained in:
parent
79287d7de9
commit
973b76a5f0
@ -2,7 +2,7 @@
|
|||||||
port: 3005,
|
port: 3005,
|
||||||
api: {
|
api: {
|
||||||
host: 'localhost:4000', // 后台代理
|
host: 'localhost:4000', // 后台代理
|
||||||
testHost: 'localhost:4000',
|
path: '/api/router',
|
||||||
},
|
},
|
||||||
allowedOrigins: ['localhost', 'xiongxiao.me', 'zxj.im'],
|
allowedOrigins: ['localhost', 'xiongxiao.me', 'zxj.im'],
|
||||||
domain: 'kevisual.xiongxiao.me',
|
domain: 'kevisual.xiongxiao.me',
|
||||||
|
@ -19,13 +19,13 @@
|
|||||||
"@rollup/plugin-json": "^6.1.0",
|
"@rollup/plugin-json": "^6.1.0",
|
||||||
"@rollup/plugin-node-resolve": "^15.3.0",
|
"@rollup/plugin-node-resolve": "^15.3.0",
|
||||||
"@rollup/plugin-typescript": "^12.1.0",
|
"@rollup/plugin-typescript": "^12.1.0",
|
||||||
"@types/node": "^22.7.4",
|
"@types/node": "^22.7.5",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"nodemon": "^3.1.7",
|
"nodemon": "^3.1.7",
|
||||||
"rollup": "^4.24.0",
|
"rollup": "^4.24.0",
|
||||||
"ts-lib": "^0.0.5",
|
"ts-lib": "^0.0.5",
|
||||||
"tslib": "^2.7.0",
|
"tslib": "^2.7.0",
|
||||||
"typescript": "^5.6.2"
|
"typescript": "^5.6.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@abearxiong/use-config": "^0.0.2",
|
"@abearxiong/use-config": "^0.0.2",
|
||||||
|
38
pnpm-lock.yaml
generated
38
pnpm-lock.yaml
generated
@ -16,7 +16,7 @@ importers:
|
|||||||
version: 0.0.2
|
version: 0.0.2
|
||||||
'@abearxiong/use-file-store':
|
'@abearxiong/use-file-store':
|
||||||
specifier: ^0.0.1
|
specifier: ^0.0.1
|
||||||
version: 0.0.1(typescript@5.6.2)
|
version: 0.0.1(typescript@5.6.3)
|
||||||
ioredis:
|
ioredis:
|
||||||
specifier: ^5.4.1
|
specifier: ^5.4.1
|
||||||
version: 5.4.1
|
version: 5.4.1
|
||||||
@ -35,10 +35,10 @@ importers:
|
|||||||
version: 15.3.0(rollup@4.24.0)
|
version: 15.3.0(rollup@4.24.0)
|
||||||
'@rollup/plugin-typescript':
|
'@rollup/plugin-typescript':
|
||||||
specifier: ^12.1.0
|
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':
|
'@types/node':
|
||||||
specifier: ^22.7.4
|
specifier: ^22.7.5
|
||||||
version: 22.7.4
|
version: 22.7.5
|
||||||
cross-env:
|
cross-env:
|
||||||
specifier: ^7.0.3
|
specifier: ^7.0.3
|
||||||
version: 7.0.3
|
version: 7.0.3
|
||||||
@ -55,8 +55,8 @@ importers:
|
|||||||
specifier: ^2.7.0
|
specifier: ^2.7.0
|
||||||
version: 2.7.0
|
version: 2.7.0
|
||||||
typescript:
|
typescript:
|
||||||
specifier: ^5.6.2
|
specifier: ^5.6.3
|
||||||
version: 5.6.2
|
version: 5.6.3
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
|
|
||||||
@ -234,8 +234,8 @@ packages:
|
|||||||
'@types/json-schema@7.0.15':
|
'@types/json-schema@7.0.15':
|
||||||
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
|
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
|
||||||
|
|
||||||
'@types/node@22.7.4':
|
'@types/node@22.7.5':
|
||||||
resolution: {integrity: sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==}
|
resolution: {integrity: sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==}
|
||||||
|
|
||||||
'@types/resolve@1.20.2':
|
'@types/resolve@1.20.2':
|
||||||
resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==}
|
resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==}
|
||||||
@ -738,8 +738,8 @@ packages:
|
|||||||
tslib@2.7.0:
|
tslib@2.7.0:
|
||||||
resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==}
|
resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==}
|
||||||
|
|
||||||
typescript@5.6.2:
|
typescript@5.6.3:
|
||||||
resolution: {integrity: sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==}
|
resolution: {integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==}
|
||||||
engines: {node: '>=14.17'}
|
engines: {node: '>=14.17'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
@ -785,10 +785,10 @@ snapshots:
|
|||||||
|
|
||||||
'@abearxiong/use-config@0.0.2': {}
|
'@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:
|
dependencies:
|
||||||
json5: 2.2.3
|
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
|
webpack: 5.95.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@swc/core'
|
- '@swc/core'
|
||||||
@ -849,11 +849,11 @@ snapshots:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
rollup: 4.24.0
|
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:
|
dependencies:
|
||||||
'@rollup/pluginutils': 5.1.2(rollup@4.24.0)
|
'@rollup/pluginutils': 5.1.2(rollup@4.24.0)
|
||||||
resolve: 1.22.8
|
resolve: 1.22.8
|
||||||
typescript: 5.6.2
|
typescript: 5.6.3
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
rollup: 4.24.0
|
rollup: 4.24.0
|
||||||
tslib: 2.7.0
|
tslib: 2.7.0
|
||||||
@ -918,7 +918,7 @@ snapshots:
|
|||||||
|
|
||||||
'@types/json-schema@7.0.15': {}
|
'@types/json-schema@7.0.15': {}
|
||||||
|
|
||||||
'@types/node@22.7.4':
|
'@types/node@22.7.5':
|
||||||
dependencies:
|
dependencies:
|
||||||
undici-types: 6.19.8
|
undici-types: 6.19.8
|
||||||
|
|
||||||
@ -1210,7 +1210,7 @@ snapshots:
|
|||||||
|
|
||||||
jest-worker@27.5.1:
|
jest-worker@27.5.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 22.7.4
|
'@types/node': 22.7.5
|
||||||
merge-stream: 2.0.0
|
merge-stream: 2.0.0
|
||||||
supports-color: 8.1.1
|
supports-color: 8.1.1
|
||||||
|
|
||||||
@ -1399,19 +1399,19 @@ snapshots:
|
|||||||
|
|
||||||
ts-lib@0.0.5: {}
|
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:
|
dependencies:
|
||||||
chalk: 4.1.2
|
chalk: 4.1.2
|
||||||
enhanced-resolve: 5.17.1
|
enhanced-resolve: 5.17.1
|
||||||
micromatch: 4.0.8
|
micromatch: 4.0.8
|
||||||
semver: 7.6.3
|
semver: 7.6.3
|
||||||
source-map: 0.7.4
|
source-map: 0.7.4
|
||||||
typescript: 5.6.2
|
typescript: 5.6.3
|
||||||
webpack: 5.95.0
|
webpack: 5.95.0
|
||||||
|
|
||||||
tslib@2.7.0: {}
|
tslib@2.7.0: {}
|
||||||
|
|
||||||
typescript@5.6.2: {}
|
typescript@5.6.3: {}
|
||||||
|
|
||||||
undefsafe@2.0.5: {}
|
undefsafe@2.0.5: {}
|
||||||
|
|
||||||
|
@ -9,9 +9,9 @@ import { pipeline } from 'stream';
|
|||||||
import { promisify } from 'util';
|
import { promisify } from 'util';
|
||||||
const pipelineAsync = promisify(pipeline);
|
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 fileStore = useFileStore('upload');
|
||||||
|
const status: { [key: string]: boolean } = {};
|
||||||
const demoData = {
|
const demoData = {
|
||||||
user: 'root',
|
user: 'root',
|
||||||
key: 'codeflow',
|
key: 'codeflow',
|
||||||
@ -40,6 +40,7 @@ type UserAppOptions = {
|
|||||||
user: string;
|
user: string;
|
||||||
app: string;
|
app: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export class UserApp {
|
export class UserApp {
|
||||||
user: string;
|
user: string;
|
||||||
app: string;
|
app: string;
|
||||||
@ -82,10 +83,8 @@ export class UserApp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 获取域名对应的用户和应用
|
// 获取域名对应的用户和应用
|
||||||
const isDev = process.env.NODE_ENV === 'development';
|
const fetchUrl = 'http://' + api.host + api.path;
|
||||||
const fetchTestUrl = 'http://' + api.testHost + '/api/router';
|
const fetchRes = await fetch(fetchUrl, {
|
||||||
const fetchUrl = 'http://' + api.host + '/api/router';
|
|
||||||
const fetchRes = await fetch(isDev ? fetchTestUrl : fetchUrl, {
|
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
@ -114,14 +113,26 @@ export class UserApp {
|
|||||||
redis.set(key, data.user + ':' + data.app, 'EX', 60 * 60 * 24 * 7); // 24小时
|
redis.set(key, data.user + ':' + data.app, 'EX', 60 * 60 * 24 * 7); // 24小时
|
||||||
return data;
|
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() {
|
async setCacheData() {
|
||||||
const app = this.app;
|
const app = this.app;
|
||||||
const user = this.user;
|
const user = this.user;
|
||||||
const key = 'user:app:' + app + ':' + user;
|
const key = 'user:app:' + app + ':' + user;
|
||||||
const isDev = process.env.NODE_ENV === 'development';
|
const fetchUrl = 'http://' + api.host + api.path;
|
||||||
const fetchTestUrl = 'http://' + api.testHost + '/api/router';
|
if (status[key]) {
|
||||||
const fetchUrl = 'http://' + api.host + '/api/router';
|
return {
|
||||||
const fetchRes = await fetch(isDev ? fetchTestUrl : fetchUrl, {
|
loading: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
status[key] = true;
|
||||||
|
const fetchRes = await fetch(fetchUrl, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
@ -137,7 +148,8 @@ export class UserApp {
|
|||||||
}).then((res) => res.json());
|
}).then((res) => res.json());
|
||||||
if (fetchRes?.code !== 200) {
|
if (fetchRes?.code !== 200) {
|
||||||
console.log('fetchRes is error', fetchRes);
|
console.log('fetchRes is error', fetchRes);
|
||||||
return false;
|
this.setLoaded();
|
||||||
|
return { code: 500, message: 'fetchRes is error' };
|
||||||
}
|
}
|
||||||
const fetchData = fetchRes.data;
|
const fetchData = fetchRes.data;
|
||||||
if (!fetchData.type) {
|
if (!fetchData.type) {
|
||||||
@ -147,12 +159,17 @@ export class UserApp {
|
|||||||
}
|
}
|
||||||
if (fetchData.status !== 'running') {
|
if (fetchData.status !== 'running') {
|
||||||
console.error('fetchData status is not running', fetchData.user, fetchData.key);
|
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);
|
const value = await downloadUserAppFiles(user, app, fetchData);
|
||||||
if (value.data.files.length === 0) {
|
if (value.data.files.length === 0) {
|
||||||
console.error('root files length is zero', user, app);
|
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');
|
let valueIndexHtml = value.data.files.find((file) => file.name === 'index.html');
|
||||||
if (!valueIndexHtml) {
|
if (!valueIndexHtml) {
|
||||||
@ -172,8 +189,9 @@ export class UserApp {
|
|||||||
data[file.name] = file.path;
|
data[file.name] = file.path;
|
||||||
});
|
});
|
||||||
await redis.hset('user:app:set:' + app + ':' + user, data);
|
await redis.hset('user:app:set:' + app + ':' + user, data);
|
||||||
|
this.setLoaded();
|
||||||
|
|
||||||
return true;
|
return { code: 200, data: valueIndexHtml.path };
|
||||||
}
|
}
|
||||||
async getAllCacheData() {
|
async getAllCacheData() {
|
||||||
const app = this.app;
|
const app = this.app;
|
||||||
|
@ -7,6 +7,7 @@ import fs from 'fs';
|
|||||||
import { useConfig } from '@abearxiong/use-config';
|
import { useConfig } from '@abearxiong/use-config';
|
||||||
import { redis } from './redis/redis.ts';
|
import { redis } from './redis/redis.ts';
|
||||||
import { getContentType } from './get-content-type.ts';
|
import { getContentType } from './get-content-type.ts';
|
||||||
|
import { sleep } from '@/utils/sleep.ts';
|
||||||
const { api, domain, allowedOrigins } = useConfig<{
|
const { api, domain, allowedOrigins } = useConfig<{
|
||||||
api: {
|
api: {
|
||||||
host: string;
|
host: string;
|
||||||
@ -128,30 +129,38 @@ export const handleRequest = async (req: http.IncomingMessage, res: http.ServerR
|
|||||||
let isExist = await userApp.getExist();
|
let isExist = await userApp.getExist();
|
||||||
if (!isExist) {
|
if (!isExist) {
|
||||||
try {
|
try {
|
||||||
const hasApp = await userApp.setCacheData();
|
const { code, loading, data } = await userApp.setCacheData();
|
||||||
if (!hasApp) {
|
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.writeHead(404, { 'Content-Type': 'text/html' });
|
||||||
res.write('Not Found App\n');
|
res.write('Not Found App\n');
|
||||||
res.end();
|
res.end();
|
||||||
return;
|
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) {
|
} catch (error) {
|
||||||
console.error('setCacheData error', error);
|
console.error('setCacheData error', error);
|
||||||
res.writeHead(500, { 'Content-Type': 'text/html' });
|
res.writeHead(500, { 'Content-Type': 'text/html' });
|
||||||
res.write('Server Error\n');
|
res.write('Server Error\n');
|
||||||
res.end();
|
res.end();
|
||||||
|
userApp.setLoaded();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
const indexFile = isExist; // 已经必定存在了
|
||||||
|
|
||||||
isExist = await userApp.getExist();
|
|
||||||
if (!isExist) {
|
|
||||||
res.writeHead(404, { 'Content-Type': 'text/html' });
|
|
||||||
res.write('Not Found App Index Page\n');
|
|
||||||
res.end();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const indexFile = isExist;
|
|
||||||
let appFileUrl: string;
|
let appFileUrl: string;
|
||||||
if (domainApp) {
|
if (domainApp) {
|
||||||
appFileUrl = (url + '').replace(`/`, '');
|
appFileUrl = (url + '').replace(`/`, '');
|
||||||
|
1
src/utils/sleep.ts
Normal file
1
src/utils/sleep.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
|
Loading…
x
Reference in New Issue
Block a user