mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
core: use cordis to manage app lifecycle
This commit is contained in:
1 parent
d7ec26b772
commit
5b7067d77d
19 files changed
+307
-375
No files matched your search
@@ -2,8 +2,6 @@
|
||||
/* eslint-disable no-await-in-loop */
|
||||
import cac from 'cac';
|
||||
import { ObjectID } from 'mongodb';
|
||||
import { validate } from '../lib/validator';
|
||||
import options from '../options';
|
||||
import db from '../service/db';
|
||||
import {
|
||||
lib, model, script, service,
|
||||
@@ -24,12 +22,7 @@ function parseParameters(fn: Function) {
|
||||
async function runScript(name: string, arg: any) {
|
||||
const s = global.Hydro.script[name];
|
||||
if (!s) return console.error('Script %s not found.', name);
|
||||
if (typeof s.validate === 'function') {
|
||||
arg = s.validate(arg);
|
||||
} else {
|
||||
console.warn('You are using the legacy script validation API, which will be dropped in the future.');
|
||||
validate(s.validate, arg);
|
||||
}
|
||||
if (typeof s.validate === 'function') arg = s.validate(arg);
|
||||
return await s.run(arg, console.info);
|
||||
}
|
||||
|
||||
@@ -84,26 +77,24 @@ async function cli() {
|
||||
return console.log(result);
|
||||
}
|
||||
|
||||
export async function load() {
|
||||
export async function load(ctx) {
|
||||
const pending = global.addons;
|
||||
const fail = [];
|
||||
require('../lib/i18n');
|
||||
require('../utils');
|
||||
require('../error');
|
||||
require('../options');
|
||||
const opts = options();
|
||||
await db.start(opts);
|
||||
await db.start();
|
||||
await require('../settings').loadConfig();
|
||||
const storage = require('../service/storage');
|
||||
await storage.loadStorageService();
|
||||
require('../lib/index');
|
||||
await lib(pending, fail);
|
||||
await lib(pending, fail, ctx);
|
||||
const systemModel = require('../model/system');
|
||||
await systemModel.runConfig();
|
||||
await service(pending, fail);
|
||||
await service(pending, fail, ctx);
|
||||
require('../model/index');
|
||||
await model(pending, fail);
|
||||
await model(pending, fail, ctx);
|
||||
require('../script/index');
|
||||
await script(pending, fail);
|
||||
await script(pending, fail, ctx);
|
||||
await cli();
|
||||
}
|
||||
@@ -5,10 +5,10 @@ import os from 'os';
|
||||
import path from 'path';
|
||||
import fs from 'fs-extra';
|
||||
import yaml from 'js-yaml';
|
||||
import { Context } from '../context';
|
||||
import i18n from '../lib/i18n';
|
||||
import { Logger } from '../logger';
|
||||
import * as bus from '../service/bus';
|
||||
import { Runtime } from '../service/module';
|
||||
|
||||
const logger = new Logger('common');
|
||||
|
||||
@@ -31,17 +31,14 @@ function locateFile(basePath: string, filenames: string[]) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const getLoader = (type: string, filename: string) => async function loader(pending: string[], fail: string[]) {
|
||||
const getLoader = (type: string, filename: string) => async function loader(pending: string[], fail: string[], ctx: Context) {
|
||||
for (const i of pending) {
|
||||
const p = locateFile(i, [`${filename}.ts`, `${filename}.js`]);
|
||||
if (p && !fail.includes(i)) {
|
||||
try {
|
||||
logger.info(`${type.replace(/^(.)/, (t) => t.toUpperCase())} init: %s`, i);
|
||||
const res = require(p);
|
||||
if (res.apply) {
|
||||
const runtime = new Runtime(p);
|
||||
runtime.load(res);
|
||||
}
|
||||
const m = require(p);
|
||||
if (m.apply) ctx.loader.reloadPlugin(ctx, p, {});
|
||||
else logger.info(`${type.replace(/^(.)/, (t) => t.toUpperCase())} init: %s`, i);
|
||||
} catch (e) {
|
||||
fail.push(i);
|
||||
logger.info(`${type.replace(/^(.)/, (t) => t.toUpperCase())} load fail: %s`, i);
|
||||
@@ -57,6 +54,7 @@ export const addon = getLoader('addon', 'index');
|
||||
export const model = getLoader('model', 'model');
|
||||
export const lib = getLoader('lib', 'lib');
|
||||
export const script = getLoader('script', 'script');
|
||||
export const service = getLoader('service', 'service');
|
||||
|
||||
export async function locale(pending: string[], fail: string[]) {
|
||||
await Promise.all(pending.map(async (i) => {
|
||||
@@ -142,25 +140,3 @@ export async function template(pending: string[], fail: string[]) {
|
||||
}
|
||||
await bus.serial('app/load/template');
|
||||
}
|
||||
|
||||
export async function service(pending: string[], fail: string[]) {
|
||||
for (const i of pending) {
|
||||
const p = locateFile(i, ['service.ts', 'service.js']);
|
||||
if (p && !fail.includes(i)) {
|
||||
try {
|
||||
logger.info('Service init: %s', i);
|
||||
require(p);
|
||||
} catch (e) {
|
||||
fail.push(i);
|
||||
logger.error('Service Load Fail: %s', i);
|
||||
logger.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const key in global.Hydro.service) {
|
||||
if (key === 'server') continue;
|
||||
const srv = global.Hydro.service[key];
|
||||
if (!srv.started && srv.start) await srv.start();
|
||||
}
|
||||
await bus.serial('app/load/service');
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import { Logger } from '../logger';
|
||||
|
||||
const logger = new Logger('setup');
|
||||
const listenPort = cac().parse().options.port || 8888;
|
||||
let resolve;
|
||||
|
||||
async function get(ctx: Context) {
|
||||
ctx.body = `<!DOCTYPE html>
|
||||
@@ -105,7 +106,8 @@ async function post(ctx: Context) {
|
||||
fs.writeFileSync(path.resolve(os.homedir(), '.hydro', 'config.json'), JSON.stringify({
|
||||
host, port, name, username, password,
|
||||
}));
|
||||
ctx.body = '<h1>Done! Please restart Hydro.</h1>';
|
||||
ctx.body = '<h1>Done! Hydro is now starting.</h1>';
|
||||
resolve?.();
|
||||
} catch (e) {
|
||||
ctx.body = `Error connecting to database: ${e.message}\n${e.stack}`;
|
||||
}
|
||||
@@ -123,4 +125,7 @@ export function load() {
|
||||
});
|
||||
server.listen(listenPort);
|
||||
logger.success('Server listening at: %d', listenPort);
|
||||
return new Promise((r) => {
|
||||
resolve = r;
|
||||
});
|
||||
}
|
||||
@@ -4,21 +4,20 @@ import os from 'os';
|
||||
import path from 'path';
|
||||
import cac from 'cac';
|
||||
import fs from 'fs-extra';
|
||||
import { Context } from '../context';
|
||||
import { Logger } from '../logger';
|
||||
import options from '../options';
|
||||
import * as bus from '../service/bus';
|
||||
import db from '../service/db';
|
||||
import { Runtime } from '../service/module';
|
||||
import {
|
||||
addon, handler, lib, locale, model,
|
||||
script, service, setting, template,
|
||||
} from './common';
|
||||
|
||||
const argv = cac().parse();
|
||||
const logger = new Logger('worker');
|
||||
const { loaderDetail: detail, watch } = cac().parse().options;
|
||||
const tmpdir = path.resolve(os.tmpdir(), 'hydro');
|
||||
|
||||
export async function load() {
|
||||
export async function apply(ctx: Context) {
|
||||
fs.ensureDirSync(tmpdir);
|
||||
require('../lib/i18n');
|
||||
require('../utils');
|
||||
@@ -26,66 +25,43 @@ export async function load() {
|
||||
const config = require('../options')();
|
||||
if (!process.env.CI && !config) {
|
||||
logger.info('Starting setup');
|
||||
return require('./setup').load();
|
||||
await require('./setup').load();
|
||||
}
|
||||
const pending = global.addons;
|
||||
const fail = [];
|
||||
if (detail) logger.info('start');
|
||||
await Promise.all([
|
||||
locale(pending, fail),
|
||||
template(pending, fail),
|
||||
]);
|
||||
if (detail) logger.info('finish: locale/template/static');
|
||||
const opts = options();
|
||||
await db.start(opts);
|
||||
await db.start();
|
||||
await require('../settings').loadConfig();
|
||||
if (detail) logger.info('finish: db.connect');
|
||||
const modelSystem = require('../model/system');
|
||||
await modelSystem.runConfig();
|
||||
if (detail) logger.info('finish: config');
|
||||
const storage = require('../service/storage');
|
||||
await storage.loadStorageService();
|
||||
if (detail) logger.info('finish: storage.connect');
|
||||
await require('hydrooj/src/service/server').apply(ctx);
|
||||
// Make sure everything is ready and then start main entry
|
||||
if (argv.options.watch) await ctx.loader.reloadPlugin(ctx, 'hydrooj/src/service/watcher', {});
|
||||
await ctx.root.start();
|
||||
require('../lib/index');
|
||||
if (detail) logger.info('finish: lib.builtin');
|
||||
await lib(pending, fail);
|
||||
if (detail) logger.info('finish: lib.extra');
|
||||
await lib(pending, fail, ctx);
|
||||
require('../service/monitor');
|
||||
if (detail) logger.info('finish: monitor');
|
||||
const server = require('../service/server');
|
||||
await server.prepare();
|
||||
if (detail) logger.info('finish: server');
|
||||
if (watch) require('../service/watcher');
|
||||
await service(pending, fail);
|
||||
if (detail) logger.info('finish: service.extra');
|
||||
await service(pending, fail, ctx);
|
||||
require('../model/index');
|
||||
if (detail) logger.info('finish: model.builtin');
|
||||
const handlerDir = path.resolve(__dirname, '..', 'handler');
|
||||
const handlers = await fs.readdir(handlerDir);
|
||||
for (const h of handlers) {
|
||||
const f = path.resolve(handlerDir, h);
|
||||
const m = require(f);
|
||||
if (m.apply) new Runtime(f).load(m);
|
||||
ctx.loader.reloadPlugin(ctx, path.resolve(handlerDir, h), {}, `hydrooj/handler/${h.split('.')[0]}`);
|
||||
}
|
||||
if (detail) logger.info('finish: handler.builtin');
|
||||
await model(pending, fail);
|
||||
if (detail) logger.info('finish: model.extra');
|
||||
await model(pending, fail, ctx);
|
||||
const modelSetting = require('../model/setting');
|
||||
await setting(pending, fail, modelSetting);
|
||||
if (detail) logger.info('finish: setting');
|
||||
await handler(pending, fail);
|
||||
await addon(pending, fail);
|
||||
if (detail) logger.info('finish: handler.extra');
|
||||
await handler(pending, fail, ctx);
|
||||
await addon(pending, fail, ctx);
|
||||
for (const i in global.Hydro.handler) await global.Hydro.handler[i]();
|
||||
if (detail) logger.info('finish: handler.apply');
|
||||
require('../script/index');
|
||||
if (detail) logger.info('finish: script.builtin');
|
||||
await script(pending, fail);
|
||||
if (detail) logger.info('finish: script.extra');
|
||||
await script(pending, fail, ctx);
|
||||
await bus.serial('app/started');
|
||||
if (detail) logger.info('finish: bus.serial(start)');
|
||||
await server.start();
|
||||
if (detail) logger.info('finish: server.start');
|
||||
if (process.env.NODE_APP_INSTANCE === '0') {
|
||||
const scripts = require('../upgrade').default;
|
||||
let dbVer = (await modelSystem.get('db.ver')) ?? 0;
|
||||
|
||||
Reference in new issue
Block a user