import BlackBoard from './Blackboard' import Message from './Message' import Algorithm from './Algorithm' import Provider from './Provider' import CronTask from '../model/CronTask' import CronJob from './CronJob' import logger from '../logger/Logger' import AppRouter from '../routes/Router' import eventManager from '../core/EventManager' import Event from '../core/Event' import { AlgorithmConfig, EventConfig, CronConfig } from './ModConfig' import fs from 'fs' import yamljs from 'yamljs' export default class Core { blackBoard!: BlackBoard algorithms: Algorithm[] providers: Provider[] buildDir: string config: any // 存放算法模块 algorithmMods: any // 事件模块 eventMods: any // 定时模块 cronMods: any constructor() { this.buildDir = process.cwd() + "/build" this.algorithms = [] this.providers = [] this.algorithmMods = {} this.eventMods = {} this.cronMods = {} this.blackBoard = new BlackBoard() } // 提供给输入器/算法输入的接口 input(msg: Message): void { const from = msg.getFrom() this.algorithms.forEach(async algorithm => { if (algorithm.getInput() == from) { const result = await algorithm.onMessage(msg) this.blackBoard.update(algorithm.getName(), result) } }) } endInput(): void { this.algorithms.forEach(algorithms => { algorithms.onDestory() }) } /** * 读取算法配置文件 * @param path 配置算法文件路径 */ loadConfig(path: string): void { this.config = yamljs.load(path) } // 注册输入器 registerProvider(provider: Provider): void { this.providers.push(provider) } /** * 根据配置文件注册算法 */ registerAlgorithms(): void { let algorithms: AlgorithmConfig[] = this.config.algorithms if (algorithms) { for (const algorithm of algorithms) { // 通过id获得对应算法的构造函数 let func = this.algorithmMods[algorithm.id] if (func) { let instance: Algorithm = new func(algorithm.type, algorithm.windowSize, algorithm.name, algorithm.input) this.algorithms.push(instance) logger.info(`注册算法 ${algorithm.name}`) } else { logger.info(`查找不到配置的算法 ${algorithm.id}`) } } } } /** * 注册定时任务 */ registerCronJobs(): void { let crons: CronConfig[] = this.config.crons if (crons) { for (const cron of crons) { let func = this.cronMods[cron.id] if (func) { let cronJob: CronJob = new func() new CronTask(cron.cronExp, () => { cronJob.execute() }) logger.info(`注册定时任务 ${cron.id}`) } else { logger.info(`查找不到配置的定时任务 ${cron.id}`) } } } } /** * 注册算法结束事件的回调 */ registerEvents(): void { let events: EventConfig[] = this.config.events if (events) { for (const event of events) { // 通过id获得对应算法的构造函数 let func = this.eventMods[event.id] if (func) { let instance: Event = new func(event.listen) eventManager.addEvent(instance) logger.info(`注册事件 ${event.id}`) } else { logger.info(`查找不到配置的事件 ${event.id}`) } } } } startProviders() { this.providers.forEach(provider => { provider.connectDataSource() }) } /** * 读取某个目录下面的类 * @param dir 需要读取的目录 * @param itemCallback 读取到的每个文件需要执行的操作 */ loadMods(dir: string, itemCallback: Function): void { if (!fs.existsSync(dir)) { logger.info(`目录 ${dir} 不存在`) return } let files = fs.readdirSync(dir) for (const file of files) { if (file.endsWith(".js")) { let mod = require(`${dir}/${file}`) let name = file.split(".")[0] if (mod && mod.default) { itemCallback(name, mod.default) } else { console.log(mod) logger.info(`无法引入:${dir}/${file}`) } } } } /** * 加载algorithm目录下的算法类 */ loadAlgorithms() { let algorithmDir = `${this.buildDir}/algorithm` this.loadMods(algorithmDir, (fileName: string, constructor: any) => { this.algorithmMods[fileName] = constructor }) } /** * 加载algorithm目录下的算法类 */ loadEvents() { let eventDir = `${this.buildDir}/events` this.loadMods(eventDir, (fileName: string, constructor: any) => { this.eventMods[fileName] = constructor }) } /** * 加载crons目录下的定时类 */ loadCrons() { let cronDir = `${this.buildDir}/crons` this.loadMods(cronDir, (fileName: string, constructor: any) => { this.cronMods[fileName] = constructor }) } start() { this.loadAlgorithms() this.registerAlgorithms() this.loadEvents() this.registerEvents() this.loadCrons() this.registerCronJobs() this.startProviders() const appRouter = new AppRouter(this) appRouter.setRoute() } }