check-api.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. /// 每个小时检查下api接口及数据一致性
  2. const axios = require('axios');
  3. const { sendEmail } = require('./email')
  4. const { sendSms } = require('./sms')
  5. const SmsTemplate = require('./sms-templates');
  6. const onlineHost = 'app2.pcoloring.com';
  7. const offlineHost = 'color.jccytech.cn';
  8. const artLatestUri = 'napi/number/v9/list/art/content?column=latest';
  9. const jigsawLatestUri = 'napi/jigsaw/mobi/list/latest';
  10. const artPuzzleLatestUri = 'napi/puzzle/mobi/list/latest';
  11. async function checkArtLatest() {
  12. let onlineUrl = `https://${onlineHost}/${artLatestUri}`;
  13. let offlineUrl = `https://${offlineHost}/${artLatestUri}`;
  14. let onlineData, offlineData;
  15. try {
  16. let resp = await axios.get(onlineUrl);
  17. onlineData = resp.data;
  18. } catch (e) {
  19. console.error('Art线上latest数据请求出错, 请及时检查:', [e.message]);
  20. return {
  21. result: false,
  22. errcode: 100,
  23. title: 'Art线上latest数据请求出错, 请及时检查',
  24. sms: SmsTemplate.SMS_API_ERROR,
  25. data: [e.message],
  26. }
  27. }
  28. try {
  29. let resp = await axios.get(offlineUrl);
  30. offlineData = resp.data;
  31. } catch (e) {
  32. console.error('Art 线下latest数据请求出错, 请及时检查:', [e.message]);
  33. return {
  34. result: false,
  35. errcode: 100,
  36. title: 'Art 线下latest数据请求出错, 请及时检查',
  37. sms: SmsTemplate.SMS_API_ERROR,
  38. data: [e.message],
  39. }
  40. }
  41. // 检查数据是否一致: 看第一条即可
  42. if (!onlineData.data || onlineData.data.length <= 0) {
  43. return {
  44. result: false,
  45. errcode: 100,
  46. title: 'Art 线上latest数据有误, 请及时检查',
  47. sms: SmsTemplate.SMS_API_ERROR,
  48. data: ['latest数据为空'],
  49. }
  50. }
  51. if (!offlineData.data || offlineData.data.length <= 0) {
  52. return {
  53. result: false,
  54. errcode: 100,
  55. title: 'Art 线下latest数据有误, 请及时检查',
  56. sms: SmsTemplate.SMS_API_ERROR,
  57. data: ['latest数据为空'],
  58. }
  59. }
  60. if (onlineData.data[0]._id != offlineData.data[0]._id) {
  61. return {
  62. result: false,
  63. errcode: 100,
  64. title: 'Art latest 线上线下数据不一致, 请及时检查',
  65. sms: SmsTemplate.SMS_SYNC_ERROR,
  66. data: [onlineUrl, offlineUrl],
  67. }
  68. }
  69. return {
  70. result: true,
  71. errcode: 0,
  72. title: 'Art 服务恢复正常运行',
  73. sms: SmsTemplate.SMS_RESUME,
  74. data: ['Art 服务一切正常']
  75. }
  76. }
  77. async function checkJigsawLatest() {
  78. let onlineUrl = `https://${onlineHost}/${jigsawLatestUri}`;
  79. let offlineUrl = `https://${offlineHost}/${jigsawLatestUri}`;
  80. let onlineData, offlineData;
  81. try {
  82. let resp = await axios.get(onlineUrl);
  83. onlineData = resp.data;
  84. } catch (e) {
  85. console.error('Jigsaw 线上latest数据请求出错, 请及时检查:', e.message);
  86. return {
  87. result: false,
  88. errcode: 200,
  89. title: 'Jigsaw 线上latest数据请求出错, 请及时检查',
  90. sms: SmsTemplate.SMS_API_ERROR,
  91. data: [e.message],
  92. }
  93. }
  94. try {
  95. let resp = await axios.get(offlineUrl);
  96. offlineData = resp.data;
  97. } catch (e) {
  98. console.error('Jigsaw 线下latest数据请求出错, 请及时检查:', e.message);
  99. return {
  100. result: false,
  101. errcode: 200,
  102. title: 'Jigsaw 线下latest数据请求出错, 请及时检查',
  103. sms: SmsTemplate.SMS_API_ERROR,
  104. data: [e.message],
  105. }
  106. }
  107. // 检查数据是否一致: 看第一条即可
  108. if (!onlineData.data || onlineData.data.length <= 0) {
  109. return {
  110. result: false,
  111. errcode: 200,
  112. title: 'Jigsaw 线上latest数据有误, 请及时检查',
  113. sms: SmsTemplate.SMS_API_ERROR,
  114. data: ['latest数据为空'],
  115. }
  116. }
  117. if (!offlineData.data || offlineData.data.length <= 0) {
  118. return {
  119. result: false,
  120. errcode: 200,
  121. title: 'Jigsaw 线下latest数据有误, 请及时检查',
  122. sms: SmsTemplate.SMS_API_ERROR,
  123. data: ['latest数据为空'],
  124. }
  125. }
  126. if (onlineData.data[0]._id != offlineData.data[0]._id) {
  127. return {
  128. result: false,
  129. errcode: 200,
  130. title: 'Jigsaw latest 线上线下数据不一致, 请及时检查',
  131. sms: SmsTemplate.SMS_SYNC_ERROR,
  132. data: [onlineUrl, offlineUrl],
  133. }
  134. }
  135. return {
  136. result: true,
  137. errcode: 0,
  138. title: 'Jigsaw 服务恢复正常运行',
  139. sms: SmsTemplate.SMS_RESUME,
  140. data: ['Jigsaw 服务一切正常']
  141. }
  142. }
  143. async function checkArtPuzzleLatest() {
  144. let onlineUrl = `https://${onlineHost}/${artPuzzleLatestUri}`;
  145. let offlineUrl = `https://${offlineHost}/${artPuzzleLatestUri}`;
  146. let onlineData, offlineData;
  147. try {
  148. let resp = await axios.get(onlineUrl);
  149. onlineData = resp.data;
  150. } catch (e) {
  151. console.error('ArtPuzzle 线上latest数据请求出错, 请及时检查:', e.message);
  152. return {
  153. result: false,
  154. errcode: 300,
  155. title: 'ArtPuzzle 线上latest数据请求出错, 请及时检查',
  156. sms: SmsTemplate.SMS_API_ERROR,
  157. data: [e.message],
  158. }
  159. }
  160. try {
  161. let resp = await axios.get(offlineUrl);
  162. offlineData = resp.data;
  163. } catch (e) {
  164. console.error('ArtPuzzle 线下latest数据请求出错, 请及时检查:', e.message);
  165. return {
  166. result: false,
  167. errcode: 300,
  168. title: 'ArtPuzzle 线下latest数据请求出错, 请及时检查',
  169. sms: SmsTemplate.SMS_API_ERROR,
  170. data: [e.message],
  171. }
  172. }
  173. if (!onlineData.data || onlineData.data.length <= 0) {
  174. return {
  175. result: false,
  176. errcode: 300,
  177. title: 'ArtPuzzle 线上latest数据有误, 请及时检查',
  178. sms: SmsTemplate.SMS_API_ERROR,
  179. data: ['latest数据为空'],
  180. }
  181. }
  182. if (!offlineData.data || offlineData.data.length <= 0) {
  183. return {
  184. result: false,
  185. errcode: 300,
  186. title: 'ArtPuzzle 线下latest数据有误, 请及时检查',
  187. sms: SmsTemplate.SMS_API_ERROR,
  188. data: ['latest数据为空'],
  189. }
  190. }
  191. // 检查数据是否一致: 看第一条即可
  192. if (onlineData.data[0]._id != offlineData.data[0]._id) {
  193. return {
  194. result: false,
  195. errcode: 300,
  196. title: 'ArtPuzzle latest 线上线下数据不一致, 请及时检查',
  197. sms: SmsTemplate.SMS_SYNC_ERROR,
  198. data: [onlineUrl, offlineUrl],
  199. }
  200. }
  201. return {
  202. result: true,
  203. errcode: 0,
  204. title: 'Jigsaw 服务恢复正常运行',
  205. sms: SmsTemplate.SMS_RESUME,
  206. data: ['Jigsaw 服务一切正常']
  207. }
  208. }
  209. // 检查art.pcoloring.com网站
  210. async function checkArtSite() {
  211. let url = `https://art.pcoloring.com/en`;
  212. let data;
  213. try {
  214. let resp = await axios.get(url);
  215. data = resp.data;
  216. } catch (e) {
  217. console.error('art.pcoloring.com 网站无法访问,请及时检查', [e.message]);
  218. return {
  219. result: false,
  220. errcode: 1000,
  221. title: 'art.pcoloring.com 网站无法访问,请及时检查',
  222. sms: SmsTemplate.SMS_PCOLORING_ERROR,
  223. data: [e.message],
  224. }
  225. }
  226. return {
  227. result: true,
  228. errcode: 0,
  229. title: 'art.pcoloring.com 网站正常运行',
  230. sms: SmsTemplate.SMS_RESUME,
  231. data: ['art.pcoloring.com 网站正常运行']
  232. }
  233. }
  234. async function run(lastErrCode = 0) {
  235. console.log("check api...", new Date());
  236. try {
  237. let result = null;
  238. // 如果出现异常,连续检测3次才发送通知,减少误报,因为出现不少次因为网络原因一时半会请求不到数据就报警的情况
  239. for (let i = 0; i < 3; i++) {
  240. result = await checkArtLatest();
  241. console.log(result);
  242. if (!result.result) {
  243. console.warn("检查Art服务出现异常,一分钟后重试");
  244. await delay(60 * 1000);
  245. } else {
  246. console.warn("Art服务一切正常");
  247. break;
  248. }
  249. }
  250. if (!result.result) {
  251. console.error("连续3次检查Art服务异常,发送通知");
  252. sendEmail(result.title, result.data);
  253. sendSms(result.sms);
  254. console.log("5分钟后再试");
  255. setTimeout(run, 5 * 60 * 1000, result.errcode);
  256. return;
  257. } else {
  258. // 如果上次时出错的情况, 那么属于服务恢复,发送恢复通知
  259. if (lastErrCode == 100) {
  260. sendEmail(result.title, result.data);
  261. sendSms(result.sms);
  262. }
  263. }
  264. for (let i = 0; i < 3; i++) {
  265. result = await checkJigsawLatest();
  266. console.log(result);
  267. if (!result.result) {
  268. console.warn("检查Jigsaw服务出现异常,一分钟后重试");
  269. await delay(60 * 1000);
  270. } else {
  271. console.warn("Jigsaw服务一切正常");
  272. break;
  273. }
  274. }
  275. if (!result.result) {
  276. console.error("连续3次检查Jigsaw服务异常,发送通知");
  277. sendEmail(result.title, result.data);
  278. sendSms(result.sms);
  279. console.log("5分钟后再试");
  280. setTimeout(run, 5 * 60 * 1000, result.errcode);
  281. return;
  282. } else {
  283. // 如果上次时出错的情况, 那么属于服务恢复,发送恢复通知
  284. if (lastErrCode == 200) {
  285. sendEmail(result.title, result.data);
  286. sendSms(result.sms);
  287. }
  288. }
  289. for (let i = 0; i < 3; i++) {
  290. result = await checkArtPuzzleLatest();
  291. console.log(result);
  292. if (!result.result) {
  293. console.warn("检查ArtPuzzle服务出现异常,一分钟后重试");
  294. await delay(60 * 1000);
  295. } else {
  296. console.warn("ArtPuzzle服务一切正常");
  297. break;
  298. }
  299. }
  300. if (!result.result) {
  301. console.error("连续3次检查ArtPuzzle服务异常,发送通知");
  302. sendEmail(result.title, result.data);
  303. sendSms(result.sms);
  304. console.log("5分钟后再试");
  305. setTimeout(run, 5 * 60 * 1000, result.errcode);
  306. return;
  307. } else {
  308. // 如果上次时出错的情况, 那么属于服务恢复,发送恢复通知
  309. if (lastErrCode == 300) {
  310. sendEmail(result.title, result.data);
  311. sendSms(result.sms);
  312. }
  313. }
  314. for (let i = 0; i < 3; i++) {
  315. result = await checkArtSite();
  316. console.log(result);
  317. if (!result.result) {
  318. console.warn("检查art.pcoloring.com网站服务出现异常,一分钟后重试");
  319. await delay(60 * 1000);
  320. } else {
  321. console.warn("art.pcoloring.com网站一切正常");
  322. break;
  323. }
  324. }
  325. if (!result.result) {
  326. console.error("连续3次检查art.pcoloring.com网站服务异常,发送通知");
  327. sendEmail(result.title, result.data);
  328. sendSms(result.sms);
  329. console.log("5分钟后再试");
  330. setTimeout(run, 5 * 60 * 1000, result.errcode);
  331. return;
  332. } else {
  333. // 如果上次时出错的情况, 那么属于服务恢复,发送恢复通知
  334. if (lastErrCode == 1000) {
  335. sendEmail(result.title, result.data);
  336. sendSms(result.sms);
  337. }
  338. }
  339. } catch (err) {
  340. console.error(err.stack);
  341. }
  342. }
  343. function delay(ms) {
  344. return new Promise(done => setTimeout(done, ms));
  345. }
  346. module.exports = { run }
  347. if (require.main == module) {
  348. run();
  349. }