mirror of
https://github.com/whyour/qinglong.git
synced 2025-12-23 15:50:07 +08:00
246 lines
7.2 KiB
TypeScript
246 lines
7.2 KiB
TypeScript
import DependenceService from '../services/dependence';
|
||
import { exec } from 'child_process';
|
||
import { Container } from 'typedi';
|
||
import { Crontab, CrontabModel, CrontabStatus } from '../data/cron';
|
||
import CronService from '../services/cron';
|
||
import EnvService from '../services/env';
|
||
import { DependenceModel, DependenceStatus } from '../data/dependence';
|
||
import { Op } from 'sequelize';
|
||
import config from '../config';
|
||
import { CrontabViewModel, CronViewType } from '../data/cronView';
|
||
import { initPosition } from '../data/env';
|
||
import { AuthDataType, SystemModel } from '../data/system';
|
||
import SystemService from '../services/system';
|
||
import UserService from '../services/user';
|
||
import { writeFile, readFile } from 'fs/promises';
|
||
import { createRandomString, fileExist, safeJSONParse, isPidRunning } from '../config/util';
|
||
import OpenService from '../services/open';
|
||
import { shareStore } from '../shared/store';
|
||
import Logger from './logger';
|
||
import { AppModel } from '../data/open';
|
||
|
||
export default async () => {
|
||
const cronService = Container.get(CronService);
|
||
const envService = Container.get(EnvService);
|
||
const dependenceService = Container.get(DependenceService);
|
||
const systemService = Container.get(SystemService);
|
||
const userService = Container.get(UserService);
|
||
const openService = Container.get(OpenService);
|
||
|
||
// 初始化增加系统配置
|
||
let systemApp = (
|
||
await AppModel.findOne({
|
||
where: { name: 'system' },
|
||
})
|
||
)?.get({ plain: true });
|
||
if (!systemApp) {
|
||
systemApp = await AppModel.create({
|
||
name: 'system',
|
||
scopes: ['crons', 'system'],
|
||
client_id: createRandomString(12, 12),
|
||
client_secret: createRandomString(24, 24),
|
||
});
|
||
}
|
||
const [systemConfig] = await SystemModel.findOrCreate({
|
||
where: { type: AuthDataType.systemConfig },
|
||
});
|
||
await SystemModel.findOrCreate({
|
||
where: { type: AuthDataType.notification },
|
||
});
|
||
const [authConfig] = await SystemModel.findOrCreate({
|
||
where: { type: AuthDataType.authConfig },
|
||
});
|
||
if (!authConfig?.info) {
|
||
let authInfo = {
|
||
username: 'admin',
|
||
password: 'admin',
|
||
};
|
||
try {
|
||
const authFileExist = await fileExist(config.authConfigFile);
|
||
if (authFileExist) {
|
||
const content = await readFile(config.authConfigFile, 'utf8');
|
||
authInfo = safeJSONParse(content);
|
||
}
|
||
} catch (error) {
|
||
Logger.warn('Failed to read auth config file, using default credentials');
|
||
}
|
||
await SystemModel.upsert({
|
||
id: authConfig?.id,
|
||
info: authInfo,
|
||
type: AuthDataType.authConfig,
|
||
});
|
||
}
|
||
|
||
const installDependencies = async () => {
|
||
const docs = await DependenceModel.findAll({
|
||
where: {},
|
||
order: [
|
||
['type', 'DESC'],
|
||
['createdAt', 'DESC'],
|
||
],
|
||
raw: true,
|
||
});
|
||
|
||
await DependenceModel.update(
|
||
{ status: DependenceStatus.queued, log: [] },
|
||
{ where: { id: docs.map((x) => x.id!) } },
|
||
);
|
||
|
||
setTimeout(async () => {
|
||
await dependenceService.installDependenceOneByOne(docs);
|
||
|
||
const bootAfterLoader = await import('./bootAfter');
|
||
bootAfterLoader.default();
|
||
}, 5000);
|
||
};
|
||
|
||
// 初始化更新 linux/python/nodejs 镜像源配置
|
||
if (systemConfig.info?.pythonMirror) {
|
||
systemService.updatePythonMirror({
|
||
pythonMirror: systemConfig.info?.pythonMirror,
|
||
});
|
||
}
|
||
if (systemConfig.info?.linuxMirror) {
|
||
systemService.updateLinuxMirror(
|
||
{
|
||
linuxMirror: systemConfig.info?.linuxMirror,
|
||
},
|
||
undefined,
|
||
() => installDependencies(),
|
||
);
|
||
} else {
|
||
installDependencies();
|
||
}
|
||
if (systemConfig.info?.nodeMirror) {
|
||
systemService.updateNodeMirror({
|
||
nodeMirror: systemConfig.info?.nodeMirror,
|
||
});
|
||
}
|
||
|
||
// 初始化新增默认全部任务视图
|
||
CrontabViewModel.findAll({
|
||
where: { type: CronViewType.系统, name: '全部任务' },
|
||
raw: true,
|
||
}).then((docs) => {
|
||
if (docs.length === 0) {
|
||
CrontabViewModel.create({
|
||
name: '全部任务',
|
||
type: CronViewType.系统,
|
||
position: initPosition / 2,
|
||
});
|
||
}
|
||
});
|
||
|
||
// 初始化更新所有任务状态为空闲
|
||
// 但保留仍在运行的任务的状态
|
||
const allCrons = await CrontabModel.findAll({ raw: true });
|
||
const idsToReset: number[] = [];
|
||
|
||
for (const cron of allCrons) {
|
||
// 如果任务有 PID 且进程仍在运行,则保持其状态
|
||
if (cron.pid != null && isPidRunning(cron.pid)) {
|
||
// 保留当前状态(running 或 queued)
|
||
continue;
|
||
}
|
||
// 收集需要重置的任务 ID
|
||
if (cron.id) {
|
||
idsToReset.push(cron.id);
|
||
}
|
||
}
|
||
|
||
// 批量更新所有需要重置的任务
|
||
if (idsToReset.length > 0) {
|
||
await CrontabModel.update(
|
||
{ status: CrontabStatus.idle, pid: undefined },
|
||
{ where: { id: { [Op.in]: idsToReset } } }
|
||
);
|
||
}
|
||
|
||
// 初始化时执行一次所有的 ql repo 任务
|
||
CrontabModel.findAll({
|
||
where: {
|
||
isDisabled: { [Op.ne]: 1 },
|
||
command: {
|
||
[Op.or]: [{ [Op.like]: `%ql repo%` }, { [Op.like]: `%ql raw%` }],
|
||
},
|
||
},
|
||
}).then((docs) => {
|
||
for (let i = 0; i < docs.length; i++) {
|
||
const doc = docs[i];
|
||
if (doc) {
|
||
exec(doc.command);
|
||
}
|
||
}
|
||
});
|
||
|
||
// 更新2.11.3以前的脚本路径
|
||
CrontabModel.findAll({
|
||
where: {
|
||
command: {
|
||
[Op.or]: [
|
||
{ [Op.like]: `%\/${config.rootPath}\/scripts\/%` },
|
||
{ [Op.like]: `%\/${config.rootPath}\/config\/%` },
|
||
{ [Op.like]: `%\/${config.rootPath}\/log\/%` },
|
||
{ [Op.like]: `%\/${config.rootPath}\/db\/%` },
|
||
],
|
||
},
|
||
},
|
||
}).then(async (docs) => {
|
||
for (let i = 0; i < docs.length; i++) {
|
||
const doc = docs[i];
|
||
if (doc) {
|
||
if (doc.command.includes(`${config.rootPath}/scripts/`)) {
|
||
await CrontabModel.update(
|
||
{ command: doc.command.replace(`${config.rootPath}/scripts/`, '') },
|
||
{ where: { id: doc.id } },
|
||
);
|
||
}
|
||
if (doc.command.includes(`${config.rootPath}/log/`)) {
|
||
await CrontabModel.update(
|
||
{
|
||
command: `${config.dataPath}/log/${doc.command.replace(
|
||
`${config.rootPath}/log/`,
|
||
'',
|
||
)}`,
|
||
},
|
||
{ where: { id: doc.id } },
|
||
);
|
||
}
|
||
if (doc.command.includes(`${config.rootPath}/config/`)) {
|
||
await CrontabModel.update(
|
||
{
|
||
command: `${config.dataPath}/config/${doc.command.replace(
|
||
`${config.rootPath}/config/`,
|
||
'',
|
||
)}`,
|
||
},
|
||
{ where: { id: doc.id } },
|
||
);
|
||
}
|
||
if (doc.command.includes(`${config.rootPath}/db/`)) {
|
||
await CrontabModel.update(
|
||
{
|
||
command: `${config.dataPath}/db/${doc.command.replace(
|
||
`${config.rootPath}/db/`,
|
||
'',
|
||
)}`,
|
||
},
|
||
{ where: { id: doc.id } },
|
||
);
|
||
}
|
||
}
|
||
}
|
||
});
|
||
|
||
// 初始化保存一次ck和定时任务数据
|
||
await cronService.autosave_crontab();
|
||
await envService.set_envs();
|
||
|
||
const authInfo = await userService.getAuthInfo();
|
||
const apps = await openService.findApps();
|
||
await shareStore.updateAuthInfo(authInfo);
|
||
if (apps?.length) {
|
||
await shareStore.updateApps(apps);
|
||
}
|
||
};
|