fork from bc4552c5a8
This commit is contained in:
221
exts/yapi-plugin-swagger-auto-sync/interfaceSyncUtils.js
Normal file
221
exts/yapi-plugin-swagger-auto-sync/interfaceSyncUtils.js
Normal file
@@ -0,0 +1,221 @@
|
||||
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) {
|
||||
if(!swaggerUrl)return;
|
||||
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(oldSyncJob._id, 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;
|
||||
Reference in New Issue
Block a user