Client.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. const API = require('../../../lib/API')
  2. const { BaseStdResponse } = require('../../../BaseStdResponse')
  3. const { TaskScheduler } = require('../../../lib/QK/TaskScheduler')
  4. const scheduler = new TaskScheduler()
  5. function getClientCredentials(body) {
  6. return {
  7. clientId: body.client_id,
  8. clientSecret: body.client_secret
  9. }
  10. }
  11. function fail(res, err, fallback = '客户端请求失败') {
  12. return res.json({
  13. ...BaseStdResponse.ERR,
  14. msg: err?.message || fallback
  15. })
  16. }
  17. class RegisterClient extends API {
  18. constructor() {
  19. super()
  20. this.setPath('/QK/Client/Register')
  21. this.setMethod('POST')
  22. }
  23. async onRequest(req, res) {
  24. try {
  25. const { clientId, clientSecret } = getClientCredentials(req.body)
  26. const result = await scheduler.registerClient(clientId, clientSecret, req.body)
  27. this.logger.info(`[QK][API][Register] 客户端注册成功 clientId=${result.client_id} max_slots=${result.max_slots}`)
  28. return res.json({ ...BaseStdResponse.OK, data: result })
  29. } catch (err) {
  30. this.logger.error(`抢课客户端注册失败:${err.stack || err}`)
  31. return fail(res, err, '抢课客户端注册失败')
  32. }
  33. }
  34. }
  35. class HeartbeatClient extends API {
  36. constructor() {
  37. super()
  38. this.setPath('/QK/Client/Heartbeat')
  39. this.setMethod('POST')
  40. }
  41. async onRequest(req, res) {
  42. try {
  43. const { clientId, clientSecret } = getClientCredentials(req.body)
  44. const result = await scheduler.heartbeat(clientId, clientSecret, req.body)
  45. return res.json({ ...BaseStdResponse.OK, data: result })
  46. } catch (err) {
  47. this.logger.error(`抢课客户端心跳失败:${err.stack || err}`)
  48. return fail(res, err, '抢课客户端心跳失败')
  49. }
  50. }
  51. }
  52. class PullTasks extends API {
  53. constructor() {
  54. super()
  55. this.setPath('/QK/Client/PullTasks')
  56. this.setMethod('POST')
  57. }
  58. async onRequest(req, res) {
  59. try {
  60. const { clientId, clientSecret } = getClientCredentials(req.body)
  61. const tasks = await scheduler.pullTasks(clientId, clientSecret, req.body.count)
  62. if (tasks.length > 0) {
  63. this.logger.info(`[QK][API][PullTasks] clientId=${clientId} 拉取到 ${tasks.length} 个任务 taskIds=${tasks.map(t => t.id).join(',')}`)
  64. }
  65. return res.json({ ...BaseStdResponse.OK, data: tasks })
  66. } catch (err) {
  67. this.logger.error(`抢课客户端拉取任务失败:${err.stack || err}`)
  68. return fail(res, err, '抢课客户端拉取任务失败')
  69. }
  70. }
  71. }
  72. class ReclaimTasks extends API {
  73. constructor() {
  74. super()
  75. this.setPath('/QK/Client/ReclaimTasks')
  76. this.setMethod('POST')
  77. }
  78. async onRequest(req, res) {
  79. try {
  80. const { clientId, clientSecret } = getClientCredentials(req.body)
  81. const tasks = await scheduler.reclaimTasks(clientId, clientSecret)
  82. if (tasks.length > 0) {
  83. this.logger.info(`[QK][API][ReclaimTasks] clientId=${clientId} 回收 ${tasks.length} 个任务 taskIds=${tasks.map(t => t.id).join(',')}`)
  84. }
  85. return res.json({ ...BaseStdResponse.OK, data: tasks })
  86. } catch (err) {
  87. this.logger.error(`抢课客户端回收任务失败:${err.stack || err}`)
  88. return fail(res, err, '抢课客户端回收任务失败')
  89. }
  90. }
  91. }
  92. class ReleaseTasks extends API {
  93. constructor() {
  94. super()
  95. this.setPath('/QK/Client/ReleaseTasks')
  96. this.setMethod('POST')
  97. }
  98. async onRequest(req, res) {
  99. try {
  100. const { clientId, clientSecret } = getClientCredentials(req.body)
  101. const result = await scheduler.releaseTasks(clientId, clientSecret, req.body)
  102. if (result.released > 0) {
  103. this.logger.info(`[QK][API][ReleaseTasks] clientId=${clientId} 释放 ${result.released} 个任务 taskIds=${result.task_ids.join(',')}`)
  104. }
  105. return res.json({ ...BaseStdResponse.OK, data: result })
  106. } catch (err) {
  107. this.logger.error(`抢课客户端释放任务失败:${err.stack || err}`)
  108. return fail(res, err, '抢课客户端释放任务失败')
  109. }
  110. }
  111. }
  112. class ReportResult extends API {
  113. constructor() {
  114. super()
  115. this.setPath('/QK/Client/ReportResult')
  116. this.setMethod('POST')
  117. }
  118. async onRequest(req, res) {
  119. try {
  120. const { clientId, clientSecret } = getClientCredentials(req.body)
  121. const result = await scheduler.reportResult(clientId, clientSecret, req.body)
  122. this.logger.info(`[QK][API][ReportResult] clientId=${clientId} taskId=${result.task_id} status=${result.status}`)
  123. return res.json({ ...BaseStdResponse.OK, data: result })
  124. } catch (err) {
  125. this.logger.error(`抢课客户端上报结果失败:${err.stack || err}`)
  126. return fail(res, err, '抢课客户端上报结果失败')
  127. }
  128. }
  129. }
  130. class ReportProgress extends API {
  131. constructor() {
  132. super()
  133. this.setPath('/QK/Client/ReportProgress')
  134. this.setMethod('POST')
  135. }
  136. async onRequest(req, res) {
  137. try {
  138. const { clientId, clientSecret } = getClientCredentials(req.body)
  139. const result = await scheduler.reportProgress(clientId, clientSecret, req.body)
  140. return res.json({ ...BaseStdResponse.OK, data: result })
  141. } catch (err) {
  142. this.logger.error(`抢课客户端上报进度失败:${err.stack || err}`)
  143. return fail(res, err, '抢课客户端上报进度失败')
  144. }
  145. }
  146. }
  147. module.exports = {
  148. RegisterClient,
  149. HeartbeatClient,
  150. PullTasks,
  151. ReclaimTasks,
  152. ReleaseTasks,
  153. ReportResult,
  154. ReportProgress
  155. }