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(`/`, '');
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user