| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- const schedule = require('node-schedule');
- const openController = require('controllers/open.js');
- const projectModel = require('models/project.js');
- const syncModel = require('./syncModel.js');
- const tokenModel = require('models/token.js');
- const yapi = require('yapi.js')
- const sha = require('sha.js');
- const md5 = require('md5');
- const { getToken } = require('utils/token');
- const jobMap = new Map();
- class syncUtils {
- constructor(ctx) {
- yapi.commons.log("-------------------------------------swaggerSyncUtils constructor-----------------------------------------------");
- this.ctx = ctx;
- this.openController = yapi.getInst(openController);
- this.syncModel = yapi.getInst(syncModel);
- this.tokenModel = yapi.getInst(tokenModel)
- this.projectModel = yapi.getInst(projectModel);
- this.init()
- }
- //初始化定时任务
- async init() {
- let allSyncJob = await this.syncModel.listAll();
- for (let i = 0, len = allSyncJob.length; i < len; i++) {
- let syncItem = allSyncJob[i];
- if (syncItem.is_sync_open) {
- this.addSyncJob(syncItem.project_id, syncItem.sync_cron, syncItem.sync_json_url, syncItem.sync_mode, syncItem.uid);
- }
- }
- }
- /**
- * 新增同步任务.
- * @param {*} projectId 项目id
- * @param {*} cronExpression cron表达式,针对定时任务
- * @param {*} swaggerUrl 获取swagger的地址
- * @param {*} syncMode 同步模式
- * @param {*} uid 用户id
- */
- async addSyncJob(projectId, cronExpression, swaggerUrl, syncMode, uid) {
- let projectToken = await this.getProjectToken(projectId, uid);
- //立即执行一次
- this.syncInterface(projectId, swaggerUrl, syncMode, uid, projectToken);
- let scheduleItem = schedule.scheduleJob(cronExpression, async () => {
- this.syncInterface(projectId, swaggerUrl, syncMode, uid, projectToken);
- });
- //判断是否已经存在这个任务
- let jobItem = jobMap.get(projectId);
- if (jobItem) {
- jobItem.cancel();
- }
- jobMap.set(projectId, scheduleItem);
- }
- //同步接口
- async syncInterface(projectId, swaggerUrl, syncMode, uid, projectToken) {
- yapi.commons.log('定时器触发, syncJsonUrl:' + swaggerUrl + ",合并模式:" + syncMode);
- let oldPorjectData;
- try {
- oldPorjectData = await this.projectModel.get(projectId);
- } catch(e) {
- yapi.commons.log('获取项目:' + projectId + '失败');
- this.deleteSyncJob(projectId);
- //删除数据库定时任务
- await this.syncModel.delByProjectId(projectId);
- return;
- }
- //如果项目已经删除了
- if (!oldPorjectData) {
- yapi.commons.log('项目:' + projectId + '不存在');
- this.deleteSyncJob(projectId);
- //删除数据库定时任务
- await this.syncModel.delByProjectId(projectId);
- return;
- }
- let newSwaggerJsonData;
- try {
- newSwaggerJsonData = await this.getSwaggerContent(swaggerUrl)
- if (!newSwaggerJsonData || typeof newSwaggerJsonData !== 'object') {
- yapi.commons.log('数据格式出错,请检查')
- this.saveSyncLog(0, syncMode, "数据格式出错,请检查", uid, projectId);
- }
- newSwaggerJsonData = JSON.stringify(newSwaggerJsonData)
- } catch (e) {
- this.saveSyncLog(0, syncMode, "获取数据失败,请检查", uid, projectId);
- yapi.commons.log('获取数据失败' + e.message)
- }
- let oldSyncJob = await this.syncModel.getByProjectId(projectId);
- //更新之前判断本次swagger json数据是否跟上次的相同,相同则不更新
- if (newSwaggerJsonData && oldSyncJob.old_swagger_content && oldSyncJob.old_swagger_content == md5(newSwaggerJsonData)) {
- //记录日志
- this.saveSyncLog(0, syncMode, "接口无更新", uid, projectId);
- oldSyncJob.last_sync_time = yapi.commons.time();
- await this.syncModel.upById(projectId, oldSyncJob);
- return;
- }
- let _params = {
- type: 'swagger',
- json: newSwaggerJsonData,
- project_id: projectId,
- merge: syncMode,
- token: projectToken
- }
- let requestObj = {
- params: _params
- };
- await this.openController.importData(requestObj);
- //同步成功就更新同步表的数据
- if (requestObj.body.errcode == 0) {
- //修改sync_model的属性
- oldSyncJob.last_sync_time = yapi.commons.time();
- oldSyncJob.old_swagger_content = md5(newSwaggerJsonData);
- await this.syncModel.upById(oldSyncJob._id, oldSyncJob);
- }
- //记录日志
- this.saveSyncLog(requestObj.body.errcode, syncMode, requestObj.body.errmsg, uid, projectId);
- }
- getSyncJob(projectId) {
- return jobMap.get(projectId);
- }
- deleteSyncJob(projectId) {
- let jobItem = jobMap.get(projectId);
- if (jobItem) {
- jobItem.cancel();
- }
- }
- /**
- * 记录同步日志
- * @param {*} errcode
- * @param {*} syncMode
- * @param {*} moremsg
- * @param {*} uid
- * @param {*} projectId
- */
- saveSyncLog(errcode, syncMode, moremsg, uid, projectId) {
- yapi.commons.saveLog({
- content: '自动同步接口状态:' + (errcode == 0 ? '成功,' : '失败,') + "合并模式:" + this.getSyncModeName(syncMode) + ",更多信息:" + moremsg,
- type: 'project',
- uid: uid,
- username: "自动同步用户",
- typeid: projectId
- });
- }
- /**
- * 获取项目token,因为导入接口需要鉴权.
- * @param {*} project_id 项目id
- * @param {*} uid 用户id
- */
- async getProjectToken(project_id, uid) {
- try {
- let data = await this.tokenModel.get(project_id);
- let token;
- if (!data) {
- let passsalt = yapi.commons.randStr();
- token = sha('sha1')
- .update(passsalt)
- .digest('hex')
- .substr(0, 20);
- await this.tokenModel.save({ project_id, token });
- } else {
- token = data.token;
- }
- token = getToken(token, uid);
- return token;
- } catch (err) {
- return "";
- }
- }
- getUid(uid) {
- return parseInt(uid, 10);
- }
- /**
- * 转换合并模式的值为中文.
- * @param {*} syncMode 合并模式
- */
- getSyncModeName(syncMode) {
- if (syncMode == 'good') {
- return '智能合并';
- } else if (syncMode == 'normal') {
- return '普通模式';
- } else if (syncMode == 'merge') {
- return '完全覆盖';
- }
- return '';
- }
- async getSwaggerContent(swaggerUrl) {
- const axios = require('axios')
- try {
- let response = await axios.get(swaggerUrl);
- if (response.status > 400) {
- throw new Error(`http status "${response.status}"` + '获取数据失败,请确认 swaggerUrl 是否正确')
- }
- return response.data;
- } catch (e) {
- let response = e.response || {status: e.message || 'error'};
- throw new Error(`http status "${response.status}"` + '获取数据失败,请确认 swaggerUrl 是否正确')
- }
- }
- }
- module.exports = syncUtils;
|