perf: 优化缓存下载
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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(`/`, '');
|
||||
|
||||
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));
|
||||
Reference in New Issue
Block a user