目录
可直接阅读核心部分, 其他内容为辅助
五、 核心部分
零、脚本中方法调用流水线概括
一、 方法解释:脚本中依赖包引入与脚本运行入口
二、 方法解释:远程接口调用
三、 方法解释:抽象sql公共部分
四、 方法解释:格式化打印日志logformat
六、 方法解释:脚本中使用的nodejs依赖
七、 总结
零、脚本中方法调用流水线概括
-
★处标明序号
★1. start(); # 入口启动 function start() { setInterval(()=>{ ★3. init(); # 获取待消费数据方法 }, 4000); ★2. impl(); # 第二个setInterval定时调用方法 } async function init() { if(libproc) { return; } sharesql = ★4.getsharesql(); # 获取公共sql的方法(有多处使用了相同的sql字段) logformat('重复执行start') libproc = true; ★5.sumtody(); # 获取分页总数 } async function sumtody() { let sumsql = `SELECT ...nt(*) as sum ${sharesql}`; mysql_pool.query(sumsql, function(err, rows, fields){ sum = rows.shift().sum; logformat(getNowDateTime()+'. sum:',sum); ★6.handlepage(sum); # 具体分页处理内容(其中包括了分页期间轮询等待) }); } async function handlepage(sum) { let totalPage = Math.floor(sum/pageSize); let remain = sum % pageSize; if(remain > 0) { totalPage += 1; } for(let i=1; i<=totalPage; i++) { let sql = `SELECT b.stu_se... limit ?, ?`; let startcount = (i-1)*pageSize; ... mysql_pool.query(sql, [(i-1)*pageSize, pageSize], function(err, rows, fields){ if(err) { logformat(err); } ★7.pagequeue = rows; # 塞入数组等待另一个setInterval消费 }); await sleep(1000);// 等待mysql异步查询结果 while(pagequeue.length == 0) { await sleep(1000); } while(pagequeue.length > 0) { await sleep(1000); } } ★8.libproc = false; # 修改标识, 第二个setInterval方法中对标识做判断 } function impl() { setInterval(()=>{ ★9.if(pagequeue.length > 0) { # 这里是第二个setInterval方法, 如果数组队列中有值则进行消费 ★9.1 let item = pagequeue.shift(); # 取出数组中的元素 logformat('patient_id:', item.patient_id, 'reg_id:', item.reg_id, 'orgCode:', ...lm_orgCode); var jsonobj = { regId: item.reg_id, orgCode: ...lm_orgCode }; var ...gCount = 0; var ...gFilePath = ""; var sqlstr = `selec... ` ...s.query(sqlstr, [item.reg_id], (err, result) => { ... ★10. handleSyncFlag(jsonobj, ...ImgCount); # 处理业务逻辑 }); } },2000); } function handleSyncFlag(jsonobj, ...unt) { request.post(`${zycloud...ceAddress}/get...Count`).send(jsonobj).end(function (err, resp) { ... let ...Count = resp.body.data; logformat('...像数量:',...gCount,'本地图片数量:',...Count); if(...mgCount != ...gCount) { ★11.updat...yncFlag(jsonobj); # 处理业务逻辑 } }); }
一、脚本中依赖包引入与脚本运行入口
- 介绍
使用setInterval+标识判断模拟队列消费(此处获取的队列值为现查询数据库获取需要处理的业务数据)
- 引入moment依赖。进行时间格式化操作sql拼接
- 引入superagent依赖。进行远程接口调用接口调用
var moment = require('moment'); var request = require('superagent') // 启动入口 start(); function start() { setInterval(()=>{ init(); }, 4000); impl(); } async function init() { if(libproc) { return; } sharesql = getsharesql(); logformat('重复执行start') libproc = true; sumtody(); } ...
二、 远程接口调用。
-
接口调用, 处理返回值
function handleSyncFlag(jsonobj, p...ImgCount) { request.post(`${z...fil...ress}/ge...ount`).send(jsonobj).end(function (err, resp) { if(err) { logformat('getrea...ount.err:', err); return; } logformat('接口返回:'+JSON.stringify(resp.body)); if (resp.body.success == false) { logformat('success.faluse:', JSON.stringify(resp.body)); return; } let ...ImgCount = resp.body.data; logformat('...数量:',...imgCount,'本地图片数量:',p...ImgCount); if(...ImgCount != p...ImgCount) { updateP...SyncFlag(jsonobj); } }); }
三、抽象sql公共部分getsharesql
,
-
避免sql查询语句冗余, 并进行测试
test()
function getsharesql() { // var time = '2023-12-20'; var time = moment().format('YYYY-MM-DD'); logformat('time:', time); let sharesql = ` FROM registra...tu_time BETWEEN CONCAT('${time}',' 00:00:00') AND CONCAT('${time}',' 23:59:59') and st...m != '' `; return sharesql; } function test() { setInterval(()=>{ var a = `'${getsharesql()}'`; var b = a + `limit ?`; logformat(b); }, 1000); }
四、格式化打印日志logformat
- 获取格式化时间戳
moment().format('YYYY-MM-DD HH:mm:ss')
- 使用语法拼接sql
`update reg...ud=2,sync_time='${moment().format('YYYY-MM-DD HH:mm:ss')}' where reg_id=${jsonobj.regId}`;
function update...cFlag(jsonobj) { var sqlArr = new Array(); sqlArr.push(`update reg...ud=2,sync_time='${moment().format('YYYY-MM-DD HH:mm:ss')}' where reg_id=${jsonobj.regId};`); var sql = sqlArr.join(''); mysql_pool.query(sql, function (err, rows, fields) { if (err) { logformat('更新...nc_cloud=2 报错. err' + err); return; } logformat('更新... 成功. reg_id:' + jsonobj.regId); }) } function logformat(... msgstr) { var msgobj = { "orgCode": z...film_orgCode, "orgName": z...film_orgName, "msg": msgstr, "time": moment().format('YYYY-MM-DD HH:mm:ss') } console.log("msgstr:", msgstr); }
五. 核心部分。
- 轮询等待消费完成, 再继续进行下一次循环。
- 若条件为真则一直循环等待, 等待第二个setInterval消费完成pagequeue中的数据。
while(pagequeue.length == 0), while(pagequeue.length > 0)
- 若条件为真则一直循环等待, 等待第二个setInterval消费完成pagequeue中的数据。
libproc
进行标识更新进行handlepage方法的被重新调用
async function handlepage(sum) { let totalPage = Math.floor(sum/pageSize); let remain = sum % pageSize; if(remain > 0) { totalPage += 1; } for(let i=1; i<=totalPage; i++) { let sql = `SELECT b.stu_se....stu_time ${sharesql} order by a.reg_id asc limit ?, ?`; let startcount = (i-1)*pageSize; logformat('startcount:',startcount,'pagesize:',pageSize) mysql_pool.query(sql, [(i-1)*pageSize, pageSize], function(err, rows, fields){ if(err) { logformat(err); } pagequeue = rows; }); await sleep(1000);// 等待mysql异步查询结果 while(pagequeue.length == 0) { await sleep(1000); } while(pagequeue.length > 0) { await sleep(1000); } } libproc = false; }
- 等待第二个setInterval消费完成pagequeue中的数据
function impl() { setInterval(()=>{ if(pagequeue.length > 0) { # 这里是第二个setInterval方法, 如果数组队列中有值则进行消费 let item = pagequeue.shift(); # 取出数组中的元素 logformat('patient_id:', item.patient_id, 'reg_id:', item.reg_id, 'orgCode:', ...lm_orgCode); var jsonobj = { regId: item.reg_id, orgCode: ...lm_orgCode }; var ...gCount = 0; var ...gFilePath = ""; var sqlstr = `selec... ` ...s.query(sqlstr, [item.reg_id], (err, result) => { ... handleSyncFlag(jsonobj, ...ImgCount); # 处理业务逻辑 }); } },2000); }
六、脚本中使用的nodejs依赖 package.json
```js
{
"name": "z...-client",
"version": "1.0.0",
"description": "",
"main": "main.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "...",
"license": "ISC",
"dependencies": {
"body-parser": "^1.19.0",
"child_process": "^1.0.2",
"cors": "^2.8.5",
"dicom-parser": "^1.8.21",
"express": "^4.17.1",
"fs": "0.0.1-security",
"http": "0.0.1-security",
"iconv-lite": "^0.6.3",
"ioredis": "^5.3.2",
"md5": "^2.3.0",
"moment": "^2.29.1",
"mssql": "^6.0.1",
"mysql": "^2.18.1",
"node-schedule": "^2.0.0",
"path": "^0.12.7",
"pg": "^8.6.0",
"redis": "^3.1.2",
"socket.io-client": "^2.2.0",
"superagent": "^6.1.0",
"uuid": "^9.0.0"
}
}
```
七、总结
脚本中使用 ... 处理了敏感信息
- 两次调用setInterval方法进行队列消费
- for循环中使用while等待
- 使用标识判断setInterval中的业务处理顺序
- 使用了moment、superagen、依赖处理时间字符串格式与远程接口调用,使用nodejs语法灵活拼接字符串。
- 使用数组作为消费队列,并使用shift数组方法获取最先进入队列的元素(第一个元素)
- 第一次使用的setInterval时长
大于
第二次的setInterval。第一次为4000ms, 第二次2000ms。这样做是因为可以加快队列的消费速度。