mirror of
https://github.com/whyour/qinglong.git
synced 2026-06-30 20:35:09 +08:00
使用sqlite替换nedb
This commit is contained in:
+11
-11
@@ -50,7 +50,7 @@ export default (app: Router) => {
|
||||
route.put(
|
||||
'/run',
|
||||
celebrate({
|
||||
body: Joi.array().items(Joi.string().required()),
|
||||
body: Joi.array().items(Joi.number().required()),
|
||||
}),
|
||||
async (req: Request, res: Response, next: NextFunction) => {
|
||||
const logger: Logger = Container.get('logger');
|
||||
@@ -68,7 +68,7 @@ export default (app: Router) => {
|
||||
route.put(
|
||||
'/stop',
|
||||
celebrate({
|
||||
body: Joi.array().items(Joi.string().required()),
|
||||
body: Joi.array().items(Joi.number().required()),
|
||||
}),
|
||||
async (req: Request, res: Response, next: NextFunction) => {
|
||||
const logger: Logger = Container.get('logger');
|
||||
@@ -86,7 +86,7 @@ export default (app: Router) => {
|
||||
route.put(
|
||||
'/disable',
|
||||
celebrate({
|
||||
body: Joi.array().items(Joi.string().required()),
|
||||
body: Joi.array().items(Joi.number().required()),
|
||||
}),
|
||||
async (req: Request, res: Response, next: NextFunction) => {
|
||||
const logger: Logger = Container.get('logger');
|
||||
@@ -104,7 +104,7 @@ export default (app: Router) => {
|
||||
route.put(
|
||||
'/enable',
|
||||
celebrate({
|
||||
body: Joi.array().items(Joi.string().required()),
|
||||
body: Joi.array().items(Joi.number().required()),
|
||||
}),
|
||||
async (req: Request, res: Response, next: NextFunction) => {
|
||||
const logger: Logger = Container.get('logger');
|
||||
@@ -123,7 +123,7 @@ export default (app: Router) => {
|
||||
'/:id/log',
|
||||
celebrate({
|
||||
params: Joi.object({
|
||||
id: Joi.string().required(),
|
||||
id: Joi.number().required(),
|
||||
}),
|
||||
}),
|
||||
async (req: Request, res: Response, next: NextFunction) => {
|
||||
@@ -140,13 +140,13 @@ export default (app: Router) => {
|
||||
);
|
||||
|
||||
route.put(
|
||||
'',
|
||||
'/',
|
||||
celebrate({
|
||||
body: Joi.object({
|
||||
command: Joi.string().optional(),
|
||||
schedule: Joi.string().optional(),
|
||||
name: Joi.string().optional(),
|
||||
_id: Joi.string().required(),
|
||||
id: Joi.string().required(),
|
||||
}),
|
||||
}),
|
||||
async (req: Request, res: Response, next: NextFunction) => {
|
||||
@@ -172,7 +172,7 @@ export default (app: Router) => {
|
||||
route.delete(
|
||||
'/',
|
||||
celebrate({
|
||||
body: Joi.array().items(Joi.string().required()),
|
||||
body: Joi.array().items(Joi.number().required()),
|
||||
}),
|
||||
async (req: Request, res: Response, next: NextFunction) => {
|
||||
const logger: Logger = Container.get('logger');
|
||||
@@ -190,7 +190,7 @@ export default (app: Router) => {
|
||||
route.put(
|
||||
'/pin',
|
||||
celebrate({
|
||||
body: Joi.array().items(Joi.string().required()),
|
||||
body: Joi.array().items(Joi.number().required()),
|
||||
}),
|
||||
async (req: Request, res: Response, next: NextFunction) => {
|
||||
const logger: Logger = Container.get('logger');
|
||||
@@ -208,7 +208,7 @@ export default (app: Router) => {
|
||||
route.put(
|
||||
'/unpin',
|
||||
celebrate({
|
||||
body: Joi.array().items(Joi.string().required()),
|
||||
body: Joi.array().items(Joi.number().required()),
|
||||
}),
|
||||
async (req: Request, res: Response, next: NextFunction) => {
|
||||
const logger: Logger = Container.get('logger');
|
||||
@@ -262,7 +262,7 @@ export default (app: Router) => {
|
||||
'/status',
|
||||
celebrate({
|
||||
body: Joi.object({
|
||||
ids: Joi.array().items(Joi.string().required()),
|
||||
ids: Joi.array().items(Joi.number().required()),
|
||||
status: Joi.string().required(),
|
||||
pid: Joi.string().optional(),
|
||||
log_path: Joi.string().optional(),
|
||||
|
||||
@@ -49,7 +49,7 @@ export default (app: Router) => {
|
||||
celebrate({
|
||||
body: Joi.object({
|
||||
name: Joi.string().required(),
|
||||
_id: Joi.string().required(),
|
||||
id: Joi.string().required(),
|
||||
type: Joi.number().required(),
|
||||
remark: Joi.number().optional().allow(''),
|
||||
}),
|
||||
@@ -70,7 +70,7 @@ export default (app: Router) => {
|
||||
route.delete(
|
||||
'/',
|
||||
celebrate({
|
||||
body: Joi.array().items(Joi.string().required()),
|
||||
body: Joi.array().items(Joi.number().required()),
|
||||
}),
|
||||
async (req: Request, res: Response, next: NextFunction) => {
|
||||
const logger: Logger = Container.get('logger');
|
||||
@@ -88,7 +88,7 @@ export default (app: Router) => {
|
||||
route.delete(
|
||||
'/force',
|
||||
celebrate({
|
||||
body: Joi.array().items(Joi.string().required()),
|
||||
body: Joi.array().items(Joi.number().required()),
|
||||
}),
|
||||
async (req: Request, res: Response, next: NextFunction) => {
|
||||
const logger: Logger = Container.get('logger');
|
||||
@@ -126,7 +126,7 @@ export default (app: Router) => {
|
||||
route.put(
|
||||
'/reinstall',
|
||||
celebrate({
|
||||
body: Joi.array().items(Joi.string().required()),
|
||||
body: Joi.array().items(Joi.number().required()),
|
||||
}),
|
||||
async (req: Request, res: Response, next: NextFunction) => {
|
||||
const logger: Logger = Container.get('logger');
|
||||
|
||||
+5
-5
@@ -51,7 +51,7 @@ export default (app: Router) => {
|
||||
value: Joi.string().required(),
|
||||
name: Joi.string().required(),
|
||||
remarks: Joi.string().optional().allow(''),
|
||||
_id: Joi.string().required(),
|
||||
id: Joi.string().required(),
|
||||
}),
|
||||
}),
|
||||
async (req: Request, res: Response, next: NextFunction) => {
|
||||
@@ -70,7 +70,7 @@ export default (app: Router) => {
|
||||
route.delete(
|
||||
'/',
|
||||
celebrate({
|
||||
body: Joi.array().items(Joi.string().required()),
|
||||
body: Joi.array().items(Joi.number().required()),
|
||||
}),
|
||||
async (req: Request, res: Response, next: NextFunction) => {
|
||||
const logger: Logger = Container.get('logger');
|
||||
@@ -112,7 +112,7 @@ export default (app: Router) => {
|
||||
route.put(
|
||||
'/disable',
|
||||
celebrate({
|
||||
body: Joi.array().items(Joi.string().required()),
|
||||
body: Joi.array().items(Joi.number().required()),
|
||||
}),
|
||||
async (req: Request, res: Response, next: NextFunction) => {
|
||||
const logger: Logger = Container.get('logger');
|
||||
@@ -130,7 +130,7 @@ export default (app: Router) => {
|
||||
route.put(
|
||||
'/enable',
|
||||
celebrate({
|
||||
body: Joi.array().items(Joi.string().required()),
|
||||
body: Joi.array().items(Joi.number().required()),
|
||||
}),
|
||||
async (req: Request, res: Response, next: NextFunction) => {
|
||||
const logger: Logger = Container.get('logger');
|
||||
@@ -149,7 +149,7 @@ export default (app: Router) => {
|
||||
'/name',
|
||||
celebrate({
|
||||
body: Joi.object({
|
||||
ids: Joi.array().items(Joi.string().required()),
|
||||
ids: Joi.array().items(Joi.number().required()),
|
||||
name: Joi.string().required(),
|
||||
}),
|
||||
}),
|
||||
|
||||
+2
-2
@@ -49,7 +49,7 @@ export default (app: Router) => {
|
||||
body: Joi.object({
|
||||
name: Joi.string().optional().allow(''),
|
||||
scopes: Joi.array().items(Joi.string()),
|
||||
_id: Joi.string().required(),
|
||||
id: Joi.string().required(),
|
||||
}),
|
||||
}),
|
||||
async (req: Request, res: Response, next: NextFunction) => {
|
||||
@@ -68,7 +68,7 @@ export default (app: Router) => {
|
||||
route.delete(
|
||||
'/apps',
|
||||
celebrate({
|
||||
body: Joi.array().items(Joi.string().required()),
|
||||
body: Joi.array().items(Joi.number().required()),
|
||||
}),
|
||||
async (req: Request, res: Response, next: NextFunction) => {
|
||||
const logger: Logger = Container.get('logger');
|
||||
|
||||
+15
-2
@@ -1,14 +1,17 @@
|
||||
import { sequelize } from '.';
|
||||
import { DataTypes, Model, ModelDefined } from 'sequelize';
|
||||
|
||||
export class AuthInfo {
|
||||
ip?: string;
|
||||
type: AuthDataType;
|
||||
info?: any;
|
||||
_id?: string;
|
||||
id?: number;
|
||||
|
||||
constructor(options: AuthInfo) {
|
||||
this.ip = options.ip;
|
||||
this.info = options.info;
|
||||
this.type = options.type;
|
||||
this._id = options._id;
|
||||
this.id = options.id;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,3 +26,13 @@ export enum AuthDataType {
|
||||
'notification' = 'notification',
|
||||
'removeLogFrequency' = 'removeLogFrequency',
|
||||
}
|
||||
|
||||
interface AuthInstance extends Model<AuthInfo, AuthInfo>, AuthInfo {}
|
||||
export const AuthModel = sequelize.define<AuthInstance>('Auth', {
|
||||
ip: DataTypes.STRING,
|
||||
type: DataTypes.STRING,
|
||||
info: {
|
||||
type: DataTypes.JSON,
|
||||
allowNull: true,
|
||||
},
|
||||
});
|
||||
|
||||
+30
-7
@@ -1,34 +1,40 @@
|
||||
import { sequelize } from '.';
|
||||
import { DataTypes, Model, ModelDefined } from 'sequelize';
|
||||
|
||||
export class Crontab {
|
||||
name?: string;
|
||||
command: string;
|
||||
schedule: string;
|
||||
timestamp?: string;
|
||||
created?: number;
|
||||
saved?: boolean;
|
||||
_id?: string;
|
||||
id?: number;
|
||||
status?: CrontabStatus;
|
||||
isSystem?: 1 | 0;
|
||||
pid?: number;
|
||||
isDisabled?: 1 | 0;
|
||||
log_path?: string;
|
||||
isPinned?: 1 | 0;
|
||||
last_running_time?: number;
|
||||
last_execution_time?: number;
|
||||
|
||||
constructor(options: Crontab) {
|
||||
this.name = options.name;
|
||||
this.command = options.command;
|
||||
this.schedule = options.schedule;
|
||||
this.saved = options.saved;
|
||||
this._id = options._id;
|
||||
this.created = options.created;
|
||||
this.status = CrontabStatus[options.status]
|
||||
? options.status
|
||||
: CrontabStatus.idle;
|
||||
this.id = options.id;
|
||||
this.status =
|
||||
options.status && CrontabStatus[options.status]
|
||||
? options.status
|
||||
: CrontabStatus.idle;
|
||||
this.timestamp = new Date().toString();
|
||||
this.isSystem = options.isSystem || 0;
|
||||
this.pid = options.pid;
|
||||
this.isDisabled = options.isDisabled || 0;
|
||||
this.log_path = options.log_path || '';
|
||||
this.isPinned = options.isPinned || 0;
|
||||
this.last_running_time = options.last_running_time || 0;
|
||||
this.last_execution_time = options.last_execution_time || 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,3 +44,20 @@ export enum CrontabStatus {
|
||||
'disabled',
|
||||
'queued',
|
||||
}
|
||||
|
||||
interface CronInstance extends Model<Crontab, Crontab>, Crontab {}
|
||||
export const CrontabModel = sequelize.define<CronInstance>('Crontab', {
|
||||
name: DataTypes.STRING,
|
||||
command: DataTypes.STRING,
|
||||
schedule: DataTypes.STRING,
|
||||
timestamp: DataTypes.STRING,
|
||||
saved: DataTypes.BOOLEAN,
|
||||
status: DataTypes.NUMBER,
|
||||
isSystem: DataTypes.NUMBER,
|
||||
pid: DataTypes.NUMBER,
|
||||
isDisabled: DataTypes.NUMBER,
|
||||
isPinned: DataTypes.NUMBER,
|
||||
log_path: DataTypes.STRING,
|
||||
last_running_time: DataTypes.NUMBER,
|
||||
last_execution_time: DataTypes.NUMBER,
|
||||
});
|
||||
|
||||
+20
-4
@@ -1,7 +1,9 @@
|
||||
import { sequelize } from '.';
|
||||
import { DataTypes, Model, ModelDefined } from 'sequelize';
|
||||
|
||||
export class Dependence {
|
||||
timestamp?: string;
|
||||
created?: number;
|
||||
_id?: string;
|
||||
id?: number;
|
||||
status?: DependenceStatus;
|
||||
type?: DependenceTypes;
|
||||
name?: number;
|
||||
@@ -9,8 +11,7 @@ export class Dependence {
|
||||
remark?: string;
|
||||
|
||||
constructor(options: Dependence) {
|
||||
this._id = options._id;
|
||||
this.created = options.created || new Date().valueOf();
|
||||
this.id = options.id;
|
||||
this.status = options.status || DependenceStatus.installing;
|
||||
this.type = options.type || DependenceTypes.nodejs;
|
||||
this.timestamp = new Date().toString();
|
||||
@@ -46,3 +47,18 @@ export enum unInstallDependenceCommandTypes {
|
||||
'pip3 uninstall -y',
|
||||
'apk del -f',
|
||||
}
|
||||
|
||||
interface DependenceInstance
|
||||
extends Model<Dependence, Dependence>,
|
||||
Dependence {}
|
||||
export const DependenceModel = sequelize.define<DependenceInstance>(
|
||||
'Dependence',
|
||||
{
|
||||
name: DataTypes.STRING,
|
||||
type: DataTypes.STRING,
|
||||
timestamp: DataTypes.STRING,
|
||||
status: DataTypes.STRING,
|
||||
log: DataTypes.JSON,
|
||||
remark: DataTypes.STRING,
|
||||
},
|
||||
);
|
||||
|
||||
+17
-6
@@ -1,17 +1,18 @@
|
||||
import { sequelize } from '.';
|
||||
import { DataTypes, Model, ModelDefined } from 'sequelize';
|
||||
|
||||
export class Env {
|
||||
value?: string;
|
||||
timestamp?: string;
|
||||
created?: number;
|
||||
_id?: string;
|
||||
id?: number;
|
||||
status?: EnvStatus;
|
||||
position?: number;
|
||||
name?: number;
|
||||
remarks?: number;
|
||||
name?: string;
|
||||
remarks?: string;
|
||||
|
||||
constructor(options: Env) {
|
||||
this.value = options.value;
|
||||
this._id = options._id;
|
||||
this.created = options.created || new Date().valueOf();
|
||||
this.id = options.id;
|
||||
this.status = options.status || EnvStatus.normal;
|
||||
this.timestamp = new Date().toString();
|
||||
this.position = options.position;
|
||||
@@ -26,3 +27,13 @@ export enum EnvStatus {
|
||||
}
|
||||
|
||||
export const initEnvPosition = 9999999999;
|
||||
|
||||
interface EnvInstance extends Model<Env, Env>, Env {}
|
||||
export const EnvModel = sequelize.define<EnvInstance>('Env', {
|
||||
value: DataTypes.STRING,
|
||||
timestamp: DataTypes.STRING,
|
||||
status: DataTypes.NUMBER,
|
||||
position: DataTypes.NUMBER,
|
||||
name: DataTypes.STRING,
|
||||
remarks: DataTypes.STRING,
|
||||
});
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import { Sequelize } from 'sequelize';
|
||||
import config from '../config/index';
|
||||
|
||||
export const sequelize = new Sequelize({
|
||||
dialect: 'sqlite',
|
||||
storage: `${config.dbPath}database.sqlite`,
|
||||
logging: false,
|
||||
});
|
||||
+15
-3
@@ -1,23 +1,26 @@
|
||||
import { sequelize } from '.';
|
||||
import { DataTypes, Model, ModelDefined } from 'sequelize';
|
||||
|
||||
export class App {
|
||||
name: string;
|
||||
scopes: AppScope[];
|
||||
client_id: string;
|
||||
client_secret: string;
|
||||
tokens?: AppToken[];
|
||||
_id?: string;
|
||||
id?: number;
|
||||
|
||||
constructor(options: App) {
|
||||
this.name = options.name;
|
||||
this.scopes = options.scopes;
|
||||
this.client_id = options.client_id;
|
||||
this.client_secret = options.client_secret;
|
||||
this._id = options._id;
|
||||
this.id = options.id;
|
||||
}
|
||||
}
|
||||
|
||||
export interface AppToken {
|
||||
value: string;
|
||||
type: 'Bearer';
|
||||
type?: 'Bearer';
|
||||
expiration: number;
|
||||
}
|
||||
|
||||
@@ -29,3 +32,12 @@ export enum CrontabStatus {
|
||||
'disabled',
|
||||
'queued',
|
||||
}
|
||||
|
||||
interface AppInstance extends Model<App, App>, App {}
|
||||
export const AppModel = sequelize.define<AppInstance>('App', {
|
||||
name: DataTypes.STRING,
|
||||
scopes: DataTypes.JSON,
|
||||
client_id: DataTypes.STRING,
|
||||
client_secret: DataTypes.STRING,
|
||||
tokens: DataTypes.JSON,
|
||||
});
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
export class SockMessage {
|
||||
message?: string;
|
||||
type?: SockMessageType;
|
||||
references?: string[];
|
||||
references?: number[];
|
||||
|
||||
constructor(options: SockMessage) {
|
||||
this.type = options.type;
|
||||
|
||||
@@ -3,6 +3,12 @@ import config from '../config';
|
||||
import Logger from './logger';
|
||||
import fs from 'fs';
|
||||
import { fileExist } from '../config/util';
|
||||
import { EnvModel } from '../data/env';
|
||||
import { CrontabModel } from '../data/cron';
|
||||
import { DependenceModel } from '../data/dependence';
|
||||
import { AppModel } from '../data/open';
|
||||
import { AuthModel } from '../data/auth';
|
||||
import { sequelize } from '../data';
|
||||
|
||||
interface Dbs {
|
||||
cronDb: DataStore;
|
||||
@@ -53,6 +59,43 @@ export default async () => {
|
||||
db.appDb.persistence.compactDatafile();
|
||||
db.authDb.persistence.compactDatafile();
|
||||
|
||||
try {
|
||||
await sequelize.sync();
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
// migrate db to sqlite
|
||||
setTimeout(async () => {
|
||||
try {
|
||||
const count = await CrontabModel.count();
|
||||
if (count !== 0) {
|
||||
return;
|
||||
}
|
||||
db.cronDb.find({}).exec(async (err, docs) => {
|
||||
await CrontabModel.bulkCreate(docs);
|
||||
});
|
||||
|
||||
db.dependenceDb.find({}).exec(async (err, docs) => {
|
||||
await DependenceModel.bulkCreate(docs);
|
||||
});
|
||||
|
||||
db.envDb.find({}).exec(async (err, docs) => {
|
||||
await EnvModel.bulkCreate(docs);
|
||||
});
|
||||
|
||||
db.appDb.find({}).exec(async (err, docs) => {
|
||||
await AppModel.bulkCreate(docs);
|
||||
});
|
||||
|
||||
db.authDb.find({}).exec(async (err, docs) => {
|
||||
await AuthModel.bulkCreate(docs);
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}, 5000);
|
||||
|
||||
Logger.info('✌️ DB loaded');
|
||||
} catch (error) {
|
||||
Logger.info('✌️ DB load failed');
|
||||
|
||||
+22
-41
@@ -1,33 +1,31 @@
|
||||
import DependenceService from '../services/dependence';
|
||||
import { exec } from 'child_process';
|
||||
import { Container } from 'typedi';
|
||||
import { Crontab, CrontabStatus } from '../data/cron';
|
||||
import { Crontab, CrontabModel, CrontabStatus } from '../data/cron';
|
||||
import CronService from '../services/cron';
|
||||
import EnvService from '../services/env';
|
||||
import _ from 'lodash';
|
||||
import { dbs } from '../loaders/db';
|
||||
import { DependenceModel } from '../data/dependence';
|
||||
import { Op } from 'sequelize';
|
||||
|
||||
export default async () => {
|
||||
const cronService = Container.get(CronService);
|
||||
const envService = Container.get(EnvService);
|
||||
const dependenceService = Container.get(DependenceService);
|
||||
const cronDb = dbs.cronDb;
|
||||
const dependenceDb = dbs.dependenceDb;
|
||||
|
||||
// 初始化更新所有任务状态为空闲
|
||||
cronDb.update(
|
||||
{ status: { $in: [CrontabStatus.running, CrontabStatus.queued] } },
|
||||
{ $set: { status: CrontabStatus.idle } },
|
||||
{ multi: true },
|
||||
await CrontabModel.update(
|
||||
{ status: CrontabStatus.idle },
|
||||
{ where: { status: [CrontabStatus.running, CrontabStatus.queued] } },
|
||||
);
|
||||
|
||||
// 初始化时安装所有处于安装中,安装成功,安装失败的依赖
|
||||
dependenceDb.find({ status: { $in: [0, 1, 2] } }).exec(async (err, docs) => {
|
||||
DependenceModel.findAll({ where: {} }).then(async (docs) => {
|
||||
const groups = _.groupBy(docs, 'type');
|
||||
for (const key in groups) {
|
||||
if (Object.prototype.hasOwnProperty.call(groups, key)) {
|
||||
const group = groups[key];
|
||||
const depIds = group.map((x) => x._id);
|
||||
const depIds = group.map((x) => x.id);
|
||||
for (const dep of depIds) {
|
||||
await dependenceService.reInstall([dep]);
|
||||
}
|
||||
@@ -36,38 +34,21 @@ export default async () => {
|
||||
});
|
||||
|
||||
// 初始化时执行一次所有的ql repo 任务
|
||||
cronDb
|
||||
.find({
|
||||
command: /ql (repo|raw)/,
|
||||
isDisabled: { $ne: 1 },
|
||||
})
|
||||
.exec((err, docs) => {
|
||||
for (let i = 0; i < docs.length; i++) {
|
||||
const doc = docs[i];
|
||||
if (doc) {
|
||||
exec(doc.command);
|
||||
}
|
||||
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);
|
||||
}
|
||||
});
|
||||
|
||||
// patch 禁用状态字段改变
|
||||
cronDb
|
||||
.find({
|
||||
status: CrontabStatus.disabled,
|
||||
})
|
||||
.exec((err, docs) => {
|
||||
if (docs.length > 0) {
|
||||
const ids = docs.map((x) => x._id);
|
||||
cronDb.update(
|
||||
{ _id: { $in: ids } },
|
||||
{ $set: { status: CrontabStatus.idle, isDisabled: 1 } },
|
||||
{ multi: true },
|
||||
(err) => {
|
||||
cronService.autosave_crontab();
|
||||
},
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 初始化保存一次ck和定时任务数据
|
||||
await cronService.autosave_crontab();
|
||||
|
||||
+7
-13
@@ -2,24 +2,14 @@ import schedule from 'node-schedule';
|
||||
import express from 'express';
|
||||
import { exec } from 'child_process';
|
||||
import Logger from './loaders/logger';
|
||||
import { CrontabStatus } from './data/cron';
|
||||
import { CrontabModel, CrontabStatus } from './data/cron';
|
||||
import config from './config';
|
||||
import { dbs } from './loaders/db';
|
||||
|
||||
const app = express();
|
||||
|
||||
const run = async () => {
|
||||
const cronDb = dbs.cronDb;
|
||||
|
||||
cronDb
|
||||
.find({})
|
||||
.sort({ created: 1 })
|
||||
.exec((err, docs) => {
|
||||
if (err) {
|
||||
Logger.error(err);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
CrontabModel.findAll({ where: {} })
|
||||
.then((docs) => {
|
||||
if (docs && docs.length > 0) {
|
||||
for (let i = 0; i < docs.length; i++) {
|
||||
const task = docs[i];
|
||||
@@ -40,6 +30,10 @@ const run = async () => {
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
Logger.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
+102
-192
@@ -1,25 +1,17 @@
|
||||
import { Service, Inject } from 'typedi';
|
||||
import winston from 'winston';
|
||||
import DataStore from 'nedb';
|
||||
import config from '../config';
|
||||
import { Crontab, CrontabStatus } from '../data/cron';
|
||||
import { Crontab, CrontabModel, CrontabStatus } from '../data/cron';
|
||||
import { exec, execSync, spawn } from 'child_process';
|
||||
import fs from 'fs';
|
||||
import cron_parser from 'cron-parser';
|
||||
import { getFileContentByName, concurrentRun } from '../config/util';
|
||||
import PQueue from 'p-queue';
|
||||
import { promises, existsSync } from 'fs';
|
||||
import { promisify } from 'util';
|
||||
import { dbs } from '../loaders/db';
|
||||
import { Op } from 'sequelize';
|
||||
|
||||
@Service()
|
||||
export default class CronService {
|
||||
private cronDb = dbs.cronDb;
|
||||
|
||||
private queue = new PQueue({
|
||||
concurrency: parseInt(process.env.MaxConcurrentNum as string) || 5,
|
||||
});
|
||||
|
||||
constructor(@Inject('logger') private logger: winston.Logger) {}
|
||||
|
||||
private isSixCron(cron: Crontab) {
|
||||
@@ -32,7 +24,6 @@ export default class CronService {
|
||||
|
||||
public async create(payload: Crontab): Promise<Crontab> {
|
||||
const tab = new Crontab(payload);
|
||||
tab.created = new Date().valueOf();
|
||||
tab.saved = false;
|
||||
const doc = await this.insert(tab);
|
||||
await this.set_crontab(this.isSixCron(doc));
|
||||
@@ -40,20 +31,12 @@ export default class CronService {
|
||||
}
|
||||
|
||||
public async insert(payload: Crontab): Promise<Crontab> {
|
||||
return new Promise((resolve) => {
|
||||
this.cronDb.insert(payload, (err, docs) => {
|
||||
if (err) {
|
||||
this.logger.error(err);
|
||||
} else {
|
||||
resolve(docs);
|
||||
}
|
||||
});
|
||||
});
|
||||
return await CrontabModel.create(payload);
|
||||
}
|
||||
|
||||
public async update(payload: Crontab): Promise<Crontab> {
|
||||
const { _id, ...other } = payload;
|
||||
const doc = await this.get(_id);
|
||||
const { id, ...other } = payload;
|
||||
const doc = await this.get(id as number);
|
||||
const tab = new Crontab({ ...doc, ...other });
|
||||
tab.saved = false;
|
||||
const newDoc = await this.updateDb(tab);
|
||||
@@ -62,20 +45,11 @@ export default class CronService {
|
||||
}
|
||||
|
||||
public async updateDb(payload: Crontab): Promise<Crontab> {
|
||||
return new Promise((resolve) => {
|
||||
this.cronDb.update(
|
||||
{ _id: payload._id },
|
||||
payload,
|
||||
{ returnUpdatedDocs: true },
|
||||
(err, num, docs: any) => {
|
||||
if (err) {
|
||||
this.logger.error(err);
|
||||
} else {
|
||||
resolve(docs);
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
const result = await CrontabModel.update(
|
||||
{ ...payload },
|
||||
{ where: { id: payload.id } },
|
||||
);
|
||||
return result[1][0];
|
||||
}
|
||||
|
||||
public async status({
|
||||
@@ -86,7 +60,7 @@ export default class CronService {
|
||||
last_running_time = 0,
|
||||
last_execution_time = 0,
|
||||
}: {
|
||||
ids: string[];
|
||||
ids: number[];
|
||||
status: CrontabStatus;
|
||||
pid: number;
|
||||
log_path: string;
|
||||
@@ -103,67 +77,35 @@ export default class CronService {
|
||||
options.last_running_time = last_running_time;
|
||||
}
|
||||
|
||||
return new Promise((resolve) => {
|
||||
this.cronDb.update(
|
||||
{ _id: { $in: ids } },
|
||||
{
|
||||
$set: options,
|
||||
},
|
||||
{ multi: true, returnUpdatedDocs: true },
|
||||
(err) => {
|
||||
resolve(null);
|
||||
},
|
||||
);
|
||||
});
|
||||
return await CrontabModel.update({ ...options }, { where: { id: ids } });
|
||||
}
|
||||
|
||||
public async remove(ids: string[]) {
|
||||
return new Promise((resolve: any) => {
|
||||
this.cronDb.remove(
|
||||
{ _id: { $in: ids } },
|
||||
{ multi: true },
|
||||
async (err) => {
|
||||
await this.set_crontab(true);
|
||||
resolve();
|
||||
},
|
||||
);
|
||||
});
|
||||
public async remove(ids: number[]) {
|
||||
await CrontabModel.destroy({ where: { id: ids } });
|
||||
await this.set_crontab(true);
|
||||
}
|
||||
|
||||
public async pin(ids: string[]) {
|
||||
return new Promise((resolve: any) => {
|
||||
this.cronDb.update(
|
||||
{ _id: { $in: ids } },
|
||||
{ $set: { isPinned: 1 } },
|
||||
{ multi: true },
|
||||
async (err) => {
|
||||
resolve();
|
||||
},
|
||||
);
|
||||
});
|
||||
public async pin(ids: number[]) {
|
||||
await CrontabModel.update({ isPinned: 1 }, { where: { id: ids } });
|
||||
}
|
||||
|
||||
public async unPin(ids: string[]) {
|
||||
return new Promise((resolve: any) => {
|
||||
this.cronDb.update(
|
||||
{ _id: { $in: ids } },
|
||||
{ $set: { isPinned: 0 } },
|
||||
{ multi: true },
|
||||
async (err) => {
|
||||
resolve();
|
||||
},
|
||||
);
|
||||
});
|
||||
public async unPin(ids: number[]) {
|
||||
await CrontabModel.update({ isPinned: 0 }, { where: { id: ids } });
|
||||
}
|
||||
|
||||
public async crontabs(searchText?: string): Promise<Crontab[]> {
|
||||
let query = {};
|
||||
if (searchText) {
|
||||
const encodeText = encodeURIComponent(searchText);
|
||||
const reg = new RegExp(`${searchText}|${encodeText}`, 'i');
|
||||
const reg = {
|
||||
[Op.or]: [
|
||||
{ [Op.like]: `%${searchText}&` },
|
||||
{ [Op.like]: `%${encodeText}%` },
|
||||
],
|
||||
};
|
||||
|
||||
query = {
|
||||
$or: [
|
||||
[Op.or]: [
|
||||
{
|
||||
name: reg,
|
||||
},
|
||||
@@ -176,69 +118,56 @@ export default class CronService {
|
||||
],
|
||||
};
|
||||
}
|
||||
return new Promise((resolve) => {
|
||||
this.cronDb
|
||||
.find(query)
|
||||
.sort({ created: -1 })
|
||||
.exec((err, docs) => {
|
||||
resolve(docs);
|
||||
});
|
||||
});
|
||||
try {
|
||||
const result = await CrontabModel.findAll({ where: query });
|
||||
return result as any;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
public async get(_id: string): Promise<Crontab> {
|
||||
return new Promise((resolve) => {
|
||||
this.cronDb.find({ _id }).exec((err, docs) => {
|
||||
resolve(docs[0]);
|
||||
});
|
||||
});
|
||||
public async get(id: number): Promise<Crontab> {
|
||||
const result = await CrontabModel.findAll({ where: { id } });
|
||||
return result[0] as any;
|
||||
}
|
||||
|
||||
public async run(ids: string[]) {
|
||||
this.cronDb.update(
|
||||
{ _id: { $in: ids } },
|
||||
{ $set: { status: CrontabStatus.queued } },
|
||||
{ multi: true },
|
||||
public async run(ids: number[]) {
|
||||
await CrontabModel.update(
|
||||
{ status: CrontabStatus.queued },
|
||||
{ where: { id: ids } },
|
||||
);
|
||||
concurrentRun(
|
||||
ids.map((id) => () => this.runSingle(id)),
|
||||
ids.map((id) => async () => await this.runSingle(id)),
|
||||
10,
|
||||
);
|
||||
}
|
||||
|
||||
public async stop(ids: string[]) {
|
||||
return new Promise((resolve: any) => {
|
||||
this.cronDb
|
||||
.find({ _id: { $in: ids } })
|
||||
.exec(async (err, docs: Crontab[]) => {
|
||||
for (const doc of docs) {
|
||||
if (doc.pid) {
|
||||
try {
|
||||
process.kill(-doc.pid);
|
||||
} catch (error) {
|
||||
this.logger.silly(error);
|
||||
}
|
||||
}
|
||||
const err = await this.killTask(doc.command);
|
||||
if (doc.log_path) {
|
||||
const str = err ? `\n${err}` : '';
|
||||
fs.appendFileSync(
|
||||
`${doc.log_path}`,
|
||||
`${str}\n## 执行结束... ${new Date()
|
||||
.toLocaleString('zh', { hour12: false })
|
||||
.replace(' 24:', ' 00:')} `,
|
||||
);
|
||||
}
|
||||
}
|
||||
this.cronDb.update(
|
||||
{ _id: { $in: ids } },
|
||||
{ $set: { status: CrontabStatus.idle }, $unset: { pid: true } },
|
||||
{ multi: true },
|
||||
);
|
||||
this.queue.clear();
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
public async stop(ids: number[]) {
|
||||
const docs = await CrontabModel.findAll({ where: { id: ids } });
|
||||
for (const doc of docs) {
|
||||
if (doc.pid) {
|
||||
try {
|
||||
process.kill(-doc.pid);
|
||||
} catch (error) {
|
||||
this.logger.silly(error);
|
||||
}
|
||||
}
|
||||
const err = await this.killTask(doc.command);
|
||||
if (doc.log_path) {
|
||||
const str = err ? `\n${err}` : '';
|
||||
fs.appendFileSync(
|
||||
`${doc.log_path}`,
|
||||
`${str}\n## 执行结束... ${new Date()
|
||||
.toLocaleString('zh', { hour12: false })
|
||||
.replace(' 24:', ' 00:')} `,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
await CrontabModel.update(
|
||||
{ status: CrontabStatus.queued, pid: undefined },
|
||||
{ where: { id: ids } },
|
||||
);
|
||||
}
|
||||
|
||||
public async killTask(name: string) {
|
||||
@@ -273,18 +202,18 @@ export default class CronService {
|
||||
}
|
||||
}
|
||||
|
||||
private async runSingle(id: string): Promise<number> {
|
||||
private async runSingle(cronId: number): Promise<number> {
|
||||
return new Promise(async (resolve: any) => {
|
||||
const cron = await this.get(id);
|
||||
const cron = await this.get(cronId);
|
||||
if (cron.status !== CrontabStatus.queued) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
let { _id, command, log_path } = cron;
|
||||
let { id, command, log_path } = cron;
|
||||
|
||||
this.logger.silly('Running job');
|
||||
this.logger.silly('ID: ' + _id);
|
||||
this.logger.silly('ID: ' + id);
|
||||
this.logger.silly('Original command: ' + command);
|
||||
|
||||
let cmdStr = command;
|
||||
@@ -296,9 +225,10 @@ export default class CronService {
|
||||
}
|
||||
|
||||
const cp = spawn(cmdStr, { shell: '/bin/bash' });
|
||||
this.cronDb.update(
|
||||
{ _id },
|
||||
{ $set: { status: CrontabStatus.running, pid: cp.pid } },
|
||||
|
||||
await CrontabModel.update(
|
||||
{ status: CrontabStatus.running, pid: cp.pid },
|
||||
{ where: { id } },
|
||||
);
|
||||
cp.stderr.on('data', (data) => {
|
||||
if (log_path) {
|
||||
@@ -311,57 +241,39 @@ export default class CronService {
|
||||
}
|
||||
});
|
||||
|
||||
cp.on('exit', (code, signal) => {
|
||||
cp.on('exit', async (code, signal) => {
|
||||
this.logger.info(
|
||||
`${command} pid: ${cp.pid} exit ${code} signal ${signal}`,
|
||||
);
|
||||
this.cronDb.update(
|
||||
{ _id },
|
||||
{ $set: { status: CrontabStatus.idle }, $unset: { pid: true } },
|
||||
await CrontabModel.update(
|
||||
{ status: CrontabStatus.idle, pid: undefined },
|
||||
{ where: { id } },
|
||||
);
|
||||
resolve();
|
||||
});
|
||||
cp.on('close', (code) => {
|
||||
cp.on('close', async (code) => {
|
||||
this.logger.info(`${command} pid: ${cp.pid} closed ${code}`);
|
||||
this.cronDb.update(
|
||||
{ _id },
|
||||
{ $set: { status: CrontabStatus.idle }, $unset: { pid: true } },
|
||||
await CrontabModel.update(
|
||||
{ status: CrontabStatus.idle, pid: undefined },
|
||||
{ where: { id } },
|
||||
);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public async disabled(ids: string[]) {
|
||||
return new Promise((resolve: any) => {
|
||||
this.cronDb.update(
|
||||
{ _id: { $in: ids } },
|
||||
{ $set: { isDisabled: 1 } },
|
||||
{ multi: true },
|
||||
async (err) => {
|
||||
await this.set_crontab(true);
|
||||
resolve();
|
||||
},
|
||||
);
|
||||
});
|
||||
public async disabled(ids: number[]) {
|
||||
await CrontabModel.update({ isDisabled: 1 }, { where: { id: ids } });
|
||||
await this.set_crontab(true);
|
||||
}
|
||||
|
||||
public async enabled(ids: string[]) {
|
||||
return new Promise((resolve: any) => {
|
||||
this.cronDb.update(
|
||||
{ _id: { $in: ids } },
|
||||
{ $set: { isDisabled: 0 } },
|
||||
{ multi: true },
|
||||
async (err) => {
|
||||
await this.set_crontab(true);
|
||||
resolve();
|
||||
},
|
||||
);
|
||||
});
|
||||
public async enabled(ids: number[]) {
|
||||
await CrontabModel.update({ isDisabled: 0 }, { where: { id: ids } });
|
||||
await this.set_crontab(true);
|
||||
}
|
||||
|
||||
public async log(_id: string) {
|
||||
const doc = await this.get(_id);
|
||||
public async log(id: number) {
|
||||
const doc = await this.get(id);
|
||||
if (!doc) {
|
||||
return '';
|
||||
}
|
||||
@@ -401,7 +313,7 @@ export default class CronService {
|
||||
}
|
||||
|
||||
private make_command(tab: Crontab) {
|
||||
const crontab_job_string = `ID=${tab._id} ${tab.command}`;
|
||||
const crontab_job_string = `ID=${tab.id} ${tab.command}`;
|
||||
return crontab_job_string;
|
||||
}
|
||||
|
||||
@@ -431,7 +343,7 @@ export default class CronService {
|
||||
if (needReloadSchedule) {
|
||||
exec(`pm2 reload schedule`);
|
||||
}
|
||||
this.cronDb.update({}, { $set: { saved: true } }, { multi: true });
|
||||
await CrontabModel.update({ saved: true }, { where: {} });
|
||||
}
|
||||
|
||||
public import_crontab() {
|
||||
@@ -439,7 +351,7 @@ export default class CronService {
|
||||
var lines = stdout.split('\n');
|
||||
var namePrefix = new Date().getTime();
|
||||
|
||||
lines.reverse().forEach((line, index) => {
|
||||
lines.reverse().forEach(async (line, index) => {
|
||||
line = line.replace(/\t+/g, ' ');
|
||||
var regex =
|
||||
/^((\@[a-zA-Z]+\s+)|(([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+))/;
|
||||
@@ -453,18 +365,16 @@ export default class CronService {
|
||||
) {
|
||||
var name = namePrefix + '_' + index;
|
||||
|
||||
this.cronDb.findOne({ command, schedule }, (err, doc) => {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
if (!doc) {
|
||||
this.create({ name, command, schedule });
|
||||
} else {
|
||||
doc.command = command;
|
||||
doc.schedule = schedule;
|
||||
this.update(doc);
|
||||
}
|
||||
const _crontab = await CrontabModel.findOne({
|
||||
where: { command, schedule },
|
||||
});
|
||||
if (!_crontab) {
|
||||
await this.create({ name, command, schedule });
|
||||
} else {
|
||||
_crontab.command = command;
|
||||
_crontab.schedule = schedule;
|
||||
await this.update(_crontab);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
+57
-109
@@ -8,16 +8,15 @@ import {
|
||||
DependenceStatus,
|
||||
DependenceTypes,
|
||||
unInstallDependenceCommandTypes,
|
||||
DependenceModel,
|
||||
} from '../data/dependence';
|
||||
import _ from 'lodash';
|
||||
import { spawn } from 'child_process';
|
||||
import SockService from './sock';
|
||||
import { dbs } from '../loaders/db';
|
||||
import { Op } from 'sequelize';
|
||||
|
||||
@Service()
|
||||
export default class DependenceService {
|
||||
private dependenceDb = dbs.dependenceDb;
|
||||
|
||||
constructor(
|
||||
@Inject('logger') private logger: winston.Logger,
|
||||
private sockService: SockService,
|
||||
@@ -34,22 +33,15 @@ export default class DependenceService {
|
||||
}
|
||||
|
||||
public async insert(payloads: Dependence[]): Promise<Dependence[]> {
|
||||
return new Promise((resolve) => {
|
||||
this.dependenceDb.insert(payloads, (err, docs) => {
|
||||
if (err) {
|
||||
this.logger.error(err);
|
||||
} else {
|
||||
resolve(docs);
|
||||
}
|
||||
});
|
||||
});
|
||||
const docs = await DependenceModel.bulkCreate(payloads);
|
||||
return docs;
|
||||
}
|
||||
|
||||
public async update(
|
||||
payload: Dependence & { _id: string },
|
||||
payload: Dependence & { id: string },
|
||||
): Promise<Dependence> {
|
||||
const { _id, ...other } = payload;
|
||||
const doc = await this.get(_id);
|
||||
const { id, ...other } = payload;
|
||||
const doc = await this.get(id);
|
||||
const tab = new Dependence({
|
||||
...doc,
|
||||
...other,
|
||||
@@ -61,46 +53,23 @@ export default class DependenceService {
|
||||
}
|
||||
|
||||
private async updateDb(payload: Dependence): Promise<Dependence> {
|
||||
return new Promise((resolve) => {
|
||||
this.dependenceDb.update(
|
||||
{ _id: payload._id },
|
||||
payload,
|
||||
{ returnUpdatedDocs: true },
|
||||
(err, num, doc) => {
|
||||
if (err) {
|
||||
this.logger.error(err);
|
||||
} else {
|
||||
resolve(doc as Dependence);
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
const [, docs] = await DependenceModel.update(
|
||||
{ ...payload },
|
||||
{ where: { id: payload.id } },
|
||||
);
|
||||
return docs[0];
|
||||
}
|
||||
|
||||
public async remove(ids: string[]) {
|
||||
return new Promise((resolve: any) => {
|
||||
this.dependenceDb.update(
|
||||
{ _id: { $in: ids } },
|
||||
{ $set: { status: DependenceStatus.removing, log: [] } },
|
||||
{ multi: true, returnUpdatedDocs: true },
|
||||
async (err, num, docs: Dependence[]) => {
|
||||
this.installOrUninstallDependencies(docs, false);
|
||||
resolve(docs);
|
||||
},
|
||||
);
|
||||
});
|
||||
const [, docs] = await DependenceModel.update(
|
||||
{ status: DependenceStatus.removing, log: [] },
|
||||
{ where: { id: ids } },
|
||||
);
|
||||
this.installOrUninstallDependencies(docs, false);
|
||||
}
|
||||
|
||||
public async removeDb(ids: string[]) {
|
||||
return new Promise((resolve: any) => {
|
||||
this.dependenceDb.remove(
|
||||
{ _id: { $in: ids } },
|
||||
{ multi: true },
|
||||
async (err) => {
|
||||
resolve();
|
||||
},
|
||||
);
|
||||
});
|
||||
public async removeDb(ids: number[]) {
|
||||
await DependenceModel.destroy({ where: { id: ids } });
|
||||
}
|
||||
|
||||
public async dependencies(
|
||||
@@ -110,68 +79,53 @@ export default class DependenceService {
|
||||
): Promise<Dependence[]> {
|
||||
let condition = { ...query, type: DependenceTypes[type as any] };
|
||||
if (searchValue) {
|
||||
const reg = new RegExp(searchValue);
|
||||
condition = {
|
||||
...condition,
|
||||
$or: [
|
||||
{
|
||||
name: reg,
|
||||
},
|
||||
const encodeText = encodeURIComponent(searchValue);
|
||||
const reg = {
|
||||
[Op.or]: [
|
||||
{ [Op.like]: `%${encodeText}&` },
|
||||
{ [Op.like]: `%${encodeText}%` },
|
||||
],
|
||||
};
|
||||
|
||||
condition = {
|
||||
...condition,
|
||||
name: reg,
|
||||
};
|
||||
}
|
||||
try {
|
||||
const result = await this.find(condition);
|
||||
return result as any;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
const newDocs = await this.find(condition, sort);
|
||||
return newDocs;
|
||||
}
|
||||
|
||||
public async reInstall(ids: string[]): Promise<Dependence[]> {
|
||||
return new Promise((resolve: any) => {
|
||||
this.dependenceDb.update(
|
||||
{ _id: { $in: ids } },
|
||||
{ $set: { status: DependenceStatus.installing, log: [] } },
|
||||
{ multi: true, returnUpdatedDocs: true },
|
||||
async (err, num, docs: Dependence[]) => {
|
||||
await this.installOrUninstallDependencies(docs);
|
||||
resolve(docs);
|
||||
},
|
||||
);
|
||||
});
|
||||
const [, docs] = await DependenceModel.update(
|
||||
{ status: DependenceStatus.installing, log: [] },
|
||||
{ where: { id: ids } },
|
||||
);
|
||||
await this.installOrUninstallDependencies(docs);
|
||||
return docs;
|
||||
}
|
||||
|
||||
private async find(query: any, sort: any): Promise<Dependence[]> {
|
||||
return new Promise((resolve) => {
|
||||
this.dependenceDb
|
||||
.find(query)
|
||||
.sort({ ...sort })
|
||||
.exec((err, docs) => {
|
||||
resolve(docs);
|
||||
});
|
||||
});
|
||||
private async find(query: any, sort?: any): Promise<Dependence[]> {
|
||||
const docs = await DependenceModel.findAll({ where: { ...query } });
|
||||
return docs;
|
||||
}
|
||||
|
||||
public async get(_id: string): Promise<Dependence> {
|
||||
return new Promise((resolve) => {
|
||||
this.dependenceDb.find({ _id }).exec((err, docs) => {
|
||||
resolve(docs[0]);
|
||||
});
|
||||
});
|
||||
public async get(id: string): Promise<Dependence> {
|
||||
const docs = await DependenceModel.findAll({ where: { id } });
|
||||
return docs[0];
|
||||
}
|
||||
|
||||
private async updateLog(ids: string[], log: string): Promise<void> {
|
||||
return new Promise((resolve) => {
|
||||
this.dependenceDb.update(
|
||||
{ _id: { $in: ids } },
|
||||
{ $push: { log } },
|
||||
{ multi: true },
|
||||
(err, num, doc) => {
|
||||
if (err) {
|
||||
this.logger.error(err);
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
private async updateLog(ids: number[], log: string): Promise<void> {
|
||||
const doc = await DependenceModel.findOne({ where: { id: ids } });
|
||||
const newLog = doc?.log ? [...doc.log, log] : [log];
|
||||
const [, docs] = await DependenceModel.update(
|
||||
{ status: DependenceStatus.installing, log: newLog },
|
||||
{ where: { id: ids } },
|
||||
);
|
||||
}
|
||||
|
||||
public installOrUninstallDependencies(
|
||||
@@ -190,7 +144,7 @@ export default class DependenceService {
|
||||
: unInstallDependenceCommandTypes
|
||||
)[dependencies[0].type as any];
|
||||
const actionText = isInstall ? '安装' : '删除';
|
||||
const depIds = dependencies.map((x) => x._id) as string[];
|
||||
const depIds = dependencies.map((x) => x.id) as number[];
|
||||
const cp = spawn(`${depRunCommand} ${depNames}`, { shell: '/bin/bash' });
|
||||
const startTime = Date.now();
|
||||
this.sockService.sendMessage({
|
||||
@@ -263,14 +217,8 @@ export default class DependenceService {
|
||||
? DependenceStatus.installFailed
|
||||
: DependenceStatus.removeFailed;
|
||||
}
|
||||
this.dependenceDb.update(
|
||||
{ _id: { $in: depIds } },
|
||||
{
|
||||
$set: { status },
|
||||
$unset: { pid: true },
|
||||
},
|
||||
{ multi: true },
|
||||
);
|
||||
|
||||
DependenceModel.update({ status }, { where: { id: depIds } });
|
||||
|
||||
// 如果删除依赖成功,3秒后删除数据库记录
|
||||
if (isSucceed && !isInstall) {
|
||||
|
||||
+51
-106
@@ -4,14 +4,12 @@ import { getFileContentByName } from '../config/util';
|
||||
import config from '../config';
|
||||
import * as fs from 'fs';
|
||||
import DataStore from 'nedb';
|
||||
import { Env, EnvStatus, initEnvPosition } from '../data/env';
|
||||
import { Env, EnvModel, EnvStatus, initEnvPosition } from '../data/env';
|
||||
import _ from 'lodash';
|
||||
import { dbs } from '../loaders/db';
|
||||
import { Op } from 'sequelize';
|
||||
|
||||
@Service()
|
||||
export default class EnvService {
|
||||
private envDb = dbs.envDb;
|
||||
|
||||
constructor(@Inject('logger') private logger: winston.Logger) {}
|
||||
|
||||
public async create(payloads: Env[]): Promise<Env[]> {
|
||||
@@ -31,20 +29,13 @@ export default class EnvService {
|
||||
}
|
||||
|
||||
public async insert(payloads: Env[]): Promise<Env[]> {
|
||||
return new Promise((resolve) => {
|
||||
this.envDb.insert(payloads, (err, docs) => {
|
||||
if (err) {
|
||||
this.logger.error(err);
|
||||
} else {
|
||||
resolve(docs);
|
||||
}
|
||||
});
|
||||
});
|
||||
const docs = await EnvModel.bulkCreate(payloads);
|
||||
return docs;
|
||||
}
|
||||
|
||||
public async update(payload: Env): Promise<Env> {
|
||||
const { _id, ...other } = payload;
|
||||
const doc = await this.get(_id);
|
||||
const { id, ...other } = payload;
|
||||
const doc = await this.get(id as number);
|
||||
const tab = new Env({ ...doc, ...other });
|
||||
const newDoc = await this.updateDb(tab);
|
||||
await this.set_envs();
|
||||
@@ -52,33 +43,19 @@ export default class EnvService {
|
||||
}
|
||||
|
||||
private async updateDb(payload: Env): Promise<Env> {
|
||||
return new Promise((resolve) => {
|
||||
this.envDb.update(
|
||||
{ _id: payload._id },
|
||||
payload,
|
||||
{ returnUpdatedDocs: true },
|
||||
(err, num, doc) => {
|
||||
if (err) {
|
||||
this.logger.error(err);
|
||||
} else {
|
||||
resolve(doc as Env);
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
const [, docs] = await EnvModel.update(
|
||||
{ ...payload },
|
||||
{ where: { id: payload.id } },
|
||||
);
|
||||
return docs[0];
|
||||
}
|
||||
|
||||
public async remove(ids: string[]) {
|
||||
return new Promise((resolve: any) => {
|
||||
this.envDb.remove({ _id: { $in: ids } }, { multi: true }, async (err) => {
|
||||
await this.set_envs();
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
await EnvModel.destroy({ where: { id: ids } });
|
||||
}
|
||||
|
||||
public async move(
|
||||
_id: string,
|
||||
id: number,
|
||||
{
|
||||
fromIndex,
|
||||
toIndex,
|
||||
@@ -100,7 +77,7 @@ export default class EnvService {
|
||||
: (envs[toIndex].position + envs[toIndex + 1].position) / 2;
|
||||
}
|
||||
const newDoc = await this.update({
|
||||
_id,
|
||||
id,
|
||||
position: targetPosition,
|
||||
});
|
||||
return newDoc;
|
||||
@@ -114,104 +91,72 @@ export default class EnvService {
|
||||
let condition = { ...query };
|
||||
if (searchText) {
|
||||
const encodeText = encodeURIComponent(searchText);
|
||||
const reg = new RegExp(`${searchText}|${encodeText}`, 'i');
|
||||
const reg = {
|
||||
[Op.or]: [
|
||||
{ [Op.like]: `%${searchText}&` },
|
||||
{ [Op.like]: `%${encodeText}%` },
|
||||
],
|
||||
};
|
||||
|
||||
condition = {
|
||||
$or: [
|
||||
{
|
||||
value: reg,
|
||||
},
|
||||
...condition,
|
||||
[Op.or]: [
|
||||
{
|
||||
name: reg,
|
||||
},
|
||||
{
|
||||
remarks: reg,
|
||||
command: reg,
|
||||
},
|
||||
{
|
||||
schedule: reg,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
const newDocs = await this.find(condition, sort);
|
||||
return newDocs;
|
||||
try {
|
||||
const result = await this.find(condition);
|
||||
return result as any;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
private async find(query: any, sort: any): Promise<Env[]> {
|
||||
return new Promise((resolve) => {
|
||||
this.envDb
|
||||
.find(query)
|
||||
.sort({ ...sort })
|
||||
.exec((err, docs) => {
|
||||
resolve(docs);
|
||||
});
|
||||
});
|
||||
private async find(query: any, sort?: any): Promise<Env[]> {
|
||||
const docs = await EnvModel.findAll({ where: { ...query } });
|
||||
return docs;
|
||||
}
|
||||
|
||||
public async get(_id: string): Promise<Env> {
|
||||
return new Promise((resolve) => {
|
||||
this.envDb.find({ _id }).exec((err, docs) => {
|
||||
resolve(docs[0]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public async getBySort(sort: any): Promise<Env> {
|
||||
return new Promise((resolve) => {
|
||||
this.envDb
|
||||
.find({})
|
||||
.sort({ ...sort })
|
||||
.limit(1)
|
||||
.exec((err, docs) => {
|
||||
resolve(docs[0]);
|
||||
});
|
||||
});
|
||||
public async get(id: number): Promise<Env> {
|
||||
const docs = await EnvModel.findAll({ where: { id } });
|
||||
return docs[0];
|
||||
}
|
||||
|
||||
public async disabled(ids: string[]) {
|
||||
return new Promise((resolve: any) => {
|
||||
this.envDb.update(
|
||||
{ _id: { $in: ids } },
|
||||
{ $set: { status: EnvStatus.disabled } },
|
||||
{ multi: true },
|
||||
async (err) => {
|
||||
await this.set_envs();
|
||||
resolve();
|
||||
},
|
||||
);
|
||||
});
|
||||
const [, docs] = await EnvModel.update(
|
||||
{ status: EnvStatus.disabled },
|
||||
{ where: { id: ids } },
|
||||
);
|
||||
await this.set_envs();
|
||||
}
|
||||
|
||||
public async enabled(ids: string[]) {
|
||||
return new Promise((resolve: any) => {
|
||||
this.envDb.update(
|
||||
{ _id: { $in: ids } },
|
||||
{ $set: { status: EnvStatus.normal } },
|
||||
{ multi: true },
|
||||
async (err, num) => {
|
||||
await this.set_envs();
|
||||
resolve();
|
||||
},
|
||||
);
|
||||
});
|
||||
const [, docs] = await EnvModel.update(
|
||||
{ status: EnvStatus.normal },
|
||||
{ where: { id: ids } },
|
||||
);
|
||||
await this.set_envs();
|
||||
}
|
||||
|
||||
public async updateNames({ ids, name }: { ids: string[]; name: string }) {
|
||||
return new Promise((resolve: any) => {
|
||||
this.envDb.update(
|
||||
{ _id: { $in: ids } },
|
||||
{ $set: { name } },
|
||||
{ multi: true },
|
||||
async (err, num) => {
|
||||
await this.set_envs();
|
||||
resolve();
|
||||
},
|
||||
);
|
||||
});
|
||||
const [, docs] = await EnvModel.update({ name }, { where: { id: ids } });
|
||||
await this.set_envs();
|
||||
}
|
||||
|
||||
public async set_envs() {
|
||||
const envs = await this.envs(
|
||||
'',
|
||||
{ position: -1 },
|
||||
{ name: { $exists: true } },
|
||||
{ name: { [Op.not]: null } },
|
||||
);
|
||||
const groups = _.groupBy(envs, 'name');
|
||||
let env_string = '';
|
||||
|
||||
+64
-95
@@ -3,29 +3,23 @@ import winston from 'winston';
|
||||
import { createRandomString } from '../config/util';
|
||||
import config from '../config';
|
||||
import DataStore from 'nedb';
|
||||
import { App } from '../data/open';
|
||||
import { App, AppModel } from '../data/open';
|
||||
import { v4 as uuidV4 } from 'uuid';
|
||||
import { dbs } from '../loaders/db';
|
||||
import sequelize, { Op } from 'sequelize';
|
||||
|
||||
@Service()
|
||||
export default class OpenService {
|
||||
private appDb = dbs.appDb;
|
||||
|
||||
constructor(@Inject('logger') private logger: winston.Logger) {}
|
||||
|
||||
public async findTokenByValue(token: string): Promise<App> {
|
||||
return new Promise((resolve) => {
|
||||
this.appDb.find(
|
||||
{ tokens: { $elemMatch: { value: token } } },
|
||||
(err, docs) => {
|
||||
if (err) {
|
||||
this.logger.error(err);
|
||||
} else {
|
||||
resolve(docs[0]);
|
||||
}
|
||||
},
|
||||
);
|
||||
public async findTokenByValue(token: string): Promise<App | null> {
|
||||
const doc = await AppModel.findOne({
|
||||
where: sequelize.fn(
|
||||
'JSON_CONTAINS',
|
||||
sequelize.col('tokens'),
|
||||
JSON.stringify({ value: token }),
|
||||
),
|
||||
});
|
||||
return doc;
|
||||
}
|
||||
|
||||
public async create(payload: App): Promise<App> {
|
||||
@@ -37,52 +31,32 @@ export default class OpenService {
|
||||
}
|
||||
|
||||
public async insert(payloads: App[]): Promise<App[]> {
|
||||
return new Promise((resolve) => {
|
||||
this.appDb.insert(payloads, (err, docs) => {
|
||||
if (err) {
|
||||
this.logger.error(err);
|
||||
} else {
|
||||
resolve(docs);
|
||||
}
|
||||
});
|
||||
});
|
||||
const docs = await AppModel.bulkCreate(payloads);
|
||||
return docs;
|
||||
}
|
||||
|
||||
public async update(payload: App): Promise<App> {
|
||||
const { _id, client_id, client_secret, tokens, ...other } = payload;
|
||||
const doc = await this.get(_id);
|
||||
const { id, client_id, client_secret, tokens, ...other } = payload;
|
||||
const doc = await this.get(id);
|
||||
const tab = new App({ ...doc, ...other });
|
||||
const newDoc = await this.updateDb(tab);
|
||||
return { ...newDoc, tokens: [] };
|
||||
}
|
||||
|
||||
private async updateDb(payload: App): Promise<App> {
|
||||
return new Promise((resolve) => {
|
||||
this.appDb.update(
|
||||
{ _id: payload._id },
|
||||
payload,
|
||||
{ returnUpdatedDocs: true },
|
||||
(err, num, doc, up) => {
|
||||
if (err) {
|
||||
this.logger.error(err);
|
||||
} else {
|
||||
resolve(doc);
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
const [, docs] = await AppModel.update(
|
||||
{ ...payload },
|
||||
{ where: { id: payload.id } },
|
||||
);
|
||||
return docs[0];
|
||||
}
|
||||
|
||||
public async remove(ids: string[]) {
|
||||
return new Promise((resolve: any) => {
|
||||
this.appDb.remove({ _id: { $in: ids } }, { multi: true }, async (err) => {
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
public async remove(ids: number[]) {
|
||||
await AppModel.destroy({ where: { id: ids } });
|
||||
}
|
||||
|
||||
public async resetSecret(_id: string): Promise<App> {
|
||||
const doc = await this.get(_id);
|
||||
public async resetSecret(id: number): Promise<App> {
|
||||
const doc = await this.get(id);
|
||||
const tab = new App({ ...doc });
|
||||
tab.client_secret = createRandomString(24, 24);
|
||||
tab.tokens = [];
|
||||
@@ -98,43 +72,44 @@ export default class OpenService {
|
||||
let condition = { ...query };
|
||||
if (searchText) {
|
||||
const encodeText = encodeURIComponent(searchText);
|
||||
const reg = new RegExp(`${searchText}|${encodeText}`, 'i');
|
||||
const reg = {
|
||||
[Op.or]: [
|
||||
{ [Op.like]: `%${searchText}&` },
|
||||
{ [Op.like]: `%${encodeText}%` },
|
||||
],
|
||||
};
|
||||
|
||||
condition = {
|
||||
$or: [
|
||||
{
|
||||
value: reg,
|
||||
},
|
||||
...condition,
|
||||
[Op.or]: [
|
||||
{
|
||||
name: reg,
|
||||
},
|
||||
{
|
||||
remarks: reg,
|
||||
command: reg,
|
||||
},
|
||||
{
|
||||
schedule: reg,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
const newDocs = await this.find(condition, sort);
|
||||
return newDocs.map((x) => ({ ...x, tokens: [] }));
|
||||
try {
|
||||
const result = await this.find(condition);
|
||||
return result.map((x) => ({ ...x, tokens: [] }));
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
private async find(query: any, sort: any): Promise<App[]> {
|
||||
return new Promise((resolve) => {
|
||||
this.appDb
|
||||
.find(query)
|
||||
.sort({ ...sort })
|
||||
.exec((err, docs) => {
|
||||
resolve(docs);
|
||||
});
|
||||
});
|
||||
private async find(query: any, sort?: any): Promise<App[]> {
|
||||
const docs = await AppModel.findAll({ where: { ...query } });
|
||||
return docs;
|
||||
}
|
||||
|
||||
public async get(_id: string): Promise<App> {
|
||||
return new Promise((resolve) => {
|
||||
this.appDb.find({ _id }).exec((err, docs) => {
|
||||
resolve(docs[0]);
|
||||
});
|
||||
});
|
||||
public async get(id: number): Promise<App> {
|
||||
const docs = await AppModel.findAll({ where: { id } });
|
||||
return docs[0];
|
||||
}
|
||||
|
||||
public async authToken({
|
||||
@@ -146,28 +121,22 @@ export default class OpenService {
|
||||
}): Promise<any> {
|
||||
const token = uuidV4();
|
||||
const expiration = Math.round(Date.now() / 1000) + 2592000; // 2592000 30天
|
||||
return new Promise((resolve) => {
|
||||
this.appDb.find({ client_id, client_secret }).exec((err, docs) => {
|
||||
if (docs && docs[0]) {
|
||||
this.appDb.update(
|
||||
{ client_id, client_secret },
|
||||
{ $push: { tokens: { value: token, expiration } } },
|
||||
{},
|
||||
(err, num, doc) => {
|
||||
resolve({
|
||||
code: 200,
|
||||
data: {
|
||||
token,
|
||||
token_type: 'Bearer',
|
||||
expiration,
|
||||
},
|
||||
});
|
||||
},
|
||||
);
|
||||
} else {
|
||||
resolve({ code: 400, message: 'client_id或client_seret有误' });
|
||||
}
|
||||
});
|
||||
});
|
||||
const doc = await AppModel.findOne({ where: { client_id, client_secret } });
|
||||
if (doc) {
|
||||
const [, docs] = await AppModel.update(
|
||||
{ tokens: [...(doc.tokens || []), { value: token, expiration }] },
|
||||
{ where: { client_id, client_secret } },
|
||||
);
|
||||
return {
|
||||
code: 200,
|
||||
data: {
|
||||
token,
|
||||
token_type: 'Bearer',
|
||||
expiration,
|
||||
},
|
||||
};
|
||||
} else {
|
||||
return { code: 400, message: 'client_id或client_seret有误' };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,22 +6,22 @@ import { exec } from 'child_process';
|
||||
|
||||
@Service()
|
||||
export default class ScheduleService {
|
||||
private scheduleStacks = new Map<string, nodeSchedule.Job>();
|
||||
private scheduleStacks = new Map<number, nodeSchedule.Job>();
|
||||
|
||||
constructor(@Inject('logger') private logger: winston.Logger) {}
|
||||
|
||||
async generateSchedule({ _id = '', command, name, schedule }: Crontab) {
|
||||
async generateSchedule({ id = 0, command, name, schedule }: Crontab) {
|
||||
this.logger.info(
|
||||
'[创建定时任务],任务ID: %s,cron: %s,任务名: %s,执行命令: %s',
|
||||
_id,
|
||||
id,
|
||||
schedule,
|
||||
name,
|
||||
command,
|
||||
);
|
||||
|
||||
this.scheduleStacks.set(
|
||||
_id,
|
||||
nodeSchedule.scheduleJob(_id, schedule, async () => {
|
||||
id,
|
||||
nodeSchedule.scheduleJob(id + '', schedule, async () => {
|
||||
try {
|
||||
exec(command, async (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
@@ -55,8 +55,8 @@ export default class ScheduleService {
|
||||
);
|
||||
}
|
||||
|
||||
async cancelSchedule({ _id = '', name }: Crontab) {
|
||||
async cancelSchedule({ id = 0, name }: Crontab) {
|
||||
this.logger.info('[取消定时任务],任务名:%s', name);
|
||||
this.scheduleStacks.has(_id) && this.scheduleStacks.get(_id)?.cancel();
|
||||
this.scheduleStacks.has(id) && this.scheduleStacks.get(id)?.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
+8
-27
@@ -3,7 +3,7 @@ import winston from 'winston';
|
||||
import config from '../config';
|
||||
import * as fs from 'fs';
|
||||
import _ from 'lodash';
|
||||
import { AuthDataType, AuthInfo, LoginStatus } from '../data/auth';
|
||||
import { AuthDataType, AuthInfo, AuthModel, LoginStatus } from '../data/auth';
|
||||
import { NotificationInfo } from '../data/notify';
|
||||
import NotificationService from './notify';
|
||||
import ScheduleService from './schedule';
|
||||
@@ -16,7 +16,6 @@ import { dbs } from '../loaders/db';
|
||||
export default class SystemService {
|
||||
@Inject((type) => NotificationService)
|
||||
private notificationService!: NotificationService;
|
||||
private authDb = dbs.authDb;
|
||||
|
||||
constructor(
|
||||
@Inject('logger') private logger: winston.Logger,
|
||||
@@ -25,34 +24,16 @@ export default class SystemService {
|
||||
) {}
|
||||
|
||||
public async getLogRemoveFrequency() {
|
||||
return new Promise((resolve) => {
|
||||
this.authDb
|
||||
.find({ type: AuthDataType.removeLogFrequency })
|
||||
.exec((err, docs) => {
|
||||
if (err || docs.length === 0) {
|
||||
resolve({});
|
||||
} else {
|
||||
resolve(docs[0].info);
|
||||
}
|
||||
});
|
||||
const doc = await AuthModel.findOne({
|
||||
where: { type: AuthDataType.removeLogFrequency },
|
||||
});
|
||||
return (doc && doc.info) || {};
|
||||
}
|
||||
|
||||
private async updateAuthDb(payload: AuthInfo): Promise<any> {
|
||||
return new Promise((resolve) => {
|
||||
this.authDb.update(
|
||||
{ type: payload.type },
|
||||
{ ...payload },
|
||||
{ upsert: true, returnUpdatedDocs: true },
|
||||
(err, num, doc: any) => {
|
||||
if (err) {
|
||||
resolve({} as NotificationInfo);
|
||||
} else {
|
||||
resolve({ ...doc.info, _id: doc._id });
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
await AuthModel.upsert({ ...payload });
|
||||
const doc = await AuthModel.findOne({ where: { type: payload.type } });
|
||||
return doc;
|
||||
}
|
||||
|
||||
public async updateNotificationMode(notificationInfo: NotificationInfo) {
|
||||
@@ -79,7 +60,7 @@ export default class SystemService {
|
||||
info: { frequency },
|
||||
});
|
||||
const cron = {
|
||||
_id: result._id,
|
||||
id: result.id,
|
||||
name: '删除日志',
|
||||
command: `ql rmlog ${frequency}`,
|
||||
schedule: `5 23 */${frequency} * *`,
|
||||
|
||||
+25
-62
@@ -6,8 +6,7 @@ import * as fs from 'fs';
|
||||
import _ from 'lodash';
|
||||
import jwt from 'jsonwebtoken';
|
||||
import { authenticator } from '@otplib/preset-default';
|
||||
import DataStore from 'nedb';
|
||||
import { AuthDataType, AuthInfo, LoginStatus } from '../data/auth';
|
||||
import { AuthDataType, AuthInfo, AuthModel, LoginStatus } from '../data/auth';
|
||||
import { NotificationInfo } from '../data/notify';
|
||||
import NotificationService from './notify';
|
||||
import { Request } from 'express';
|
||||
@@ -15,13 +14,11 @@ import ScheduleService from './schedule';
|
||||
import { spawn } from 'child_process';
|
||||
import SockService from './sock';
|
||||
import got from 'got';
|
||||
import { dbs } from '../loaders/db';
|
||||
|
||||
@Service()
|
||||
export default class UserService {
|
||||
@Inject((type) => NotificationService)
|
||||
private notificationService!: NotificationService;
|
||||
private authDb = dbs.authDb;
|
||||
|
||||
constructor(
|
||||
@Inject('logger') private logger: winston.Logger,
|
||||
@@ -174,33 +171,24 @@ export default class UserService {
|
||||
}
|
||||
|
||||
public async getLoginLog(): Promise<AuthInfo[]> {
|
||||
return new Promise((resolve) => {
|
||||
this.authDb.find({ type: AuthDataType.loginLog }).exec((err, docs) => {
|
||||
if (err || docs.length === 0) {
|
||||
resolve([]);
|
||||
} else {
|
||||
const result = docs.sort(
|
||||
(a, b) => b.info.timestamp - a.info.timestamp,
|
||||
);
|
||||
if (result.length > 100) {
|
||||
this.authDb.remove({ _id: result[result.length - 1]._id });
|
||||
}
|
||||
resolve(result.map((x) => x.info));
|
||||
}
|
||||
});
|
||||
const docs = await AuthModel.findAll({
|
||||
where: { type: AuthDataType.loginLog },
|
||||
});
|
||||
if (docs && docs.length > 0) {
|
||||
const result = docs.sort((a, b) => b.info.timestamp - a.info.timestamp);
|
||||
if (result.length > 100) {
|
||||
await AuthModel.destroy({
|
||||
where: { id: result[result.length - 1].id },
|
||||
});
|
||||
}
|
||||
return result.map((x) => x.info);
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
private async insertDb(payload: AuthInfo): Promise<AuthInfo> {
|
||||
return new Promise((resolve) => {
|
||||
this.authDb.insert(payload, (err, doc) => {
|
||||
if (err) {
|
||||
this.logger.error(err);
|
||||
} else {
|
||||
resolve(doc);
|
||||
}
|
||||
});
|
||||
});
|
||||
const doc = await AuthModel.create({ ...payload }, { returning: true });
|
||||
return doc;
|
||||
}
|
||||
|
||||
private initAuthInfo() {
|
||||
@@ -315,48 +303,23 @@ export default class UserService {
|
||||
}
|
||||
|
||||
public async getNotificationMode(): Promise<NotificationInfo> {
|
||||
return new Promise((resolve) => {
|
||||
this.authDb
|
||||
.find({ type: AuthDataType.notification })
|
||||
.exec((err, docs) => {
|
||||
if (err || docs.length === 0) {
|
||||
resolve({} as NotificationInfo);
|
||||
} else {
|
||||
resolve(docs[0].info);
|
||||
}
|
||||
});
|
||||
const doc = await AuthModel.findOne({
|
||||
where: { type: AuthDataType.notification },
|
||||
});
|
||||
return (doc && doc.info) || {};
|
||||
}
|
||||
|
||||
public async getLogRemoveFrequency() {
|
||||
return new Promise((resolve) => {
|
||||
this.authDb
|
||||
.find({ type: AuthDataType.removeLogFrequency })
|
||||
.exec((err, docs) => {
|
||||
if (err || docs.length === 0) {
|
||||
resolve({});
|
||||
} else {
|
||||
resolve(docs[0].info);
|
||||
}
|
||||
});
|
||||
const doc = await AuthModel.findOne({
|
||||
where: { type: AuthDataType.removeLogFrequency },
|
||||
});
|
||||
return (doc && doc.info) || {};
|
||||
}
|
||||
|
||||
private async updateAuthDb(payload: AuthInfo): Promise<any> {
|
||||
return new Promise((resolve) => {
|
||||
this.authDb.update(
|
||||
{ type: payload.type },
|
||||
{ ...payload },
|
||||
{ upsert: true, returnUpdatedDocs: true },
|
||||
(err, num, doc: any) => {
|
||||
if (err) {
|
||||
resolve({} as NotificationInfo);
|
||||
} else {
|
||||
resolve({ ...doc.info, _id: doc._id });
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
await AuthModel.upsert({ ...payload });
|
||||
const doc = await AuthModel.findOne({ where: { type: payload.type } });
|
||||
return doc;
|
||||
}
|
||||
|
||||
public async updateNotificationMode(notificationInfo: NotificationInfo) {
|
||||
@@ -383,7 +346,7 @@ export default class UserService {
|
||||
info: { frequency },
|
||||
});
|
||||
const cron = {
|
||||
_id: result._id,
|
||||
id: result.id,
|
||||
name: '删除日志',
|
||||
command: `ql rmlog ${frequency}`,
|
||||
schedule: `5 23 */${frequency} * *`,
|
||||
|
||||
Reference in New Issue
Block a user